Thursday, September 30, 2010

Tutorial: Simple game with HTML5 Canvas - part 5

Tutorial: Simple game with HTML5 Canvas
Part 1 - Introduction & Background
Part 2 - Character & Animation
Part 3 - Physics & Controls
Part 4 - Platforms & Collisions
Part 5 - Scrolling & Game States

First of all I want to thanks for the responses to my tutorial, all the comments, emails and tweets I receive. It's an awesome feeling - to be aware that someone is reading all that stuff and even likes it. Oh, and don't forget to follow me on Twitter - http://twitter.com/michalbe.

Part 5a. SCROLLING & POINTS
During the last lesson we teach our angel how to use platforms. Now let him jump higher than screen height. To obtain that we need to use trick as old as platform games - stop the character in one place and move everything else in opposite direction. In our example angel will stop in the middle of the screen and rest of the speed will move background and platforms down. Let's modify checkJump() method of the player:
(...)
that.checkJump = function() {     
    if (that.Y > height*0.4) {
//if player is under about half of the screen - let him move
        that.setPosition(that.X, that.Y - that.jumpSpeed);        
    } else {
//in other dont move player up, move platforms and circles down instead
        MoveCircles(that.jumpSpeed * 0.5); 
//clouds are in the background, further than platforms and player, so we will move it with half speed
        
        platforms.forEach(function(platform, ind){
            platform.y += that.jumpSpeed;

            if (platform.y > height) {
//if platform moves outside the screen, we will generate another one on the top
                var type = ~~(Math.random() * 5);
                if (type == 0) 
                    type = 1;
                else 
                    type = 0;
                platforms[ind] = new Platform(Math.random() * (width - platformWidth), platform.y - height, type);
            }
        });
    }
    
    
    that.jumpSpeed--;
    if (that.jumpSpeed == 0) {
        that.isJumping = false;
        that.isFalling = true;
        that.fallSpeed = 1;
    }

}
When the platform moves outside the screen we will generates another one on the top, but not directly on 0-y, because we need to keep the distance between the platforms. So first we calculate how far it goes under the bottom, subtract hat value from total height and generate platform on that Y with random X. Yes, I know that it will show up suddenly in the middle of the screen, but while whole attention of the player is focused on the character, no one will notice that.
Ok, it is possible now to jump as high as we want, but there are still couple of things to fix, eg difficulty level.
To make everything harder let's give movement ability to some platforms. The higher your character will be, the faster platforms will move. To achieve this, first we will implement very simple points system, and after that modify a little Platform object and GameLoop() part responsible for drawing platforms.
var width = 320, 
    height = 500,
    gLoop,
    points = 0,
//adding points to global variables
(...)

var Platform = function(x, y, type){
(...)
    that.isMoving = ~~(Math.random() * 2);
//first, let's check if platform will be able to move (1) or not (0)
    that.direction= ~~(Math.random() * 2) ? -1 : 1;
//and then in which direction
(...)
}

