Home
» Games
»
HTML5 - Canvas: Game tank simple - part 2 (end)
HTML5 - Canvas: Game tank simple - part 2 (end)
Video HTML5 - Canvas: Game tank simple - part 2 (end)
Following the previous section , in this section I will perform the main content:
- Change the key function to the tanks began to move smoother.
- Add the obstacles in the game to shoot and destroy tanks.
- A Some visual effects, sound.
In the previous section, I use the trigger mechanism of action of the objects in the game every time you get the corresponding event from the user. This makes control difficult and not continuous. The solution to this problem is that I will write a separate method of treatment necessary in each object and transmit the status of the keyboard, mouse, ... on how to handle this:
// Sample.html:
function update () {
_tank.handleInput (_keyStates);
// ...
}
function canvas_keyDown (e) {
if (AVAILABLE_KEYS.indexOf (e.keyCode)! = - 1)
_keyStates [e.keyCode] = true ;
}
function canvas_keyUp (e) {
if (_keyStates [e.keyCode])
_keyStates [e.keyCode] = false ;
}
// Tank.js:
Tank.prototype.handleInput = function (keyStates) {
this .speedX = 0;
this .speedY = 0;
if (keyStates [Keys.KEY_W])
this .moveUp ();
if (keyStates [Keys.KEY_S])
this .moveDown ();
if (keyStates [Keys.KEY_A])
this .moveLeft ();
if (keyStates [Keys.KEY_D])
this .moveRight ();
this .move ();
}
More obstacles: meteorite
The plot of the game is that players will be playing a tank with the task of protecting the earth from meteorites fell by shooting to destroy them. Thus the obstacles here is the meteorite comes above the canvas and fell with random direction.
// Sample.html:
var _obstacles = [];
function update () {
_tank.handleInput (_keyStates);
if (_obstacles.length <10)
_obstacles.push ( new Obstacle (_canvas.width, _canvas.height, _context));
for ( var i = 0; i <_obstacles.length; i ++)
{
var ob = _obstacles [i];
ob.update ();
}
_tank.update (_obstacles);
draw ();
}
// Obstacke.js:
function Obstacle (mapWidth, exampleadd, context) {
this .mapWidth = mapWidth;
this .mapHeight = exampleadd;
this .context = context;
this .size = Math.floor (Math.random () * 60) +60;
this .left = Math.floor (Math.random () * (mapWidth- this .size)) + 1;
this .top = -Math.floor (Math.random () * exampleadd);
this .speedY = Math.floor (Math.random () * 4) +1;
this .speedX = Math.floor (Math.random () * 3) -3;
}
To draw the asteroid, I use images taken from a file rock.png. In the method update (), I will let the meteorite can be reflected back by hitting a double into the canvas to ensure they are not beyond the scope of screen, and also to increase the degree of difficulty for players.
var rockImg = new Image ();
rockImg.src = "rock.png" ;
// ...
Obstacle.prototype.draw = function () {
this .context.drawImage (rockImg, this .left, this .top, this .size, this .size);
}
Obstacle.prototype.update = function () {
if ( this .left <0 || this .right> this .mapWidth)
this .speedX = - this .speedX;
this .top + = this .speedY;
this .left + = this .speedX;
this .right = this .left + this .size;
this .bottom = this .top + this .size;
}
Result:
Making different meteorites
You can use several different image and randomly assigned for each meteorite that they have specific characteristics in terms of shape and size. Here I chose a simpler approach is rotated each asteroid a random angle.
How to do is use the methods context.translate () to move the origin to the center of the meteorite draw, rotate with context.rotate () and draw. Remember to save and restore the state of the context when you perform this operation:
function Obstacle (mapWidth, exampleadd, context) {
// ...
this .halfSize = Math.floor (Math.random () * 30) +30;
this .context.translate ( this .left + this .halfSize, this .top + this .halfSize);
this .context.rotate ( this .angle);
this .context.drawImage (rockImg, - this .halfSize, - this .halfSize, this .size, this .size);
this .context.restore ();
}
Check collision
In this example, I just do functional testing of a meteorite collision with bullets. Because the size of the relatively small bullets may consider it to be 1 point. So the method collide () after I just passed two parameters x, y coordinates representing the center of the bullet. The simple test is to identify a point in a rectangle or not.
Obstacle.prototype.collide = function (x, y) {
return this .left <= x && this .right> = x &&
this .top <= y && this .bottom> = y;
}
Next, I'll use it in class Tank:
Tank.prototype.update = function (obstacles) {
for ( var i = 0; i < this .balls.length; i ++)
{
var ball = this .balls [i];
if (ball.update ())
{
this .balls.splice (i - 1);
} else {
for ( var j = 0; j <obstacles.length; j ++)
{
var ob = obstacles [j];
if (ob.collide (ball.cx, ball.cy))
{
// Do something ích
this .balls.splice (i - 1);
break ;
}
}
}
}
}
Explosive Effects
To make this effect, I just draw a picture meteorite after it collided other.
Obstacle.prototype.draw = function () {
var img = this .isCollided? explodeImg: rockImg;
this .context.save ();
this .context.translate ( this .left + this .halfSize, this .top + this .halfSize);
this .context.rotate ( this .angle);
this .context.drawImage (img, - this .halfSize, - this .halfSize, this .size, this .size);
this .context.restore ();
}
The display pictures of the asteroid explosion can not see due to take place up too fast. So, I used a counter to maintain the "lifetime" of meteorites after collision:
When collision, isCollided flag is enabled (true), the counter is set to 3. explosionCounter
After each update, This variable will be reduced by 1 and the 0, flag isExploded will be enabled to notify the application deletes it from the list of meteorites.
Obstacle.prototype.explode = function () {
this .isCollided = true ;
}
Obstacle.prototype.update = function () {
if ( this .isCollided)
this .explosionCounter--;
if ( this == .explosionCounter 0)
this .isExploded = true ;
if ( this .left <0 || this .right> this .mapWidth)
this .speedX = - this .speedX;
if ( this .bottom> this .mapHeight)
this .explode ();
this .top + = this .speedY;
this .left + = this .speedX;
this .right = this .left + this .size;
this .bottom = this .top + this .size;
}
Also, I added an explosive sound effects when the methods explode () is called:
var snd = new Audio ( "explosion.wav" );
Obstacle.prototype.explode = function () {
this .isCollided = true ;
snd.currentTime = 0;
snd.play ();
}
Complete example
Adding extra functions follows:
- Allow only move horizontally: only handle two keys A and D
- Draw Background: use a photograph to paint full-screen canvas.
- Score: create a Tank class variable banding scores in the 1 each bullet collision detection with meteorites.
To be a true game, then this example is missing many features to reality. Such as checking meteorite impact with tanks, HP, level, ... and can add more sophisticated enemy. These functions are not hard to do but I will stop at this article to regain part 2 covered in other articles, and more logical order.