Skip to content

Instantly share code, notes, and snippets.

@bryanedds
Created September 27, 2024 08:20
Show Gist options
  • Save bryanedds/3e8c5237d2b2005179ce19fd55b19ee5 to your computer and use it in GitHub Desktop.
Save bryanedds/3e8c5237d2b2005179ce19fd55b19ee5 to your computer and use it in GitHub Desktop.
namespace MyGame
open System
open System.Numerics
open Prime
open Nu
type GameplayState =
| Playing
| Quitting
// this is our MMCC model type representing gameplay.
// this model representation uses update time, that is, time based on number of engine updates.
type Gameplay =
{ GameplayTime : int64
GameplayState : GameplayState }
// this represents the gameplay model in an unutilized state, such as when the gameplay screen is not selected.
static member empty =
{ GameplayTime = 0L
GameplayState = Quitting }
// this represents the gameplay model in its initial state, such as when gameplay starts.
static member initial =
{ Gameplay.empty with
GameplayState = Playing }
// this extends the Screen API to expose the Gameplay model as well as the Quit event.
[<AutoOpen>]
module GameplayExtensions =
type Screen with
member this.GetGameplay world = this.GetModelGeneric<Gameplay> world
member this.SetGameplay value world = this.SetModelGeneric<Gameplay> value world
member this.Gameplay = this.ModelGeneric<Gameplay> ()
// this is the dispatcher that defines the behavior of the screen where gameplay takes place.
type GameplayDispatcher () =
inherit ScreenDispatcher<Gameplay> (Gameplay.empty)
// here we define the screen's fallback model depending on whether screen is selected
override this.GetFallbackModel (_, screen, world) =
if screen.GetSelected world
then Gameplay.initial
else Gameplay.empty
// here we define the behavior of our gameplay
override this.Run (gameplay, screen, world) =
// declare scene group when selected
let world =
if screen.GetSelected world then
// begin scene declaration
let world = World.beginGroupFromFile "Scene" "Assets/Gameplay/Scene.nugroup" [] world
let (_, world) = World.doCharacter3d "Player" [Entity.AnimatedModel .= Assets.Gameplay.Sophie; Entity.Position .= v3 1.0f 0.0f -1.0f] world
// move player
let player = world.RecentEntity
let playerBodyId = player.GetBodyId world
let playerSpeed = 1.8f * world.GameDelta.Seconds
let playerRotation = player.GetRotation world
let playerVelocity =
(if World.isKeyboardKeyDown KeyboardKey.W world then playerRotation.Forward * playerSpeed else v3Zero) +
(if World.isKeyboardKeyDown KeyboardKey.S world then playerRotation.Back * playerSpeed else v3Zero) +
(if World.isKeyboardKeyDown KeyboardKey.A world then playerRotation.Left * playerSpeed else v3Zero) +
(if World.isKeyboardKeyDown KeyboardKey.D world then playerRotation.Right * playerSpeed else v3Zero)
let grounded = World.getBodyGrounded playerBodyId world
let turnSpeed = 1.8f * world.GameDelta.Seconds * if grounded then 1.0f else 0.75f
let turnVelocity =
(if World.isKeyboardKeyDown KeyboardKey.Left world then turnSpeed else 0.0f) +
(if World.isKeyboardKeyDown KeyboardKey.Right world then -turnSpeed else 0.0f)
let world = player.SetPosition (player.GetPosition world + playerVelocity) world
let world = player.SetRotation (player.GetRotation world * Quaternion.CreateFromAxisAngle (v3Up, turnVelocity)) world
// update eye to look at player
let world =
if world.Advancing then
let position = player.GetPosition world
let rotation = player.GetRotation world
let world = World.setEye3dCenter (position + v3Up * 1.75f - rotation.Forward * 2.0f) world
let world = World.setEye3dRotation rotation world
world
else world
// end scene declaration
World.endGroup world
else world
// declare gui group
let world = World.beginGroup "Gui" [] world
let (gameplay, world) =
match World.doButton "Quit" [Entity.Text .= "Quit"; Entity.Position .= v3 232.0f -144.0f 0.0f] world with
| (true, world) -> ({ gameplay with GameplayState = Quitting }, world)
| (false, world) -> (gameplay, world)
let world = World.endGroup world
// advance gameplay time
let gameDelta = world.GameDelta
let gameplay = { gameplay with GameplayTime = gameplay.GameplayTime + gameDelta.Updates }
(gameplay, world)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment