Chapter 5

Introducing simpleGame.js

In This Chapter

arrow Using the simpleGame engine

arrow Building a game with simpleGame

arrow Understanding properties and methods

arrow Sprite motion methods

arrow Reading the keyboard

Games are a lot of fun to play, and they can be even more fun to create. However, game programming is often considered one of the more difficult forms of programming to learn. Game development might seem a bit intimidating, but there’s good news. It’s more manageable to learn how to build games when you have a library that simplifies all various features you need.

This chapter introduces you to a simple game engine and library called… simpleGame. Along the way you’ll also learn about object-oriented programming and one of the most important types of objects you’ll use: the sprite.

Using a Game Engine

Games often use sophisticated programming techniques, and often require a great deal of math knowledge. Eventually, you’ll learn these things, but even experienced programmers frequently use some sort of gaming library to simplify the task.

Essential game engine features

Game engines normally have a few important features:

check.png A game/animation loop: Most games use a coding structure called the game and animation loop. This is code that executes very quickly (usually 20 to 30 times per second). Game engines usually have some automated way to create and control this structure.

check.png Sprite objects: The various elements that bounce around on the screen (zombie robot banana slugs or whatever) are called sprites. The player is usually a sprite and so are the enemies, bullets, and sometimes even scoreboards and the background itself. A game engine needs some way to manage sprites. Most sprites are based on one or more images.

check.png Movement system: Sprites need some way to move around. Often you can set the position directly, but also often you can modify the position of each sprite a number of ways. Some systems allow you to set the speed and direction of a sprite, which simplifies many types of games.

check.png Collision detection: When sprites start moving around on the screen, they will bonk into each other. Game engines need some mechanism for detecting these collisions, because most of the interesting stuff that happens in a game occurs when sprites have crashed into each other.

check.png Event detection: Games are about events. Somehow, the user will need to provide input to the game. This can be through the keyboard, joystick, mouse, or other elements. For web-based gaming, you will mainly use the mouse and keyboard. In Chapter 9, I demonstrate how to use the touch screen on mobile devices for user input.

check.png Audio support: Sound effects are more than a final touch. They can add important feedback to the user. Game engines usually have some mechanism for loading and playing sounds.

check.png Advanced features: Often a game engine will contain other advanced features, like a physics system (which allows more realistic motion and gravity effects), a tile-based system (which simplifies building large map-based games), and a state system that allows sprites to have different animations and behaviors in different circumstances.

Gaming on the web

JavaScript by itself is not an ideal platform for game development. This is why most game development on the web has been based on Adobe’s Flash environment (in fact, I wrote a book about creating games with Flash). Although Flash is a great tool, it can be expensive, and it isn’t supported on all platforms. HTML5 now has some very interesting features that make it a viable tool for game development.

The most important of these tools is a new HTML element called the canvas tag. The canvas is a piece of the page that can be changed with programming code. You can draw images on the canvas and change the rotation and scale of each image. It’s not difficult to draw an image on the canvas, but transformations (moving, rotating, and resizing the image) are a bit more challenging.

The canvas tag does not directly support sprites or collisions, but it’s possible to make a special object that can add these features.

HTML5 has support for new audio elements that can be controlled through JavaScript code. Although this is easy enough to use, it isn’t integrated tightly with the canvas element.

JavaScript has long supported a behavior called setTimeOut, which allows you to specify a function to run on intervals. See Chapter 12 for an example of a program that uses the setTimeOut mechanism.

Building an Animation with simpleGame.js

It’s possible to build a library that simplifies all of these various features discussed in the previous section. Such a library can provide abstractions to make everything work without worrying about the details.

Of course, I’ve provided exactly such a library: simpleGame.js. This library is easy to use and is fully capable of sophisticated game development. It uses a notion called object-oriented programming to simplify the complexity of game development. This idea (object-oriented programming) is not really new because you’ve been using objects all along. (The document is an object, and form elements are objects, for example.) Building a game with the library involves creating objects and using them. To get started, you really need to understand only two objects:

check.png The scene: This object starts with an HTML canvas object and adds the main loop. The scene is the unifying object that controls the game.

