菜鸟教程丨密室逃生Egret游戏教程

这次给大家带来的是通过Egret实现密室逃生小游戏的教程。该游戏包括人物状态机、MVC设计模式和单例模式,该游戏在1.5s内通过玩家点击操作寻找安全点,方可进入下一关,关卡无限,分数无限。下面是具体的模块介绍和代码实现。

该游戏主要内容包括

  • 开始游戏场景
  • 游戏场景
  • 游戏结束结算场景
  • 全局常量类
  • 人物状态机类

游戏源码素材下载:https://github.com/shenysun/RoomRun

创建全局常量类

在所有舞台搭建之前先写一个全局的静态方法类,取名为GameConst。这个类里面的方法和常量可以供全局使用,例如舞台宽高、通过名字获取位图、通过名字获取纹理集精灵等等。这个类可以大大减少后期的代码量,降低整体的耦合度。

/**常用常量类 */
class GameConst {
    /**舞台宽度 */
    public static StageW:number;
    /**舞台高度 */
    public static StageH:number;

    /**根据名字创建位图 */
    public static CreateBitmapByName(name:string):egret.Bitmap {
        let texture:egret.Texture = RES.getRes(name);
        let bitmap:egret.Bitmap = new egret.Bitmap(texture);
        return bitmap;
    }
    /**
     * 根据name关键字创建一个Bitmap对象。此name 是根据TexturePacker 组合成的一张位图
     */
    public static createBitmapFromSheet(name:string, sheetName:string):egret.Bitmap {
        let texture:egret.Texture = RES.getRes(`${sheetName}_json.${name}`);
        let result:egret.Bitmap = new egret.Bitmap(texture);
        return result;
    }

    public static getTextureFromSheet(name:string, sheetName:string):egret.Texture {
        let result:egret.Texture = RES.getRes(`${sheetName}_json.${name}`);
        return result;
    }
    /**移除子类方法 */
    public static removeChild(child:egret.DisplayObject) {
        if(child && child.parent) {
            if((<any>child.parent).removeElement) {
                (<any>child.parent).removeElement(<any>(child));
            }
            else {
                child.parent.removeChild(child);
            }
        }
    }
}

如果游戏中设置图片锚点较多也可以在这个类里面加一个设置锚点的方法,传入对象,横轴锚点和纵轴锚点坐标三个参数。

开始场景

开始页面比较简洁,有一个LOGO和两个按钮分别是开始游戏,更多游戏。

/**游戏开始场景 */
class StartGameLayer extends egret.Sprite {
    /**开始按钮 */
    private startBtn:MyButton;
    /**更多按钮 */
    private moreBtn:MyButton;
    /**LOGO */
    private titleImage:egret.Bitmap;
    public constructor() {
        super();
        this.init();
    }
    private init():void {
        /**添加游戏LOGO */
        this.titleImage = GameConst.createBitmapFromSheet("logo_mishitaosheng", "ui");
        this.titleImage.x = 51;
        this.titleImage.y = 161;
        this.addChild(this.titleImage);
        //开始按钮设置
        this.startBtn = new MyButton("btn_y", "btn_kaishi");
        this.addChild(this.startBtn);
        this.startBtn.x = (GameConst.StageW - this.startBtn.width) / 2;
        this.startBtn.y = GameConst.StageH / 2 - 75;
        this.startBtn.setClick(this.onStartGameClick);
        //更多按钮设置
        this.moreBtn = new MyButton("btn_b", "btn_gengduo");
        this.moreBtn.x = (GameConst.StageW - this.startBtn.width) / 2;
        this.moreBtn.y =GameConst.StageH / 2 + 75;
        this.addChild(this.moreBtn);
        this.moreBtn.setClick(this.onMoreBtnClick);
        //文本
        let tex:egret.TextField = new egret.TextField();
        tex.width = GameConst.StageW;
        tex.textAlign = egret.HorizontalAlign.CENTER;
        tex.strokeColor = 0x403e3e;
        tex.stroke = 1;
        tex.bold = true;
        tex.y = GameConst.StageH / 2 + 250;
        tex.text = "Powered By ShenYSun";
        this.addChild(tex);
    }
    private onStartGameClick() {
        GameControl.Instance.onGameScenesHandler();
    }
    private onMoreBtnClick() {
        console.log("更多游戏");
        platform.GetInfo();
    }
}

点击startBtn按钮执行GameControl类的切换场景方法。

场景控制类
/**游戏管理 */
class GameControl extends egret.Sprite {
    private static _instance:GameControl;
    public static get Instance() {
        if(!GameControl._instance) {
            GameControl._instance = new GameControl();
        }
        return GameControl._instance;
     }
    /**当前场景 */
    private currentStage:egret.DisplayObjectContainer;
    //开始游戏
    private startGame:StartGameLayer;
    /**游戏场景 */
    private gameScenes:GameScenesLayer;
    /**结束场景 */
    private overScenes:GameOverLayer;
    /**背景 */
    private bgImg:egret.Bitmap;
    public constructor() {
        super();
        this.startGame = new StartGameLayer();
        this.gameScenes = new GameScenesLayer();
        this.overScenes = new GameOverLayer();
    }

    public setStageHandler(stage:egret.DisplayObjectContainer):void {
        /**设置当前场景的背景 */
        this.currentStage = stage;
        this.bgImg = GameConst.CreateBitmapByName("bg_jpg");
        this.bgImg.width = GameConst.StageW;
        this.bgImg.height = GameConst.StageH;
        //把背景添加到当期场景
        this.currentStage.addChild(this.bgImg);
    }
    /**开始游戏的场景 */
    public startGameHandler():void {
        if(this.gameScenes && this.gameScenes.parent) {
            GameConst.removeChild(this.gameScenes);
        }
        if(this.gameScenes && this.overScenes.parent) {
            GameConst.removeChild(this.overScenes);
        }
        this.currentStage.addChild(this.startGame);
        GameApp.xia.visible = true;
    }

    /**游戏场景 */
    public onGameScenesHandler():void {
        if(this.startGame && this.startGame.parent) {
            GameConst.removeChild(this.startGame);
        }
        if(this.overScenes && this.overScenes.parent) {
            GameConst.removeChild(this.overScenes);
        }
        this.currentStage.addChild(this.gameScenes);
        GameApp.xia.visible = false;
    }

    /**游戏结束场景 */
    public showGameOverSceneHandler():void{
        if(this.startGame && this.startGame.parent){
            GameConst.removeChild(this.startGame)
        }
        if(this.gameScenes && this.gameScenes.parent){
            GameConst.removeChild(this.gameScenes)
        }
        this.currentStage.addChild(this.overScenes);
        GameApp.xia.visible = true;
    }

    public getGameOverDisplay():GameOverLayer {
        return this.overScenes;
    }

}

场景切换贯穿游戏全局,封装成类方便调用,以及后期扩展只需要加上新场景类的实例,便可以切换自如。

自定义按钮类

不难发现上面的开始游戏界面的按钮是MyButton类型,在MyButton类的构造函数中传入背景图和显示文字,创建出一个按钮。此类有一个设置点击事件的方法,按钮调用此公开方法传入触发事件即可设置点击事件。

/**自定义按钮类 */
class MyButton extends egret.Sprite {
    private _bg:egret.Bitmap;
    private title:egret.Bitmap;
    private onClick:Function;

    public constructor(bgName:string, titleName:string) {
        super();
        this._bg = GameConst.createBitmapFromSheet(bgName, "ui");
        this.addChild(this._bg);

        this.title = GameConst.createBitmapFromSheet(titleName, "ui");

        this.title.x = (this._bg.width - this.title.width) >> 1;
        this.title.y = (this._bg.height - this.title.height) >> 1;
        this.addChild(this.title);
    }

    //设置点击触发事件
    public setClick(func:Function):void {
        this.touchEnabled = true;
        this.addEventListener(egret.TouchEvent.TOUCH_TAP, this.onClickEvent, this);
        this.onClick = func;
    }
    //点击触发的事件
    private onClickEvent() {
        this.onClick();
    }

    public setTitle(title:string):void {
        this.title = GameConst.CreateBitmapByName(title);
    }

    public get bg() {
        return this._bg;
    }
    public set bg(bg:egret.Bitmap) {
        this._bg = bg;
    }
}

自定义特殊数字类

