6
\$\begingroup\$

I'm planning to make a small game for learning purposes. So far, I've got the hang of the canvas element and using the context to draw things on it, as well as object notation and classes in JavaScript.

But before moving on to making the rest of the game, I'd like you to please take a look at my code and see if there's something I should have done differently. Anything, such as that shouldn't be called or anything as simple as that. Any tips and suggestions are happily accepted!

Here is a link to the jsbin: http://jsbin.com/hozazeki/1

If that one throws an error or doesn't work, try this: http://jsbin.com/hozazeki/1/edit

P.S: I refer to the red cube as goat. Placeholder graphics, 'ya know?

//Creating requestAnimationFrame to avoid crashing the browser
var requestAnimationFrame = window.requestAnimationFrame 
                        || window.mozRequestAnimationFrame 
                        || window.webkitRequestAnimationFrame 
                        || window.msRequestAnimationFrame 
                        || fallbackRequestAnimationFrame;

function fallbackRequestAnimationFrame(func) {
    setTimeout(func, 0); // Emulate a requestAnimationFrame if none is available
}

//Game object - doesn't have to be a class
game = {

    state: "stopped", //initial state of the game
    W: 800, //canvas size vars
    H: 600,

    //Function called by the html page - initializes the game
    init: function(){

        //get canvas context object
        var canvas = document.getElementById("canvas");
        this.context = canvas.getContext("2d");

        //create goat
        this.goat = new Goat();

        //start game
        this.start(this.context);
    },

    //Function called to start the game - triggers the game loop
    start: function(canvas){

        //change the game state
        this.state = "running";

        //variables used for deltaTime
        this.previousTime = new Date().getTime();

        //trigger game loop
        requestAnimationFrame(this.onFrame);
    },

    //The game loop basically calls this function over and over
    onFrame: function(){
        //game loop
        if(game.state === "running"){

            //calculate deltaTime
            var currentTime = new Date().getTime();
            var deltaTime = currentTime - game.previousTime;
            game.previousTime += deltaTime;

            //draw and update
            game.draw(deltaTime);
            game.update(deltaTime);

            //continue looping
            requestAnimationFrame(game.onFrame);
        }
    },

    update: function(deltaTime){
        //update the goat
        this.goat.update(deltaTime);
    },

    draw: function(deltaTime){
        this.clearCanvas(game.context);
        //Draw the goat
        this.context.fillStyle = "#FF0000";
        this.context.fillRect(this.goat.x, this.goat.y, this.goat.w, this.goat.h);
    },

    clearCanvas: function(canvas){
        canvas.beginPath();
        canvas.rect(0,0,this.W, this.H);
        canvas.fillStyle = "#CCCC99";
        canvas.fill();
    }
}

function Goat(){
    //size
    this.w = 50;
    this.h = 50;
    //position
    this.x = 0; // (game.W + this.w) / 2;
    this.y = (game.H + this.h) / 2;
    //speed - pixels per second
    this.vx = 200;
    this.vy = 100;

    this.update = function(deltaTime){
        //if it hit the wall, reverse its velocity
        if( this.x >= game.W - this.w || this.x <= 0 ){
            this.vx *= -1;
        }
        if( this.y >= game.H - this.h || this.y <= 0){
            this.vy *= -1;
        }
        this.x += this.vx * (deltaTime / 1000);
        this.y += this.vy * (deltaTime / 1000);
    }
}

And the HTML, just because:

<!DOCTYPE html>
<html lang="en">
<head>
        <meta charset="utf-8" />
        <title>Game!</title>
        <script src="flappygoat.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<canvas id="canvas" width="800" height="600" />
<script>
    window.onload = function(){
        game.init();
    };
</script>
</body>
</html>

(There is a known non-critical bug: if you hide the tab for a while and then come back, the cube disappears.)

\$\endgroup\$
4
\$\begingroup\$

Interesting,

  • http://jsperf.com/path-rect-vs-fillrect/7 will tell you that fillRect is faster than what you use in clearCanvas.

  • window.onload <- consider using addEventListener instead of assigning straight to window.onload

  • (deltaTime / 1000) <- you should cache this, division is expensive

  • game.previousTime += deltaTime; <- Cant you just game.previousTime = currentTime ? An assignment is faster than addition. Also, this would show that perhaps, previousTime is a misnomer ;)

  • in update, you really update the data(model), your function name should reflect that

Other than that, I like your style. I would advise you to read up on IIFE's, as they can help you avoid writing this. all the time. Your code is fine now, but at some point this. might get annoying.

\$\endgroup\$
  • \$\begingroup\$ Thank you very much for your input! About caching the deltaTime division, what do you mean by that, practically? What should I change the update function name to? Again, thank you very, very much! \$\endgroup\$ – Marcos Pereira Apr 8 '14 at 8:45
  • \$\begingroup\$ And how should I go about using IIFE's instead of this? I'm sorry, I understand what you mean, but I can't seem to figure out how to practically apply those things to the code. \$\endgroup\$ – Marcos Pereira Apr 8 '14 at 10:00
  • \$\begingroup\$ And as a last comment, I just wanted to ask, what should previousTime be renamed to? I can't seem to think of a better name for it, just something like previousFrameTime. \$\endgroup\$ – Marcos Pereira Apr 8 '14 at 10:12
  • \$\begingroup\$ I take it back, previousTime is fine, since you use it to calculate deltaTime. As for IIFE's I will see if I can clone your jsbin project and use an IIFE. \$\endgroup\$ – konijn Apr 8 '14 at 10:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.