PS: This tank battle was a rewrite after a piece of source code online and offline. There is nothing too difficult in itself. This case uses js object-oriented, which can be used as an introductory tutorial for js object-oriented.
1. Create basic objects to realize simple movement of tanks
1.1 How to draw a canvas in a map ?
Considering the problem of browser compatibility, we use the dom to draw and refresh game objects. How do we store our maps? We should save the map as a two-dimensional array. There is no two-dimensional array in js, but it can be achieved by storing the array in a one-dimensional array.
1.2 Code implementation
We design the canvas as a two-dimensional array of 13 * 13. Each element has a corresponding length and width in the map. We can regard the entire map as a table composed of cells of 40px*40px size, so the size of our entire canvas is 520px * 520px;
Before entering the code, I will give you an object relationship diagram:
1.2.1 Creating a top-level object
html code:
The code copy is as follows:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Tank War</title>
<link rel=stylesheet href="css/main.css" />
<script src="js/Common.js"></script>
<script src="js/TankObject.js"></script>
<script src="js/Mover.js"></script>
<script src="js/Tank.js"></script>
<script src="js/Frame.js"></script>
<script>
window.onload = function () {
// Call the game loading object
var loader = new GameLoader();
loader.Begin();
}
</script>
</head>
<body>
<!--Map Container-->
<div id="divMap">
</div>
<div id="debugInfo">
</div>
</body>
</html>
TankObject.js file:
The code copy is as follows:
// Top-level object
TankObject = function () {
this.XPosition = 0; // The position of the object in X in the map (13*13)
this.YPosition = 0;
this.UI = null; // dom element
}
// Change UI static method
TankObject.prototype.UpdateUI = function (battlFiled) { }
// Set the position, the parameters are as follows: 1*40, 6*40
TankObject.prototype.SetPosition = function (leftPosition, topPosition) {
// Round in the map location Math.round
this.XPosition = Math.round(leftPosition / 40);
this.YPosition = Math.round(topPosition / 40);
// Set the position on the form
if (this.UI != null && this.UI.style != null) {
this.UI.style.left = leftPosition + "px";
this.UI.style.top = topPosition + "px";
}
}
Here we use X and Y coordinates to represent the position of the object on the map. Later, we will put each object in the map into a two-dimensional array, and at this time, we can obtain the corresponding object through the X and Y coordinates.
Then use left and top in css to control the position of our object in the form. (Typeable objects: tanks, bullets)
1.2.2 Creating a public object
We also need to create a public object to write some of our commonly used methods.
Common.js:
The code copy is as follows:
// Four directions of tank movement
var EnumDirection = {
Up: "0",
Right: "1",
Down: "2",
Left: "3"
};
// General method object
var UtilityClass = {
// Create dom element into parentNode, specify id and className
CreateE: function (type, id, className, parentNode) {
var J = document.createElement(type);
if (id) { J.id = id };
if (className) { J.className = className };
return parentNode.appendChild(J);
}, // Remove elements
RemoveE: function (obj, parentNode) {
parentNode.removeChild(obj);
},
GetFunctionName: function (context, argumentCallee) {
for (var i in context) {
if (context[i] == argumentCallee) { return i };
}
return "";
}, //Bind the event, return the func method, this is the passed obj
BindFunction: function (obj,func) {
return function () {
func.apply(obj, arguments);
};
}
};
1.2.3 Creating a moving object
Mover.js
The code copy is as follows:
// Move the object, inherit from the top-level object
Mover = function () {
this.Direction = EnumDirection.Up;
this.Speed = 1;
}
Mover.prototype = new TankObject();
Mover.prototype.Move = function () {
if (this.lock) {
return;/* Deactivated or is still in progress, the operation is invalid*/
}
// Set the background picture of the tank according to the direction
this.UI.style.backgroundPosition = "0 -" + this.Direction * 40 + "px";
// If the direction is up and down, vp is top; if the direction is up and left, val is -1
var vp = ["top", "left"][((this.Direction == EnumDirection.Up) || (this.Direction == EnumDirection.Down)) ? 0 : 1];
var val = ((this.Direction == EnumDirection.Up) || (this.Direction == EnumDirection.Left)) ? -1 : 1;
this.lock = true;/* Lock*/
// Save the current object to This
var This = this;
// Record object movement start position
var startmoveP = parseInt(This.UI.style[vp]);
var xp = This.XPosition, yp = This.YPosition;
var subMove = setInterval(function () {
// Start moving, 5px each time
This.UI.style[vp] = parseInt(This.UI.style[vp]) + 5 * val + "px";
// 40px per cell
if (Math.abs((parseInt(This.UI.style[vp]) - startmoveP)) >= 40) {
clearInterval(subMove);
This.lock = false;/* Unlock, allowing stepping again*/
// Record the position of the object in the table after it is moved
This.XPosition = Math.round(This.UI.offsetLeft / 40);
This.YPosition = Math.round(This.UI.offsetTop / 40);
}
}, 80 - this.Speed * 10);
}
The moving object here inherits from our top-level object, and this represents the object that calls the Move method.
The function of the Move object moves according to the direction and speed of the object. Each time you move 5px, move a total of 40px one cell. The object will be expanded later and collision detection and other functions will be added.
1.2.4 Creating a Tank Object
Tank.js file:
The code copy is as follows:
//The tank object inherits from Mover
Tank=function(){}
Tank.prototype = new Mover();
// Create a player tank, inherit from a tank object
SelfTank = function () {
this.UI = UtilityClass.CreateE("div", "", "itank", document.getElementById("divMap"));
this.MovingState = false;
this.Speed = 4;
}
SelfTank.prototype = new Tank();
// Set the position of the tank
SelfTank.prototype.UpdateUI = function () {
this.UI.className = "itank";
// Top object method, set the position of the tank
this.SetPosition(this.XPosition * 40, this.YPosition * 40);
}
Now only player tanks have been created, and we will add enemy tanks to them later.
1.2.5 Create a game loading object (core)
The code copy is as follows:
// The game loads the object of the entire game's core object
GameLoader = function () {
this.mapContainer = document.getElementById("divMap"); // The div that stores the game map
this._selfTank = null; // Player Tank
this._gameListener = null; // The main loop timer id of the game
}
GameLoader.prototype = {
Begin: function () {
// Initialize the player tank
var selfT = new SelfTank();
selfT.XPosition = 4;
selfT.YPosition = 12;
selfT.UpdateUI();
this._selfTank = selfT;
// Add key event
var warpper = UtilityClass.BindFunction(this, this.OnKeyDown);
window.onkeydown = document.body.onkeydown = warpper;
warpper = UtilityClass.BindFunction(this, this.OnKeyUp);
window.onkeyup = document.body.onkeyup = warpper;
// The main loop of the game
warpper = UtilityClass.BindFunction(this, this.Run);
/*Long timer monitoring control key*/
this._gameListener = setInterval(warpper, 20);
}
// Press the player tank on the keyboard to start moving
, OnKeyDown: function (e) {
switch ((window.event || e).keyCode) {
case 37:
this._selfTank.Direction = EnumDirection.Left;
this._selfTank.MovingState = true;
break; //left
case 38:
this._selfTank.Direction = EnumDirection.Up;
this._selfTank.MovingState = true;
break; //On
case 39:
this._selfTank.Direction = EnumDirection.Right;
this._selfTank.MovingState = true;
break; //Right
case 40:
this._selfTank.Direction = EnumDirection.Down;
this._selfTank.MovingState = true;
break; //Next
}
}
// The buttons pop up and stop moving
, OnKeyUp: function (e) {
switch ((window.event || e).keyCode) {
case 37:
case 38:
case 39:
case 40:
this._selfTank.MovingState = false;
break;
}
}
/*The main loop running function of the game, the heart of the game, the hub*/
, Run: function () {
if (this._selfTank.MovingState) {
this._selfTank.Move();
}
}
};
The game loading object code looks a lot, but in fact, it only does two things:
1. Create a player tank object.
2. Add a key monitoring event. When the player presses the mobile key, call the tank Move method to move the tank.
Summary: At this point, our tank can move freely by pressing the buttons. Next step we need to improve the map and collision detection.