一般游戏中的分数、时间等数字组成的UI为了美观都会使用位图文本,但是当游戏逻辑跑起来需要不断的刷新游戏的分数,每次改变分数的时候都要从纹理集里面调用对应位图,在时间上是一个大大的浪费,所以创建一个特殊字符类SpecialNumber,让这个类替我们实现转换特殊字符。

具体代码如下:

/**特殊字符数字类 */
class SpecialNumber extends egret.DisplayObjectContainer {
    public constructor() {
        super();
    }
    public gap:number = 0;
    /**设置显示的字符串 */
    public setData(str:string):void {
        this.clear();
        if(str == "" || str == null) {
            return;
        }
        //把所有数字每一个都存进数组中
        let chars:Array<string> = str.split("");
        let w:number = 0;
        //所有的长度
        let length:number = chars.length;
        for(let i:number = 0; i < length; i++) {
            try {
                let image:egret.Bitmap = GameConst.createBitmapFromSheet(chars[i], "ui");
                if(image) {
                    image.x = w;
                    w += image.width + this.gap;
                    this.addChild(image);
                }
            } catch (error) {
                console.log(error);
            }
        }
        this.anchorOffsetX = this.width / 2;
    }
    public clear() {
        while(this.numChildren) {
            this.removeChildAt(0);
        }
    }
}

在体验过游戏的时候会发现任务会根据不一样的墙体高度摆不一样的poss,这才poss全是来自于帧动画纹理集,只需要把对应一套的动画解析出来人物就会跳起舞来。下面是人物状态类。

状态机类

人物共有五个状态,其中一个是默认状态state为跳舞状态STAGE1,还有设置当前状态的方法setState

/**角色动作类 */
class Role extends egret.Sprite{
    //状态
    public static STATE1:number = 0;
    public static STATE2:number = 1;
    public static STATE3:number = 2;
    public static STATE4:number = 3;
    public static STATE5:number = 4;
    /**人物状态集合 */
    public static FRAMES:Array<any> = [
        ["0020003", "0020004", "0020005", "0020006","0020007"],
        ["0020008"],
        ["0020009", "0020010"],
        ["0020011", "0020012"],
        ["xue0001", "xue0002", "xue0003", "xue0004", "xue0005"]
    ]
    //身体
    private Body:egret.Bitmap;
    private state:number;
    private currFrames:Array<any>;
    private currFramesIndex:number = 0;
    private runFlag:number;
    private isLoop:boolean;

    public constructor() {
        super();
        this.Body = new egret.Bitmap;
        //人物初始状态
        this.Body = GameConst.createBitmapFromSheet("Role.FRAMES[0][0]", "Sprites");
        //设置锚点
        this.Body.anchorOffsetX = this.Body.width * 0.5;
        this.addChild(this.Body);
    }

    /**设置状态 */
    public setState(state:number) :void {
        this.state = state;
        //死亡状态
        if(this.state == Role.STATE5) {
            this.isLoop = false;
            this.Body.anchorOffsetY = this.Body.height * 0;
        }else{
            this.isLoop = true;
            this.Body.anchorOffsetY = this.Body.height * 1;
        }

        if(this.state == Role.STATE3 || this.state == Role.STATE4){
            this.currFrames = [];
            if(Math.random() > 0.5){
                this.currFrames.push(Role.FRAMES[this.state][0]);
            }else{
                this.currFrames.push(Role.FRAMES[this.state][1]);
            }
        }else{
            this.currFrames = Role.FRAMES[this.state];
        }
        this.currFramesIndex = 0;
        this.setBody();
    }

    private setBody() {
        this.Body.texture = GameConst.getTextureFromSheet(this.currFrames[this.currFramesIndex], "Sprites");
        this.Body.anchorOffsetX = this.Body.width * 0.5;
        if(this.state == Role.STATE5){
            this.isLoop = false;
            this.Body.anchorOffsetY = this.Body.height * 0;
        }else{
            this.isLoop = true;
            this.Body.anchorOffsetY = this.Body.height * 1;
        }
    }
    public run():boolean{
        this.runFlag ++;
        if(this.runFlag > 4){
            this.runFlag = 0;
        }
        if(this.runFlag != 0){
            return;
        }
        var gotoFrameIndex:number = this.currFramesIndex + 1;
        if(gotoFrameIndex == this.currFrames.length){
            if(this.isLoop){
                gotoFrameIndex = 0;
            }else{
                gotoFrameIndex = this.currFramesIndex;
            }
        }
        if(gotoFrameIndex != this.currFramesIndex){
            this.currFramesIndex = gotoFrameIndex;
            this.setBody();
        }
        return false;
    }

