From decc2a88d716afcee698c7260eff692124f99f20 Mon Sep 17 00:00:00 2001 From: luxick Date: Thu, 9 Apr 2020 19:18:29 +0200 Subject: [PATCH] Run at 60 FPS --- mttt.nim | 45 +++++++++++++++++++++++++++++++++++++++------ public/index.html | 6 +++++- src/game.nim | 30 ++++++++++++++++-------------- 3 files changed, 60 insertions(+), 21 deletions(-) diff --git a/mttt.nim b/mttt.nim index fa20cdb..f04be80 100644 --- a/mttt.nim +++ b/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 \ No newline at end of file diff --git a/public/index.html b/public/index.html index fcb8080..de8ee73 100644 --- a/public/index.html +++ b/public/index.html @@ -18,7 +18,11 @@ - +
+ + + +
diff --git a/src/game.nim b/src/game.nim index 5a1a2d8..e033388 100644 --- a/src/game.nim +++ b/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() \ No newline at end of file + game.draw()