所用平台:cocos creator
所用语言:js
游戏的实现点:
1.可碰撞物体:以白球、其他球、球袋、球杆、球桌分五类,使用creator内置的操作设置可产生碰撞的节点;添加刚体,以节点形状选择刚体形状。以节点属性选择刚体类型是静态还是动态,其中球袋要多设置一项:
sensor,即不产生碰撞效果,只产生碰撞监测。
2.球杆的移动、拉伸:球杆要随着白球为中心移动,为不接触白球,要设置最小距离,达到此距离则隐藏。以点击点与白球中心得到一个向量,用得到的向量长度拉伸球杆并改变球杆冲量;向量和水平轴的夹角得到球杆旋转度数。
3.白球进洞操作区别其他球:白球缩小尺寸,其他球则在完全隐藏,这样可以继续对白球的操作,同时,对其他球可以通过每帧执行一个函数:检查球桌上是否还有其他球(除白球)来判断游戏胜利。
代码
* 挂在白球节点上 cc.Class({ extends: cc.Component, properties: { cue: { type:
cc.Node,default: null, }, max_dis: 100, min_dis: 5, // 如果拖动的距离到白球的中心 <
这个距离,那么我们就隐藏球杆,否者的话,显示球杆; }, start () { this.body = this
.getComponent(cc.RigidBody);this.cue_inst = this.cue.getComponent("cue"); this
.start_x =this.node.x; this.start_y = this.node.y; this
.node.on(cc.Node.EventType.TOUCH_START,function(e) { }.bind(this), this); this
.node.on(cc.Node.EventType.TOUCH_MOVE,function(e) { var w_pos = e.getLocation();
var dst = this.node.parent.convertToNodeSpaceAR(w_pos);
//相对于this.node.parent(canvas)这个为参照物,AR为原点的坐标,(假设)白球移动到移动到世界坐标为 w_pos
//就是去获得点击点的二维向量 var src = this.node.getPosition();//白球二维向量 var dir =
cc.pSub(dst, src);//向量相减得到的一个方向向量 var len = cc.pLength(dir); if (len < this
.min_dis) {this.cue.active = false; // 设置球杆为隐藏; return; } if (len > this
.max_dis) {this.cue.active = false; // 设置球杆为隐藏; return; } this.cue.active = true
;var r = Math.atan2(dir.y, dir.x);//得到弧度 var degree = r * 180 / Math.PI; degree
=360 - degree; this.cue.rotation = degree + 90; //旋转球杆 var cue_pos = dst; var
cue_len_half =this.cue.width * 0.1;//本来cue的锚点在中心的,应该是* 0.5的 cue_pos.x +=
(cue_len_half * dir.x / len); cue_pos.y += (cue_len_half * dir.y / len);
//使得球杆好像在随着点击点的后移向后拉 this.cue.setPosition(cue_pos); }.bind(this), this); this
.node.on(cc.Node.EventType.TOUCH_END,function(e) { if(this.cue.active === false
) {return; } this.cue_inst.shoot_at(this.node.getPosition());//朝白球方向射击 }.bind(
this), this); this.node.on(cc.Node.EventType.TOUCH_CANCEL, function(e) { if(this
.cue.active ===false) { return; } this.cue_inst.shoot_at(this
.node.getPosition()); }.bind(this), this); }, reset: function() { this
.node.scale =0.35;//当时加入的时候就是0.35 this.node.x = this.start_x; this.node.y = this
.start_y;this.body.linearVelocity = cc.p(0, 0);//线性转速 this.body.angularVelocity
=0;//角转速 }, onBeginContact: function(contact, selfCollider, otherCollider) {
// 白球有可能,碰球杆,碰球,碰边,球袋 if(otherCollider.node.groupIndex == 2) { //
隔1秒一种,要把白球放回原处; this.node.scale = 0;//消失 this.scheduleOnce(this.reset.bind(this
),1);//1秒后白球重置 // end return; } }, // update (dt) {}, });
* 挂在其他球节点上 cc.Class({ extends: cc.Component, //
属性列表,它将会作为组件实例的数据成员,到组件里面,绑定到我们的编辑器上; properties: { value: 1, }, onLoad () {
//每帧比update先 // this,指的就是当前的组件实例 }, start () {//初始化时 // this,指的就是当前的组件实例 this
.body =this.getComponent(cc.RigidBody);//同一节点的其他组件 this.start_x = this.node.x;
this.start_y = this.node.y; }, // dt: 距离上一次刷新的时间; update (dt) {//每帧 //
this,指的就是当前的组件实例 }, reset: function() { this.node.active = true; this.node.x =
this.start_x; this.node.y = this.start_y; this.body.linearVelocity = cc.p(0, 0);
this.body.angularVelocity = 0; }, onBeginContact: function(contact,
selfCollider, otherCollider) { // 白球有可能,碰球杆,碰球,碰边,球袋 if
(otherCollider.node.groupIndex ==2) { this.node.active = false; return; } }, });
* 挂在canvas节点上的游戏引擎 cc.Class({ extends: cc.Component, properties: { is_debug:
false, gravity: cc.p(0, -320), }, // onLoad () {}, onLoad: function() { cc
.director.getPhysicsManager().enabled = true; if(this.is_debug) { var Bits = cc
.PhysicsManager.DrawBits; cc.director.getPhysicsManager().debugDrawFlags = Bits
.e_jointBit | Bits.e_shapeBit; } else cc.director.getPhysicsManager()
.debugDrawFlags = 0; cc.director.getPhysicsManager().gravity = this.gravity; },
// update (dt) {}, });
* 挂在canvas节点上总场景 cc.Class({ extends: cc.Component, properties: { ball_root: {
type: cc.Node,default: null, }, w_ball: { type: cc.Node, default: null, }, },
// onLoad () {}, start () { this.is_game_started = true; }, restart_game:
function() { for(var i = 0; i < this.ball_root.childrenCount; i ++) { var b =
this.ball_root.children[i]; b.getComponent("ball").reset(); } this
.w_ball.getComponent("w_ball").reset(); this.is_game_started = true; },
check_game_over:function() { for(var i = 0; i < this.ball_root.childrenCount; i
++) {var b = this.ball_root.children[i]; if(b.active === true) { return; } }
this.is_game_started = false; // game_over; this.scheduleOnce(this
.restart_game.bind(this), 3); }, update (dt) { if (!this.is_game_started) {
return; } // 是否所有的球都打入进去了; }, });
挂在球杆节点上
cc.Class({ extends: cc.Component, properties: { SHOOT_POWER: 18, // 合适的值就可以了 },
// onLoad () {}, start () { this.body = this.getComponent(cc.RigidBody); },
shoot_at:function(dst) { // 冲量: 给这个球杆一个方向的冲量,矢量,大小,有方向; // 方向问题: src---> dst;
var src = this.node.getPosition();//此时的球杆头位置 var dir = cc.pSub(dst, src);
//dst白球位置 // 大小问题; var cue_len_half = this.node.width * 0.5; var len =
cc.pLength(dir);var distance = len - cue_len_half; // end var power_x =
distance *this.SHOOT_POWER * dir.x / len; var power_y = distance * this
.SHOOT_POWER * dir.y / len;//对该点施加冲量 applyLinearImpulse(冲量大小向量, 球杆的原点转成世界坐标,
true) this.body.applyLinearImpulse(cc.p(power_x, power_y), this
.node.convertToWorldSpaceAR(cc.p(0, 0)), true); }, onPreSolve: function
(contact, selfCollider, otherCollider) { this.node.active = false; }, // update
(dt) {}, });
热门工具 换一换