check.png Sprites: These objects are the elements that move around on the screen. Most of the game elements are sprites. Each sprite must belong to a single scene, but you can have as many sprites as you want. A sprite is based on an image.

Take a look at Figure 5-1, and you see a simple program that uses this library.

9781118074763-fg0501.tif

Figure 5-1: It looks like a rectangle with a ball, but it’s much more than that.

This code is actually a lot more sophisticated than it looks. Here’s what it does:

check.png It adds a canvas to the page. The gray rectangle is actually a canvas tag that’s been automatically added to the page.

check.png It begins a game loop. This program has a game loop already running at 20 frames per second.

check.png It contains a sprite. The ball image is much more than an image. It’s a sprite, which has the capability to move any speed in any direction and other interesting features like collision detection built in.

check.png The ball is moving. I know you can’t see this on a screen shot, but the ball is moving on the screen. It automatically wraps to the other side of the screen when it leaves one side.

With all the interesting stuff happening under the hood, you may be surprised at how simple the code is. Here’s the entire code listing:

<!DOCTYPE HTML>

<html lang=”en-US”>

<head>

    <meta charset=”UTF-8”>

    <title>redBall.html</title>

    <script type=”text/javascript”

            src = “simpleGame.js”></script>

    <script type=”text/javascript”>

    //simple game with a single moving ball

    var scene;

    var ball;

    

    function init(){

      scene = new Scene();

      ball = new Sprite(scene, ”redBall.png”, 50, 50);

      ball.setMoveAngle(180);

      ball.setSpeed(3);

      scene.start();

    } // end init

    

    function update(){

      scene.clear();

      ball.update();

    } // end update

    

    </script>

</head>

<body onload = ”init()”>

    

</body>

</html>

The surprising thing about this code is how simple it is. The game engine takes a very complex process and makes it pretty easy to understand. You begin with a basic HTML5 page and add a few features to turn it into a gaming environment.

Building your page

Begin by building the underlying page:

1. Begin with an HTML5 page.

You can use the same tools you’ve been using for your other web development. Build a basic HTML5 template like you do for any other HTML5 document.

2. Import the simpleGame.js library.

This library is available for free from my website (www.aharrisbooks.net). Use a <script> tag to import the library. Set the src property to the name of the library (simpleGame.js). It’s generally easier to keep a copy in the same directory as your page.

3. Keep the HTML simple.

You can put whatever HTML you want on the page, but you don’t need much. The game engine will create a canvas containing the scene. You might put a title, instructions, or other tools like scoreboards on the page, but the game engine will do most of the work.

4. Call init() when the body loads.

It’s very common to have a function called when the body loads. Add onload = “init()” to the body tag to call the init() method.

5. Create a second script tag to contain your code.

You need to have a second script tag for custom code. Place this after the tag that imports the library.

6. Place two functions in your script.

All simpleGame programs will have at least two functions: init() happens on startup, and update() happens once per frame.

Initializing your game

The initialization part of the game happens as the page loads. It’s mainly taken up with setting up sprites and other resources. Here’s the code:

    var scene;

    var ball;

    

    function init(){

      scene = new Scene();

      ball = new Sprite(scene, “redBall.png”, 50, 50);

      ball.setMoveAngle(180);

      ball.setSpeed(3);

    } // end init

Most games will use a similar style of initialization. Here’s how you set up the game:

1. Define a variable to contain the scene.

Every simpleGame game will have at least one scene object. Define the scene outside any functions, so it is available to all of them. You will actually create the scene inside the init() function.

2. Define a variable for each sprite.

Every sprite in your game will need to belong to a global variable as well. You’ll create the sprites in the init() function, but you need to make the variable available to all functions.

3. Build the init() function.

This function is called by body onload. It will run after the page has loaded into memory.

4. Create the scene.

To build the scene, create an instance of the scene class. What you’re really saying is “Make me a Scene object and call this particular instance ‘scene.’” (See the later section Making instance pudding on class and instance for more details.) The scene doesn’t require any parameters.

5. Create the ball sprite.

The ball is a Sprite instance. To make a sprite, you need a few more bits of information. You need a scene, an image filename, width, and height.

6. Set the ball’s movement angle.

You can change the angle the ball moves. The angles are measured in degrees like on a map (0 is North, 90 is East, and so on).

7. Set the ball’s movement speed.

You can also determine the speed of the ball (in pixels per frame).

8. Start the scene.

When you’re done setting everything up, tell the scene to start.

Updating the animation

After you start the scene, a timer will begin. Twenty times a second, it will call a function on your page called update(). So, you need to have such a function, and it needs to have some code for your game to run.

The update() function is not terribly difficult either.

    function update(){

      scene.clear();

      ball.update();

    } // end update

The update() function typically does three things:

check.png Clears the previous screen: The first order of business is to clean up any mess caused by the last screen. The Scene object has a clear() function for exactly this purpose.

check.png Checks for events: Usually in a game, things will happen (or it isn’t much of a game). Typically, you check for these types of events, like user input, sprites crashing into each other, sprites leaving the screen, or whatever. For this simple animation, the only event is a sprite leaving the screen, and I’ve automated the behavior associated with this action.

check.png Updates each sprite: The final part of the screen update is updating the sprites. When you update a sprite, it will draw in its new position (taking into account any changes you’ve made to the sprite’s speed or direction).

In this case, it isn’t necessary to check for any events. All the program does is clear the screen and update the ball sprite.

Figure 5-2 shows what happens if you don’t clear the screen. All the sprite motion will be drawn on the canvas, and it looks like a big smear rather than a moving ball.

9781118074763-fg0502.tif

Figure 5-2: If you forget to clear the scene, the animation will look like this.

It might seem like a lot of work, but a similar version of this animation without the simpleGame library would be much more complex, and would take well more than 100 lines of code to write. (And that’s nothing. It would be easily more than 200 lines in C++.)

Starting from a template

Almost every game in the rest of the book will begin with exactly the same code. If you want, you can start from this template, but really you should just type it yourself a few times until you can do it from memory:

<!DOCTYPE HTML>

<html lang=”en-US”>

<head>

    <meta charset=”UTF-8”>

    <title>template for simple games</title>

    <script type=”text/javascript”

            src = ”simpleGame.js”></script>

    <script type=”text/javascript”>

        var scene;

        var sprite1;

        

        function init(){

            scene = new Scene();

            sprite1 = new Sprite(scene, ”image.png”, 30, 30);

            

            scene.start();

        } // end init

        

        function update(){

            scene.clear();

            //handle events here

            

            //update all the sprites

            sprite1.update();

        }

    </script>

</head>

<body onload = ”init()”>

    

</body>

</html>

You can download this template from my website or type it in. Here are a few things to remember:

check.png You’ll probably have several sprites. I just put one sprite in the template, but most games will have several: One for the user and one for each enemy or target. Use better names than sprite1 so you can remember what things are.

check.png You’ll need some other files. Be sure your directory contains some suitable sprite images and the simpleGame.js file.

check.png Define variables outside the functions. The variables for the sprites and the scene will need to be defined outside all the functions.

check.png Create the scene and the variables inside the init() function. The main purpose of the init() function is to build all the various elements that will be populating your game.

check.png Don’t forget to start the scene. The last line of the init() function should be scene.start(). This command begins the animation loop that gets the whole ball rolling. If your game isn’t doing anything, check to be sure this line is here.

check.png You need to have an update() function. The update() function is not optional. All the game action is controlled by this function.

check.png Clear the scene every frame. The first thing to do in the update() function is to clear the screen with scene.clear(). If you forget to do this, you’ll have very strange trail effects.

check.png Check for events in the update() function. The update() function is where you look for events (key presses, collisions, leaving the screen, and so on).

Considering Objects

The idea of object-oriented programming is really important in game programming because it’s natural to think of games in terms of objects. You can do more interesting things with the game engine, but you need to have a grasp of how objects work. The game itself is an object (called a scene in simpleGame). The things that move around on the screen are also objects, called sprites. When a programming language allows you to think about your code as objects, it’s called an object-oriented language. The simpleGame library makes heavy use of object-oriented techniques, so it’s important to understand a few terms.

First, an object is simply a combination of code and data. Just like functions can be used to combine code statements and arrays can combine data elements, an object can combine functions and variables to make something bigger and cooler. With explosions.

Making instance pudding

