H5游戲開發之Stick Hero


   自從上次發布一個小恐龍游戲以后,到現在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;
}
View Code

調用的方式和我上次那個差不多,也是傳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();
        }
    }
};
View Code

 

 下面是生成人物和柱子的代碼,通過參數可以區分他們。

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);
    }
    
};
View Code
游戲類

這個類里面一個主循環控制着我們所有移動的進行,這里我分步來說一下我遇到的問題。

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;
        }
    },
View Code

 2.當我以為這個游戲已經結束的時候出現了一個bug,就是每次棍子的繪制路徑都被保留下來了,這是我canvas控制能力不足,每次繪制之前加一個beginPath就好了。

結束語

在這里,感謝幫助我的每一個人,以后我也會成為大牛,寫更多更好的博文,盡自己的力量去幫助更多人。

最近在實驗室學習,突然很想回家了,畢竟好久沒看見家人了,還有10天就能回家了,心里還是很高興。

只有半年的時間就要去找工作了,有時間都去研究JS,感覺JS真是非常強大,我現在的水平想開發框架還是太難了,不過慢慢來吧,欲速則不達,一步一步積累終有一天我能自己開發框架。

謝謝大家,如有什么疑問或者建議請留言。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM