日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

js原生捕鱼达人(一)

發布時間:2024/6/21 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 js原生捕鱼达人(一) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

捕魚達人的游戲大家都很熟悉吧,接下來的兩三天,我會將整個游戲的原生js寫法詳細的寫出來,整個游戲應用了面向對象的寫法:創建構造函數,在構造函數上面添加對象的屬性,然后在構造函數的原型上添加方法,當然這個程序使用了canvas來繪制,每一步的我都已經分別寫出來,詳細的步驟我在寫代碼的過程中都已經標注了出來。

下面是捕魚達人的素材庫:

1》加載資源

<style>*{padding: 0;margin: 0;}body{background:#000;text-align:center;overflow:hidden;}#c1{background:url(img/game_bg_2_hd.jpg);margin:40px auto;}</style><script>var JSON={};function loadImage(arr,fnSucc){//為了測試是否加載完成,設置count,在加載的時候使count++,判斷count的值來判斷是否加載完成var count=0;for(var i=0;i<arr.length;i++){var oImg=new Image();//加載所有魚的資源(function(index){oImg.οnlοad=function(){//把所有資源加載,并且存到JSON中,注意,循環中有事件,事件里的i值不對,解決用封閉空間JSON[arr[index]]=this;count++;//當count的值和需要加載的資源的數組相同的時候,資源加載完畢if(count==arr.length){fnSucc && fnSucc();}};})(i);oImg.src='img/'+arr[i]+'.png';}}document.addEventListener('DOMContentLoaded',function(){var oC=document.getElementById('c1');var gd=oC.getContext('2d');var oImg=new Image();loadImage(['fish1','fish2','fish3','fish4','fish5'],function(){gd.drawImage(JSON['fish3'],0,0);})},false);</script> </head> <body><canvas id="c1" width="800" height="600"></canvas> </body>

  

2》拆文件 ? com(util.js).js? 工具函數文件 resource -> 資源文件 com.js文件 /** * Created by Jason on 2016/11/2. */ var JSON={}; function loadImage(arr,fnSucc){//為了測試是否加載完成,設置count,在加載的時候使count++,判斷count的值來判斷是否加載完成var count=0;for(var i=0;i<arr.length;i++){var oImg=new Image();//加載所有魚的資源(function(index){oImg.οnlοad=function(){//把所有資源加載,并且存到JSON中,注意,循環中有事件,事件里的i值不對,解決用封閉空間JSON[arr[index]]=this;count++;//當count的值和需要加載的資源的數組相同的時候,資源加載完畢if(count==arr.length){fnSucc && fnSucc();}};})(i);oImg.src='img/'+arr[i]+'.png';} }

  ?resource.js文件

/** * Created by Jason on 2016/11/2. */ //把所有資源放到一個resource的數組中,方便加載資源的函數loadImage調用 var resource=['fish1','fish2','fish3','fish4','fish5'];

  index.html

<style>*{padding: 0;margin: 0;}body{background:#000;text-align:center;overflow:hidden;}#c1{background:url(img/game_bg_2_hd.jpg);margin:40px auto;}</style><script src="js/resource.js"></script><script src="js/com.js"></script><script>document.addEventListener('DOMContentLoaded',function(){var oC=document.getElementById('c1');var gd=oC.getContext('2d');var oImg=new Image();loadImage(resource,function(){gd.drawImage(JSON['fish3'],0,0);})},false);</script> </head> <body><canvas id="c1" width="800" height="600"></canvas> </body>

  3》先畫一條魚(以下步驟js文件中未改變的都沒有提到,大家自己把代碼歸類存放,最后我會給出所有最終版的多有文件的全部代碼)

關于魚游動的角度的計算我也畫了圖

以下尺寸經過ps測量:

//魚
var FISH_SIZE=[
???? null,
???? {w: 55, h: 37, collR: 17},
???? {w: 78, h: 64, collR: 24},
???? {w: 72, h: 56, collR: 20},
???? {w: 77, h: 59, collR: 22},
???? {w: 107, h: 122, collR: 29}
];
--------------------------
炮臺尺寸:
寬度:765, 高度:70
距離畫布上方的距離是:532
--------------------------
炮的位置:
???? x=431;
???? y=570;
--------------------------
炮的尺寸:
//炮
var CANNON_SIZE=[
???? null,
???? {w: 74, h: 74},
???? {w: 74, h: 76},
???? {w: 74, h: 76},
???? {w: 74, h: 83},
???? {w: 74, h: 85},
???? {w: 74, h: 90},
???? {w: 74, h: 94}
];
-----------------------------
//炮彈具體尺寸
var BULLET_SIZE=[
???? null,
???? {x: 86, y: 0, w: 24, h: 26},
???? {x: 62, y: 0, w: 25, h: 29},
???? {x: 30, y: 0, w: 31, h: 35},
???? {x: 32, y: 35, w: 27, h: 31},
???? {x: 30, y: 82, w: 29, h: 33},
???? {x: 0, y: 82, w: 30, h: 34},
???? {x: 0, y: 0, w: 30, h: 44}
];

<script src="js/resource.js"></script><script src="js/com.js"></script><script>function d2a(n){return n*Math.PI/180;}//各種不同的魚的圖片的數據var FISH_SIZE=[null,{w: 55, h: 37, collR: 17},{w: 78, h: 64, collR: 24},{w: 72, h: 56, collR: 20},{w: 77, h: 59, collR: 22},{w: 107, h: 122, collR: 29}];//使用面向對象的思想創建對象的屬性和方法,屬性寫在構造函數中,方法放在原型上//先畫一條魚,魚的屬性有魚的種類type 位置x,y 游動時候尾巴運動cur 游動的方向rotate 游動的速度iSpeed 向前運動move 先創建魚的構造函數function Fish(type){this.type=type;this.x=0;this.y=0;this.cur=0;this.rotate=220;this.iSpeed=1;this.move();}//在添加魚的方法 畫魚draw 魚的運動moveFish.prototype.draw=function(gd){//魚的圖片的寬高,不同魚的不同寬高不相同,先把魚的寬高存入一個提前量好的數組FISH_SIZE中,再根據不同種類的魚來獲取不同的寬高var w=FISH_SIZE[this.type].w;var h=FISH_SIZE[this.type].h;//開始畫魚 注意畫魚先要save,結束以后restore 魚的出場時可以改變方向的,所以畫魚的時候注意提前準備好角度gd.save();gd.translate(this.x,this.y);gd.rotate(d2a(this.rotate));//魚是有陰影的,當魚從左面出來的時候,陰影是在魚的右下面,當魚從左面出來的時候,陰影是在魚的左下面,在旋轉完角度后魚可能從左面出來也可能從右面出來,當魚從右面出來的時候,需要scale圖片,使圖片翻轉來修正陰影的位置if(this.rotate>45 && this.rotate<270){gd.scale(1,-1);}//利用drawImage這個函數來畫魚,JSON['fish'+this.type]可以選擇不同種類的魚,注意魚的rotate是根據頭部的位置來改變的gd.drawImage(JSON['fish'+this.type],//使用this.cur 來變換魚的圖片的位置0,h*this.cur,w,h,-w/2,-h/2,w,h);gd.restore();};//魚的move的方法Fish.prototype.move=function(){//魚的運動分為向前游動和尾巴的擺動兩個運動//向前游動 向前游動是改變的魚的this.x 和 this.y 的值 不停的往前游動需要配合定時器的實現//注意事件中套定時器,定時器的this的指向不準確,解決辦法是 提前存儲一個正確的this_this=this;setInterval(function(){//將this.x this.y分解到斜線坐標上_this.x+=Math.cos(d2a(_this.rotate))*_this.iSpeed;_this.y+=Math.sin(d2a(_this.rotate))*_this.iSpeed;},30);//魚尾巴的擺動 魚尾巴的擺動是在不停的更換魚的圖片來實現的 相同的是定時器配合this.cur的加減setInterval(function(){//圖片的位置是改變魚的精靈圖上的魚的起始位置x y來實現 這里用這個cur的值來關聯這組坐標_this.cur++;//循環這組數字if(_this.cur==4){_this.cur=0;}},200);};document.addEventListener('DOMContentLoaded',function(){var oC=document.getElementById('c1');var gd=oC.getContext('2d');//調用面向對象方法中創造的魚,并在畫布上畫出魚loadImage(resource,function(){var f1=new Fish(5);//給出新創建出魚的出事位置f1.x=300;f1.y=300;//在畫魚的時候需要先清除一次畫布 同樣畫之前需要先保存,結束以后再存儲//使魚動起來需要不停的在畫布上擦除上衣畫的魚并且不停的創建新的魚,需要配合定時器來實現setInterval(function(){gd.clearRect(0,0,oC.width,oC.height);gd.save();//畫魚的方法在面向對象中都已經創建,在這直接使用就可以f1.draw(gd);gd.restore();},30);})},false);</script> </head> <body><canvas id="c1" width="800" height="600"></canvas> </body>

  4》畫炮臺 ?尺寸見3中的位置

document.addEventListener('DOMContentLoaded',function(){var oC=document.getElementById('c1');var gd=oC.getContext('2d');//開始畫炮臺 畫炮臺需要先加載資源,然后再畫,這里沒有使用面向對象的概念loadImage(resource,function(){gd.drawImage(JSON['bottom'],0,0,765,70,0,532,765,70)});

  5》畫炮,尺寸詳見3中的位置,代碼思路同畫魚

//炮var CANNON_SIZE=[null,{w: 74, h: 74},{w: 74, h: 76},{w: 74, h: 76},{w: 74, h: 83},{w: 74, h: 85},{w: 74, h: 90},{w: 74, h: 94}];//構建炮的構造函數 炮彈的屬性有位置x y type rotate 添加的同時注意在resource.js文件中添加需要加載的資源function Cannon(type){this.type=type;this.x=0;this.y=0;this.rotate=0;}//構建炮的原型,炮的原型上面有draw的方法Cannon.prototype.draw=function(gd){//和魚的原型相同,先要設置炮臺的尺寸w h,同樣的再2中的尺寸表中var w=CANNON_SIZE[this.type].w;var h=CANNON_SIZE[this.type].h;//開始畫炮臺,注意先save最后再restore,炮臺是可以旋轉的gd.save();gd.translate(this.x,this.y);gd.rotate(d2a(this.rotate));gd.drawImage(JSON['cannon'+this.type],0,0,w,h,-w/2,-h/2,w,h);gd.restore();};document.addEventListener('DOMContentLoaded',function(){var oC=document.getElementById('c1');var gd=oC.getContext('2d');//開始畫炮臺 畫炮臺需要先加載資源,然后再畫,這里沒有使用面向對象的概念loadImage(resource,function(){gd.drawImage(JSON['bottom'],0,0,765,70,0,532,765,70)//炮是在炮臺上的,可以在畫炮臺的時候一起畫出來var c=new Cannon(4);//設置炮的初始位置,初始位置在資源文件中已經寫明c.x=431;c.y=570;//調用炮的方法draw來畫炮gd.save();c.draw(gd);c.restore();});/* //調用面向對象方法中創造的魚,并在畫布上畫出魚loadImage(resource,function(){var f1=new Fish(1);//給出新創建出魚的出事位置f1.x=300;f1.y=300;//在畫魚的時候需要先清除一次畫布 同樣畫之前需要先保存,結束以后再存儲//使魚動起來需要不停的在畫布上擦除上衣畫的魚并且不停的創建新的魚,需要配合定時器來實現setInterval(function(){gd.clearRect(0,0,oC.width,oC.height);gd.save();//畫魚的方法在面向對象中都已經創建,在這直接使用就可以f1.draw(gd);gd.restore();},30);});*/},false);</script> </head> <body><canvas id="c1" width="800" height="600"></canvas>

  6》創建點擊畫布炮轉向的功能 ? 相同的再這一步完成之后,給炮單獨建立一個js文件存放到js文件夾下(cannon.js文件);并把a2d的函數放到com.js文件中

關于炮的旋轉角度的計算,請看我的圖,其中寫錯了一個,懶得改了大家應該能看懂

<script src="js/resource.js"></script><script src="js/com.js"></script><script src="js/fish.js"></script><script>function a2d(n){return n*180/Math.PI;}//炮var CANNON_SIZE=[null,{w: 74, h: 74},{w: 74, h: 76},{w: 74, h: 76},{w: 74, h: 83},{w: 74, h: 85},{w: 74, h: 90},{w: 74, h: 94}];//構建炮的構造函數 炮彈的屬性有位置x y type rotate 添加的同時注意在resource.js文件中添加需要加載的資源function Cannon(type){this.type=type;this.x=0;this.y=0;this.rotate=0;}//構建炮的原型,炮的原型上面有draw的方法Cannon.prototype.draw=function(gd){//和魚的原型相同,先要設置炮臺的尺寸w h,同樣的再2中的尺寸表中var w=CANNON_SIZE[this.type].w;var h=CANNON_SIZE[this.type].h;//開始畫炮臺,注意先save最后再restore,炮臺是可以旋轉的gd.save();gd.translate(this.x,this.y);gd.rotate(d2a(this.rotate));gd.drawImage(JSON['cannon'+this.type],0,0,w,h,-w/2,-h/2,w,h);gd.restore();};document.addEventListener('DOMContentLoaded',function(){var oC=document.getElementById('c1');var gd=oC.getContext('2d');//開始畫炮臺 畫炮臺需要先加載資源,然后再畫,這里沒有使用面向對象的概念loadImage(resource,function(){var c=new Cannon(4);//設置炮的初始位置,初始位置在資源文件中已經寫明c.x=431;c.y=570;setInterval(function(){//炮是在炮臺上的,可以在畫炮臺的時候一起畫出來,畫之前為了避免重繪,需要先清除畫布gd.save();gd.clearRect(0,0,oC.width,oC.height);gd.drawImage(JSON['bottom'],0,0,765,70,0,532,765,70);//調用炮的方法draw來畫炮 和魚的轉動相同,當點擊畫布的時候,炮需要跟隨鼠標的指向來轉動,這里在轉動的時候我們改改變炮的轉動角度,然后重新不停的刪除,再畫炮 這個效果思路和畫魚相同,需要配合定時器來實現c.draw(gd);gd.restore();},30);//當點擊畫布的時候炮的角度對著鼠標點擊的位置,并進行重繪oC.οnclick=function(ev){//這里需要梳理鼠標點擊的位置和炮旋轉角度之間的關系(附圖說明--炮的旋轉角度.png)var x=ev.clientX-oC.offsetLeft- c.x;var y= c.y-(ev.clientY+oC.offsetTop);//計算角度,注意角度的公式tan是臨邊比對邊,和數學公式的有所不同 Math.atan2(y,x);并且這里是弧度轉角度,需要在com.js中添加a2d的函數var d=90-a2d(Math.atan2(y,x));c.rotate=d;};});/* //調用面向對象方法中創造的魚,并在畫布上畫出魚loadImage(resource,function(){var f1=new Fish(1);//給出新創建出魚的出事位置f1.x=300;f1.y=300;//在畫魚的時候需要先清除一次畫布 同樣畫之前需要先保存,結束以后再存儲//使魚動起來需要不停的在畫布上擦除上衣畫的魚并且不停的創建新的魚,需要配合定時器來實現setInterval(function(){gd.clearRect(0,0,oC.width,oC.height);gd.save();//畫魚的方法在面向對象中都已經創建,在這直接使用就可以f1.draw(gd);gd.restore();},30);});*/},false);</script> </head> <body><canvas id="c1" width="800" height="600"></canvas> </body>

  7》構造炮彈 ? 思路和前面都是一樣一樣的 ? 注意構造函數中需要考慮的屬性 ?和 ?構造函數的原型上面的方法

<script src="js/resource.js"></script><script src="js/com.js"></script><script src="js/fish.js"></script><script src="js/cannon.js"></script><script>//開始構造炮彈//炮彈具體尺寸var BULLET_SIZE=[null,{x: 86, y: 0, w: 24, h: 26},{x: 62, y: 0, w: 25, h: 29},{x: 30, y: 0, w: 31, h: 35},{x: 32, y: 35, w: 27, h: 31},{x: 30, y: 82, w: 29, h: 33},{x: 0, y: 82, w: 30, h: 34},{x: 0, y: 0, w: 30, h: 44}];//炮彈的構造函數,同樣先在resource.js中加載炮彈的資源, 炮彈的屬性有 type 位置x y rotate iSpeed movefunction Bullet(type){this.type=type;this.x=0;this.y=0;this.rotate=0;this.iSpeed=1;this.move();}//暫時想到的炮彈原型上的方法有draw move ,先寫,后面出現其他的再補充Bullet.prototype.draw=function(gd){//同樣的炮彈的尺寸數據表中已經量好并且給出var w=BULLET_SIZE[this.type].w;var h=BULLET_SIZE[this.type].h;//這里與前面不同的是需要定義不同尺寸炮彈的起始位置,數據表中已經給出,直接獲取var x=BULLET_SIZE[this.type].x;var y=BULLET_SIZE[this.type].y;//開始畫炮彈,gd.save();gd.translate(this.x,this.y);gd.rotate(this.rotate);gd.drawImage(JSON['bullet'],x,y,w,h,-w/2,-h/2,w,h);gd.restore();};//添加炮彈move的方法,和fish運動的思路相同Bullet.prototype.move=function(){//開啟定時器不停的改變炮彈的位置并且重繪,同樣,注意事件中的定時器里的this有問題,需要提前存正確的this的指向var _this=this;setInterval(function(){//和魚的move有些不同的是炮彈的y軸的方向不同炮彈都是是向上射出的_this.x+=Math.sin(d2a(_this.rotate))*_this.iSpeed;_this.y-=Math.cos(d2a(_this.rotate))*_this.iSpeed;},30);};document.addEventListener('DOMContentLoaded',function(){var oC=document.getElementById('c1');var gd=oC.getContext('2d');//開始畫炮臺 畫炮臺需要先加載資源,然后再畫,這里沒有使用面向對象的概念loadImage(resource,function(){//設置炮的初始位置,初始位置在資源文件中已經寫明var c=new Cannon(4);c.x=431;c.y=570;//存放炮彈的數組var arrBullet=[];setInterval(function(){//炮是在炮臺上的,可以在畫炮臺的時候一起畫出來,畫之前為了避免重繪,需要先清除畫布/* gd.save();*/gd.clearRect(0,0,oC.width,oC.height);gd.drawImage(JSON['bottom'],0,0,765,70,0,532,765,70);//調用炮的方法draw來畫炮 和魚的轉動相同,當點擊畫布的時候,炮需要跟隨鼠標的指向來轉動,這里在轉動的時候我們改改變炮的轉動角度,然后重新不停的刪除,再畫炮 這個效果思路和畫魚相同,需要配合定時器來實現c.draw(gd);//將當次點擊所產生的炮彈畫出來for(var i=0;i<arrBullet.length;i++){arrBullet[i].draw(gd);}/*gd.restore();*/},30);//當點擊畫布的時候炮的角度對著鼠標點擊的位置,并進行重繪oC.οnclick=function(ev){//這里需要梳理鼠標點擊的位置和炮旋轉角度之間的關系(附圖說明--炮的旋轉角度.png)var x=ev.clientX-oC.offsetLeft- c.x;var y= c.y-(ev.clientY-oC.offsetTop);//計算角度,注意角度的公式tan是臨邊比對邊,和數學公式的有所不同 Math.atan2(y,x);并且這里是弧度轉角度,需要在com.js中添加a2d的函數var d=90-a2d(Math.atan2(y,x));c.rotate=d;//當點擊的時候生成炮彈,所以在點擊事件中添加炮彈var bullet=new Bullet(c.type);//炮彈的位置和旋轉角度和炮的位置和旋轉角度相同,bullet.x= c.x;bullet.y= c.y;bullet.rotate = c.rotate;//注意炮彈不能畫在這里,如果畫在這里會被畫炮和炮臺時所清空,當然潘丹并不是只畫一個,可以用一個數組來存儲所畫出來的炮彈,然后在炮旋轉重繪的時候同時添加炮彈,為了讓點擊事件和定時器都能用到這個數組,這個數組應該寫到事件和定時器的父級的變量空間中/*bullet.draw(gd);*///講當次點擊畫布所創建的炮彈存入arrBullet中arrBullet.push(bullet);};});/* //調用面向對象方法中創造的魚,并在畫布上畫出魚loadImage(resource,function(){var f1=new Fish(1);//給出新創建出魚的出事位置f1.x=300;f1.y=300;//在畫魚的時候需要先清除一次畫布 同樣畫之前需要先保存,結束以后再存儲//使魚動起來需要不停的在畫布上擦除上衣畫的魚并且不停的創建新的魚,需要配合定時器來實現setInterval(function(){gd.clearRect(0,0,oC.width,oC.height);gd.save();//畫魚的方法在面向對象中都已經創建,在這直接使用就可以f1.draw(gd);gd.restore();},30);});*/},false);</script> </head> <body><canvas id="c1" width="800" height="600"></canvas> </body>

  

其中炮彈中有個小bug,明天繼續寫

?

?

轉載請注明‘轉載于Jason齊齊的博客http://www.cnblogs.com/jasonwang2y60/’

轉載于:https://www.cnblogs.com/jasonwang2y60/p/6025101.html

總結

以上是生活随笔為你收集整理的js原生捕鱼达人(一)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。