亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

javascript 模擬坦克大戰游戲(html5版)附源碼下載

2019-11-20 20:51:16
字體:
來源:轉載
供稿:網友
一、總結關鍵點和遇到的問題

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功能,刪除指定元素
復制代碼 代碼如下:

//擴展 刪除指定元素
Array.prototype.deleteElement = function (obj) {
if (obj) {
for (var i = 0; i < this.length; i++) {
if (this[i] === obj) {
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

復制代碼 代碼如下:

<!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 () {
//畫布信息
width = document.getElementById ('Map').width;
height = document.getElementById ('Map').height;
ctx = document.getElementById ('Map').getContext ('2d');
//初始頁面
var starImg = new Image ();
starImg.src = "img/star.jpg";
starImg.onload = function () {
ctx.drawImage (starImg, 0, 0, width, height);
}

//鍵盤監聽 回車開始游戲
document.body.onkeydown = function () {
var keycode = event.keyCode;
switch (keycode) {
case 13:
//初始化參數
init ()
//刷新頁面
setInterval (draw, 30);
document.body.onkeydown = gameControl;
break;
}
}
}

function init () {
//玩家和電腦
hero = new Hero (100, 300, 0);
enemys = [];
for (var i = 0; i < 3; i++) {
enemys.push (new Enemy (100 + i * 50, 0, 2));
}
//合并數組
allTank = enemys.concat (hero);

//炸彈
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;//左
case 83:
hero.moveDown ();
break;//下
case 87:
hero.moveUp ();
break;//上
case 68:
hero.moveRight ();
break;//右
case 74:
hero.shot ();
break;
case 49:
hero.addLife ()
break;
}
}

//擴展 刪除指定元素
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>按下回車鍵開始游戲</p>

<p>按下1鍵增加生命,默認是1</p>

<p>剩余生命數 :<label id="life">1</label></p>

<div id="data">

</div>
</div>
</body>
</html>

2.Draw.js
復制代碼 代碼如下:

/**
* Created by Alane on 14-3-18.
*/

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

//畫炸彈
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(){
//檢測敵人子彈生死
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);
}
}
}
//檢測玩家子彈生死
var temp = hero.bulletsList;
for (var i = 0; i < temp.length; i++) {
var o = temp[i];
if(o.isdead){
temp.deleteElement(o);
}
}

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

Bomb.js
復制代碼 代碼如下:

/**
* 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
復制代碼 代碼如下:

/**
* Created by Alane on 14-3-7.
*/
/**
* direct 0 上
* 1 右
* 2 下
* 3 左
* @param x
* @param y
* @param direct
* @constructor
*/
//******************************************************************************************/
//坦克父類
function Tank (x, y, direct) {
this.speed = 2;

}
Tank.prototype.moveUp = function () {
//邊界檢測
if (this.y < 0) {
//換方向
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;

}

//變換方向
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)
}

//射擊子彈
Tank.prototype.shot = function () {
if(this.isdead){
return;
}
if (this.bulletsList.length < this.maxBulletSize) {
//新建子彈
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;
}
//放入彈夾
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 = 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;
}


//******************************************************************************************/
//敵人坦克
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;


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

//定時器,射擊
this.timer2 = setInterval ((function (context) {
return function () {
//射擊
Tank.prototype.shot.call (context);
}
}) (this), 2000);

