Javascript simulated tank war game (html5 version) with source code download

Source: Internet
Author: User
Tags sleep function

I. Summarize the key points and problems encountered

1. Inheritance in javascript. It is recommended that the parent class only provide method sharing, and the attributes should be written to the Child classes of the parent class and the constructor of the Child classes.

2. prototype simulate inherited code, which should be written before the definition of all methods. Otherwise, if the prototype object is changed, the method becomes undefined, for example:
Copy codeThe Code is as follows:
Hero. prototype = new Tank (0, 0, 0 );
Hero. prototype. constructor = Hero;
Hero. prototype. addLife = function (){
This. lifetimes ++;
Document. querySelector ("# life"). innerHTML = hero. lifetimes;
}

3. When painting a chart on the canvas, ctx. beginPath (); and ctx. closePath (); must be added to all other elements except the rectangle. Otherwise, unexpected errors may occur.

4. The concat function can merge arrays, or the element returns a new array.

5. After the src attribute of the Image is assigned a value, the Image will be loaded. However, if the Image is not loaded, it will become invalid. Therefore, onload event processing is used.

6. Extend the Array Function to delete specified elements.
Copy codeThe Code is as follows:
// Extended deletion of specified elements
Array. prototype. deleteElement = function (obj ){
If (obj ){
For (var I = 0; I <this. length; I ++ ){
If (this [I] === obj ){
This. splice (I, 1 );
}
}
}
}

7. timer settings, the first parameter of the setInterval ("fun", 1000) method, can be a string, such as "hero. say () ", similar to eval, this code string will be executed, so it can add parameters to the function and specify the running context of the function. However, if the input is a function handle, the parameter cannot be included and the context cannot be specified. Apart from the first solution, I used a closure to solve this problem.
Copy codeThe Code is as follows:
// Timer, self-Motion
This. timer = setInterval (function (context ){
Return function (){
Bullet. prototype. move. call (context)
}
}) (This), 30 );

I saved the current execution environment and called the call Method for manual execution.

8. Function Design of the method should include the condition detection for executing this function, except for the function. For example, if you move the method, it should include the circumstances in which it can be moved and the place where it can be moved will not be moved. This check should not be performed externally.

9. When writing code, you should not design or optimize the problem. First, implement the function, then optimize it, or design and then implement it. The train of thought should be clear, don't be confused, and focus on one point.

10. There is no sleep function in javascript. You can create a variable as a buffer to achieve the purpose of executing the variable at intervals.

Ii. Code Implementation

1.this program is divided into bomb.js, bullet.js, draw.js, tank.js, index.html, img, music,

2. Final Results



 

3. Code

1.index.html
Copy codeThe Code is as follows:
<! DOCTYPE html>
<Html>
<Head>
<Title> </title>
<Meta charset = "UTF-8">
<Style type = "text/css">
Body {
Font: 14px "sans-serif"
}

# Map {
Background-color: #000000;
}

. Show {
Float: left
}

# Guide {
Float: left;
Width: 200px;
Height: 390px;
Margin-left: 5px;
Background: # CCCCCC;
Padding: 5px;
}
</Style>
<Script type = "text/javascript" src = "Tank. js"> </script>
<Script type = "text/javascript" src = "Bullet. js"> </script>
<Script type = "text/javascript" src = "Bomb. js"> </script>
<Script type = "text/javascript" src = "Draw. js"> </script>

<Script type = "text/javascript">
Window. onload = function (){
// Canvas Information
Width = document. getElementById ('map'). width;
Height = document. getElementById ('map'). height;
Ctx = document. getElementById ('map'). getContext ('2d ');
// Initial Page
Var starImg = new Image ();
StarImg. src = "img/star.jpg ";
StarImg. onload = function (){
Ctx. drawImage (starImg, 0, 0, width, height );
}

// Press enter to start the game.
Document. body. onkeydown = function (){
Var keycode = event. keyCode;
Switch (keycode ){
Case 13:
// Initialization parameters
Init ()
// Refresh the page
SetInterval (draw, 30 );
Document. body. onkeydown = gameControl;
Break;
}
}
}

