{"id":158,"date":"2011-10-21T20:06:34","date_gmt":"2011-10-22T01:06:34","guid":{"rendered":"http:\/\/blog.cubicleninja.com\/?p=158"},"modified":"2026-04-23T17:40:03","modified_gmt":"2026-04-23T22:40:03","slug":"javascript-and-html5-simple-game-creation-part-3-2","status":"publish","type":"post","link":"https:\/\/blog.cubicleninja.com\/?p=158","title":{"rendered":"JavaScript and HTML5 \u2013 Simple Game Creation Tutorial (part 4)"},"content":{"rendered":"<p>In <a href=\"https:\/\/blog.cubicleninja.com\/?p=101\">part 1<\/a> I went through the basics of setting up the canvas and adding a simple sprite to it.  Then <a href=\"https:\/\/blog.cubicleninja.com\/?p=119\">part 2<\/a> got through handling keyboard controls and animating the hero character.  Most recently, <a href=\"https:\/\/blog.cubicleninja.com\/?p=148\">part 3<\/a> added some scenery objects and the basics of collision detection.   We now are to a point where we can leverage the framework we&#8217;ve created to add in some bad guys to roam around the canvas.  We&#8217;ll make some modifications to our heroObject in order to allow it to accommodate NPC characters as well as the player controlled hero.   Because I&#8217;m all for clich\u00e9s I&#8217;ll be using the same sprite we used for the hero character&#8230;only making it evil.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/html5.cubicleninja.com\/images\/Evil_Mage_Sprite.png\" alt=\"Evil Mage Sprite\" \/><\/p>\n<p>We&#8217;ll start off with similar functionality that we used for our rock objects in <a href=\"https:\/\/blog.cubicleninja.com\/?p=148\">part 3<\/a> and add a variable at the top for the number of bad guys we want to have on the screen at one time, an array to hold them all and a base image object to hold the sprite image.<\/p>\n<pre class=\"lang:js decode:true\">\n\/\/ variable to determine how many enemies to draw into the scene\nvar numEnemies = 10;\n\/\/ array to hold all of the enemy objects we have\nvar enemies = new Array();\n\/\/ variable to hold our base enemy image\nvar baseEnemy = null;\n<\/pre>\n<p>The next part is to create an initEnemies function that will combine elements of the initRocks and the initHero functions.   For each enemy we want to create we have to make sure it doesn&#8217;t collide with the hero and also that it doesn&#8217;t collide with any of the rocks that are on the scene.  <\/p>\n<pre class=\"lang:js decode:true\">\nfunction initEnemies()\n{\n    \/\/ Set up the base enemy Image object\n    \/\/ and load in the correct image we want to use\n    baseEnemy = new Image();\n    baseEnemy.src = \"images\/Evil_Mage_Sprite.png\";\n    \/\/ once it has loaded into memory we loop through\n    \/\/ and create a new heroObject and set the image to our base\n    baseEnemy.onload = function()\n    {\n        for (var i = 0; i < numEnemies; i++)\n        {\n            \/\/ we have to make sure the enemy is not drawn on top of the hero\n            \/\/ or on top of a rock\n            do\n            {\n                \/\/ this creates the enemy which we set up to have a random\n                \/\/ x and y coordinate\n                enemies[i] = new heroObject();\n\n                \/\/ check if we have a hero collision, if so we recreate the enemy\n                if (enemies[i].checkCollision(hero))\n                    enemies[i].collision = true;\n                else\n                {\n                    \/\/ if it didn't collide with the hero, check to make sure it doesn't collide\n                    \/\/ with any of the rocks\n                    for (curRock in rocks)\n                    {\n                        if (enemies[i].checkCollision(rocks[curRock]))\n                        {\n                            \/\/ if it collides with a rock, break out of the for loop and recreate the enemy\n                            enemies[i].collision = true;\n                            break;\n                        }\n                    }\n                }\n            }\n            while (enemies[i].collision);\n\n            \/\/ use the baseEnemy object as our image\n            enemies[i].image = baseEnemy;\n            \/\/ render it to the baseContext\n            enemies[i].render();\n        }\n    }\n}\n<\/pre>\n<p>We need to make a call to the in the game loop:<\/p>\n<pre class=\"lang:js decode:true\">\n    \/\/ do a foreach type loop through the enemies\n    for (curEnemy in enemies)\n    {\n        enemies[curEnemy].render();\n    }\n<\/pre>\n<p>At this point you should be able to run the game and have a screen with pseudo-randomly placed rocks and bad guys with none of them stacking on top of the other.  The next piece will be to adjust the value randomly to one of the 4 valid directions.<\/p>\n<pre class=\"lang:js decode:true\">\n            \/\/ use the baseEnemy object as our image\n            enemies[i].image = baseEnemy;\n\n            \/\/ set the enemy to be moving a random direction at the start\n            enemies[i].keys[0] = Math.floor(Math.random() * 4) + 37;\n            \n            \/\/ render it to the baseContext\n            enemies[i].render();\n<\/pre>\n<p>Before that change will make any difference we need to modify the game loop so that before it renders out each enemy it calls the update method for it<\/p>\n<pre class=\"lang:js decode:true\">\n    \/\/ do a foreach type loop through the enemies\n    for (curEnemy in enemies)\n    {\n        \/\/ Update the enemy based upon how long it took for the game loop\n        enemies[curEnemy].update(elapsed \/ timerRatio);\n        \/\/ draw the enemy to the screen again\n        enemies[curEnemy].render();\n    }\n<\/pre>\n<p>Running the game at this point you'll notice that the enemies are basically very poorly developed roombas and will just walk in a single direction until they hit a rock and then they just repeatedly slam their heads into it(luckily, reusing the heroObject means they already have our collision detection logic without having to do anything additional).   We'll slightly upgrade their AI and allow them to turn away from a rock any time there is a collision.   This is also done in the game loop after the call to the update method, and before the call to the render method.<\/p>\n<pre class=\"lang:js decode:true\">\n    \/\/ do a foreach type loop through the enemies\n    for (curEnemy in enemies)\n    {\n        \/\/ Update the enemy based upon how long it took for the game loop\n        enemies[curEnemy].update(elapsed \/ timerRatio);\n\n        \/\/ check if the enemy collided with a rock, if it did turn it a random direction\n        if (enemies[curEnemy].collision)\n            enemies[curEnemy].keys[0] = Math.floor(Math.random() * 4) + 37;\n            \n        \/\/ draw the enemy to the screen again\n        enemies[curEnemy].render();\n    }\n<\/pre>\n<p>This works well enough for the most part, but we have an issue if one of the enemies starts walking down a path that doesn't contain any rocks...they just keep going ad nauseum.   To correct that we'll need to add a new property to the heroObject and then another test inside the game loop for the enemies (again, before the call to render).   The property we're going to add will be called \"lastKeyChange\" and it will be used to check how long it's been since the enemy last changed movement directions.   We can set whatever type of limit on that we want before we force a direction change.  Inside the heroObject add the property underneath the property<\/p>\n<pre class=\"lang:js decode:true\">\n    \/\/ When was the last time we had a direction change?\n    this.lastKeyChange = Date.now();\n<\/pre>\n<p>Then update the loop to make use of that property<\/p>\n<pre class=\"lang:js decode:true\">\n    \/\/ do a foreach type loop through the enemies\n    for (curEnemy in enemies)\n    {\n        \/\/ Update the enemy based upon how long it took for the game loop\n        enemies[curEnemy].update(elapsed \/ timerRatio);\n\n        \/\/ check if the enemy collided with a rock, if it did turn it a random direction\n        if (enemies[curEnemy].collision)\n        {\n            enemies[curEnemy].keys[0] = Math.floor(Math.random() * 4) + 37;\n            enemies[curEnemy].lastKeyChange = Date.now();\n        }\n\n        \/\/ if the enemy has gone a while without changing directions, turn it a random direction\n        if (now - enemies[curEnemy].lastKeyChange > ((Math.random() * 3000) + 5000))\n        {\n            enemies[curEnemy].keys[0] = Math.floor(Math.random() * 4) + 37;\n            enemies[curEnemy].lastKeyChange = Date.now();\n        }\n            \n        \/\/ draw the enemy to the screen again\n        enemies[curEnemy].render();\n    }\n<\/pre>\n<p>At this point you should be able to run the game and have all the randomly placed rocks from before in addition to the new enemy mages wandering around on the screen bouncing off the rocks and pseudo-randomly changing directions.   The next part of the series will get into allowing the hero to throw fireballs to kill the enemy mages and adding in some point tracking for the game.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/html5.cubicleninja.com\/images\/SimpleGame_4.png\" alt=\"Simple Game 4 - Sample Image\" \/><\/p>\n<p>Here's the link to the <a href=\"https:\/\/html5.cubicleninja.com\/SimpleGame_4.htm\" target=\"_blank\">demo for this code<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In part 1 I went through the basics of setting up the canvas and adding a simple sprite to it. Then part 2 got through handling keyboard controls and animating the hero character. Most recently, part 3 added some scenery objects and the basics of collision detection. We now are to a point where we &hellip; <a href=\"https:\/\/blog.cubicleninja.com\/?p=158\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;JavaScript and HTML5 \u2013 Simple Game Creation Tutorial (part 4)&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,7],"tags":[17,25,29,31,32,39],"class_list":["post-158","post","type-post","status-publish","format-standard","hentry","category-html5","category-javascript","tag-canvas","tag-game","tag-html5","tag-javascript","tag-jquery","tag-tutorial"],"_links":{"self":[{"href":"https:\/\/blog.cubicleninja.com\/index.php?rest_route=\/wp\/v2\/posts\/158","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.cubicleninja.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.cubicleninja.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.cubicleninja.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.cubicleninja.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=158"}],"version-history":[{"count":3,"href":"https:\/\/blog.cubicleninja.com\/index.php?rest_route=\/wp\/v2\/posts\/158\/revisions"}],"predecessor-version":[{"id":21803,"href":"https:\/\/blog.cubicleninja.com\/index.php?rest_route=\/wp\/v2\/posts\/158\/revisions\/21803"}],"wp:attachment":[{"href":"https:\/\/blog.cubicleninja.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=158"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.cubicleninja.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=158"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.cubicleninja.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=158"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}