    public play():void{
        egret.startTick(this.run,this);
        this.runFlag = 0;
    }
    public stop():void{
        egret.stopTick(this.run,this);
    }
}

游戏场景

一切工作准备就绪,下面就是本文的重点-----游戏场景的搭建以及逻辑的实现。先看一下游戏内的主要内容

首先是蓝色的游戏背景,和开始游戏界面背景如出一辙不用更换,在场景管理的时候注意背景保留一下继续使用。

其次分数、关卡、上背景图等等这些只需要调用常量类的获取纹理集图片的方法调整位置即可实现。

最后重点介绍一下内容:

  • 墙体生成和运动
  • 人物运动和状态切换
  • 分数和关卡数改变并记录最高分数

下面是重要代码片段

墙体生成和运动

墙体分别包括上半部分和下半部分

/**上部分墙体容器 */
    private topContianer:egret.Sprite;
    /**下部分墙体容器 */
    private bottomContianer:egret.Sprite;

容器内又包含了上下部分的墙体图片,上下边界线

    /**上下墙体填充图 */
    private topSprite:egret.Sprite;
    private bottomSprite:egret.Sprite;
    /**上下边界线 */
    private topLine:egret.Shape;
    private bottomLine:egret.Shape;

把填充图和边界线加到容器内(以上边界为例)

this.topContianer = new egret.Sprite();
    this.addChild(this.topContianer);
    this.topSprite = new egret.Sprite();
    this.topContianer.addChild(this.topSprite);
    this.topContianer.addChild(this.topLine);

定义一个top和bottom范围区间,随机在舞台范围内取值。

let min:number = 150;
        let flag:boolean = false;
        let len:number = 8;
        let w:number = GameConst.StageW / len;
        for(let i:number = 0; i < len; i++) {
            var h:number = min + Math.floor(Math.random() * 8) * 10;
            this.bottomRects.push(new egret.Rectangle(i * w, GameConst.StageH - h, w, h));

            h = GameConst.StageH - h;
            if (Math.random() < 0.2 || (!flag && i == len - 1)) {
                var index:number = Math.floor(Math.random() * this.spaceArr.length);
                h -= this.spaceArr[index];
                flag = true;
            }
            this.topRects.push(new egret.Rectangle(i * w, 0, w, h));
        }

这是随机取区域已经完成,不过都是理想的区域,并没有填充实际上的图片,下面写一个方法通过区域来填充背景墙。

private fullFront(bgSptite:egret.Sprite, rects:Array<egret.Rectangle>, isBottom:boolean = false):void {
        bgSptite.cacheAsBitmap = false;
        this.clearBg(bgSptite);
        var len:number = rects.length;
        for (var i:number = 0; i < len; i++) {
            var rec:egret.Rectangle = rects[i];
            var bitmap:egret.Bitmap;

            if (this.bgBitmaps.length) {
                bitmap = this.bgBitmaps.pop();
            } else {
                bitmap = new egret.Bitmap();
                bitmap.texture = this.bg;
            }
            bitmap.scrollRect = rec;
            bitmap.x = rec.x;
            bitmap.y = rec.y;
            bgSptite.addChild(bitmap);
        }
    }

关键代码bitmap.scrollRect = rec是把位图按照区域进行分割,显示对象的滚动矩形范围。显示对象被裁切为矩形定义的大小,当您更改 scrollRect 对象的 x 和 y 属性时,它会在矩形内滚动。

上下背景位图填充完毕,下面可是画上下边界线,同样是写了一个方法(以上边界为例),如下:

    private drawLine():void {
        var lineH:number = 10;
        this.topLine.graphics.clear();
        this.topLine.graphics.lineStyle(lineH, 0x33E7FE);
        this.bottomLine.graphics.clear();
        this.bottomLine.graphics.lineStyle(lineH, 0x33E7FE);
        this.drawTopLine(lineH / 2);
        this.drawBottomLine(lineH / 2);
        this.topLine.graphics.endFill();
        this.bottomLine.graphics.endFill();
    }

    private drawTopLine(lineH:number):void {
        var len:number = this.topRects.length;
        for (var i:number = 0; i < len; i++) {
            var rec:egret.Rectangle = this.topRects[i];
            if (i == 0) {
                this.topLine.graphics.moveTo(rec.x, rec.height);
                this.topLine.graphics.lineTo(rec.x + rec.width, rec.height);
            } else {
                this.topLine.graphics.lineTo(rec.x, rec.height);
                this.topLine.graphics.lineTo(rec.x + rec.width, rec.height);
            }
        }
    }

