基于egret引擎、P2物理库的搭积木游戏

1 篇文章 0 订阅
1 篇文章 0 订阅

最近更新源代码:

https://github.com/lixintong1992/egret_game


最近不务正业,参加了一个HTML5游戏设计比赛。速成了一个搭积木游戏。



因为有重力感应,手机玩效果好一些,微信扫一扫!(用的是比赛官方给的服务器,不知道什么时候链接就会失效)。。


好了!我们开始:


egret:

使用的是egret游戏引擎,因为以前没接触过H5游戏制作,这个的新手教程十分简单。
看了看入门:
http://edn.egret.com/cn/index.php/docs/page/639

还有视频教程讲的也是十分的细致:

http://edn.egret.com/cn/list/video/


编辑器用的也是egret wing,还是有一些bug的。开发过程中egret也在不断更新,还是蛮好哒。


P2物理库:

不好用啊,虽然是egret官方推荐的,但是教程非常少版本也是非常的旧。给开发带来了好多的麻烦。
竟然在创建三角形刚体上卡住了好久。。。最后请教了@ladeng6666(陈文登),用了神改过的P2库才解决问题。神的egret书要出版了,大家支持支持~
如果能再选择一次,我会去试试BOX2D,起码它教程很多,还跨平台。


创建工程,导入第三方库P2:

egret wing创建工程,在项目文件夹的平级目录加入第三方库文件。 例如项目路径 C:\project\demo\src。拷贝 myLibs(http://download.csdn.net/detail/lixintong1992/9386255)第三方库文件夹位置到 C:\project。修改egretProperties.json文件 modules 中增加
之后运行命令行,cd到工程文件目录,执行下egret build -e


P2物理世界初始化:

我们来创建世界!(中二病。。。)
private world: p2.World = new p2.World();
节省资源模式启动!
this.world.sleepMode = p2.World.BODY_SLEEPING;
我带了重力!
this.world.gravity = [0,-5];

P2物理世界通过
this.world.step(t);
计算t秒后世界中所有刚体的位置。

egret中有心跳函数,我们只要每次心跳调用
this.world.step(t);
就能让世界运转!

我写的不好,不明白的可以参考下
http://edn.egret.com/cn/docs/page/627

重力感应:

        var orientation = new egret.DeviceOrientation();//创建 DeviceOrientation 类
        orientation.addEventListener(egret.Event.CHANGE,this.onOrientation,this);//添加事件监听器
        orientation.start(); //开始监听设备方向变化
    private onOrientation(e: egret.OrientationEvent) {
        this.beta_gamma = Math.round(e.gamma); 
    }
没什么好解释的···


游戏胜利失败判断:

过关条件:

1.场景中活动实体达到上限且都是静止

2.场景中活动实体达到上限且经过一段时间没失败

失败条件:

存在实体的y坐标超过屏幕下限(就是掉下去啦)


当然要在心跳函数中实时判断过关还是失败啦:
        egret.Ticker.getInstance().register(function(dt) {
            this.world.step(dt / 1000);
            this.world.gravity[0] = this.beta_gamma / 30; 
            if(!this._isDebug) {
                var stageHeight: number = egret.MainContext.instance.stage.stageHeight;
                var l = this.world.bodies.length;
                    for(var i: number = 0;i < l;i++) {
                        var boxBody: p2.Body = this.world.bodies[i];
                        if(boxBody) {
                            if(boxBody.displays[0]) {
                                var box: egret.DisplayObject = boxBody.displays[0];
                            }

                            if(box) {
                                box.x = boxBody.position[0] * this.factor;
                                box.y = stageHeight - boxBody.position[1] * this.factor;
                                if(box.y > 900) {
                                    count = 0;
                                    this.level(-2);
                                }
                                box.rotation = 360 - boxBody.angle * 180 / Math.PI;
                                if(boxBody.sleepState == p2.Body.SLEEPING) {
                                    box.alpha = 0.8;
                                    count_sleep += 1;
                                }
                                else {
                                    box.alpha = 1;
                                }
                                if(l == this.success_num[this.level_num]) {
                                    if(count == 4000) {
                                        this.level_num += 1;
                                        Data.score = this.level_num;
                                        this.level(this.level_num);
                                        l = 0;
                                        count = 0;
                                    }
                                    else { count = count + 1; }
                                }
                            }
                        }
                    }
                if(count_sleep == this.sleep_num[this.level_num]) {
                    this.level_num += 1;
                    Data.score = this.level_num;
                    this.level(this.level_num);
                    l = 0;
                    count = 0;
                    count_sleep = 0;
                }
                else {
                    count_sleep = 0;
                }
            }
        },this);
相当于一个while(1),其中dt就是两次执行自身的时间间隔,遍历所有刚体,更新实体对应贴图的坐标,休眠的刚体变透明。判断胜利失败条件。

里面还加了一发重力感应:
            this.world.gravity[0] = this.beta_gamma / 30; 

创建支撑三角、方块、圆刚体:

创建那种不会动的静止刚体函数:

    private supportertrect(_width:number,_height:number,_rotation:number,_x:number,_y:number) {
        var supporterShape: p2.Shape = new p2.Box({ width: _width,height: _height });
        var supporterBody: p2.Body = new p2.Body({ mass: 0,position: [_x/this.factor,_y/this.factor],angle:Math.PI*((_rotation)/180),angularVelocity: 0 });
        supporterBody.addShape(supporterShape);
        this.world.addBody(supporterBody);
        var display: egret.DisplayObject = this.createBitmapByName("rect2");
        display.width = (<p2.Box>supporterShape).width * this.factor;
        display.height = (<p2.Box>supporterShape).height * this.factor;
        display.anchorOffsetX = display.width / 2;
        display.anchorOffsetY = display.height / 2;
        supporterBody.displays = [display];
        this.addChild(display);
    }
    private supportertriangle(_sidelenght:number,_rotation:number,_x:number,_y:number) {
        var center1: number[] = new Array(0, 0);
        var mousePos_11: number[] = new Array(0, _sidelenght/this.factor);
        var mousePos_21: number[] = new Array(_sidelenght/this.factor, _sidelenght/this.factor);
        var mousePos_31: number[] = new Array(0, 0);
        var points1: number[][] = new Array();
        p2.vec2.centroid(center1,mousePos_11,mousePos_21,mousePos_31);
        p2.vec2.subtract(mousePos_11,mousePos_11,center1);
        p2.vec2.subtract(mousePos_21,mousePos_21,center1);
        p2.vec2.subtract(mousePos_31,mousePos_31,center1);
        points1.push(mousePos_11);
        points1.push(mousePos_21);
        points1.push(mousePos_31);
 
        var supporterBody: p2.Body = new p2.Body({ mass: 0,position: [_x/this.factor,_y/this.factor],angle:Math.PI*((_rotation)/180),angularVelocity: 0 });
        supporterBody.fromPolygon(points1,{optimalDecomp:false});
        this.world.addBody(supporterBody);
        
        var items1:egret.Bitmap = new egret.Bitmap();
        items1.texture = RES.getRes('triangle');
        items1.width = _sidelenght;
        items1.height = _sidelenght;
        items1.rotation = -_rotation;
        items1.x = _x;
        items1.y = _y;
        items1.anchorOffsetX = center1[0] * this.factor;
        items1.anchorOffsetY = items1.height-center1[1] * this.factor;
        supporterBody.displays = [items1];
        this.addChild(items1);
    }
    private supportercircle(_radius:number,_x:number,_y:number) {
        var supporterShape: p2.Shape = new p2.Circle( {radius:((_radius/2)/this.factor) });
        var supporterBody: p2.Body = new p2.Body({ mass: 0,position: [_x/this.factor,_y/this.factor],angularVelocity: 0 });
        supporterBody.addShape(supporterShape);
        this.world.addBody(supporterBody);
        var display: egret.DisplayObject = this.createBitmapByName("circle2");
        display.width = _radius;
        display.height = _radius;
        display.x = _x;
        display.y = _y;
        display.anchorOffsetX = display.width / 2;
        display.anchorOffsetY = display.height / 2;
        supporterBody.displays = [display];
        this.addChild(display);
    }

三个函数的流程都一样,创建shape,创建body,通过body的addShape为body绑定shape,之后建立一个显示贴图的DisplayObject,通过body的displays为body绑定贴图。最后addChild。

对于三角形来说有点麻烦,三角形是通过创建多边形fromPolygon来实现的。fromPolygon是body的一个方法,给他坐标,它就能自动给你搞出来一个shape绑到body上
要根据三角形三点坐标算一下重心(centroid)。之后根据重心坐标对三个坐标做减法(subtract)

创建活动的三角、方块、圆刚体:

创建那种手指拖的活动的刚体:

    private creatrect(_width:number,_height:number,_rotation:number,_x:number,_y:number){
        var display :egret.DisplayObject= this.createBitmapByName('rect') 
        display.width = _width;
        display.height = _height;
        display.x = _x;
        display.y = _y;
        display.rotation = -_rotation;
        display.anchorOffsetX = display.width / 2;
        display.anchorOffsetY = display.height / 2;
        this.addChild(display);
        display.touchEnabled = true;
        display.addEventListener(egret.TouchEvent.TOUCH_BEGIN,startMove,this);
        display.addEventListener(egret.TouchEvent.TOUCH_END,stopMove,this);  
        var draggedObject:egret.Shape;
        var offsetX:number;
        var offsetY:number;
        function startMove(e:egret.TouchEvent):void{
            //把手指按到的对象记录下来
            draggedObject = e.currentTarget;
            //计算手指和要拖动的对象的距离
            offsetX = e.stageX - draggedObject.x;
            offsetY = e.stageY - draggedObject.y;
            //把触摸的对象放在显示列表的顶层
            this.addChild(draggedObject);
            //手指在屏幕上移动,会触发 onMove 方法
            this.stage.addEventListener(egret.TouchEvent.TOUCH_MOVE,onMove,this);
        }
        function stopMove(e:egret.TouchEvent) {
//            console.log(22);
            //手指离开屏幕,移除手指移动的监听
            this.stage.removeEventListener(egret.TouchEvent.TOUCH_MOVE,onMove,this);
            draggedObject = e.currentTarget;
                                                                                
            var positionX: number = draggedObject.x / this.factor;
            var positionY: number = (egret.MainContext.instance.stage.stageHeight - draggedObject.y) / this.factor;
            var boxShape: p2.Shape = new p2.Box({width:_width/this.factor,height:_height/this.factor});
            var boxBody: p2.Body = new p2.Body({ mass: 1,position: [positionX,positionY],angle:Math.PI*((_rotation)/180),angularVelocity: 0 });
            boxBody.addShape(boxShape);        
            this.world.addBody(boxBody);
            boxBody.displays = [e.currentTarget];
            e.currentTarget.touchEnabled = false;
//            var sound:egret.Sound = RES.getRes( "bgm_2" ); 
//            var channel:egret.SoundChannel = sound.play(0,1);
        }
        function onMove(e:egret.TouchEvent):void{
            //通过计算手指在屏幕上的位置,计算当前对象的坐标,达到跟随手指移动的效果
            draggedObject.x = e.stageX - offsetX;
            draggedObject.y = e.stageY - offsetY;
        } 
    }
    private creatrect_candy(_width:number,_height:number,_rotation:number,_x:number,_y:number){
        var display :egret.DisplayObject= this.createBitmapByName('candy') 
        display.width = _width;
        display.height = _height;
        display.x = _x;
        display.y = _y;
        display.rotation = -_rotation;
        display.anchorOffsetX = display.width / 2;
        display.anchorOffsetY = display.height / 2;
        this.addChild(display);
        display.touchEnabled = true;
        display.addEventListener(egret.TouchEvent.TOUCH_BEGIN,startMove,this);
        display.addEventListener(egret.TouchEvent.TOUCH_END,stopMove,this);  
        var draggedObject:egret.Shape;
        var offsetX:number;
        var offsetY:number;
        function startMove(e:egret.TouchEvent):void{
            //把手指按到的对象记录下来
            draggedObject = e.currentTarget;
            //计算手指和要拖动的对象的距离
            offsetX = e.stageX - draggedObject.x;
            offsetY = e.stageY - draggedObject.y;
            //把触摸的对象放在显示列表的顶层
            this.addChild(draggedObject);
            //手指在屏幕上移动,会触发 onMove 方法
            this.stage.addEventListener(egret.TouchEvent.TOUCH_MOVE,onMove,this);
        }
        function stopMove(e:egret.TouchEvent) {
            //            console.log(22);
            //手指离开屏幕,移除手指移动的监听
            this.stage.removeEventListener(egret.TouchEvent.TOUCH_MOVE,onMove,this);
            draggedObject = e.currentTarget;
                                                                                            
            var positionX: number = draggedObject.x / this.factor;
            var positionY: number = (egret.MainContext.instance.stage.stageHeight - draggedObject.y) / this.factor;
            var boxShape: p2.Shape = new p2.Box({width:_width/this.factor,height:_height/this.factor});
            var boxBody: p2.Body = new p2.Body({ mass: 1,position: [positionX,positionY],angle:Math.PI*((_rotation)/180),angularVelocity: 0 });
                boxBody.addShape(boxShape);        
                this.world.addBody(boxBody);
                boxBody.displays = [e.currentTarget];
                e.currentTarget.touchEnabled = false;
                //            var sound:egret.Sound = RES.getRes( "bgm_2" ); 
                //            var channel:egret.SoundChannel = sound.play(0,1);
            }
            function onMove(e:egret.TouchEvent):void{
                //通过计算手指在屏幕上的位置,计算当前对象的坐标,达到跟随手指移动的效果
                draggedObject.x = e.stageX - offsetX;
                draggedObject.y = e.stageY - offsetY;
            } 
        }
    private creatcircle(_radius:number,_x:number,_y:number){
        var display1 :egret.DisplayObject= this.createBitmapByName('circle') 
        display1.width = _radius;
        display1.height = _radius;
        display1.x = _x;
        display1.y = _y;
        display1.anchorOffsetX = display1.width / 2;
        display1.anchorOffsetY = display1.height / 2;
        this.addChild(display1);
        display1.touchEnabled = true;
        display1.addEventListener(egret.TouchEvent.TOUCH_BEGIN,startMove2,this);
        display1.addEventListener(egret.TouchEvent.TOUCH_END,stopMove2,this);  
        var draggedObject:egret.Shape;
        var offsetX:number;
        var offsetY:number;
        function startMove2(e:egret.TouchEvent):void{
            //把手指按到的对象记录下来
            draggedObject = e.currentTarget;
            //计算手指和要拖动的对象的距离
            offsetX = e.stageX - draggedObject.x;
            offsetY = e.stageY - draggedObject.y;
            //把触摸的对象放在显示列表的顶层
            this.addChild(draggedObject);
            //手指在屏幕上移动,会触发 onMove 方法
            this.stage.addEventListener(egret.TouchEvent.TOUCH_MOVE,onMove2,this);
        }
        function stopMove2(e:egret.TouchEvent) {
//            console.log(22);
            //手指离开屏幕,移除手指移动的监听
            this.stage.removeEventListener(egret.TouchEvent.TOUCH_MOVE,onMove2,this);
            draggedObject = e.currentTarget;
                                                                                            
            var positionX: number = draggedObject.x / this.factor;
            var positionY: number = (egret.MainContext.instance.stage.stageHeight - draggedObject.y) / this.factor;                                               
            var boxShape: p2.Shape = new p2.Circle({radius:((_radius/2)/this.factor)});
            var boxBody: p2.Body = new p2.Body({ mass: 1,position: [positionX,positionY] });
            boxBody.addShape(boxShape);
            this.world.addBody(boxBody);                                                     
            boxBody.displays = [e.currentTarget];
            e.currentTarget.touchEnabled = false;
//            var sound:egret.Sound = RES.getRes( "bgm_3" ); 
//            var channel:egret.SoundChannel = sound.play(0,1);
        }
        function onMove2(e:egret.TouchEvent):void{
            //通过计算手指在屏幕上的位置,计算当前对象的坐标,达到跟随手指移动的效果
            draggedObject.x = e.stageX - offsetX;
            draggedObject.y = e.stageY - offsetY;
        }
    }


三个函数差不多的。先显示图,为这个图添加事件侦听。具体的图片移动看这个
http://edn.egret.com/cn/docs/page/583
我就不细说了,在最后手离开屏幕的事件中,为这个贴图创建一个刚体body,以及shape。

整个游戏流程:



ps:流程图在线画哒:https://www.processon.com/network


最开始就是为每个关卡赋值对应的所有刚体数,能活动的刚体数。



初始化,大清洗,世界清空,显示清空


关卡函数



每个关卡函数就是这个样子啦


其他的就是基本教程里的东西啦,按钮啊,事件啦


over~





  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值