想用React寫遊戲第一天:構造與繼承

遊戲編程模式

《game programming patterns》 這是一本講設計模式在遊戲中的應用的書,我以爲做者講得很好,有興趣的小夥伴能夠去看看原著。若是懂得編碼的快樂的話,你必定會樂在其中的。這也是原著裏我很喜歡的一句話: if you want to make something fun, have fun making it. (若是你想作出讓人享受的東西,那就享受作它的過程)前端

我接下來的文章也會圍繞這本書展開,使用React+JavaScript實現一些這本書上的簡單例子。 好了,立刻開始吧。git

第一天:構造與繼承

1.構造

在學習遊戲設計模式以前,有必要先了解一下繼承github

MilK:你能不能用鍵盤控制DIV移動。編程

丁丁:簡單。設計模式

一天後...markdown

丁丁:作完了。函數

MilK:效果不錯,你能不能多加幾個這樣的DIV。oop

丁丁:簡單,複製出來就行了。性能

MilK:複製?那你也太撈了。試試用構造的方式寫吧。學習

丁丁:好吧,我想一想...

單元(unit)是遊戲中最簡單也是最重要的一部分,想要高效的生成各類各樣的元素,確定離不單元的開構造與繼承。

來一個簡單的構造函數:

function CreateUnit (){
    this.width = 100;//寬度
    this.height = 100;//高度
    this.left = 100;//X座標
    this.top = 100;//Y座標
    this.v = 100;//移動速度
    this.move = function (left,top) {//移動到某個座標
        this.left = left;
        this.top = top;
    }
}
複製代碼

而後把這個單元new出來

unit = new CreateUnit();
複製代碼

輸出結果:

unit->CreateUnit {
    width: 100,
    height: 100,
    left: 100,
    top: 100,
    v: 100,
    move: ƒ (left, top),
    __proto__: Object
}
複製代碼

而後把屬性賦予給DIV:(這裏是REACT的寫法,若是不用React的話能夠用createElement或getElementById,我我的以爲React更方便)

<div
    style = {{
        border:"1px black solid",
        width:this.nuit.width,
        height:this.nuit.height,
        left:this.nuit.left-this.nuit.width/2,
        top:this.nuit.top-this.nuit.height/2,
        position:"absolute",
    }}
/>
複製代碼

這樣就能看到一個長100px寬100px的框框浮動在頁面上了

2.繼承

咱們對這個構造函數稍加修改,讓它能夠附上初值:

function CreateUnit (unit){
    this.width = unit.width||100;//寬度
    this.height = unit.height||100;//高度
    this.left = unit.left||100;//X座標
    this.top = unit.top||100;//Y座標
    this.v = unit.v||100;//移動速度
    this.move = function (left,top) {//移動函數
        this.left = left;
        this.top = top;
    }
}
複製代碼

不過這個最簡單的確定不夠,咱們不妨再定義一個Boy的構造函數,繼承這個unit:

function Boy (boy){
    this.name = boy.name||"boy";//名字
}
Boy.prototype = new CreateUnit({});
複製代碼

就是這麼簡單,一個最基本的繼承關係就實現了,Boy會具備本身的名字,和繼承來的unit屬性(有關於prototype的基礎能夠去百度找到更詳細的教學)

如今再構造出一個Boy看看:

boy = new Boy({
    name: "小明"
});
複製代碼

輸出結果:

boy->Boy{
    name: "小明",
    __proto__: CreateUnit {
        width: 100,
        height: 100,
        left: 100,
        top: 100,
        v: 100,
        move: ƒ (left, top),
        __proto__: Object
    }
}
複製代碼

這裏的__proto__指的是父類繼承來的屬性,調用父類的值不須要輸入__proto__,本身沒有的屬性js就會自動去父類中找(知識點:原型模式,劃重點,要考):

console.log(unit.width);//100,本身的屬性
console.log(boy.name);//小明,本身的屬性
console.log(boy.width);//100,繼承來的屬性
複製代碼

繼承實現了,是時候批開始量生產了:

boyList=[
    new Boy({name:"小王"}),
    new Boy({name:"小北"}),
    new Boy({name:"小清"}),
    new Boy({name:"小狗"})
];
複製代碼

render 函數中顯示:

{
    this.boyList.map((item,i)=>{
        return <div
            key = {i}
            style = {{
                border:"1px black solid",
                width:item.width,
                height:item.height,
                left:item.left-item.width/2,
                top:item.top-item.height/2,
                position:"absolute",
                textAlign:"center",
                lineHeight:item.height+"px"
            }}
        >
            {item.name}
        </div>
    })
}
複製代碼

效果:

能夠看到4個Boy的名字重疊出如今了頁面上,批量生產大功告成~

3.角色移動

接下來就須要控制咱們的角色移動了:

this.boy.move(200,100);//把小明移動到200,100的位置
複製代碼

看看效果:

還能夠吧~接下來結合鍵盤的操做:

boyList = [new Boy({name:"小王"}),new Boy({name:"小北"}),new Boy({name:"小清"}),new Boy({name:"小狗"}),];
boy = new Boy({name:"小明"});
focus = this.boy;//焦點,鍵盤只控制焦點上的角色,初始值設爲小明

/**
 * REACT生命週期函數,組件渲染後調用
 */
