首頁 > web前端 > js教程 > javascript 模擬坦克大戰遊戲(html5版)附原始碼下載_javascript技巧

javascript 模擬坦克大戰遊戲(html5版)附原始碼下載_javascript技巧

WBOY
發布: 2016-05-16 16:52:56
原創
1521 人瀏覽過

一、總結關鍵點和遇到的問題

1.javascript中的繼承,最好父類只提供方法共享,屬性寫到各自子類中,避免父類和子類的構造函數混雜。

2.prototype模擬繼承的程式碼,應寫在所有方法定義之前,否則原型物件被改變,方法就變成了未定義,如:

複製程式碼 程式碼如下:

Hero.prototype = new Tank (0, 0, 0);
Hero.prototype.constructor Hero = ;
Hero.prototype.addLife = function(){
this.lifetimes ;
document.querySelector("#life").innerHTML = hero.lifetimes;
}








3.canvas畫圖形時,除了畫矩形,其他的都要加上ctx.beginPath();、ctx.closePath();,否則會出現意想不到的錯誤。

4.concat函數可以合併數組,或是元素回傳一個新的陣列

5.Image的src屬性賦值後就會載入圖片,但如果沒有載入完畢就畫圖片,會導致失效,所以使用onload事件處理

6.擴展Array功能,刪除指定元素




複製代碼


程式碼如下:this.splice (i, 1);
}
}
}
}


7.定時器設置,setInterval(“fun”,1000)方法的第一個參數,可以是字符串,如"hero.say()",類似eval會去執行這串程式碼,所以它可以給函數帶上參數,也指定了這個函數的運行上下文。但如果傳入是函數的句柄,則不能帶參數,並且不能指定上下文,除了第一種方式解決外,我用了閉包來解決這個問題



複製程式碼


程式碼如下:


//定時器,自行移動
this.timer = setInterval ((function (context) {
return function () {
Bullet.prototype.move.call (context)
}
}) (this), 30);

我儲存了目前的執行環境,並調用call方法手動執行。

8.方法的功能設計,除了功能外,應該包括執行此功能的條件檢測,如move,就應該包括什麼情況下可以移動,移動到什麼地方就不能移動了。此檢測不應該放在外部。

9.寫程式碼時不應該去想設計或最佳化的問題,先實現功能,再談最佳化,或先設計再實現。思緒要清晰,別混亂,著重一點。

10.javascript中沒有sleep的功能,可以建立一個變數作為緩衝,來達到間隔執行的目的

二、程式碼實作

1.本程式分為Bomb.js,Bullet.js,Draw.js,Tank.js,index.html,img,music,

2.最終效果

 3.代碼1.index.html 複製代碼 程式碼如下:




標題>


正文{
字型:14px "sans-serif"
}

#Map {
背景顏色:#000000;
}


.show {
浮動:左
}

#guide {
浮動:左;
寬度:200px;
高度:390px;
左邊距:5px ;
背景:#CCCCCC;
內邊距:5px;
}
風格>





window.onload = function ( ) {
//消耗資訊
width = document.getElementById('Map').width;
height = document.getElementById('地圖').height;
ctx = document.getElementById( '地圖').getContext('2d');
//初始頁面
var starImg = new Image ();
starImg.src = "img/star.jpg";
starImg. onload = function () {
ctx.drawImage(starImg, 0, 0, 寬度, 高度);
}
//鍵盤監聽回車開始遊戲
document.body.onkeydowndown = function () {
var keycode = event.keyCode;
switch (keycode) {
case 13:
//初始化參數
init ()
//刷新頁面
setInterval (draw, 30);
document.body.onkeydown = gameControl;
休息;
}
}
}

function init () {
}

function init () {
} >//玩家與電腦
hero = new Hero (100, 300, 0);
敵人=[];
for (var i = 0; i enemys .push (new Enemy (100 i * 50, 0, 2));
}
//修復備份
allTank = nationes.concat (hero);

