天天看点

见缝插针小游戏开发

一、主要逻辑

​ 首先根据配置表设置好游戏数据(比如大球的旋转速度、旋转方向、默认已经插上的针数及间隔角度,小球的数量等按需设置即可),开始游戏后大球不停的旋转,点击屏幕从下方发射“大头针”,并计算好移动距离,这样可以不需要检测针尖和大球的碰撞,当“大头针”移动到指定位置时修改它的父节点为大球,关键来了,这里因为大球一直在旋转,为了让“大头针”始终垂直的插上大球,这里要正确设置小球的旋转角度,大头针的目标坐标为大球的底部,根据大球的半径和角度可以求得具体x、y。如果大头针和大头针相碰了则游戏失败,如果没有相碰则继续下一轮,如果全部发射完毕则过关。

二、主要结构

​ 大球-小球-大头针

​ 大球:只是个精灵节点

​ 小球: 下方待发射区展示用,精灵+label显示编号

​ 大头针:点击发射时,根据小球的编号来创建一个大头针并使其飞向大球同时移除待发射区最上面的一颗小球,大头针的锚点为针尖位置,方便计算旋转角度。

三、上代码:

大头针
/**
 * Created by xujiawei on 2020-04-29 17:58:39
 */

cc.Class({
    extends: cc.Component,
    properties: {
        arrow: cc.Node,
        numLabel: cc.Label,
    },

    initSmallBall(params) {
        this.numLabel.string = params.num;
        this.arrow.active = !!params.showArrow;
    },

    /**
    * 当碰撞产生的时候调用
    * @param  {Collider} other 产生碰撞的另一个碰撞组件
    * @param  {Collider} self  产生碰撞的自身的碰撞组件
    */
    onCollisionEnter: function (other, self) {
        other.node.stopAllActions();
        self.node.stopAllActions();
        zy.event.emit("gameover");
        cc.log('小球碰撞,游戏失败');
    }
});
           
主要逻辑 Game.js
/**
 * Created by xujiawei on 2020-04-29 17:37:50
 */

cc.Class({
    extends: cc.Component,
    properties: {
        ballPanel: cc.Node,
        smallBallPF: cc.Prefab,
        bigBall: cc.Node,
        levelLabel: cc.Label,
        bulletNode: cc.Node,
        bgNode: cc.Node,
    },

    init(params) {
        this.smallBalls = [];
        this.tmpBalls = []; // 发射的尚未添加到大球上的小球
        this._bigSpeed = 0;
        this._bigDir = -1;
        this._gameStart = false;
        this.curLevel = zy.dataMng.userData.curLevel;
        this.curLevel = parseInt(this.curLevel);
        this.loadLevel(this.curLevel);
    },

    loadLevel(l) {
        let data = zy.dataMng.levelData.getLevelData(l);
        this._bigDir = data.dir == 0 ? (Math.random() < 0.5 ? 1 : -1) : data.dir;
        this._bigSpeed = data.speed;
        this.levelLabel.string = "第 " + l + " 关";

        // 清空数据
        for (let b of this.tmpBalls) {
            b.destroy();
        }
        for (let b of this.smallBalls) {
            b.destroy();
        }
        this.tmpBalls.splice(0);
        this.smallBalls.splice(0);

        for (let i = 0; i < data.smallNum; i++) {
            let ball = cc.instantiate(this.bulletNode);
            ball.parent = this.ballPanel;
            this.smallBalls.push(ball);
            ball.getComponentInChildren(cc.Label).string = data.smallNum - i;
        }

        this.bgNode.color = cc.color("#436770");
        this.loadBigBall(data.bigNum);

        this.scheduleOnce(() => {
            this._gameStart = true;
        }, 0.1);
    },

    start() {
        let mng = cc.director.getCollisionManager();
        mng.enabled = true;
        // mng.enabledDebugDraw = true;
        // mng.enabledDrawBoundingBox = true;
        this.node.on(cc.Node.EventType.TOUCH_START, this.onTouchStart, this);
        zy.event.on("gameover", () => {
            if (this._gameStart) {
                this._gameStart = false;
                this.bgNode.color = cc.color("#7A3341");
                zy.ui.tip.show("游戏失败,即将重新开始");
                this.scheduleOnce(() => {
                    this.loadLevel(this.curLevel);
                }, 2);
            }
        }, this);
    },

    loadBigBall(counts) {
        this.bigBall.destroyAllChildren();
        let radius = this.bigBall.width / 2 - 2;
        let degree = 360 / counts;
        for (let i = 0; i < counts; i++) {
            let ball = cc.instantiate(this.smallBallPF);
            let radian = cc.misc.degreesToRadians(i * degree);
            let x = radius * Math.sin(radian);
            let y = radius * Math.cos(radian);
            ball.x = x;
            ball.y = y;
            ball.parent = this.bigBall;
            // 计算旋转角度
            ball.angle = 180 - i * degree;
            ball.getChildByName("numLabel").active = false;
        }
    },

    onTouchStart(event) {
        if (!this._gameStart) {
            return;
        }

        if (this.smallBalls.length > 0) {
            let bullet = this.smallBalls.shift();
            let wordPos = bullet.parent.convertToWorldSpaceAR(bullet.getPosition());

            let ball = cc.instantiate(this.smallBallPF);
            ball.getComponentInChildren(cc.Label).string = bullet.getComponentInChildren(cc.Label).string;
            ball.parent = this.bigBall.parent;
            ball.position = this.bigBall.parent.convertToNodeSpaceAR(wordPos);
            this.tmpBalls.push(ball);
            bullet.destroy();

            let radius = this.bigBall.height / 2 - 2;
            let des = cc.v2(0, this.bigBall.y - radius);
            ball.runAction(cc.sequence(cc.moveTo(0.05, des).easing(cc.easeSineOut()), cc.callFunc(() => {
                this.tmpBalls.shift();
                ball.parent = this.bigBall;
                let angle = this.bigBall.angle;
                angle = angle % 360 + 180;
                let radian = cc.misc.degreesToRadians(angle);

                let x = radius * Math.sin(radian);
                let y = radius * Math.cos(radian);
                ball.x = x;
                ball.y = y;
                ball.angle = 180 - angle;

                this.scheduleOnce(this._checkPass.bind(this), 0);
            })));
        }
    },

    _checkPass() {
        if (this._gameStart && this.smallBalls.length == 0) {
            this._gameStart = false;
            this.bgNode.color = cc.color("#4C7043");
            let des = "恭喜过关,即将进入下一关";
            const max = zy.dataMng.levelData.getMaxLevel();
            if (this.curLevel < max) {
                this.curLevel += 1;
            } else {
                des = "恭喜你通关了";
            }
            zy.ui.tip.show(des);
            this.scheduleOnce(() => {
                this.loadLevel(this.curLevel);
            }, 2);

            zy.dataMng.userData.curLevel = this.curLevel;
        }
        
    },

    lateUpdate(dt) {
        if (!this._gameStart) {
            return;
        }
        this.bigBall.angle += this._bigDir * this._bigSpeed;
    }
});
           

源码下载

见缝插针小游戏开发

继续阅读