基于egret引擎、P2物理库的搭积木游戏
2015-12-03 18:21
387 查看
最近不务正业,参加了一个HTML5游戏设计比赛。速成了一个搭积木游戏。
http://dev.redianbar.com/6fb2e2ef1a/
因为有重力感应,手机玩效果好一些,微信扫一扫!(用的是比赛官方给的服务器,不知道什么时候链接就会失效)。。
好了!我们开始:
看了看入门: http://edn.egret.com/cn/index.php/docs/page/639
还有视频教程讲的也是十分的细致:
http://edn.egret.com/cn/list/video/
编辑器用的也是egret wing,还是有一些bug的。开发过程中egret也在不断更新,还是蛮好哒。
竟然在创建三角形刚体上卡住了好久。。。最后请教了@ladeng6666(陈文登),用了神改过的P2库才解决问题。神的egret书要出版了,大家支持支持~
如果能再选择一次,我会去试试BOX2D,起码它教程很多,还跨平台。
C:\project\demo\src。拷贝
myLibs(http://download.csdn.net/detail/lixintong1992/9386255)第三方库文件夹位置到 C:\project。修改egretProperties.json文件
modules 中增加
之后运行命令行,cd到工程文件目录,执行下egret
build -e
P2物理世界通过
egret中有心跳函数,我们只要每次心跳调用
就能让世界运转!
我写的不好,不明白的可以参考下 http://edn.egret.com/cn/docs/page/627
1.场景中活动实体达到上限且都是静止
2.场景中活动实体达到上限且经过一段时间没失败
失败条件:
存在实体的y坐标超过屏幕下限(就是掉下去啦)
当然要在心跳函数中实时判断过关还是失败啦:
里面还加了一发重力感应:
对于三角形来说有点麻烦,三角形是通过创建多边形fromPolygon来实现的。fromPolygon是body的一个方法,给他坐标,它就能自动给你搞出来一个shape绑到body上
要根据三角形三点坐标算一下重心(centroid)。之后根据重心坐标对三个坐标做减法(subtract)
三个函数差不多的。先显示图,为这个图添加事件侦听。具体的图片移动看这个 http://edn.egret.com/cn/docs/page/583 我就不细说了,在最后手离开屏幕的事件中,为这个贴图创建一个刚体body,以及shape。
ps:流程图在线画哒:https://www.processon.com/network
初始化,大清洗,世界清空,显示清空
关卡函数
每个关卡函数就是这个样子啦
其他的就是基本教程里的东西啦,按钮啊,事件啦
over~
http://dev.redianbar.com/6fb2e2ef1a/
因为有重力感应,手机玩效果好一些,微信扫一扫!(用的是比赛官方给的服务器,不知道什么时候链接就会失效)。。
好了!我们开始:
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~
相关文章推荐
- Android出现Immutable bitmap passed to Canvas constructor错误的原因
- scst target在设置开机自启动时所遇问题的原因及解决办法
- Centos下python安装 MySQLdb报错
- 基础
- 实现在GET请求下调用WCF服务时传递对象(复合类型)参数
- Android快捷方式解密
- Android设置Settings实现:PreferenceActivity
- Atom插件安装及推荐
- android微信分享到朋友圈 图片过大闪退
- 2015年人力资源管理十大新趋势
- js制作日历,获取月份内有多少天。
- android ant多渠道混淆打包
- VS2010创建和使用COM组件
- Git学习笔记与IntelliJ IDEA整合 - MrJun
- c#快排算法
- Android应用程序永久获取root权限方法
- 1203 实验三 进程调度模拟实验
- 堆和栈
- Java+MySQL实现网络爬虫程序
- print打印16进制时前面会多很多FF,解决办法。