此时,背景填充完毕,但墙体还不能运动。前面this.topContianer.y = -200;把上部分墙体的的纵轴设置在-200的位置,等到游戏开始执行Tween动画,使this.topContianer.y = 0,为了有更好的效果游戏开始延迟1.5s再调用墙体运动,Tween动画如下:

 let self = this;
        setTimeout(function() {
            // self.shakeRun();
            //上面的模块往下运动
            egret.Tween.get(this.topContianer).to({"y":0}, 100).call(function():void {
            self.landOver();
            })
        }, 1500);
人物运动和状态切换

人物运动:给舞台添加点击事件,判断点击位置并移动。

/**点击事件 */
private onClick(e:egret.TouchEvent):void {
    let len:number = this.bottomRects.length;
    for(let i:number = 0; i < len; i++) {
        let rec:egret.Rectangle = this.bottomRects[i];
        if(e.stageX > rec.x && e.stageX < rec.x + rec.width) {
            this.setRolePos(i);
            break;
        }
    }
}

操作角色所在位置全部是根据上面定义的人物所在位置下标rolePosIndex的相对位置来决定的。

private setRolePos(index:number, offY:number = 17, offX:number = 0, isInit:boolean = false):void {
        if (!isInit) {
            //人物每次移动一个格子
            if (this.rolePosIndex > index) {
                index = this.rolePosIndex - 1;
            }
            else if (this.rolePosIndex < index) {
                index = this.rolePosIndex + 1;
            }
        }
        this.rolePosIndex = index;
        var rec:egret.Rectangle = this.bottomRects[index];
        //一次只移动一格
        this.role.x = rec.x + rec.width / 2 + offX;
        this.role.y = rec.y + offY;
    }

状态切换:

墙体运动完毕之后,通过人物所在位置下标找到上半部分墙体和下半部分墙体对应的位置的差值,并根据差值判断人物是否存活,如果存活应该表现出什么状态。

获取人物所在位置上下墙体的距离:

 
 privategetSpace():number{
       lettop:egret.Rectangle=this.topRects[this.rolePosIndex];
       letbottom:egret.Rectangle=this.bottomRects[this.rolePosIndex];
       returnGameConst.StageH-top.height-bottom.height;
  }

根据返回的距离差值判断人物的状态:

 
  privatecheckState() {
       letspace:number=this.getSpace();
       if(space==0) {
           this.role.setState(Role.STATE5);
      } elseif(space==this.spaceArr[2]) {
           this.role.setState(Role.STATE4);
      } elseif(space==this.spaceArr[0]) {
           this.role.setState(Role.STATE3);
      } elseif(space==this.spaceArr[1]) {
           this.role.setState(Role.STATE2);
      }
       if(space==0) {
           this.setRolePos(this.rolePosIndex, -10, 4);
      }
  }

根据返回的距离判断游戏状态,若返回值为0,游戏结束;不为0,进入下一关:

   /**检验这关结束主角是否存活 */
   privatecheckResult() {
       letspace:number=this.getSpace();
       letself=this;
       if(space==0) {
           this.dieNum++;
           if(this.dieNum==1) {
               this.role.stop();
               setTimeout(function() {
                   //游戏结束
                   GameControl.Instance.getGameOverDisplay().setGameOverDataHandler(self.score, self.curretMaxScore);
                   GameControl.Instance.showGameOverSceneHandler();
              }, 500);

               return;
          }
      }
       //进入下一关
       else{
           this.curretLevel++;
           this.score+=10;
           if(this.score>this.curretMaxScore) {
               this.curretMaxScore=this.score;
          }
           //刷新成绩
           this.refreshScore();
      }
       setTimeout(function() {
           self.refurbish()
      }, 1000);
  }
