游戏节点结构:
最终效果
游戏逻辑
- 添加玩家与子弹的生成
玩家的节点主要控制移动的点击事件监听、子弹的动态生成
因为子弹需要频繁地生成与消除,故使用对象池来动态生成子弹,在Player脚本中生成子弹,在子弹脚本添加控制运动与碰撞的响应方法。
玩家Player_plane脚本:移动响应方法、子弹动态生成方法、碰撞响应方法
- 敌人的动态生成,将敌人设置为预制体,在Game主控脚本中随机生成,同时在敌人的脚本中添加控制运动、碰撞响应(包括被子弹击中和与玩家碰撞)
- 得分统计,使用Score脚本中静态变量来计分
- 游戏结束提示框,初始设置active属性为false,使用脚本控制在Game的游戏结束方法中唤起
- 背景滚动:添加两张图片,如下,并控制移动速度,在背景的位置到达边界时在重设位置。
- 一些细节动画在脚本中显示
注意将背景用widget组件设置位置,同时脚本中为相对Canvas的位置,注意区分。
脚本
Player_plane脚本
import Game from "./Game";
const {
ccclass, property } = cc._decorator;
@ccclass
export default class Player_plane extends cc.Component {
@property(cc.SpriteFrame)
explodeImg: cc.SpriteFrame = null;
private canvasNode: cc.Node = null;
interval = 0.2;
onLoad() {
this.node.on('touchmove', this.onMove, this);
this.schedule(this.onTimer, this.interval);
this.canvasNode = cc.find('Canvas');
}
//移动响应方法
onMove(e: cc.Event.EventTouch) {
let de = e.getDelta();
this.node.x += de.x;
}
//发射子弹
onTimer() {
//获得预制体中的节点
let bulletNode = Game.bulletPool.get();
if (bulletNode == null) {
bulletNode = cc.instantiate(Game.inst.bulletPrefab);
}
//设置节点的位置与层级
bulletNode.parent = this.canvasNode;
bulletNode.x = this.node.x;
bulletNode.y = this.node.y + 75;
}
//碰撞响应,游戏结束
onCollisionEnter(other, self) {
cc.log("碰撞");
this.endGame();
}
endGame() {
this.explode();
Game.inst.endGame();
this.clear();
}
//将屏幕上的子弹和敌人都清空
clear() {
let nodes: cc.Node[] = this.canvasNode.children;
//注意这里要倒着遍历,每一次删除节点索引都会变化
for (let i = nodes.length-1; i > 0; i--) {
let node = nodes[i];
if (node.name == "激光") {
nodes[i].destroy();
}
else if (node.name == "敌人") {
nodes[i].destroy();
}
}
}
explode() {
//生成爆炸节点
let node = new cc.Node();
node.parent = cc.find('Canvas');
node.setPosition(this.node.getPosition());
this