Showing posts with label html5. Show all posts
Showing posts with label html5. Show all posts

Sunday, November 14, 2010

Experiments in HTML5: canvas 2

So after knocking out a quick example yesterday of an HTML5 canvas app, I ended up making pong. This is the typical "hello world" game to make, and I've done them before so I was familiar with the already pretty simple logic.

Here is the high level breakdown:

  • has two "classes", paddleObj and ballObj
  • there are two instances of the paddleObj, one for each side
  • the objects will keep track of the location and has helper functions clear, draw
  • the ballObj acts much like a controller, in that is can reset the board, performs collision detection and all the logic involved, and maintains its own automatic movements with a move function
  • the move function drives the game, it is set on interval of 100ms
  • has a toggleGame function to start and stop the interval when needed
  • use a direction variable as negative or positive and a change variable for each axis (x and y)
  • reverse appropriate direction on collision, increase change variables on paddle collision
  • if ball is past either paddle, reset board, increase score, toggleGame to pause
  • W, S control player 1 (left) and up, down control player2 (right), click or space control toggleGame
There isn't too much to a pong game. Regardless of the language, the "objects" will remain the same, the rules are the same, etc. Some helper notes: 
  • store x,y,width and height for sprites
  • make (x+width) and (y+height) your best friends
  • you need an "engine" to drive motion
  • remember to check the y's on the paddle for collision detection
Some of the more customizable things I have found:
  • How to handle paddle bounce backs (include paddle momentum, increase speed each time?)
  • How fast should everything move?
  • How to track score and what is a winning score?
  • Graphics, incentives, etc
Unfortunately, I only have weekends to really work on these projects, so it was more important for me to get something up and working than to make it polished. I hate to pass out my "work" when it is hardly ideal, but then again when is a program ever really "ideal" and I am still learning this stuff. So keep in mind that this is not optimized, fully debugged, browser tested, source cleaned up, fully commented, etc, but it DOES WORK! (in all non-IE browsers, except maybe 9) 

Have a look at the source code here.
And the demo here.

I also thought it was pretty funny that I used plain old javascript (POJS) for the entire game, but used jquery for the show/hide form. I gotta get that out of there haha.