Function init (){
// Players and computers
Hero = new Hero (100,300, 0 );
Enemys = [];
For (var I = 0; I <3; I ++ ){
Enemys. push (new Enemy (100 + I * 50, 0, 2 ));
}
// Merge Arrays
AllTank = enemys. concat (hero );

// Bomb
Bombs = [];
Im = new Image ();
Im2 = new Image ();
Im3 = new Image ();
Im. src = "img/bomb_3.gif ";
Im2.src = "img/bomb_2.gif ";
Im3.src = "img/bomb_1.gif ";
}

Function gameControl (){
Var keycode = event. keyCode;
Switch (keycode ){
Case 65:
Hero. moveLeft ();
Break; // left
Case 83:
Hero. moveDown ();
Break; // lower
Case 87:
Hero. moveUp ();
Break; // top
Case 68:
Hero. moveRight ();
Break; // right
Case 74:
Hero. shot ();
Break;
Case 49:
Hero. addLife ()
Break;
}
}

// Extended deletion of specified elements
Array. prototype. deleteElement = function (obj ){
If (obj ){
For (var I = 0; I <this. length; I ++ ){
If (this [I] === obj ){
This. splice (I, 1 );
}
}
}
}

</Script>
</Head>
<Body>
<Div class = "show">
<Canvas id = "Map" width = "500px" height = "400px">
</Canvas>
<Audio id = "music" autoplay = "autoplay">
<Source src = "music/111.wav">
</Audio>
</Div>
<Div id = "guide">

<P> press the Enter key to start the game </p>

<P> press the 1 key to increase the lifecycle. The default value is 1. </p>

<P> remaining lifecycle: <label id = "life"> 1 </label> </p>

<Div id = "data">

</Div>
</Div>
</Body>
</Html>

2. Draw. js
Copy codeThe Code is as follows:
/**
* Created by Alane on 14-3-18.
*/

Function draw (){
// Detect bullets and tank life and death
CheckDead ();
// Clear the canvas
Ctx. clearRect (0, 0, 500,400 );
// Draw players
If (! Hero. isdead ){
DrawTank (hero );
} Else {
Hero. cutLife ();
}
// Draw enemy tanks
For (var I = 0; I <enemys. length; I ++ ){
DrawTank (enemys [I]);
}
// Draw enemy bullets
For (var j = 0; j <enemys. length; j ++ ){
Var temp = enemys [j]. bulletsList;
For (var I = 0; I <temp. length; I ++ ){
DrawBullet (temp [I]);
}
}
// Draw a player bullet
Var temp = hero. bulletsList;
For (var I = 0; I <temp. length; I ++ ){
DrawBullet (temp [I]);
}

// Draw a bomb
For (var I = 0; I <Bombs. length; I ++ ){
DrawBown (Bombs [I]);
}

}

Function drawTank (tank ){
Var x = tank. x;
Var y = tank. y;
Ctx. fillStyle = tank. color;

If (tank. direct = 0 | tank. direct = 2 ){
Ctx. fillRect (x, y, 5, 30 );
Ctx. fillRect (x + 15, y, 5, 30 );

Ctx. fillRect (x + 6, y + 8, 8, 15 );

Ctx. strokeStyle = tank. color;
Ctx. lineWidth = '1. 5 ';
If (tank. direct = 0 ){
Ctx. beginPath ();
Ctx. moveTo (x + 10, y-2 );
Ctx. lineTo (x + 10, y + 8 );
Ctx. closePath ();
} Else {
Ctx. beginPath ();
Ctx. moveTo (x + 10, y + 24 );
Ctx. lineTo (x + 10, y + 32 );
Ctx. closePath ();
}

Ctx. stroke ();
} Else {
Ctx. fillRect (x, y, 30,5 );
Ctx. fillRect (x, y + 15, 30,5 );

Ctx. fillRect (x + 8, y + 6, 15, 8 );

Ctx. strokeStyle = '# FF0000 ';
Ctx. lineWidth = '1. 5 ';
If (tank. direct = 3 ){
Ctx. beginPath ();
Ctx. moveTo (X-2, y + 10 );
Ctx. lineTo (x + 8, y + 10 );
Ctx. closePath ();
} Else {
Ctx. beginPath ();
Ctx. moveTo (x + 24, y + 10 );
Ctx. lineTo (x + 32, y + 10 );
Ctx. closePath ();
}

Ctx. stroke ();
}

}
Function drawBullet (bullet ){
Ctx. fillStyle = bullet. color;
Ctx. beginPath ();
Ctx. arc (bullet. x, bullet. y, 2,360, true );
Ctx. closePath ();
Ctx. fill ();
}