componentDidMount(){
    //添加鍵盤監聽
    document.addEventListener("keydown", this.onKeyDown);
}

/**
 * REACT生命週期函數,組件銷燬前調用
 */
componentWillUnmount(){
    //鍵盤監聽結束
    document.removeEventListener("keydown", this.onKeyDown);
}

/**
 * 鍵盤監聽事件
 * @param e
 */
onKeyDown = (e) => {
    console.log(e.keyCode);
    switch(e.keyCode) {
        case 39://向右移動
            this.focus.move(this.focus.left+this.focus.v,this.focus.top);//焦點向右移動
            this.setState({});//從新渲染頁面
            break;
        case 37://向左移動
            this.focus.move(this.focus.left-this.focus.v,this.focus.top);
            this.setState({});
            break;
        case 38://向上移動
            this.focus.move(this.focus.left,this.focus.top-this.focus.v);
            this.setState({});
            break;
        case 40://向下移動
            this.focus.move(this.focus.left,this.focus.top+this.focus.v);
            this.setState({});
            break;
        default:
            break
    }
};

/**
 * 設置焦點
 */
setFocus = (util) => {
    this.focus=util;
};

/**
 * REACT生命週期主函數,用於渲染頁面
 * @returns {*}
 */
render() {
    return (
        <div className = {"game1"}>
            <div
                onClick = {onClick}
                style = {{
                    border:"1px black solid",
                    width:this.boy.width,
                    height:this.boy.height,
                    left:this.boy.left-this.boy.width/2,
                    top:this.boy.top-this.boy.height/2,
                    position:"absolute",
                    textAlign:"center",
                    lineHeight:this.boy.height+"px"
                }}
            >
                {this.boy.name}
            </div>
            {
                this.boyList.map((item,i) => {//循環輸出boyList
                    return <div
                        key = {i}
                        onClick = {onClick}
                        style = {{
                            border:"1px black solid",
                            width:item.width,
                            height:item.height,
                            left:item.left-item.width/2,
                            top:item.top-item.height/2,
                            position:"absolute",
                            textAlign:"center",
                            lineHeight:item.height+"px"
                        }}
                    >
                        {item.name}
                    </div>
                })
            }
        </div>
    );
}
複製代碼

這裏解釋一下焦點focus,咱們確定得讓鍵盤分開控制不一樣的角色,因此,設置一個焦點給鍵盤控制,焦點就是某個角色的引用。咱們再給每個div設置一個onClick函數,把焦點設置爲本身,就能夠在點擊這個div以後控制這個角色了。

看看效果:(雖然醜了點,可是意會就好啦,這就是一個多角色遊戲的最基本實現)

4.優化

爲了讓代碼更加好看一點,把角色作成一個組件吧,修改這個組件的樣式,就能按照你的喜愛創建角色啦!

BoyUnit組件:

class BoyUnit extends Component{
    render() {
        const {onClick,unit} = this.props;
        return <div
            onClick = {onClick}
            style = {{
                border:"1px black solid",
                width:unit.width,
                height:unit.height,
                left:unit.left-unit.width/2,
                top:unit.top-unit.height/2,
                position:"absolute",
                textAlign:"center",
                lineHeight:unit.height+"px"
            }}
        >
            {unit.name}
            {/**這裏還能夠添加圖片,甚至修改角色的形狀**/}
            {/*<img/>*/}
        </div>;
    }
}
複製代碼

Render函數:(看起來是否是清爽不少了)

render() {
    return (
        <div className = {"game1"}>
            {
                this.boyList.map((item,i)=>{
                    return <BoyUnit
                        key = {i}
                        onClick = {()=>{
                            this.setFocus(item);
                        }}
                        unit = {item}
                    />
                })
            }
            <BoyUnit
                onClick = {()=>{
                    this.setFocus(this.boy);
                }}
                unit = {this.boy}
            />
        </div>
    );
}
複製代碼

代碼優化完以後老是能讓人心情舒暢,不是麼~~

好了,學習React小遊戲開發第一天,複習了一下JS基礎,以後會學習更復雜的應用場景,寫更有趣的demo,全部的demo都能在git上找到嗷。

Github源碼

爲何用JavaScript寫遊戲

哈哈相信你們必定都有必定的困惑,爲何要用JS寫遊戲呢,C、C#在性能上的優點不香嘛,緣由有兩點:

  1. 簡單
  2. WEB遊戲安裝成本低

JavaScript做爲一個腳本語言,相比較於其餘語言(C,C++)更加容易理解,flash與計算機語言又有着本質上的不一樣。想入門遊戲,不妨從前端/JavaScript開始,若是你以爲能夠了的話,想作大遊戲再轉行C語言也不遲,由於不少編程的思惟,都是互通的,學會了思想,什麼都好辦。(其實主要緣由仍是由於大學第一年就學會了用JS作動畫,很方便不是麼)

我這我的嘛,是從4399小遊戲的時代過來的,即便如今打開也是滿滿的童年味。小時候想玩遊戲了,打開4399,隨便點開一個遊戲,立刻就能玩,不須要註冊什麼帳號,不用繁瑣的安裝流程,方便的啓動老是能讓人想點開更多的遊戲。這就是WEB端在小遊戲上的自然優點。而做爲遊戲開發者,誰不是從小遊戲開始的呢?奧利給!加油吧!

相關文章
相關標籤/搜索