用ts代码实现吃鸡游戏刷毒小demo(cocos creator引擎)
闲来无事,写下来的,用的cocos creator引擎
刷毒逻辑一般为四个步骤:
1,安全区在毒圈内重新刷新,外圆必须全包含内圆
2,倒计时结束,毒圈沿着毒圈圆心点缩小
3,当外圆与内圆相切的时候,相切点不动,毒圈继续缩小,但外圆圆心朝内圆圆心移动
4,当内圆半径等于外圆时,重新刷新下一个安全区,以此内推
实现步骤:
搭建场景:
用的正方形场景,模拟一个大地图,毒圈用了引擎带的mask组件,反向遮罩,这样就产生了一个中间空白的圆,四周绿布的效果
代码:
完整代码如下:
const { ccclass, property } = cc._decorator;
@ccclass
export default class Test extends cc.Component {
@property(cc.Node)
safeNode: cc.Node = null;//安全区节点
@property(cc.Node)
poisonNode: cc.Node = null;//毒圈节点
@property(cc.Label)
timeLab: cc.Label = null;//倒计时lablel
// LIFE-CYCLE CALLBACKS:
private _radio = 640;//安全区的半径
private _safeNodeCenter = cc.v2(0, 0);//安全区的圆心坐标
private _moveSpeed = 2;//毒圈每帧移动速度
private _canMove = false;//是否可以移动毒圈
private _startCount = false;//是否开始倒计时缩毒
private _time = 4;//倒计时缩毒的时间
// onLoad () {}
start() {
this.setSafeNode();
}
/**
* 加载下一个安全区
*/
setSafeNode() {
this._radio /= 2;//每次半径减少一半
this._moveSpeed /= 2;//每次毒圈移动速度减少一半
this.safeNode.width = this._radio * 2;
this.safeNode.height = this._radio * 2;//安全区宽高等于圆的直径
let centerPos = this.getSafeNodeCenterPos();
this._safeNodeCenter.x += centerPos.x;
this._safeNodeCenter.y += centerPos.y;
this.safeNode.position = cc.v3(this._safeNodeCenter.x, this._safeNodeCenter.y, 0);
this._startCount = true;//开始倒计时
this.timeLab.node.active = true;
}
/**
* 获取下一个安全区的圆心
* @returns
*/
getSafeNodeCenterPos(): cc.Vec2 {
let dis = this.safeNode.width / 2;
dis *= Math.random();
let randAngle = Math.random() * 360;
let x = Math.cos(randAngle) * dis;
let y = Math.sin(randAngle) * dis;
return cc.v2(x, y);
}
/**
* 判断两个圆是否重合,或者是相内切
* @param pOuter 外圆圆心
* @param rOuter 外圆半径
* @param pInner 内圆圆心
* @param rInner 内圆半径
* @returns
*/
isIntersect(pOuter, rOuter, pInner, rInner) {
//判定条件:两圆心的距离 + rInner = rOuter
var distance = parseFloat('' + Math.sqrt((pOuter.x - pInner.x) * (pOuter.x - pInner.x) + (pOuter.y - pInner.y) * (pOuter.y - pInner.y)))
if (distance + rInner >= rOuter) {
return true;
}
return false;
}
/**
* 相切后,毒圈圆心朝安全区圆心移动
*/
movePoisonNode() {
if (Math.abs(this.poisonNode.x - this._safeNodeCenter.x) + Math.abs(this.poisonNode.y - this._safeNodeCenter.y) <= 4) {
this.poisonNode.x = this._safeNodeCenter.x;
this.poisonNode.y = this._safeNodeCenter.y;
this._canMove = false;
this.setSafeNode();
}
let moveCenter = this.poisonNode.position;
let speed = Math.sqrt(this._moveSpeed * this._moveSpeed * 2);
let angle = this.countAngle(this._safeNodeCenter, moveCenter);
let x = Math.cos(angle) * speed;
let y = Math.sin(angle) * speed;
this.poisonNode.x += x;
this.poisonNode.y += y;
}
/**
* 计算两个点的angle
* @param p1
* @param p2
* @returns
*/
countAngle(p1, p2) {
var angle: number = Math.atan2((p2.y - p1.y), (p2.x - p1.x)); //弧度
var theta: number = angle * (180 / Math.PI); //角度
return theta;
}
update(dt) {
if (this._startCount) {
this._time -= dt;
this.timeLab.string = Math.floor(this._time) + '';
if (this._time <= 0) {
this._canMove = true;
this.timeLab.node.active = false;
this._startCount = false;
}
} else {
this._time = 4;
}
if (!this._canMove) {
return
}
let inCenter = this.isIntersect(this.poisonNode.position, this.poisonNode.width / 2, this._safeNodeCenter, this.safeNode.width / 2);
this.poisonNode.width -= this._moveSpeed;
this.poisonNode.height -= this._moveSpeed;
if (inCenter) {
//已经相切,要移动
this.movePoisonNode();
}
}
}