//炸彈
炸彈= [];
im = 新圖像();
im2 = 新圖像();
im3 = 新圖像();
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;//左
case 83:
hero.moveDown. ();
break;//下
case 87:
hero.moveUp ();
break;//上
case 68:
hero.moveRight (); case 68:
hero.moveRight ();
break;//右邊
case 74:
hero.shot ();
休息;
案例49:
hero.addLife ()
break;
}}
}

//擴充刪除指定元素
Array.prototype.deleteElement = function (obj) {
if (obj) {
for (var i = 0; i if (this[i] === obj) {
this.splice (i, 1);
}
}
}
}

;
頭>



畫布>



按回車鍵開始遊戲



按1鍵增加生命,預設是1



剩餘生命數:






身體>
複製程式碼程式碼如下:

/**
* 由 Alane 於 2018 年 3 月 14 日創立。
*/

function draw(){
//偵測子彈與水箱生死
checkDead();
//清空畫布
ctx.clearRect(0,0,500,400);
//畫玩家
if(!hero.isdead){
drawTank(hero);
}else{
hero.cut(hero); );
}
//畫敵人坦克
for (var i = 0; i drawTank(enemys[i]);
}
drawTank(enemys[i]);
}
//畫敵人子彈
for(var j=0;jvar temp = enemys[j].bulletsList;
for (var i = 0; i drawBullet(temp[i]);
}
}
//畫玩家子彈
var temp = hero.bulletsList;
for (var i = 0; i drawBullet(temp[i]);
}

//畫炸彈
for(var i=0;idrawBown(Bombs[i]);
}

}

function drawTank(tank){
var x = tank. ;
var y = tank.y;
ctx.fillStyle = tank.color;

if(tank.direct == 0 || tank.direct ==2){
ctxx .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 = bulletcolor; >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,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.lifeBombs.deleteElement(obj);
}
}

function checkDead(){
//偵測敵人子彈生死
for(var j=0;jvar temp = enemys[j].bulletsList;
for (var i = 0; i var o = temp[i];
if(o.isdead){
temp.deleteElement(o);
}
}
}
//偵測玩家子彈生死
var temp = hero.bulletsList;
for (var i = 0; i var o = temp[i];
if(o.isdead){
temp.deleteElement(o);
}
}

//偵測敵人坦克生死
for (var i = 0; i var o = enemys[i];
if(o.isdead){
enemys.deleteElement(o);
}
}
}

Bomb.js Bomb.js



程式碼如下:


/**
* 由 Alane 於 2018 年 3 月 14 日創立。
*/
function Bomb(x,y){
this.life = 12
this.x = x;
this.y = y;
}
Bomb.prototype.lifeDown = function(){
this.life--; 複製程式碼 程式碼如下:

/**
* 由 Alane 於 14-3-7 所創造。
*/
/**
* direct 0 上
* 1 右
* 2 下
* 3 左
* @param x
* @param y
* @param direct
* @param y
* @param direct
* @param y
* @param direct
* @param y
* @param direct
* @param y
* @param direct * @constructor
*/
//************************************************** **** **** *********************************************/
//坦克父類
function Tank (x, y, 直接) {
this.speed = 2;

}
Tank.prototype.moveUp = function () {
//邊界偵測
if (this.y //方向換
this .changeDirect();
回傳;
}
this.y -= this.speed;
this.direct = 0;

}
Tank.prototype.moveDown = function () {
if (this.y > height - 30) {
this.changeDirect ();
回傳;
}
this.y = this.speed;
this.direct = 2;
}
Tank.prototype.moveLeft = function () {
if (this.x this.changeDirect ();
回傳;
}
this.x -= this.speed;
this.direct = 3;

}
Tank.prototype.moveRight = function () {
if (this.x > width - 30) {
this.changeDirect ();
回傳;
}
this.x = this.speed;
this.direct = 1;

}

//變換方向
Tank.prototype.changeDirect = function () {
while (true) {
var temp = Math.round (Math.隨機() * 3);
if (this.direct != temp) {
this.direct = temp;
休息;
}
}
//alert("x=" this.x " y=" this.y " direct=" this.direct)
}

//拍攝子彈
Tank.prototype.shot = function () {
if(this.isdead){
return;
}
if (this.bulletsList.length //新子彈
varBullet = null;
switch (this.direct) {
case 0:
bullet = new Bullet (this.x 10, this.y - 2, 0, this.color);
休息;
情況1:
bullet = new Bullet(this.x 32, this.y 10, 1, this.color);
休息;
情況2:
bullet = new Bullet(this.x 10, this.y 32, 2, this.color);
休息;
情況3:
bullet = new Bullet (this.x - 2, this.y 10, 3, this.color);
休息;
}
//放入彈夾
this.bulletsList.push (bullet);
}
}
//************************************************** **** **** *********************************************/
//玩家
function Hero (x, y, direct) {
this.lifetimes = 5;
this.isdead = false;
this.color = '#FF0000';
this.x = x;
this.y = y;
this.direct = 直接;
this.bulletsList = [];
this.maxBulletSize = 10;
this.newlife = null;
}
Hero.prototype = new Tank(0, 0, 0);
Hero.prototype.constructor = 英雄;
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;
}