Function drawBown (obj ){
If (obj. life> 8 ){
Ctx. drawImage (im, obj. x, obj. y, 50, 50 );
} Else if (obj. life> 4 ){
Ctx. drawImage (im2, obj. x, obj. y, 50, 50 );
} Else {
Ctx. drawImage (im3, obj. x, obj. y, 50, 50 );
}

Obj. lifeDown ();
If (obj. life <= 0 ){
Bombs. deleteElement (obj );
}
}

Function checkDead (){
// Detect death and death of enemy bullets
For (var j = 0; j <enemys. length; j ++ ){
Var temp = enemys [j]. bulletsList;
For (var I = 0; I <temp. length; I ++ ){
Var o = temp [I];
If (o. isdead ){
Temp. deleteElement (o );
}
}
}
// Detects the life and death of a player bullet
Var temp = hero. bulletsList;
For (var I = 0; I <temp. length; I ++ ){
Var o = temp [I];
If (o. isdead ){
Temp. deleteElement (o );
}
}

// Detect enemy tank life and death
For (var I = 0; I <enemys. length; I ++ ){
Var o = enemys [I];
If (o. isdead ){
Enemys. deleteElement (o );
}
}
}

Bomb. js
Copy codeThe Code is as follows:
/**
* Created by Alane on 14-3-18.
*/
Function Bomb (x, y ){
This. life = 12;
This. x = x;
This. y = y;
}
Bomb. prototype. lifeDown = function (){
This. life --;
}

Tank. js
Copy codeThe Code is as follows:
/**
* Created by Alane on 14-3-7.
*/
/**
* On direct 0
* 1 right
* 2
* 3 left
* @ Param x
* @ Param y
* @ Param direct
* @ Constructor
*/
//************************************** **************************************** ************/
// Tank parent class
Function Tank (x, y, direct ){
This. speed = 2;

}
Tank. prototype. moveUp = function (){
// Border detection
If (this. y <0 ){
// Change the direction
This. changeDirect ();
Return;
}
This. y-= this. speed;
This. direct = 0;

}
Tank. prototype. moveDown = function (){
If (this. y> height-30 ){
This. changeDirect ();
Return;
}
This. y + = this. speed;
This. direct = 2;
}
Tank. prototype. moveLeft = function (){
If (this. x <0 ){
This. changeDirect ();
Return;
}
This. x-= this. speed;
This. direct = 3;

}
Tank. prototype. moveRight = function (){
If (this. x> width-30 ){
This. changeDirect ();
Return;
}
This. x + = this. speed;
This. direct = 1;

}

// Change the direction
Tank. prototype. changeDirect = function (){
While (true ){
Var temp = Math. round (Math. random () * 3 );
If (this. direct! = Temp ){
This. direct = temp;
Break;
}
}
// Alert ("x =" + this. x + "y =" + this. y + "direct =" + this. direct)
}

