Close

The main loop and the render engine

A project log for HTML5 Retro Game Engine(s)

A Side project where I try and build various scriptable retro game engines in the browser.

timescaleTimescale 04/30/2019 at 15:550 Comments

Right, I make some executive decisions on this pet project of mine concerning timing and the render engine. From my failed Shovelization project I learned that modern day browsers on modest hardware are able to push an amazing amount of data with blooming Javascript! Writing image data to a buffer and plonking it on a canvas takes fractions of a second, it really is amazing how optimized it is compared to the mid naughties.

In my previous attempt to build a game, I wrote it such that only when absolutely needed, a screen redraw was requested. This makes for all sorts of problems that are a pain to force code away, requiring some elements to buffer the background.... but not after a redraw and all other sorts of shenanigans. Secondly, this approach took away some options that I would have liked like filter effects and it made animating "sprites" a royal pain. Who would have guessed! I'm not a game coder...

But I do learn and I have come to the following conclusions. My render engine will simply (try to) render 33 frames per second regardless of state. Sure, a bit overkill in most scenes I think, but it's 2019, I'm not racing the beam on an Atari 2600! In a 240 by 300 pixel canvas, this is peanuts on a moderate desktop. This will also be my "tick". I know the clock for SCUMM games were measured in Jiffies, being a 60th of a second, but I do not think I need that resolution. Every frame being 1 tick means roughly 30 frames is a second which is easy to work with and will support everything from animation to timers.

Two of the more controversial choices I have make are that A. I'm not going to use requestAnimationFrame() but rather use a timeout and B. As a product of the 80's and 90's, I'm not going to use classes at all. My data struct is going to be the maximum of OOP in my game and that is that!

The reason my I'm not going to use requestAnimationFrame() is because I believe it fixes nothing for me but would cause useless overhead. Sure, flickering and shearing are awful, but I do not think my brute force approach will have any issues with this. I will be controlling every sub-pixel and only after the buffer is completed, it will be dumped to the canvas so shearing is impossible. As for flicker, we'll just have to see. It can always be implemented if needs be. (famous last words). As for the main loop :

	function main(){
	    var sTime = performance.now();
	    ++counter;
			
	    // main code starts here.
            gameStateTic(); // do game'y stuff
	    renderer(); // render the gamestate
	    // main code ends here.
	    
            // timing to match a precise FPS number.	
	    var xTime = Math.round(performance.now() - sTime),
	        waitTime = setRate - xTime,
	        processTime = waitTime;
        
		if (waitTime < 0){
		    // process took longer than the fixed rate.
		    waitTime = 0;
		}
			
		if (fps){
		    rateMonitor(xTime, waitTime);
		}		

		if (loop){
		    setTimeout(function(){ main(); }, waitTime);		
		} else {
		    alert("end program")
		}
	}
	

That is the main loop and seeing as user input will be handled via events which will be set up before the main loop starts, I do not think the function will be much different in the future. As you can imagine, this loop is chooching along nicely with nothing to do, so I'll have to give it something to chew on!

Next time I'll be setting up a basic hard coded data structure and building the rudimentary render engine and then we'll see how much cycles we are left with to actually build this thing!

Discussions