When you create an object, you’re essentially creating a new data type. First, you need to define what the object is and how it works. This is called a class definition. A class is essentially the instructions or blueprint for an object. Sprite and Span are the main objects in the simpleGame library. (There are others, but these are by far the most important.) Note the capital letters. It’s customary to capitalize class names.

A class is like a recipe, but you wouldn’t eat the recipe. Instead, you use a recipe to make cookies. (Okay, I’ve made some cookies that aren’t much better to eat than the recipe, but you get my drift.) The actual cookies are instances of the class. The distinction is important because sometimes you’re talking about a particular object, and sometimes you’re talking about a whole class of objects. Instance names are not usually capitalized. Now look back at this line of code:

      ball = new Sprite(scene, “redBall.png”, 50, 50);

What it’s really saying is the variable ball will now contain an instance of the Sprite class, with all the various characteristics indicated by the parameters. Now you can also see why the capitalization is so important in this line:

      scene = new Scene();

It isn’t as redundant as it seems. It means that the variable scene will contain an instance of the Scene class. It’s common to give instances and classes the same name (but with different capitalization) when there’s only one instance of the class, but different names when there are several. There are usually many sprites in a scene, and it’s helpful to give them useful variable names like ball so you can tell what they are.

Adding methods to the madness

Objects are like variables, but they have a lot of other features ordinary variables don’t have. For one thing, an object can have properties. These are like sub-variables attached to a primary variable. For example, input elements in ordinary JavaScript have a value property. You can often read and change a property directly. Properties usually describe something about an object.

Objects also have methods, which are things the object can do. If properties are essentially variables, methods are functions attached to an object. You’ve seen this before, too. The document is the primary object of a web page, and it has a method called getElementById() that is commonly used to get access to that element as a JavaScript variable.

Custom-built objects like the Scene and Sprite classes in simpleGame also can have properties and methods. Generally, however, I’ll stay away from properties and mainly use methods instead. (This practice is a bit safer because properties can cause problems if you’re not careful.) Look at the simpleGame documentation to see all the methods of the various objects, but don’t worry if you don’t understand them all.

Bringing Your Game

Animations and object-oriented theory are nice and all, but we’re here to build a game. The biggest difference between a game and an animation is user interaction. If you want to make it a game, you need the user to get involved. Figure 5-3 shows a new game with a car driving around on the screen.

It really doesn’t make sense to view an interactive program on a static book page. Please go to my website (www.aharrisbooks.net) and see the program run in your own browser. It’s kind of fun, even if it isn’t a real game yet.

9781118074763-fg0503.tif

Figure 5-3: The user can steer this car with arrow keys!

The car game is similar to the ball animation, but it has some slightly different behaviors:

check.png It’s a car, not a ball. I’ll get the obvious stuff out of the way first. I can make a sprite out of any web-capable image, so this time I’ll make the sprite a car by basing it on a car image. (See Chapter 11 for tips on building graphics for your games.)

check.png Up and down arrows change the speed. You can change the speed of the car with the up and down arrows. (You’ll need a keyboard for this example. If you’re on a mobile device, please look at Chapter 9 for more on using a virtual joystick or keypad solution.)

check.png Left and right keys change the direction. Pressing the left- or right-arrow key changes the direction the car is going. Turning even works correctly when going into reverse!

The code is actually not much more complicated than the ball animation.

<!DOCTYPE HTML>

<html lang=”en-US”>

<head>

    <meta charset=”UTF-8”>

    <title>car.html</title>

    <script type=”text/javascript”

            src = ”simpleGame.js”></script>

    <script type=”text/javascript”>

    var scene;

    var car;

    

    function init(){

        scene = new Scene();

        car = new Sprite(scene, ”car.png”, 50, 30);

        car.setAngle(270);

        car.setSpeed(0);

        scene.start();

    } // end init

    

    function update(){

        scene.clear();

        //check keys

        

        if (keysDown[K_LEFT]){

            car.changeAngleBy(-5);

        } // end if

        

        if (keysDown[K_RIGHT]){

            car.changeAngleBy(5);

        } // end if

        

        if (keysDown[K_UP]){

            car.changeSpeedBy(1);

        } // end if

        

        if (keysDown[K_DOWN]){

            car.changeSpeedBy(-1);

        } // end if

        

        car.update();

    } // end update

    </script>

