【Cocos Creator游戏开发教程】仿微信趣味画赛车小游戏(一)前言,界面UI 【Cocos Creator游戏开发教程】仿微信趣味画赛车小游戏(二)物理刚体关节
项目地址已放到 github 上,需要的小伙伴可自行下载。 这节我们讲一下游戏代码实现
1.开启物理世界
protected onLoad(): void {
cc.director.getPhysicsManager().enabled = true;
}
protected start(): void {
cc.debug.setDisplayStats(false);
this.openPhysics();
this.node.on(DrawArea.DRAW_VEHICLE, this.onDrawVehicle, this);
}
private openPhysics(): void {
let manager: cc.PhysicsManager = cc.director.getPhysicsManager();
manager.enabledAccumulator = true;
manager.debugDrawFlags = 1;
cc.PhysicsManager.FIXED_TIME_STEP = 1 / 30;
cc.PhysicsManager.VELOCITY_ITERATIONS = 8;
cc.PhysicsManager.POSITION_ITERATIONS = 8;
}
2.画车
监听触摸DrawArea开始事件,将绘画节点移到触摸点,记录存储当前触摸点
private onTouchStart(event: cc.Event.EventTouch): void {
let pos = this.node.convertToNodeSpaceAR(event.getLocation());
this.drawLine.moveTo(pos.x, pos.y);
this.recordPos = cc.v2(pos.x, pos.y);
this.drawPoints.push(cc.v2(pos.x, pos.y));
}
监听触摸DrawArea移动事件
private onTouchMove(event: cc.Event.EventTouch): void {
let pos: cc.Vec2 = this.node.convertToNodeSpaceAR(event.getLocation());
let widthLimit: number = (this.node.width + DrawArea.DRAW_CIRCLE_R) / 2;
let heightLimit: number = (this.node.height + DrawArea.DRAW_CIRCLE_R) / 2;
if (pos.x < -widthLimit || pos.x > widthLimit) {
return;
}
if (pos.y < -heightLimit || pos.y > heightLimit) {
return;
}
this.drawLine.lineTo(pos.x, pos.y);
this.drawLine.stroke();
this.drawLine.moveTo(pos.x, pos.y);
this.currentPos = cc.v2(pos.x, pos.y);
let subVec: cc.Vec2 = this.currentPos.sub(this.recordPos);
let distance: number = subVec.mag() + 5;
if (distance >= 25) {
this.recordPos = cc.v2(pos.x, pos.y);
this.drawPoints.push(cc.v2(pos.x, pos.y));
}
}
监听触摸DrawArea结束事件,发送自定义画车事件,将触摸点数组发送出去
private onTouchEnd(event: cc.Event.EventTouch): void {
if (this.drawPoints.length <= 1) {
this.drawPoints = [];
return;
}
let customEvent: cc.Event.EventCustom = new cc.Event.EventCustom(DrawArea.DRAW_VEHICLE, true);
customEvent.setUserData(this.drawPoints);
this.node.dispatchEvent(customEvent);
this.drawLine.clear();
this.drawPoints = [];
}
3.创建小车
监听自定义画车事件,获取绘画节点数组,调用Vehicle.ts脚本刷新小车
private onDrawVehicle(event: cc.Event.EventCustom): void {
event.stopPropagation();
(this.vehicle.getComponent('Vehicle') as Vehicle).updateVehicle(event.getUserData());
}
收到监听,调用刷新车方法
public updateVehicle(drawPoints: Array<cc.Vec2>): void {
if (drawPoints.length <= 0) {
return;
}
let _self = this;
_self.node.x = 0;
_self.node.y = 200;
_self.resetVehicle();
_self.drawVehicleBody(drawPoints);
_self.drawWheel(drawPoints);
if (!_self.node.active) {
_self.node.active = true;
}
}
重置车,清空子节点
private resetVehicle(): void {
let _self = this;
let vehicleNode: cc.Node = _self.vehicle.node;
vehicleNode.removeAllChildren();
_self.vehicleBodys = [];
_self.wheelRear = null;
_self.wheelFront = null;
}
画车身
private drawVehicleBody(drawPoints: Array<cc.Vec2>): void {
let _self = this;
let vehicleNode: cc.Node = _self.vehicle.node;
let beforePos: cc.Vec2 = drawPoints[0];
for (let i = 1; i < drawPoints.length; i++) {
let curPos: cc.Vec2 = drawPoints[i];
let subVec: cc.Vec2 = curPos.sub(beforePos);
let distance: number = subVec.mag() + 5;
let tempVec: cc.Vec2 = cc.v2(0, 10);
let rotateVec: number = subVec.signAngle(tempVec) / Math.PI * 180 - 90;
let lineItem: cc.Node = cc.instantiate(_self.linePrefab);
lineItem.angle = -rotateVec;
lineItem.setPosition(beforePos);
lineItem.setParent(vehicleNode);
lineItem.width = distance;
lineItem.getComponent(cc.PhysicsBoxCollider).offset.x = lineItem.width / 2;
lineItem.getComponent(cc.PhysicsBoxCollider).size.width = lineItem.width;
lineItem.getComponent(cc.PhysicsBoxCollider).sensor = true;
lineItem.getComponent(cc.PhysicsBoxCollider).restitution = 100;
lineItem.getComponent(cc.PhysicsBoxCollider).apply();
if (_self.vehicleBodys.length > 0) {
let beforeLine: cc.Node = _self.vehicleBodys[_self.vehicleBodys.length - 1];
let weldJoint: cc.WeldJoint = lineItem.addComponent(cc.WeldJoint);
weldJoint.referenceAngle = -rotateVec - beforeLine.angle;
weldJoint.connectedBody = beforeLine.getComponent(cc.RigidBody);
weldJoint.connectedAnchor = cc.v2(beforeLine.width - 5, 0);
}
_self.vehicleBodys.push(lineItem);
beforePos = cc.v2(curPos.x, curPos.y);
}
}
画轮子
private drawWheel(drawPoints: Array<cc.Vec2>): void {
let _self = this;
let vehicleNode: cc.Node = _self.vehicle.node;
let lineRear: cc.Node = _self.vehicleBodys[0];
let lineFront: cc.Node = _self.vehicleBodys[_self.vehicleBodys.length - 1];
let wheelSF: cc.SpriteFrame = new cc.SpriteFrame("HelloWorld");
let rearPos: cc.Vec2 = drawPoints[0];
let frontPos: cc.Vec2 = drawPoints[drawPoints.length - 1];
let wheelRear: cc.Node = cc.instantiate(_self.wheelPrefab);
wheelRear.getComponent(cc.Sprite).spriteFrame = wheelSF;
wheelRear.setPosition(rearPos);
vehicleNode.addChild(wheelRear);
let wheelFront: cc.Node = cc.instantiate(_self.wheelPrefab);
wheelRear.getComponent(cc.Sprite).spriteFrame = wheelSF;
wheelFront.setPosition(frontPos);
vehicleNode.addChild(wheelFront);
wheelRear.getComponent(cc.PhysicsCircleCollider).tag = VehicleEnum.COLLIDER_TAG.REAR_TAG;
wheelFront.getComponent(cc.PhysicsCircleCollider).tag = VehicleEnum.COLLIDER_TAG.FRONT_TAG;
wheelRear.getComponent(cc.PhysicsCircleCollider).apply();
wheelFront.getComponent(cc.PhysicsCircleCollider).apply();
let wheelJointRear: cc.WheelJoint = ComponentUtil.addWheelJointToObj(lineRear, {
connectedNode: wheelRear,
anchor: cc.v2(0, 0)
});
let wheelJointFront: cc.WheelJoint = ComponentUtil.addWheelJointToObj(lineFront, {
connectedNode: wheelFront,
anchor: cc.v2(lineFront.width - 5, 0)
});
let distanceJoint: cc.DistanceJoint = wheelRear.addComponent(cc.DistanceJoint);
distanceJoint.connectedBody = wheelFront.getComponent(cc.RigidBody);
distanceJoint.distance = frontPos.sub(rearPos).mag();
_self.wheelRear = wheelRear;
_self.wheelFront = wheelFront;
}
|