分数和关卡

接着上一步此时如果人物存活进入下一关,那么就要刷新游戏成绩和关卡数,并检验此时是否为最高成绩:

/**刷新成绩数据 */
privaterefreshScore() {
this.LvNum.setData(this.curretLevel.toString());
this.recodeNum.setData(this.score.toString());
}

游戏进入下一关卡:

   /**刷新游戏关卡 */
   privaterefreshPoint() {
       this.initData();
       this.start();
  }
 

游戏结算界面

游戏结算界面效果图

和开始界面差不多,有所不同的是需要从游戏场景中传入本局分数和做高分数,在这个页面写一个公开的setGameOverDataHandler方法,游戏结束是调用此方法传入数值。

/**游戏结束页面分数最高分数 */
publicsetGameOverDataHandler(score:number=0, maxScore:number=0):void{
this.scoreNum.setData(score.toString());
this.maxScore.setData(maxScore.toString());
}
 

扩展

墙体晃动效果

游戏场景内当墙体要下落的时候墙体会晃动一下,晃动墙体不仅提醒玩家这个墙体即将下落,同时也增加了这个游戏的可玩性,下面是控制墙体晃动的Shake类。

/**墙体晃动 */
classShake{
privateinitY:number;
privateshakeNum:number;
privateoverFunc:Function;
privateobj:egret.DisplayObject;
privatenum:number;
privateflag:number;
?
publicrun(obj:egret.DisplayObject, shakeNum:number, overFunc:Function=null) {
this.obj=obj;
this.initY=obj.y;
this.shakeNum=shakeNum;
this.overFunc=overFunc;
egret.startTick(this.loop, this);
this.num=0;
this.flag=0;
}
privateloop():boolean{
if(this.flag==0) {
if(this.obj.y<=this.initY) {
this.obj.y+=5;
} else{
this.obj.y-=5;
}
if(this.obj.y==this.initY) {
this.num++;
if(this.num==this.shakeNum) {
egret.stopTick(this.loop, this);
if(this.overFunc) {
this.overFunc();
}
}
}
}
this.flag++;
if(this.flag==2) {
this.flag=0;
}
returnfalse;
}
}
 
小结

本文通过对一个简单小游戏进行模块化的分析,并介绍了模块化的好处,降低这些模块之间的耦合度,后期如果要加新功能对旧的代码无需进行大的修改。

原文地址:https://www.cnblogs.com/egret-edcation/p/9728345.html

时间: 2024-11-05 23:32:24

菜鸟教程丨密室逃生Egret游戏教程的相关文章

egret游戏入门之学习资源篇

最近因需要,入手H5游戏. 写游戏当然需要有引擎. H5游戏开发:游戏引擎入门推荐 如何选择 H5 游戏引擎 白鹭引擎和layabox哪个好用,哪个技术更成熟 ? LayaBox 与 Egret 选择哪个呢? Egret 4.1.6 和 LayaBox(LayaAir 2.0) 的 易用性 对比 经过初步分析和咨询,基本确认Egret和LayaAir, 个人讲真从官网和社区逛过后.真心喜欢LayaAir一些.但是最后还是选择了这一只白鹭. 要学习当然要有学习资源. Egret官网 其首页的新闻动

Android 游戏教程让人物动起来

在这里给大家分享Android游戏教程怎样让人物动起来,话不多说了,直接进入正题.一. 准备工作     首先要准备好要使用的人物动作图和地形图.把它分割成16个不同的动作,循环播放同一行的4个不同动作就可以让人物动起来了.二. 动画实现    按照简单的android游戏框架所述先搭建一个框架,接着编写如下类:         人物类Person主要代码如下:    private int x;          private int y;          private int dist

Quick-Cocos2d-x初学者游戏教程(二) -------------------- Quick内部的代码结构及相应的原理

Quick-Cocos2d-x初学者游戏教程(二) 上一章我们已经了解了Quick的一些基础知识,所以本章我们将开始深入到Quick内部,了解它内部的代码结构,同时在解析的过程中学到相应的原理,并学会如何修改.添加相应的代码文件,比如实现屏幕的分辨率适配. 前面我们创建了一个叫做parkour的游戏项目,其意思就是本人本来打算要做一个跑酷游戏的,但是因为这几天玩了一款叫做<el>的飞行游戏,非常有意境,并且几乎零差评,所以请允许我任性一下,善变的我不想做跑酷游戏了,而是想要挑战下这种类型的游戏