</head>

<body onload = “init()”>

    <h1>Drive the car!</h1>

</body>

</html>

Checking the keyboard

Somehow the user needs to interact with the page. The keyboard is one of the easiest input elements to use. simpleGame provides a couple ways to check the keyboard, but the most powerful technique uses a special variable called keysDown. Here’s how it works:

check.png keysDown is a global array. This variable is automatically created when you build a scene. It is an array of Boolean values — that means each element can be only true or only false.

check.png There is a constant defined for each key. Each key on the standard keyboard has a special constant already defined. For example, K_A represents the A key, and K_B represents the B key. See the chart for the names of special characters like the arrow keys and space bar.

check.png keysDown tells the status of every key. If the A key is currently pressed, keysDown[A] will contain the value true. If the A key is not pressed, keysDown[A] will contain the value false. See Table 5-1 for a rundown of the keyboard constants.

check.png You can determine the current status of any key. Just check the keysDown[] array to determine the current status of any key.

check.png You can have multiple keys down at once. The primary purpose of this technique is to allow for multiple keys to be pressed at once. In normal computing, it’s unusual to have more than one key at a time (except special keys like Shift and Ctrl). In gaming, it’s very common to press more than one key at a time, so you need a mechanism that can support this expectation.

Table 5-1 Keyboard Constants in simpleGame

simpleGame Constant

Key

K_AK_Z

Standard character keys (capitalization is irrelevant)

K_UP

Up arrow

K_DOWN

Down arrow

K_LEFT

Left arrow

K_RIGHT

Right arrow

K_SPACE

Spacebar

See Chapter 12 for information on using other keys and defining new constants for them.

Moving the sprite

Sprites have a number of interesting built-in methods that allow you to change the position, angle, and speed of your sprite. Table 5-2 shows the highlights.

Table 5-2 Sprite Movement Methods

Method

Description

Parameters

setPosition (x, y)

Places the sprite at the indicated position.

x: horizontal position

y: vertical position

setX(x)

Sets the X position to a specific value.

x: new x position of sprite

setY(y)

Sets the Y position to a specific value.

y: new y position of sprite

changeXby(dx)

Changes the X position by some amount one time.

dx: amount to change x (positive values move right)

changeYby(dy)

Changes the Y position by some amount one time.

dy: amount to change y (positive values move down)

setChangeX(dx)

Sets an ongoing change in X (keeps going until you change it).

dx: amount to change x

setChangeY(dx)

Sets an ongoing change in Y (keeps going until you change it).

dy: amount to change y

setAngle(angle)

Sets both visual and motion angle of sprite.

angle: angle in degrees (standard map format)

changeAngleBy (dAngle)

Changes both visual and motion angle by some amount.

dAngle: degrees to change (positive is clockwise)

setImgAngle (angle)

Sets only the visual angle (does not affect motion).

angle: angle in degrees (standard map format)

changeImgAngle (angle)

Changes only the visual angle (does not affect motion).

dAngle: degrees to change (positive is clockwise)

setMoveAngle (angle)

Sets only the movement angle (does not affect appearance).

angle: angle in degrees (standard map format)

changeImgAngle (angle)

Changes only the movement angle (does not affect appearance).

dAngle: degrees to change (positive is clockwise)

setSpeed(speed)

Sets the speed of the car (in pixels / frame).

speed: new speed (can be negative for backward motion)

changeSpeedBy (dSpeed)

Changes the speed of the car.

dSpeed: positive values to speed up, negative values to slow down

There’s a lot of information in Table 5-2, but it’s not as complicated as it might look. Essentially, a sprite has a position, which is controlled by X and Y properties. If you remember from math class, X represents horizontal values, and Y is for vertical location. The origin (0, 0) is the top-left corner of the screen.

X coordinates work just like you remember from math class. As X values get larger, the sprite moves to the right. In computer graphics, Y acts a little different than it did in math class. Most display hardware scans from top to bottom, so Y is 0 at the top of the screen and increases as you move downward. This can be confusing at first, but I promise, you’ll get used to it.

Figure 5-4 shows the coordinate system for a scene. Note that the maximum height and width are stored in variables: scene.height and scene.width. (The default scene is 400px by 300px, but you can change it if you want.)

