當前位置:
首頁 >
前端技术
> javascript
>内容正文
javascript
用canvas,javascript制作“坦克大战“小游戏
生活随笔
收集整理的這篇文章主要介紹了
用canvas,javascript制作“坦克大战“小游戏
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
游戲截圖
這個是游戲做出來的效果:
用到的圖片資源:
這里把所有的坦克動畫所需的圖片,地形圖片等放在了一張圖中,使用的時候就可以通過截取一部分來使用。
游戲代碼
下面就是整個游戲目前的代碼,有什么建議或者不懂的可以評論,反正我現在也正好在學html的canvas和javascript。
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>坦克大戰</title> <script src="modernizr.js"></script> <script type="text/javascript"> //當網頁加載完畢后運行js代碼 window.addEventListener('load', eventWindowLoaded, false); //運行canvasApp()函數 function eventWindowLoaded() {canvasApp(); } function canvasSupport () {return Modernizr.canvas; } function canvasApp(){if (!canvasSupport()) {return;}else{var theCanvas = document.getElementById('canvas'); //將變量theCanvas與畫布綁定var context = theCanvas.getContext('2d'); //將變量context作為畫布內容}var tileSheet=new Image(); //創建圖片對象tileSheet.addEventListener('load', eventSheetLoaded , false);tileSheet.src="tanks_sheet.png";//地圖屬性var mapRows=10;var mapCols=10;var tileMap=[[32,31,31,31,1,31,31,31,31,32],[1,1,1,1,1,1,1,1,1,1],[32,1,1,26,1,1,1,26,1,32],[32,1,26,26,26,1,26,26,1,32],[32,1,1,26,1,1,1,1,1,32],[32,1,1,1,1,1,26,26,1,32],[32,1,26,1,26,1,26,1,1,32],[1,1,26,1,26,1,1,1,1,1],[32,1,1,1,1,1,1,1,1,32],[32,31,31,31,1,31,31,31,31,32]];//與坦克動畫相關var animationFrames=[1,2,3,4,5,6,7,8]; //用來存儲坦克移動動畫的8張圖片的下標var frameIndex=0;//與坦克屬性有關,包括坐標,方向,是否移動var x=0; //當前x坐標var y=32; //當前y坐標var dx=4; //x方向上的移動速度var dy=0; //y方向上的移動速度var count=0; //用于記錄坦克動畫執行的次數,到8后會清0,0代表著未執行動畫,即沒有移動var rotation=90; //旋轉角度var moveflag=false; //是否移動var live=1;var win=false;//敵方坦克的屬性var tanks=[]; //用于存儲所有敵方坦克function Tanks(x,y){this.x=x;this.y=y;this.xspeed=0;this.yspeed=-4;this.count=0;this.rotation=0;this.moveflag=false; //移動指令,為false時可以移動this.frameIndex=0; //動畫幀}tanks[0]=new Tanks(32,256);tanks[1]=new Tanks(224,256);//與子彈動畫相關var bullets=[]; //用于存儲子彈對象的數組//與子彈屬性有關,如子彈的方向,飛行速度function Bullet(rotation,x,y,xspeed,yspeed,checkFlag){this.rotation=rotation;this.x=x;this.y=y;this.xspeed=xspeed;this.yspeed=yspeed;this.checkFlag=checkFlag; //子彈是否碰撞的標志}//與爆炸動畫有關var booms=[];//爆炸點的屬性,主要是坐標值,爆炸動畫由三張圖片組成,需要記錄當前幀播放的是哪張圖片function Boom(x,y){this.x=x;this.y=y;this.nowpic=1;}//與游戲結束相關var gameover=false; //游戲結束的標志var tt; //運行動畫的函數function eventSheetLoaded() {drawScreen();}function drawScreen() {//繪制背景context.fillStyle="#aaaaaa";context.fillRect(0,0,320,320);//繪制地圖for(var rowCtr=0;rowCtr<mapRows;rowCtr++) { for(var colCtr=0;colCtr<mapCols;colCtr++){ var tileId = tileMap[rowCtr][colCtr]-1;var sourceX = Math.floor(tileId % 8) *32;var sourceY = Math.floor(tileId / 8) *32;context.drawImage(tileSheet, sourceX,sourceY,32,32,colCtr*32,rowCtr*32,32,32);} }//玩家的坦克動畫if(moveflag==true){ //如果moveflag==true,則進行移動x=x+dx;y=y+dy;count++; //每一步,count加1frameIndex++; // 調用下一張圖片if (frameIndex ==animationFrames.length) {frameIndex=0; //下標清零,重新開始播放動畫}}if(count==8){ //當count==8時,一次移動完畢,即移動了32pxcount=0; //將count清零moveflag=false; //令moveflag=false,停止移動}context.save(); //保存當前變換狀態context.translate(x+16,y+16); //平移原點坐標context.rotate(rotation * Math.PI / 180); //旋轉整個坐標系var sourceX=Math.floor(animationFrames[frameIndex] % 8) *32;var sourceY=Math.floor(animationFrames[frameIndex] / 8) *32;context.drawImage(tileSheet, sourceX, sourceY,32,32,-16,-16,32,32);context.restore(); //讀取保存的變換狀態//敵方坦克動畫var tankslength=tanks.length;for(var i=0;i<tankslength;i++){//敵方坦克檢測到十字方向上有玩家坦克時,瞄準玩家開火if(tanks[i].count==0){tanksAttack(i);}//敵方坦克進行隨機移動if(tanks[i].moveflag==true){tanks[i].x+=tanks[i].xspeed;tanks[i].y+=tanks[i].yspeed;tanks[i].count++;tanks[i].frameIndex++;if(tanks[i].frameIndex==animationFrames.length){tanks[i].frameIndex=0;}}else{tanksChange(i);}if(tanks[i].count==8){tanks[i].count=0;tanks[i].moveflag=false;}context.save();context.translate(tanks[i].x+16,tanks[i].y+16);context.rotate(tanks[i].rotation*Math.PI/180);sourceX=Math.floor(animationFrames[tanks[i].frameIndex]%8)*32;sourceY=Math.floor(animationFrames[tanks[i].frameIndex]/8+1)*32;context.drawImage(tileSheet,sourceX,sourceY,32,32,-16,-16,32,32);context.restore();}//子彈飛行動畫var bulletCount=bullets.length;for(var i=0;i<bulletCount;i++){//檢測子彈碰撞的效果checkChase(i,bullets[i].x,bullets[i].y);//繪制子彈if(bullets[i].checkFlag==false){context.save();context.translate(bullets[i].x+16,bullets[i].y+16);context.rotate(bullets[i].rotation*Math.PI/180);context.drawImage(tileSheet,128,64,32,32,-16,-16,32,32);context.restore();//子彈前進bullets[i].x+=bullets[i].xspeed;bullets[i].y+=bullets[i].yspeed;}else{createBoom(bullets[i].rotation,bullets[i].x,bullets[i].y); //產生一個爆炸動畫對象}}for(var i=0;i<bulletCount;i++){if(bullets[i].checkFlag==true){bullets.splice(i,1); //將該子彈對象從數組中移除并重排數組i--;bulletCount--;}}//子彈爆炸動畫var boomCount=booms.length;for(var i=0;i<boomCount;i++){context.save();context.translate(booms[i].x,booms[i].y);context.drawImage(tileSheet,32*booms[i].nowpic,64,32,32,0,0,32,32);context.restore();booms[i].nowpic++;}for(var i=0;i<boomCount;i++){if(booms[i].nowpic==4){booms.splice(i,1);i--;boomCount--;}}if(live==0||tanks.length==0){gameover=true;if(live==0){win=false;}if(tanks.length==0){win=true;}}if(gameover==true){clearInterval(tt);if(win==false)alert("你輸了");elsealert("你贏了");window.location=window.location;}}//鍵盤監聽事件,用于改變玩家坦克的方向,同時修改坦克的一些數值function changeDirection(e){if(count==0){ //count==0代表著坦克的前一個動作執行完畢 var xindex=x/32;var yindex=y/32;switch(e.keyCode){case 37:if(tileMap[yindex][xindex-1]==1){moveflag=true;rotation=-90;dx=-4;dy=0;}else if(tileMap[yindex][xindex-1]==undefined){moveflag=true;rotation=-90;x=320;dx=-4;dy=0;}break;case 38:if(yindex-1==-1){moveflag=true;rotation=0;y=320;dx=0;dy=-4;}else if(tileMap[yindex-1][xindex]==1){moveflag=true;rotation=0;dx=0;dy=-4;}break;case 39:if(tileMap[yindex][xindex+1]==1){moveflag=true;rotation=90;dx=4;dy=0;}else if(tileMap[yindex][xindex+1]==undefined){moveflag=true;rotation=90;x=0;dx=4;dy=0;}break;case 40:if(yindex+1==10){moveflag=true;rotation=180;y=0;dx=0;dy=4;}else if(tileMap[yindex+1][xindex]==1){moveflag=true;rotation=180;dx=0;dy=4;}}}}//改變敵方坦克移動方向的函數function tanksChange(i){var randMath=Math.floor(Math.random()*4-1);var xindex=tanks[i].x/32;var yindex=tanks[i].y/32;switch(randMath){case -1:if(tileMap[yindex][xindex-1]==1){tanks[i].moveflag=true;tanks[i].rotation=-90;tanks[i].xspeed=-4;tanks[i].yspeed=0;}else if(tileMap[yindex][xindex-1]==undefined){tanks[i].moveflag=true;tanks[i].rotation=-90;tanks[i].x=320;tanks[i].xspeed=-4;tanks[i].yspeed=0;}break;case 0:if(yindex-1==-1){tanks[i].moveflag=true;tanks[i].rotation=0;tanks[i].y=320;tanks[i].xspeed=0;tanks[i].yspeed=-4;}else if(tileMap[yindex-1][xindex]==1){tanks[i].moveflag=true;tanks[i].rotation=0;tanks[i].xspeed=0;tanks[i].yspeed=-4;}break;case 1:if(tileMap[yindex][xindex+1]==1){tanks[i].moveflag=true;tanks[i].rotation=90;tanks[i].xspeed=4;tanks[i].yspeed=0;}else if(tileMap[yindex][xindex+1]==undefined){tanks[i].moveflag=true;tanks[i].rotation=90;tanks[i].x=0;tanks[i].xspeed=4;tanks[i].yspeed=0;}break;case 2:if(yindex+1==10){tanks[i].moveflag=true;tanks[i].rotation=180;tanks[i].y=0;tanks[i].xspeed=0;tanks[i].yspeed=4;}else if(tileMap[yindex+1][xindex]==1){tanks[i].moveflag=true;tanks[i].rotation=180;tanks[i].xspeed=0;tanks[i].yspeed=4;}}}//鍵盤監聽事件,用于產生子彈,根據坦克當前方向和位置,產生子彈的方向,坐標,以及速度var time=0;function createBullet(e){if(count==0&&time==0){var newBullet;if(e.keyCode==32){switch(rotation){case -90:newBullet=new Bullet(-90,x-32,y,-32,0,false);break;case 0:newBullet=new Bullet(0,x,y-32,0,-32,false);break;case 90:newBullet=new Bullet(90,x+32,y,32,0,false);break;case 180:newBullet=new Bullet(180,x,y+32,0,32,false);}bullets.push(newBullet);time=1;setTimeout(retime,400); //設置延時是為了不讓子彈快速連發,快速連發會破壞游戲體驗function retime(){time=0;}}}}//敵方坦克檢測十字方向上是否有玩家坦克,若有,則開火function tanksAttack(i){if(tanks[i].x==x&&!checkBlocky(i)){if(tanks[i].y>y){bullets.push(new Bullet(0,tanks[i].x,tanks[i].y-32,0,-32,false));}if(tanks[i].y<y){bullets.push(new Bullet(180,tanks[i].x,tanks[i].y+32,0,32,false));}}if(tanks[i].y==y&&!checkBlockx(i)){if(tanks[i].x>x){bullets.push(new Bullet(-90,tanks[i].x-32,tanks[i].y,-32,0,false));}if(tanks[i].x<x){bullets.push(new Bullet(90,tanks[i].x+32,tanks[i].y,32,0,false));}}function checkBlocky(i){var y1=Math.min(Math.floor(y/32),tanks[i].y/32);var y2=Math.max(Math.floor(y/32),tanks[i].y/32);var x_=tanks[i].x/32;for(var i=y1;i<y2;i++){if(tileMap[i][x_]!=1){return true;}}return false;}function checkBlockx(i){var x1=Math.min(Math.floor(x/32),tanks[i].x/32);var x2=Math.max(Math.floor(x/32),tanks[i].x/32);var y_=tanks[i].y/32;for(var i=x1;i<x2;i++){if(tileMap[y_][i]!=1){return true;}}return false;}}//根據地圖數組來檢測子彈的碰撞,若子彈所在格子不為1,將播放子彈爆炸效果function checkChase(a,b,c){if(c/32>0&&c/32<9){if(tileMap[c/32][b/32]!=1){bullets[a].checkFlag=true;}else if(x-16<=b&&b<=x+16&&y-16<=c&&c<=y+16){bullets[a].checkFlag=true;live=false;}else if(attackTanks(b,c)==true){bullets[a].checkFlag=true;}}else{bullets[a].checkFlag=true;}}//判定子彈是否打中了敵方坦克function attackTanks(b,c){var aa=tanks.length;for(var i=0;i<aa;i++){if(tanks[i].x-16<=b&&b<=tanks[i].x+16&&tanks[i].y-16<=c&&c<=tanks[i].y+16){tanks.splice(i,1);return true;}}}//產生一個爆炸動畫,并根據子彈方向調整爆炸動畫的坐標function createBoom(a,b,c){var newBoom;switch(a){case -90:newBoom=new Boom(b+16,c);break;case 0:newBoom=new Boom(b,c+16);break;case 90:newBoom=new Boom(b-16,c);break;case 180:newBoom=new Boom(b,c-16);}booms.push(newBoom);}//開始游戲按鈕點擊事件var button=document.getElementById("start"); //將參數button與id="start"的按鈕綁定button.addEventListener("click",startgame); //按鈕點擊事件//開始游戲var tt; //用于保存播放動畫函數,在游戲結束時需要刪除動畫(即clearInterval(tt)),才能刷新頁面function startgame(){button.style.visibility="hidden"; //將開始游戲按鈕隱藏document.getElementById("mask").style.visibility="hidden";tt=setInterval(drawScreen, 50);window.addEventListener("keydown",changeDirection,true); //添加鍵盤監聽事件(鍵盤按下)——用于改變坦克運動方向window.addEventListener("keyup",createBullet,true); //添加鍵盤監聽事件(鍵盤松開)——用于產生子彈} }</script> </head> <body> <div style="position: absolute; top: 50px; left: 50px;"> <canvas id="canvas" width="320" height="320">Your browser does not support the HTML 5 Canvas. </canvas> <div id="mask" style="position:absolute;top:0;left:0;background-color:black;opacity:0.4;"><table width="320" height="320"></table> </div> <button id="start" style="position:absolute;left:80px;top:150px;width:150px;height:40px;">開始游戲</button> </div><span style="position:absolute;left:50px;top:400px;color:blue">使用上下左右方向鍵移動,空格鍵開火</span> </body> </html>總結
以上是生活随笔為你收集整理的用canvas,javascript制作“坦克大战“小游戏的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【java】---坦克大战
- 下一篇: 语雀:如何打造 Serverless J