var GameLoop = function(){
    clear();
    DrawCircles();

    if (player.isJumping) player.checkJump();
    if (player.isFalling) player.checkFall();
 
    player.draw();
//moving player.draw() above drawing platforms will draw player before, so platforms will be drawn over him. It looks better that way because sometimes angel 'sinks' in the platform with his legs.

    platforms.forEach(function(platform, index){
        if (platform.isMoving) {
//if platform is able to move
            if (platform.x < 0) {
//and if is on the end of the screen
                platform.direction = 1;
            } else if (platform.x > width - platformWidth) {
                platform.direction = -1;
//switch direction and start moving in the opposite direction
            }
            platform.x += platform.direction * (index / 2) * ~~(points / 100);
//with speed dependent on the index in platforms[] array (to avoid moving all the displayed platforms with the same speed, it looks ugly) and number of points
        }
        platform.draw();
    });
Increasing points should be implement in player.checkJump(), after checking if player is in the middle of the screen:
that.checkJump = function() {
    if (that.Y > height*0.4) {
        that.setPosition(that.X, that.Y - that.jumpSpeed);        
    } else {
        if (that.jumpSpeed > 10) points++; //here!
        MoveCircles(that.jumpSpeed * 0.5);
(...)
When everything is already drawn we could render GUI on the top of everything. So add in GameLoop(), just before calling another frame:
ctx.fillStyle = "Black";
//change active color to black
ctx.fillText("POINTS:" + points, 10, height-10);
//and add text in the left-bottom corner of the canvas
Part 5b. GAME STATES
Everything works cool, but it is not possible to lose. In case we use setTimeout() instead of setInterval(), we need to create boolean variable with game state. It will be 'true' during the game and 'false' when game ends. It is nice to prepare also some GameOver screen. Let's start with adding new variables and modifying GameLoop().
var width = 320, 
    height = 500,
    gLoop,
    points = 0,
    state = true,
(...)

var GameLoop = function(){
(...)
//go to another frame only when state is true
    if (state)
        gLoop = setTimeout(GameLoop, 1000 / 50);
(...)
}

//GameOver screen
var GameOver = function(){
    state = false;
//set state to false
    clearTimeout(gLoop);
//stop calling another frame
    setTimeout(function(){
//wait for already called frames to be drawn and then clear everything and render text
        clear(); 
        ctx.fillStyle = "Black";
        ctx.font = "10pt Arial";
        ctx.fillText("GAME OVER", width / 2 - 60, height / 2 - 50);
        ctx.fillText("YOUR RESULT:" + points, width / 2 - 60, height / 2 - 30);
    }, 100);
};
Now we must determine when to stop the game and display GameOver Screen. We need to modify player's checkfall() method
that.checkFall = function(){
    if (that.Y < height - that.height) {
        that.setPosition(that.X, that.Y + that.fallSpeed);
        that.fallSpeed++;
    } else {
        if (points == 0) 
//allow player to step on the floor at he beginning of the game
            that.fallStop();
        else 
            GameOver();
    }
}
And that's all! Thank you one more time for your time. I'm waiting for questions and ideas of improvement so feel free to ask/write. As usual: - sources on github Simple game with HTML5 Canvas - and working example on jsbin: Simple game with HTML5 Canvas Tutorial: Simple game with HTML5 Canvas Part 1 - Introduction & Background Part 2 - Character & Animation Part 3 - Physics & Controls Part 4 - Platforms & Collisions Part 5 - Scrolling & Game States

UPDATE
I would like to thanks anyone who found my Simple HTML5 canvas game tutorial useful. I receive a lot of emails, tweets, and couple of comments in here with a lot of positive feedback. I know also that some of you tried to create own games based on my tips. Below I put links to games I know about, I hope authors don't mind. If you also have leaned something from my tutorial, and created anything interesting with it, feel free to write me about that, I will put your link here also.

35 comments:

  1. Thanks! For the tutorial and for the link to my blog. I'm still practicing developing games in HTML5. And your blog is a good reference to start with.

    ReplyDelete
  2. Hi there dude! Would it be possible to associate the controls with a mouse click instead of position to allow this to be compatible with a touch screen?
    Thanks! Great tutorial btw!

    ReplyDelete
  3. of course, just remember the position of the click and check position of the character in relation to that click, no actual mouse position.

    ReplyDelete
  4. Very good tutorial Michalbe..

    It helps me a lot in understanding HTML5.
    By the way, can you also make a tutorial to make a shooter game (like space invader) ? that would be great...

    Anyways, well done, and keep up the good work :)

    ReplyDelete
  5. Hey,

    thanks a lot for this tutorial!
    Was planning a "doodle jump" clone for a while now but had some problems creating it.
    You really helped me with Collisions and Scrolling of the Platforms! :)

    You can check out my game here:
    http://fearhat.bplaced.net/plygrnd/

    ReplyDelete
  6. Great Tutorial Man. That's really help-me A LOT

    ReplyDelete
  7. This comment has been removed by the author.

    ReplyDelete
  8. Thank you man!

    Hmmm and about sounds?

    Any tips?

    Cheers!

    ReplyDelete
  9. Hello.
    I have been searching for tutorials and this is the best one i found. Thanks.
    but where can we get the source code?
    Also would be nice if you add sounds.

    ReplyDelete
  10. source code is on my github - https://github.com/michalbe/Simple-game-with-HTML5-Canvas

    And sound really sucks in HTML5, It's hard to achieve satisfied results.

    ReplyDelete
    Replies
    1. So any suggestion if I want to add sound effects or sound background at least ? specially for mobile games ?

      Delete
    2. On iOS for example you can play only one sound at a time. Dominic Szablewski wrote great review of audio support in all the browsers (it's almost 2 years old but still mostly true) http://phoboslab.org/log/2011/03/the-state-of-html5-audio

      Delete
  11. Thank you so much for these 5 tutorials!

    ReplyDelete
  12. could I or should I paste this code into Dreamweaver and experiment with it to learn HTML5?

    ReplyDelete
  13. Great tutorial, thank you very much.

    ReplyDelete
  14. Good tutorials! How can i make it starts over when i drop?

    ReplyDelete
  15. I have been seeking training which is the foremost a single i found. Many thanks.Was arranging a "doodle jump" replicated for some time currently however got a number of issues developing that.

    ReplyDelete
  16. Thanks for it - very good tutorial for fresh ones.

    ReplyDelete
  17. You´re a genius!!!

    I´m working on a version with improoved 'physic engine', improoved controls, more platform types and a more Doodle Jump design.

    Will you let me making a german Version of this tutorial with mine improovments, if I link to you?

    ReplyDelete
  18. And almost 2 years after you published these tuto, somebody else thanks you for that.

    Thanks Michal :)

    SamFromFrance

    ReplyDelete
  19. Nice tutorial =)

    ReplyDelete
  20. Thanks a lot for this tutorial, I am HTML noob as of now..hope these help in getting to know HTML5 :-)

    ReplyDelete
  21. Es un excelente tutorial, ya que explica muy bien, paso a paso las principales características de la programación usando HTML5 + Canvas + CSS.

    Muchas gracias Michal!!

    ReplyDelete
  22. Great tutorial, Michal. This was my first attempt at an HTML 5 game and I was able to follow your tutorial with very little difficulty.

    Thank you!

    ReplyDelete
  23. Thanks a lot for your tutorial!Now I can try making my own game from your help!It is quite hard at the beginning.

    Thank you!

    ReplyDelete
  24. Really great tutorial, thanks a lot!

    ReplyDelete
  25. Fantastic tutorial, thank you very much!

    ReplyDelete
  26. thank you for sharing. very great tutorial. :)

    ReplyDelete
  27. Thank you for this great tutorial! I will be doing a project with kids from a local school following your tutorial. They will have a a blast!

    ReplyDelete
  28. awesome tutorial! finally walk through it completely!

    ReplyDelete
  29. I am a newbie and it really helped a lot... nice post. Nice blog Very useful information is providing by ur blog. find Great beginning html tutorials Very clear and helpful for beginners.

    ReplyDelete