自從上次發布一個小恐龍游戲以后,到現在10天了,前后又寫了3個游戲,挑了一個感覺比較有挑戰的游戲和大家分享一下。

這是我模擬一個蘋果游戲《stick hero》游戲寫的一個小游戲,在這里記錄一下,希望大家會喜歡。
一直按下鼠標,會出一根棍子,棍子會變長,小人會根據棍子長度來移動。判斷小人是否停留在柱子上,因為放在網上以后,鼠標判斷有點卡,請大家見諒。
那我們還是從頭開始介紹一下這游戲的開發過程吧。
這次的圖片加載器是用的《H5手把手教你瑪麗游戲》的圖片加載器,個人感覺非常好用,可能是我沒接觸更好的圖片加載器,大神都是用自己框架寫的,感覺研究起來我很吃力,基礎跟不上,最近一個大哥叫我去研究OOP思想來編寫框架開發游戲,這也是我以后的方向,很感謝這位大哥給我的指導。
function loadImg(imgCount,callback){ var img = {}, total = imgCount.length, loaded = 0; for(var i = 0;i < total;i++){ var imgs = img[imgCount[i].id] = new Image(); imgs.src = imgCount[i].src; imgs.onload = function(){ loaded++; }; } if(typeof callback == "function"){ function check(){ if(loaded >= total) callback(); else setTimeout(check,300); } check(); } return img; }
調用的方式和我上次那個差不多,也是傳id和src,和回調函數,確保圖片加載完以后執行。
var imgs = null, game = null; function init(){ imgs = loadImg([ {id:"bg",src:"img/bg2.png"}, {id:"player",src:"img/player.png"} ],start); } init(); function start(){ game = new Game({ width:500, height:600, FPS:30, }); game.init(); game.move(); }
這次比較復雜的是存在着精靈,精靈存在動畫,所以加了2個類,Sprite和Animation,在這個游戲中,我把柱子也當做精靈處理,因為每次的柱子他的寬度和初始位置是隨機的,而且在檢測人物是否站在柱子上的時候比較好檢測。
function Sprite(option){ for(var attr in option){ this[attr] = option[attr]; } } Sprite.prototype = { constructor:Sprite, x:0, y:340, w:0, h:0, maxX:999, maxY:999, animation:null, accX:0, accY:0, init:function(){ if(this.animation){ this.animation.init(); this.animation.setNow(0); } }, //每次更變人物的移動動畫,讓人物動起來。 update:function(sleep,long){ this.x += this.accX; this.animation.update(sleep); if(this.x >= long+40){ this.x = long+40; this.animation.setNow(0); this.checkCollide(); } }, //人物的繪制 draw:function(ct){ this.animation.draw(ct,this.x,this.y); }, //矩形的繪制 drawRect:function(ct){ ct.fillRect(this.x,this.y,this.w,this.h); }, //檢測人物是否在柱子上 checkCollide:function(){ var Px1 = this.x; var Px2 = this.x + 40; var Rx1 = game.colRect.x; var Rx2 = game.colRect.x + game.colRect.w ; if(Px1 > Rx2 || Px2 < Rx1){ this.y += this.accY; if(this.y >= this.maxY){ clearInterval(game.mainLoop); alert("挑戰失敗! "); } }else{ game.initStart(); } } };
下面是生成人物和柱子的代碼,通過參數可以區分他們。
function createPlayer(){ var config = { //人物走路速度 accX:4, //人物掉落速度 accY:7, //人物初始位置 x:0, y:340, maxY:600, //人物移動過程 animation:new Animation({ frame:[ {x:20,y:0,w:80,h:80,action:100}, {x:120,y:0,w:80,h:80,action:100}, {x:220,y:0,w:80,h:80,action:100}, {x:320,y:0,w:80,h:80,action:100}, ] }) }; return new Sprite(config); }
function createRect(){ var config = { //每次隨機獲取寬度和x位置,這樣讓游戲更有挑戰 w:(Math.random()*40 + 20)|0, x:(Math.random()*300+150)|0, y:400, h:200, }; return new Sprite(config); }
下面介紹的是人物的移動,通過組圖的不斷更換,讓人物動起來。
function Animation(option){ for(var attr in option){ this[attr] = option[attr]; } } Animation.prototype = { constructor:Animation, img:null, //移動過程 frame:null, //動作的索引值 index:null, //一個動作的進行時間 time:null, //當前為多少幀 frameNow:null, len:-1, init:function(){ this.img = imgs["player"]||null; this.frame = this.frame||[]; this.len = this.frame.length - 1; this.index = 0; this.setNow(this.index); }, setNow:function(index){ this.index = index; this.frameNow = this.frame[this.index]; }, //action為每個動作進行多長時間(前面傳過來) update:function(sleep){ if(this.time >= this.frameNow.action){ this.time = 0; if(this.index >= this.len){ this.index = 0; }else{ this.index++; } this.setNow(this.index); }else{ this.time += sleep; } }, //人物的繪制 draw:function(ct,x,y){ var f = this.frameNow; ct.drawImage(this.img,f.x,f.y,f.w,f.h,x,y,60,60); } };
這個類里面一個主循環控制着我們所有移動的進行,這里我分步來說一下我遇到的問題。
1.如何實現一個柱子倒下的過程,開始我的想法是畫一個矩形,然后通過rotate來實現傾斜,因為以前沒有用過rotate方法,進入嘗試了一次,才知道他的傾斜是將整個畫布傾斜,這樣連背景一起傾斜,根本無法達到效果,然后通過在紙上畫了一下,用數學知識解決了這個問題,我把矩形換成換線,改變他的lineWidth讓他看起來像一個矩形。
stick:function(){ //當鼠標按下以后執行,並且在棍子移動時不會再次觸發。 if(this.moused && !this.clicked){ this.time += this.sleep; //讓棍子垂直向上伸展,通過循環讓他的長度累加 this.drawStick(this.time); }else if(!this.moused && this.long > 0){ //當鼠標松開(mouseup)以后,讓棍子倒下去 this.clicked = true; this.length = this.stickY - this.long; this.fallRect(this.length); } }, //棍子向上伸展 drawStick:function(time){ this.time = time; this.long += (time/200)|0; this.ct.beginPath(); this.ct.lineWidth = 5; this.ct.moveTo(this.stickX,this.stickY); this.ct.lineTo(this.stickX,this.stickY - this.long); this.ct.stroke(); }, //棍子向下掉落,記錄下棍子的長度,就是人物行走的距離 fallRect:function(length){ this.length = length; if(this.angle < 30){ this.angle += this.sleep/50; this.ct.beginPath(); this.lineWidth = 5; this.ct.moveTo(this.stickX,this.stickY); var hudu = (2*Math.PI / 360) * 3 * this.angle; this.fallX = this.stickX + this.long*Math.sin(hudu); this.fallY = this.stickY - this.long*Math.cos(hudu); if(this.fallY >= this.stickY){ this.fallY = this.stickY; } this.ct.lineTo(this.fallX,this.fallY); this.ct.stroke(); }else{ this.ct.beginPath(); this.lineWidth = 5; this.ct.moveTo(this.stickX,this.stickY); this.ct.lineTo(this.fallX,this.fallY); this.ct.stroke(); this.success = true; } },
2.當我以為這個游戲已經結束的時候出現了一個bug,就是每次棍子的繪制路徑都被保留下來了,這是我canvas控制能力不足,每次繪制之前加一個beginPath就好了。
在這里,感謝幫助我的每一個人,以后我也會成為大牛,寫更多更好的博文,盡自己的力量去幫助更多人。
最近在實驗室學習,突然很想回家了,畢竟好久沒看見家人了,還有10天就能回家了,心里還是很高興。
只有半年的時間就要去找工作了,有時間都去研究JS,感覺JS真是非常強大,我現在的水平想開發框架還是太難了,不過慢慢來吧,欲速則不達,一步一步積累終有一天我能自己開發框架。
謝謝大家,如有什么疑問或者建議請留言。