// Shooting bullets
Tank. prototype. shot = function (){
If (this. isdead ){
Return;
}
If (this. bulletsList. length <this. maxBulletSize ){
// Create a bullet
Var bullet = null;
Switch (this. direct ){
Case 0:
Bullet = new Bullet (this. x + 10, this. y-2, 0, this. color );
Break;
Case 1:
Bullet = new Bullet (this. x + 32, this. y + 10, 1, this. color );
Break;
Case 2:
Bullet = new Bullet (this. x + 10, this. y + 32, 2, this. color );
Break;
Case 3:
Bullet = new Bullet (this. x-2, this. y + 10, 3, this. color );
Break;
}
// Add the clip
This. bulletsList. push (bullet );
}
}
//************************************** **************************************** ************/
// Players
Function Hero (x, y, direct ){
This. lifetimes = 5;
This. isdead = false;
This. color = '# FF0000 ';
This. x = x;
This. y = y;
This. direct = direct;
This. bulletsList = [];
This. maxBulletSize = 10;
This. newlife = null;
}
Hero. prototype = new Tank (0, 0, 0 );
Hero. prototype. constructor = Hero;
Hero. prototype. addLife = function (){
This. lifetimes ++;
Document. querySelector ("# life"). innerHTML = hero. lifetimes;
}
Hero. prototype. cutLife = function (){
If (this. lifetimes> = 1 &&! This. newlife ){
This. lifetimes --;
This. newlife = setTimeout ("hero. newLife ()", 2000 );
}
}
Hero. prototype. newLife = function (){
This. isdead = false;
ClearTimeout (hero. newlife );
Hero. newlife = null;
Document. querySelector ("# life"). innerHTML = hero. lifetimes;
}


//************************************** **************************************** ************/
// Enemy tank
Function Enemy (x, y, direct ){
This. isdead = false;
This. color = 'blue ';
This. x = x;
This. y = y;
This. direct = direct;
This. bulletsList = [];
This. maxBulletSize = 1;


// Timer, automatically move
This. timer1 = setInterval (function (context ){
Return function (){
// Move
Enemy. prototype. move. call (context );
}
}) (This), 30 );

// Timer, shooting
This. timer2 = setInterval (function (context ){
Return function (){
// Shooting
Tank. prototype. shot. call (context );
}
}) (This), 2000 );

// Timer, changing the direction
This. timer3 = setInterval (function (context ){
Return function (){
// Shooting
Tank. prototype. changeDirect. call (context );
}
}) (This), 3000 );
}

Enemy. prototype = new Tank (0, 0, 0 );
Enemy. prototype. constructor = Enemy;
Enemy. prototype. move = function (){
Switch (this. direct ){
Case 0:
This. moveUp ();
Break;
Case 1:
This. moveRight ();
Break;
Case 2:
This. moveDown ();
Break;
Case 3:
This. moveLeft ();
Break;
}
}

Bullet. js
Copy codeThe Code is as follows:
/**
* Created by Alane on 14-3-11.
*/
Function Bullet (x, y, direct, color ){
This. isdead = false;
This. x = x;
This. y = y;
This. direct = direct;
This. speed = 4;
This. color = color;
// Timer, self-Motion
This. timer = setInterval (function (context ){
Return function (){
Bullet. prototype. move. call (context)
}
}) (This), 30 );
}
Bullet. prototype. move = function (){
Switch (this. direct ){
Case 0:
This. y-= this. speed;
Break;
Case 1:
This. x + = this. speed;
Break;
Case 2:
This. y + = this. speed;
Break;
Case 3:
This. x-= this. speed;
Break;
}

// Border detection
If (this. y <0 | this. x> width | this. y> height | this. x <0 ){
ClearInterval (this. timer );
This. isdead = true;
}

// Collision Detection and detection of enemy tanks
For (var I = 0; I <allTank. length; I ++ ){
Var temp = allTank [I];
If (temp. isdead ){
Continue;
}
Switch (temp. direct ){
Case 0:
Case 2: if (this. x> temp. x & this. x <temp. x + 20 & this. y> temp. y & this. y <temp. y + 30 ){
If (this. color = temp. color ){
Break;
}
Bombs. push (new Bomb (temp. X-10, temp. y-10 ));
ClearInterval (this. timer );
This. isdead = true;
Temp. isdead = true;
} Break
Case 1:
Case 3: if (this. x> temp. x & this. x <temp. x + 30 & this. y> temp. y & this. y <temp. y + 20 ){
If (this. color = temp. color ){
Break;
}
Bombs. push (new Bomb (temp. X-10, temp. y-10 ));
ClearInterval (this. timer );
This. isdead = true;
Temp. isdead = true;
} Break;
}
}

}

Source code download

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.