//定時器,變換方向
this.timer3 = setInterval ((function (context) {
return function () {
//射擊
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
復制代碼 代碼如下:

/**
* 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;
//定時器,自行運動
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;
}

//邊界檢測
if (this.y < 0 || this.x > width || this.y > height || this.x < 0) {
clearInterval (this.timer);
this.isdead = true;
}

//碰撞檢測 檢測敵人坦克
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;
}
}

}

源碼下載

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美日韩性视频| 九九久久国产精品| 日韩在线观看你懂的| 成人网址在线观看| 国产偷亚洲偷欧美偷精品| 91精品国产91久久| 97精品久久久中文字幕免费| 免费不卡欧美自拍视频| 97超级碰在线看视频免费在线看| 亚洲欧美在线一区二区| 亚洲国产精品女人久久久| 国产一区二区三区视频免费| 国产伦精品一区二区三区精品视频| 久久久久久久国产| 国语自产精品视频在免费| 欧美在线影院在线视频| 亚洲精品一区久久久久久| 亚洲第一偷拍网| 亚洲国产成人精品女人久久久| 最新国产成人av网站网址麻豆| 国产小视频91| 亚洲色无码播放| 亚洲人成电影网站| 欧美大片在线看| 久久久久久91香蕉国产| 亚洲老板91色精品久久| 国外成人在线视频| 欧亚精品在线观看| 亚洲免费一级电影| 成人av色在线观看| 精品成人国产在线观看男人呻吟| 在线观看日韩欧美| 不卡毛片在线看| 国产精品一区二区三区久久久| 日韩的一区二区| 51久久精品夜色国产麻豆| 精品国内亚洲在观看18黄| 欧美资源在线观看| 欧美性高潮在线| 国产中文日韩欧美| 国产精品美女午夜av| 精品久久久国产精品999| 成人国产精品久久久| 日韩欧美极品在线观看| 亚洲精品av在线播放| 久久精品国产亚洲精品2020| 久久久免费av| 久久久亚洲网站| 日韩av电影在线免费播放| 亚洲黄在线观看| 国产日本欧美一区二区三区在线| 爽爽爽爽爽爽爽成人免费观看| 日韩欧美在线视频免费观看| 国产成人精品在线| 色播久久人人爽人人爽人人片视av| 日韩中文字幕在线视频播放| 一区二区国产精品视频| 91夜夜揉人人捏人人添红杏| 伊人久久大香线蕉av一区二区| 9.1国产丝袜在线观看| 亚洲国模精品一区| 欧美日韩亚洲网| 在线看国产精品| 国产成人亚洲综合青青| 精品久久国产精品| 亚洲福利在线看| 欧美激情免费在线| 高清视频欧美一级| 亚洲第一精品福利| 欧美在线视频在线播放完整版免费观看| 夜夜嗨av一区二区三区免费区| 中国china体内裑精亚洲片| 亚洲一区精品电影| 亚洲自拍偷拍福利| 国产一级揄自揄精品视频| 国产亚洲在线播放| 欧美一级黑人aaaaaaa做受| 亚洲午夜色婷婷在线| 久久久久久国产| 懂色av一区二区三区| 精品国产乱码久久久久久婷婷| 亚洲成av人片在线观看香蕉| 久久av在线播放| 国产精品女视频| 伊人一区二区三区久久精品| 亚洲欧美在线免费| 欧美在线一区二区三区四| 国产91在线播放九色快色| 国产精品一区二区三区免费视频| 久久国产加勒比精品无码| 欧美性在线观看| 亚洲男女性事视频| 欧美色videos| 国产+成+人+亚洲欧洲| 日韩av免费在线播放| 欧美成人剧情片在线观看| 日本一区二区在线播放| 久久综合伊人77777尤物| 国产精品视频自拍| www.亚洲免费视频| 亚洲成人动漫在线播放| 国产精品丝袜视频| 亚洲成人久久网| 国产精品综合久久久| 亚洲欧美日韩精品久久奇米色影视| 中文在线资源观看视频网站免费不卡| 中文字幕久热精品视频在线| 久久精品成人欧美大片古装| 57pao成人永久免费视频| 日韩精品在线影院| 亚洲精品国产精品国自产观看浪潮| 成人激情视频免费在线| 亚洲欧洲中文天堂| 国产精品美乳在线观看| 98精品国产高清在线xxxx天堂| 91av网站在线播放| 日韩经典一区二区三区| 欧美性xxxx极品高清hd直播| 97国产成人精品视频| 日韩中文字幕国产| 欧美日韩国产一区在线| 欧美亚洲国产视频| 黑人极品videos精品欧美裸| 成人xvideos免费视频| 成人激情电影一区二区| 亚洲国产精品va在线看黑人动漫| 91精品视频大全| 中文字幕成人在线| 精品一区二区三区四区| 日韩电影在线观看永久视频免费网站| 午夜精品免费视频| 亚洲一级黄色av| 欧美性猛交视频| 日本精品视频在线播放| 97人洗澡人人免费公开视频碰碰碰| 九九热这里只有精品免费看| 97成人超碰免| 国产免费一区二区三区在线能观看| 色综合久久88| 国产在线精品自拍| 国产成人一区二区三区小说| 国产婷婷97碰碰久久人人蜜臀| 国产亚洲精品美女久久久久| 精品久久香蕉国产线看观看gif| 欧美日韩激情小视频| 久久久久久久久久久久久久久久久久av| 久久久久久久影视| 久久久久北条麻妃免费看| 久99久在线视频| 97超级碰碰人国产在线观看| 国产91色在线|免| 亚洲综合在线做性| 17婷婷久久www| 亚洲999一在线观看www| 亚洲欧美日韩精品久久| 国产97在线亚洲| 欧美日韩国产精品专区| 97在线视频免费| 亚洲精品国产suv| 日韩在线精品视频| 国产精品自产拍在线观看| 91亚洲精品在线观看| 免费91麻豆精品国产自产在线观看| 久热精品视频在线观看|