Run at 60 FPS

This commit is contained in:
2020-04-09 19:18:29 +02:00
parent a8c82f2ed2
commit decc2a88d7
3 changed files with 60 additions and 21 deletions

View File

@@ -1,16 +1,49 @@
import dom, jsconsole, sugar import dom, jsconsole, sugar, times, strformat
import src/game import src/game
const const
canvasId = "game_canvas" canvasId = "game_canvas"
proc onTick(game: Game, time: float) = var frameCount = 0
discard window.requestAnimationFrame((time: float) => onTick(game, time)) var mtttGame: Game
game.nextFrame(time) 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.} = proc onLoad(event: Event) {.exportc.} =
var game = newGame(canvasId, window.innerWidth, window.innerHeight) mtttGame = newGame(canvasId, window.innerWidth, window.innerHeight)
onTick(game, 60) startAnimating(60)
window.onload = onLoad window.onload = onLoad

View File

@@ -18,7 +18,11 @@
</head> </head>
<body> <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_center">
<div id="game"> <div id="game">
<canvas id="game_canvas"></canvas> <canvas id="game_canvas"></canvas>

View File

@@ -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 import libmttt
type type
Game* = ref object Game* = ref object
renderer: Renderer2D renderer: Renderer2D
lastUpdate, totalTime: float startTime: Time
totalTime*: Duration
paused: bool paused: bool
scene: Scene scene: Scene
state: GameState state: GameState
@@ -38,10 +39,10 @@ proc switchScene(game: Game, scene: Scene) =
of Scene.Game: of Scene.Game:
var elements: seq[Element] = @[] 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) 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) game.timeElement = game.renderer.createTextElement("0", timePos, "#000000", 14, font)
@@ -57,23 +58,24 @@ proc newGame*(canvasId: string, width, height: int): Game =
renderer: newRenderer2D(canvasId, width, height), renderer: newRenderer2D(canvasId, width, height),
scene: Scene.Game, scene: Scene.Game,
state: newGameState(player1, player2), state: newGameState(player1, player2),
paused: false paused: false,
startTime: getTime()
) )
switchScene(result, Scene.Game) switchScene(result, Scene.Game)
proc update(game: Game, time: float) = proc update(game: Game, time: Duration) =
# Update the game logic # Update the game logic
# Return early if paused. # Return early if paused.
if game.paused or game.scene != Scene.Game: return if game.paused or game.scene != Scene.Game: return
game.totalTime += time game.totalTime = getTime() - game.startTime
proc drawMainMenu(game: Game) = proc drawMainMenu(game: Game) =
discard discard
proc drawGame(game: Game) = proc drawGame(game: Game) =
# Draw changing UI Elements # 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 # Draw the current screen on the canvas
@@ -85,7 +87,7 @@ proc draw(game: Game) =
of Scene.Game: of Scene.Game:
drawGame(game) drawGame(game)
proc nextFrame*(game: Game, frameTime: float) = proc nextFrame*(game: Game, frameTime: Duration) =
# Determine id an update is necessary # Determine id an update is necessary
game.update(frameTime) game.update(frameTime)
game.draw() game.draw()