//************************************************** **** **** *********************************************/
//敵人坦克
function Enemy (x, y, direct) {
this.isdead = false ;
this.color = '藍色';
this.x = x;
this.y = y;
this.direct = 直接;
this.bulletsList = [];
this.maxBulletSize = 1;


//計時器,自動移動
this.timer1 = setInterval ((function (context) {
return function () {
//移動
敵人。原型.move.call (上下)
}
}) (this), 30);

//計時器、射擊
this.timer2 = setInterval ((function (context) {
return function () {
//射擊
Tank.prototype.shot.呼叫(上下文)
}
}) (this), 2000);

//定時器,變換方向
this.timer3 = setInterval ((function (context) {
return function () {
//取
Tank.prototype.changeDirect .call (上下)
}
}) (這個), 3000);
}

Enemy.prototype = new Tank(0, 0, 0);
Enemy.prototype.constructor = Enemy;
Enemy.prototype.move = function () {
switch (this.direct) {
case 0:
this.moveUp ();
休息;
情況1:
this.moveRight();
休息;
情況2:
this.moveDown();
休息;
情況3:
this.moveLeft();
休息; } } Bullet.js
複製代碼程式碼如下:

/**
* 由 Alane 於 2011 年 3 月 14 日創立。
*/
function Bullet (x, y, direct, color) {
this.isdead = false;
this.x = x;
this.y = y;
this.direct = 直接;
this.speed = 4;
this.color = 顏色;
//計時器,自行運動
this.timer = setInterval ((function (context) {
return function () {
Bullet.prototype.move.call (context)
}
}) (這個), 30);
}
Bullet.prototype.move = function () {
switch (this.direct) {
case 0:
this.y -= this.speed;
休息;
情況1 1 :
this.x = this.speed;
休息;
情況2:
this.y = this.speed;
休息;
情況3:
this. x -= this.speed;
休息;
}

//邊界偵測
if (this.y 寬度|| this.y > 高度|| this.x clearInterval(this.timer);
this.isdead = true;
}

//碰撞偵測敵方偵測坦克
for (var i=0;ivar temp = allTank[i];
if(temp.isdead){
繼續;
}
switch ( temp.direct){
情況0:
情況2:if(this.x>temp.x && this.xtemp .y&& this.yif(this.color == temp.color){
break;
}
Bombs.push(new Bomb(temp.x-10,temp.y-10)) ;
clearInterval(this.timer);
this.isdead = true;
temp.isdead = true;
}打破
情況1:
情況3:if(this. x>temp.x && this.xtemp.y&& this.yif(this.color == temp.color){
break;
}
Bombs.push(new Bomb(temp.x-10,temp.y-10));
clearInterval(this.timer);
this.isdead = true;
temp.isdead = true;
}休息;
}
}

}

源碼下載
相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板