All of the various movement methods are really about manipulating X and Y. You can set these values manually (setPosition(), setX(), and setY()), or you can change the values (changeXby(), changeYby()). Each of these methods acts immediately, so you can use them to direct the position or motion of the sprite.

Some of these functions seem similar to each other. For example, changeXby() looks a lot like setChangeX(). These functions have a subtle but important difference. The changeXby() function changes the value of X one time. If you want the change to continue, you have to keep calling this function. The setChangeX() function is more powerful because you can call it one time, and it repeatedly changes x by whatever value you determine until you call setChangeX() again (or something else that affects the car’s speed).

9781118074763-fg0504.tif

Figure 5-4: Computer screens have the origin at the upper-left corner.

It’s fine if all this is a little lost on you right now because you’re not going to use any of these techniques yet. The whole point of a game engine is to provide abstraction, which allows the programmer to think in a less mathematical way.

For most sprites, you really want to simply give the sprite an angle and a speed, and let it go. The sprite object has exactly the methods you need for this behavior. setAngle() allows you to determine the direction the sprite will go, and setSpeed() lets you specify the speed to go in that direction. Like most motion functions, there are also changeAngle() and changeSpeed() methods.

Note that for basic examples, I’m assuming that the sprite goes in the direction it’s pointing, but that’s not always the case. Sometimes, you’ll want a car that skids or a spaceship that drifts sideways. It’s possible to separate the movement angle from the visual angle with the provided methods.

technicalstuff.eps Using the speed and angle to control a sprite is a really big deal. It vastly simplifies your game programming, but what’s really going on under the hood? Well, it’s math. The speed and angle are used to calculate a new change in X and change in Y every frame, using a mathematical technique called vector projection (which in turn uses basic trigonometry). I explain the technique in Chapter 12. For now, you can consider it magic, but I absolutely promise you’re going to use math in game programming, so it might be time to break out those math books. When will you use math in real life? How about today?

Baby, you can drive my car

The keysDown mechanism can be combined with the motion methods to easily control your car. Here’s the relevant code from update() again:

    function update(){

        scene.clear();

        //check keys

        

        if (keysDown[K_LEFT]){

            car.changeAngleBy(-5);

        } // end if

        

        if (keysDown[K_RIGHT]){

            car.changeAngleBy(5);

        } // end if

        

        if (keysDown[K_UP]){

            car.changeSpeedBy(1);

        } // end if

        

        if (keysDown[K_DOWN]){

            car.changeSpeedBy(-1);

        } // end if

        

        car.update();

    } // end update

The actual coding is pretty easy to understand:

1. Clear the scene.

As usual, the first order of business in the update() function is to clean up the playroom. Make sure you’ve erased the previous frame before you do anything else.

2. Check for a left-arrow press.

Use the keysDown mechanism to determine whether the left arrow is currently pressed. (Of course, you can use WASD or some other control scheme if you prefer.)

3. If the left arrow is pressed, turn the car left.

If the user is currently pressing the left-arrow key, turn the car five degrees counter-clockwise (which will turn its nose to the car’s left). Use the changeAngleBy() method to change the car’s visual appearance as well as the direction it’s travelling.

4. Repeat for the right arrow.

The right arrow check is similar, but this time turn the car five degrees clockwise (a positive angle turns the car’s nose to the car’s right).

5. Use the up arrow to accelerate.

If the user presses the up arrow, change the car’s speed. Use a positive value to accelerate the car. It won’t take much because this code is being checked 20 times a second.

6. Slow the car down with the down arrow.

Use a similar mechanism for the down arrow. Change the speed by a negative value to slow down the car. This approach allows for negative values, and the car will back up if you want.

7. Draw the car in its new position.

It’s critically important to remember that calling the sprite’s motion functions does not change the location of the car! It only changes internal data in the game’s memory. You must call the car’s update() method to see these changes in action.

You’ve got a pretty good start. Try building your own. Create an image, build a control system, and get it going. If you’re ready for a challenge, see if you can figure out how to make your sprite go in the direction you pressed. For example, if you press the right arrow, the car goes right. If you press the up arrow, the car goes up.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset