Run at 60 FPS
This commit is contained in:
45
mttt.nim
45
mttt.nim
@@ -1,16 +1,49 @@
|
||||
import dom, jsconsole, sugar
|
||||
import dom, jsconsole, sugar, times, strformat
|
||||
|
||||
import src/game
|
||||
|
||||
const
|
||||
canvasId = "game_canvas"
|
||||
|
||||
proc onTick(game: Game, time: float) =
|
||||
discard window.requestAnimationFrame((time: float) => onTick(game, time))
|
||||
game.nextFrame(time)
|
||||
var frameCount = 0
|
||||
var mtttGame: Game
|
||||
var startTime, now, then: Time
|
||||
var elapsed, fpsInterval: Duration
|
||||
|
||||
proc animate(): void =
|
||||
# request another frame
|
||||
discard window.requestAnimationFrame((time: float) => animate())
|
||||
# calc elapsed time since last loop
|
||||
now = getTime();
|
||||
elapsed = now - then;
|
||||
|
||||
# if enough time has elapsed, draw the next frame
|
||||
if elapsed > fpsInterval:
|
||||
# Get ready for next frame by setting then=now, but also adjust for your
|
||||
# specified fpsInterval not being a multiple of RAF's interval (16.7ms)
|
||||
then = now - fpsInterval
|
||||
var sinceStart = now - startTime;
|
||||
frameCount.inc
|
||||
var currentFps = (1000 / (sinceStart.inMilliseconds.int / frameCount) * 100) / 100;
|
||||
|
||||
var e: Element
|
||||
e = dom.document.getElementById("fps")
|
||||
e.innerHTML = fmt"Current FPS: {currentFps:9.2f}"
|
||||
e = dom.document.getElementById("fps-interval")
|
||||
e.innerHTML = fmt"FPS Interval: {fpsInterval}"
|
||||
e = dom.document.getElementById("then")
|
||||
e.innerHTML = fmt"Seconds since start: {sinceStart.inSeconds}"
|
||||
|
||||
mtttGame.nextFrame(elapsed)
|
||||
|
||||
proc startAnimating(fps: int): void =
|
||||
fpsInterval = initDuration(milliseconds = (1000 / fps).toInt)
|
||||
then = getTime()
|
||||
startTime = then
|
||||
animate()
|
||||
|
||||
proc onLoad(event: Event) {.exportc.} =
|
||||
var game = newGame(canvasId, window.innerWidth, window.innerHeight)
|
||||
onTick(game, 60)
|
||||
mtttGame = newGame(canvasId, window.innerWidth, window.innerHeight)
|
||||
startAnimating(60)
|
||||
|
||||
window.onload = onLoad
|
||||
@@ -18,7 +18,11 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- <div>This site requires javascript...</div> -->
|
||||
<div id="debug" style="display: flex; justify-content: space-around;">
|
||||
<span id="fps"></span>
|
||||
<span id="fps-interval"></span>
|
||||
<span id="then"></span>
|
||||
</div>
|
||||
<div id="game_center">
|
||||
<div id="game">
|
||||
<canvas id="game_canvas"></canvas>
|
||||
|
||||
30
src/game.nim
30
src/game.nim
@@ -1,13 +1,14 @@
|
||||
import dom, math, strformat
|
||||
import dom, math, strformat, times
|
||||
|
||||
import gamelight/[graphics, geometry, vec, utils]
|
||||
import gamelight/[graphics, vec]
|
||||
|
||||
import libmttt
|
||||
|
||||
type
|
||||
Game* = ref object
|
||||
renderer: Renderer2D
|
||||
lastUpdate, totalTime: float
|
||||
startTime: Time
|
||||
totalTime*: Duration
|
||||
paused: bool
|
||||
scene: Scene
|
||||
state: GameState
|
||||
@@ -22,7 +23,7 @@ const
|
||||
font = "Helvetica, monospace"
|
||||
padding = 10 # Padding around the game area in pixels
|
||||
|
||||
var
|
||||
var
|
||||
renderWidth, renderHeight: int ## Canvas render area in pixels
|
||||
|
||||
proc toTimeString(milliseconds: float): string =
|
||||
@@ -38,15 +39,15 @@ proc switchScene(game: Game, scene: Scene) =
|
||||
of Scene.Game:
|
||||
var elements: seq[Element] = @[]
|
||||
|
||||
let timeTextPos = (padding.toFloat, padding.toFloat)
|
||||
let timeTextPos = (padding.toFloat, padding.toFloat).toPoint
|
||||
elements.add game.renderer.createTextElement("Time", timeTextPos, "#000000", 26, font)
|
||||
|
||||
let timePos = (padding.toFloat, padding.toFloat + 35.0)
|
||||
let timePos = (padding.toFloat, padding.toFloat + 35.0).toPoint
|
||||
game.timeElement = game.renderer.createTextElement("0", timePos, "#000000", 14, font)
|
||||
|
||||
|
||||
proc newGame*(canvasId: string, width, height: int): Game =
|
||||
var
|
||||
var
|
||||
player1 = Player(name: "Player 1")
|
||||
player2 = Player(name: "Player 2")
|
||||
|
||||
@@ -57,25 +58,26 @@ proc newGame*(canvasId: string, width, height: int): Game =
|
||||
renderer: newRenderer2D(canvasId, width, height),
|
||||
scene: Scene.Game,
|
||||
state: newGameState(player1, player2),
|
||||
paused: false
|
||||
paused: false,
|
||||
startTime: getTime()
|
||||
)
|
||||
switchScene(result, Scene.Game)
|
||||
|
||||
proc update(game: Game, time: float) =
|
||||
proc update(game: Game, time: Duration) =
|
||||
# Update the game logic
|
||||
# Return early if paused.
|
||||
if game.paused or game.scene != Scene.Game: return
|
||||
|
||||
game.totalTime += time
|
||||
game.totalTime = getTime() - game.startTime
|
||||
|
||||
proc drawMainMenu(game: Game) =
|
||||
discard
|
||||
|
||||
proc drawGame(game: Game) =
|
||||
# Draw changing UI Elements
|
||||
game.timeElement.innerHTML = game.totalTime.toTimeString
|
||||
game.timeElement.innerHTML = fmt"{game.totalTime.inMinutes}m {game.totalTime.inSeconds mod 60}s"
|
||||
|
||||
proc draw(game: Game) =
|
||||
proc draw(game: Game) =
|
||||
# Draw the current screen on the canvas
|
||||
# Fill background color.
|
||||
game.renderer.fillRect(0.0, 0.0, renderWidth, renderHeight, gameBgColor)
|
||||
@@ -85,7 +87,7 @@ proc draw(game: Game) =
|
||||
of Scene.Game:
|
||||
drawGame(game)
|
||||
|
||||
proc nextFrame*(game: Game, frameTime: float) =
|
||||
proc nextFrame*(game: Game, frameTime: Duration) =
|
||||
# Determine id an update is necessary
|
||||
game.update(frameTime)
|
||||
game.draw()
|
||||
game.draw()
|
||||
|
||||
Reference in New Issue
Block a user