I am also working on an iPhone version that was pretty much complete, but doesn't seem to like running on the server like it did running locally. If anyone has any iPhone dev experience and knows what I'm missing (for example evt.preventDefault() doesn't work), I'm initially guessing its a cross-script thing? But I am also having an issue with the graphics not getting cleared entirely, leaving a "frame-trail", like the outline of the object being left behind where it moves.

Hope you like and come on people leave me some comments, I'm dying for feedback here!

Saturday, November 13, 2010

Experiments in HTML5: canvas

With HTML5 quickly becoming all the rage, and rightfully so, I think it was very important to learn what seems to be one of the more groundbreaking innovations, the canvas.

I started by searching through my Google Reader (RSS reader which I've become a fan of) since I know I had starred a few articles on HTML5 and the canvas element in particular. Here is what I came up with, sixrevisions.com, AWESOME examples from tutsplus.com, bouncing ball from sixrevisions.com, again, I'm sold, this stuff is WAY too call to ignore!

After a quck 5 minute browsing of some tutorials and samples, it seems pretty similar in use to a typical graphics api. I've had some minor exposure to these in the form of OpenGL, DirectX, and XNA, but it was very limited and I quickly lost interest as it was dealing with what I consider the dying native app. I still have the desire to make a game and perhaps now I have the technology to reach the audience and potential I was looking for.

Here is the recommended canvas template:

<html>
<head>
<title>Canvas</title>
<script type="text/javascript">
// When the window has loaded, DOM is ready. Run the draw() function.
window.onload = draw;   

function draw(){
  var canvas = document.getElementById('myCanvas');
  if (canvas.getContext){
    var context = canvas.getContext('2d');
    // Put canvas drawing stuff here, e.g. context.fillStyle
  }
  else{
    // Put code to execute if browser doesn't have canvas support here
  }
}
</script>

<style type="text/css">
  canvas { border: 1px solid black; }</style>
</head>
<body>
  <canvas id="myCanvas" width="200" height="200"></canvas>
</body>
</html>

Since I already have a page set up, I'm just taking the necessary pieces and placing them where they belong according to this template. I started with a 500 x 500 canvas, this is rather arbitrary, but I have found the most limiting size on regular web pages is facebook profiles at 520px. I styled the canvas to be center aligned by display: block, margin: 0px auto, and border so I know where it is! I put the javascript on the html page, but will remove this once initial development is done.

Ok not too bad to get set up. Now lets get to the fun stuff! I used a great tutorial from Mozilla to get these intial startups going.

The first set of instructions are about drawing shapes, pretty simple stuff really. The only pre-defined shape is a rectangle, but there are several "path" functions. These are similar to drawing freehand. You can draw lines, arcs, and curves using a typical coordinate system in which (0,0) is the top left of the canvas and (width, height) is the bottom right of the canvas. All of this is unfortunately familiar to me. I only say unfortunately because drawing with geometry can be a painful experience at times. First successful canvas javascript api will make someone really rich and/or really famous for shaping internet gaming forever (hint, hint).

The images section reads much like a chapter on sprites in my opinion. I barely read this section since the methods are rather self explanatory. Something that is very important to note on this page though is how images are "loaded". You can use any image already on the page or within the canvas by selecting it by id or tag name, or you can also use document.images, though I personally am unfamiliar with this method. But it seems the preferred method in this tutorial is to load the image using a javascript Image object:

var img = new Image();   // Create new Image object  
img.src = 'myImage.png'; // Set source path  

You can then position, scale, and crop this image and draw it to the canvas with drawImage functions. The rest of the article is still very good, but I ran out of patience and wanted "something". I was somewhat familiar with the remaining topics, and since they are somewhat "heady" I didn't feel like absorbing all that knowledge (probably again) right now. If all of this sounds crazy to you, take it slower, and experiment a lot as the gap between code and visuals is too big to bridge just in your head. So I figured I'll make a small canvas with a "sprite" of some kind, or perhaps a drawn image, that will move around according to key presses. Lets start.

First things first, I am using this as my groundwork.



Nice work by this guy and just wanted to give credit even though I plan on doing some things a little differently. Lets get our shape on there, for simplicity I'm going to create a small 20x20 gray square in a paint tool and draw it to the canvas in the top left:

var img = new Image();
 // When the window has loaded, DOM is ready. Run the init() function.
 window.onload = init;

 function init() { 
  ctx = document.getElementById("mycanvas").getContext("2d");
  img.src = "/images/dev/gray_box.png";
  img.onload = function() {
   ctx.drawImage(img,0,0); 
  }
 }

Now lets add some logic to make it move on a key press:

function keyDown(evt) {
 // so a key was pressed, only react to the keys below
 // left = 37, up = 38, right = 39, down = 40
 // movement workflow: get key, check if at edge, if not move, 
 // if moved off edge then set it to edge, draw at new location
 // if you drew a new square then prevent default key action
 if(evt.keyCode == 37) {
  if(imgObj.x > 0) {
   imgObj.x -= 20;
   if(imgObj.x<0) { imgObj.x=0; } 
   draw();
   evt.preventDefault();
  }
 }
 if(evt.keyCode == 39) {
  if(imgObj.x + imgObj.w < 500) {
   imgObj.x += 20;
   if(imgObj.x + imgObj.w > 500) {imgObj.x=500-imgObj.w; }
   draw();
   evt.preventDefault();
  }
 }

 if(evt.keyCode == 38) {
  if(imgObj.y > 0) {
   imgObj.y -= 20;
   if(imgObj.y<0) { imgObj.y = 0; }
   draw();
   evt.preventDefault();
  }
 }
 if(evt.keyCode == 40) {
  if(imgObj.y + imgObj.h < 500) {
   imgObj.y += 20;
   if(imgObj.y + imgObj.h > 500){imgObj.y = 500 - imgObj.h; }
   draw();
   evt.preventDefault();
  }
 }
 return false;
}

I tried to document the process as concisely as possible. And finally our new draw function:


function draw(){
 // we get the context again (needs efficiency improvement for that)
 var ctx = document.getElementById("mycanvas").getContext("2d");
 // clear the entire canvas, should have a built in function like ctx.clear();
 ctx.clearRect(0,0,500,500);
 // save context (not needed here but a best practice for future)
 ctx.save();
 // draw square in new location
 ctx.drawImage(img,imgObj.x,imgObj.y);
 // restore the context (again not needed but a best practice)
 ctx.restore();
}

Here you can find the complete javascript file.
And a working demo.

This was all done in an hour or two (including the initial research). This is proof that this is a great entry way for web developers to get a taste of game development without such a steep learning curve. A lot of this code isn't anywhere near optimized and was simply more to get a working example and get my feet wet.

I plan to clean this code up, comment more fully, then add functionality, and finally some polish. Hopefully by the end I'll have a fully functional, yet rudimentary html5 canvas game!

UPDATE: Check out the same demo page above for a version of pong.