Quick-Cocos2d-x初学者游戏教程(三) ---------------------------- 解析quick新建项目的代码文件

Quick-Cocos2d-x初学者游戏教程(三) 2.main.lua 在src目录下,除了 config.lua 文件外,还有一个 main.lua 文件,这个 main.lua 是 Quick 项目的通用入口文件,它类似于 Cocos2d-x 中的 AppDelegate.h/cpp 文件,同时也类似于一般 Windows 工程中的 main 文件. 打开 main.lua 文件,其内容如下所示: 1 2 3 4 5 6 7 8 9 10 function __G__TRACKBACK__

Quick-Cocos2d-x初学者游戏教程(四) --------------- 开发初探(添加背景,标题,动作,按钮)

Quick-Cocos2d-x初学者游戏教程(四) 前面我们已经大概的讲解完了Quick的框架和代码结构,接下来,本章开始我们将正式进入到游戏的开发.当然在开发的过程中,如果遇到值得一提的知识点和概念,我们还是会为大家详细讲解的. 哈哈,这章的内容我加它为——开发初探,因为我们将先来实现一些基础的内容.本章将实现的效果如下图所示: 菜单场景 从前面章节讲解的的知识点中,我们知道每个新建的 Quick 项目里都已经默认创建好了一个 mainScene 场景,所以下面我们将利用这个现成的场景,把它改

Alex 的 Hadoop 菜鸟教程: 第4课 Hadoop 安装教程 - HA方式 (2台服务器)

声明 本文基于Centos 6.x + CDH 5.x 官方英文安装教程 http://www.cloudera.com/content/cloudera/en/documentation/cdh5/v5-0-0/CDH5-Installation-Guide/cdh5ig_cdh5_install.html 本文并不是简单翻译,而是再整理 如果没有yum源请参考http://blog.csdn.net/nsrainbow/article/details/36629339#t2 准备工作 用vm

Quick-Cocos2d-x初学者游戏教程(一)--------------------Quick的一些基础知识

本文转自Quick-Cocos2d-x初学者游戏教程(一) 前言 虽然之前已经写过了很多 Cocos2d-x 相关的教程和文档,但本次却是我第一次接触 Quick,第一次接触 Lua,所以此次的教程本人将站在一个初学者的角度(看到这里是不是想白眼我了,哈哈,别切啊!尽管第一次,但我身边可是有很多 Quick 大神的,廖大大也在旁边办公室,没准撒个娇大神就把他知道的全部要点倾囊相授了啦!),全方位的解析 Quick 的学习过程,并同大家一起学习如何利用 Quick-Cocos2d-x 开发一款属于

Quick-Cocos2d-x初学者游戏教程(六) --------------------- 游戏逻辑

Quick-Cocos2d-x初学者游戏教程(六) 上一章我 们介绍了开发中会用到的辅助工具,并创建了 GameScene 场景,接下来这章我们将继续 GameScene 的传(bai)奇(bi).不过在开始编写 GameScene 场景的代码之前,我们还是先来明确一下游戏的功能和实现方法.这样可以帮我们更好的理解并设计逻辑.下面是总结出的结论: 在 GameScene 场景中,我们将创建一个飞行的娃娃角色,这个角色是游戏的唯一主角.游戏初始状态下,这个角色有满满的生命值,但随着时间的推移,生命

Quick-Cocos2d-x初学者游戏教程(五) --------------------- 辅助工具和跳转场景

Quick-Cocos2d-x初学者游戏教程(五) 上一章我们创建了游戏的菜单场景,并讲解了一些基础元素的创建,接下来这章,我们会先让大家了解一些接下来游戏开发中需要用到的辅助工具,然后再教大家创建另一个游戏场景,并跳着到该场景中来. 工具介绍 在开始真真的写代码之前,其实早该讲讲以下这些辅助工具的.这些工具可以让我们更好更方便的实现程序中的某些功能,比如地图编辑工具.粒子编辑工具 等.尽管这些工具在我之前的教程中已经不厌其烦的讲了好多次了,但是为了做到真正的初学者教程,本小节还是先来简单的介绍