Cocos creator实现飞机大战空中大战《战击长空》小游戏资源及代码
最近在学习Cocos Creator,作为新手,刚刚开始学习Cocos Creator,刚刚入门,这里记录一下飞机大战小游戏实现。
https://wxaurl.cn/VEgRy2eTMyi
一 安装CocosDashBoard
这里就不介绍如何安装了
二 新建2D项目FlyWar
2.1、管理项目目录
在资源管理器中新建文件夹
anim 动画
preb 预制体
res 图片、语音资源
scene 场景
scripts 脚本资源
将资源文件拖到res目录下
三、关键步骤
3.1 实现背景的移动代码
背景的星空会有移动的效果
import GameConstant from "./GameConstant";
const {ccclass, property} = cc._decorator;
@ccclass
export default class MoveBackground extends cc.Component {
bgs : cc.Node[];
@property
speed : number = 50;
canvasWidth: number;
canvasHeight: number;
onLoad () {
let canvas = cc.find('Canvas');
this.canvasWidth = canvas.width;
this.canvasHeight = canvas.height;
// 注册特定事件
cc.director.on(GameConstant.kUpdateGameStatus, this.listenGameStatus, this);
}
listenGameStatus() {
}
start () {
this.node.width= this.canvasWidth;
this.node.height = this.canvasHeight;
this.bgs = this.node.children;
for (let index = 0; index < this.bgs.length; index++) {
let element = this.bgs[index];
element.width = this.canvasWidth;
element.height = this.canvasHeight;
}
// 设置默认
if (this.bgs.length >= 2) {
this.bgs[1].y = this.bgs[0].y + this.bgs[0].height;
}
}
update (dt) {
this.bgs[0].y -= this.speed * dt;
this.bgs[1].y -= this.speed * dt;
if (this.bgs[0].y < -this.canvasHeight) {
this.bgs[0].y = this.bgs[1].y + this.bgs[1].height;
}
if (this.bgs[1].y < -this.canvasHeight) {
this.bgs[1].y = this.bgs[0].y + this.bgs[0].height;
}
}
}
3.2 实现自己飞机的绑定击碰撞检测
首先将load方法中开启碰撞检测
// 碰撞检测
cc.director.getCollisionManager().enabled = true;
将手指移动飞机
start() {
// touch input
this.node.on(cc.Node.EventType.TOUCH_START, this.onTouchBegan, this);
this.node.on(cc.Node.EventType.TOUCH_END, this.onTouchEnded, this);
this.node.on(cc.Node.EventType.TOUCH_CANCEL, this.onTouchEnded, this);
this.node.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
}
// touch事件
onTouchBegan(event) {
if (this.isSelected == true) {
return;
}
let position = event.getLocation();
this.isSelected = true;
this.touchStartX = position.x;
this.touchStartY = position.y;
}
onTouchEnded() {
this.isSelected = false;
}
onTouchMove(e: cc.Event.EventTouch) {
let gameStatus = GameStateManager.instance().getGameStatus();
if (this.isSelected && (GameConstant.GameStatus.BOSSBOOMFINISH != gameStatus)) {
let position = e.getLocation();
let moveX = position.x;
let moveY = position.y;
let disX = (moveX - this.touchStartX);
let disY = (moveY - this.touchStartY);
this.updateNodeX(disX, disY);
this.touchStartX = position.x;
this.touchStartY = position.y;
}
}
// 更新位置
updateNodeX(distanceX, distanceY) {
this.playerRoot.x += distanceX;
if (this.playerRoot.x < -this.canvasWidth / 2) {
this.playerRoot.x = -this.canvasWidth / 2;
}
if (this.playerRoot.x > this.canvasWidth / 2) {
this.playerRoot.x = this.canvasWidth / 2;
}
this.playerRoot.y += distanceY;
if (this.playerRoot.y < -this.canvasHeight / 2) {
this.playerRoot.y = -this.canvasHeight / 2;
}
if (this.playerRoot.y > this.canvasHeight / 2) {
this.playerRoot.y = this.canvasHeight / 2;
}
this.playerBulletRoot.x = this.playerRoot.x;
this.playerBulletRoot.y = this.playerRoot.y + 50;
}
玩家飞机的碰撞,当碰撞到不同的敌机就会出现血量减少的
onCollisionEnter(other, self) {
if (this.isDead == true) {
return;
}
let deltax = 0;
if (other.tag == 999) {
// 撞击到敌机BOSS
// dead,游戏结束,跳转到结果页面
this.isDead = true;
this.showPlaneBoom();
return;
}
if (other.tag == 888) {
// 获得金币,每个金币50分
this.updateScore();
}
if (other.tag == 911) {
// 获得血量
this.updateBlood();
}
if (other.tag == 100 || other.tag == 914) {
// 默认子弹 -1
// 减去血量
this.bloodNumber -= 1;
deltax = 1;
} else if (other.tag == 101 || other.tag == 102) {
// boss大炮弹 -5
this.bloodNumber -= 5;
deltax = 5;
} else if ((other.tag == 90 || other.tag == 91)) {
// 敌机 -2
this.bloodNumber -= 2;
deltax = 2;
}
if (this.bloodNumber <= 0) {
// dead,游戏结束,跳转到结果页面
this.isDead = true;
this.showPlaneBoom();
}
if (this.bloodNumber < 0) {
this.bloodNumber = 0;
}
this.updateBloodUI(deltax);
}
// 血量控制参考
https://blog.csdn.net/gloryFlow/article/details/130898462
3.2 实现当前飞机发射子弹的效果
当前子弹发射会有角度设置,代码如下
import EnemyPlane from "./EnemyPlane";
const {ccclass, property} = cc._decorator;
// 直线的Bullet类型
@ccclass
export default class BulletLiner extends cc.Component {
// 角度,默认90
@property(Number)
rotation: number = 90;
// 速度
@property(Number)
speed: number = 1000;
// 时间
@property(Number)
time: number = 0.0;
// 时间点
lifeTime: number = 2.5;
// LIFE-CYCLE CALLBACKS:
// 初始位置
originPos: any;
canvasWidth: number;
canvasHeight: number;
isDead: boolean = false;
onLoad() {
let canvas = cc.find('Canvas');
this.canvasWidth = canvas.width;
this.canvasHeight = canvas.height;
}
start () {
this.originPos = this.node.position;
}
update (dt) {
this.onMove(dt);
}
// 移动
onMove(dt) {
let distance = dt * this.speed;
let radian = this.rotation * Math.PI / 180;
let v2 = this.node.position;
let delta = cc.v2(distance * Math.cos(radian), distance * Math.sin(radian));
v2.x += delta.x;
v2.y += delta.y;
this.node.position = v2;
if (v2.y > this.canvasHeight) {
this.node.removeFromParent();
this.node.destroy();
}
}
onCollisionEnter(other, self) {
if ((other.tag != 110 && other.tag != 1111 && other.tag != 9911 && other.tag != 911 && other.tag != 888) && !this.isDead) {
this.die();
}
}
die() {
this.isDead = true;
this.node.removeFromParent();
this.destroy();
}
}
3.4 敌机的移动击及碰撞检测
import GameStateManager from "./GameStateManager";
const { ccclass, property } = cc._decorator;
// 敌人飞机
@ccclass
export default class EnemyPlane extends cc.Component {
// 角度,默认90
@property(Number)
rotation: number = 90;
// 速度
@property(Number)
speed: number = 1000;
// 时间
@property(Number)
time: number = 0.0;
// 时间点
lifeTime: number = 2.5;
// LIFE-CYCLE CALLBACKS:
// 初始位置
originPos: any;
canvasWidth: number;
canvasHeight: number;
@property(cc.Prefab)
enemyBoom: cc.Prefab = null;
@property(cc.Prefab)
enemyBullet: cc.Prefab = null;
@property([cc.Prefab])
coinPrebs: cc.Prefab[] = [];
// 音效资源
@property(cc.AudioClip)
boomAudio: cc.AudioClip = null;
isDead: boolean = false;
isBoomAnimating: boolean = false;
onLoad() {
let canvas = cc.find('Canvas');
this.canvasWidth = canvas.width;
this.canvasHeight = canvas.height;
}
start() {
this.originPos = this.node.position;
this.enemyBulletSchedule();
}
update(dt) {
this.onMove(dt);
}
// 移动
onMove(dt) {
// this.time += dt;
// if (this.time >= this.lifeTime) {
// this.node.position = this.originPos;
// this.time = 0;
// }
let distance = dt * this.speed;
let radian = this.rotation * Math.PI / 180;
let v2 = this.node.position;
let delta = cc.v2(distance * Math.cos(radian), distance * Math.sin(radian));
v2.x -= delta.x;
v2.y -= delta.y;
this.node.position = v2;
if (v2.y < -this.canvasHeight) {
this.node.removeFromParent();
this.node.destroy();
}
}
// 动效效果
showPlaneBoom() {
if (this.isBoomAnimating) {
return;
}
// 调用声音引擎播放声音
cc.audioEngine.playEffect(this.boomAudio, false);
this.isBoomAnimating = true;
// 播放动画
let boom;
let callFunc = cc.callFunc(function () {
this.createCoin();
boom = cc.instantiate(this.enemyBoom);
this.node.parent.addChild(boom);
boom.setPosition(this.node.position);
this.node.removeFromParent();
let anim = boom.getComponent(cc.Animation);
anim.play('enemy_boom');
}, this);
let aTime = cc.delayTime(0.1);
let finish = cc.callFunc(function () {
boom.removeFromParent();
boom.destroy();
this.isBoomAnimating = false;
this.removeFromParent();
this.destroy();
}, this);
// 创建一个缓动
var tween = cc.tween()
// 按顺序执行动作
.sequence(callFunc, aTime, finish);
cc.tween(this.node).then(tween).start();
}
onCollisionEnter(other, self) {
if ((other.tag == 110 || other.tag == 1111) && !this.isDead) {
this.die();
}
}
die() {
this.isDead = true;
this.showPlaneBoom();
this.updateScore();
}
// 更新得分
updateScore() {
// 每个敌机得分为10
GameStateManager.instance().updateScore(10);
}
// 创建金币 每个金币10分
createCoin() {
let delta = 50;
for (let index = 0; index < this.coinPrebs.length; index++) {
let coin = cc.instantiate(this.coinPrebs[index]);
this.node.parent.addChild(coin);
coin.setPosition(this.node.position);
coin.x = this.node.x + Math.random() * delta;
coin.y = this.node.y;
}
}
// 倒计时
enemyBulletSchedule() {
this.schedule(this.onCreateEnemyBullet, 1.5);
}
onCreateEnemyBullet() {
let bullet = cc.instantiate(this.enemyBullet);
this.node.parent.addChild(bullet);
bullet.setPosition(this.node.position);
bullet.x = this.node.x;
bullet.y = this.node.y;
}
stopSchedule() {
this.unschedule(this.onCreateEnemyBullet);
}
protected onDestroy(): void {
this.stopSchedule();
}
}
3.5 敌机BOSS
敌机BOSS有血量
当前敌机BOSS只要血量为0时候就是击败了该BOSS
// Learn TypeScript:
// - https://docs.cocos.com/creator/2.4/manual/en/scripting/typescript.html
// Learn Attribute:
// - https://docs.cocos.com/creator/2.4/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
// - https://docs.cocos.com/creator/2.4/manual/en/scripting/life-cycle-callbacks.html
import EnemyBossBoom from "./EnemyBossBoom";
import GameConstant from "./GameConstant";
import GameStateManager from "./GameStateManager";
const {ccclass, property} = cc._decorator;
@ccclass
export default class EnemyBossPlane extends cc.Component {
@property(cc.Prefab)
bloodBarPreb: cc.Prefab = null;
// boss爆炸效果
@property(cc.Prefab)
bossBoomPreb: cc.Prefab = null;
// 血量
@property(Number)
bloodCount: number = 100;
@property(Number)
bloodNumber: number = 100;
// LIFE-CYCLE CALLBACKS:
bloodBar: cc.ProgressBar = null;
isDead: boolean = false;
onLoad () {
// 不同等级boss的血量不同
// this.bloodNumber = 100;
// this.bloodCount = 100;
let blood = cc.instantiate(this.bloodBarPreb);
blood.y = 100;
blood.x = 0;
this.node.addChild(blood);
this.bloodBar = blood.getComponent(cc.ProgressBar);
this.bloodBar.progress = 1.0;
this.bloodBar.getComponentInChildren(cc.Label).string = ""+this.bloodNumber;
}
start () {
this.bloodBar.getComponentInChildren(cc.Label).string = ""+this.bloodNumber;
}
update (dt) {}
// 更新血量
updateBloodCount(aBloodCount) {
this.bloodNumber = aBloodCount;
this.bloodCount = aBloodCount;
}
onCollisionEnter(other, self) {
if (this.isDead == true) {
return;
}
let deltax = 0;
if (other.tag == 110) {
// 默认子弹 -1
// 减去血量
this.bloodNumber -= 1;
deltax = 1;
}
if (this.bloodNumber <= 0) {
// dead,游戏结束,跳转到结果页面
this.isDead = true;
this.startBossBoom();
}
if (this.bloodNumber < 0) {
this.bloodNumber = 0;
}
this.bloodBar.getComponentInChildren(cc.Label).string = ""+this.bloodNumber;
let progress = this.bloodNumber/this.bloodCount;
let totalLength = this.bloodBar.totalLength;
this.bloodBar.getComponentInChildren(cc.Label).node.x -= deltax*(totalLength/this.bloodCount);
this.bloodBar.progress = progress;
}
// boss爆炸了
startBossBoom() {
GameStateManager.instance().updateGameStatus(GameConstant.GameStatus.BOSSDISMISSING);
let bossBoom = cc.instantiate(this.bossBoomPreb);
bossBoom.y = 0;
bossBoom.x = 0;
this.node.addChild(bossBoom);
bossBoom.getComponent(EnemyBossBoom).setBossBoomFinished(()=>{
this.updateScore();
this.bossBoomFinish();
});
bossBoom.getComponent(EnemyBossBoom).startPlayAnimation();
}
// 爆炸效果结束了
bossBoomFinish() {
this.node.removeAllChildren();
this.node.removeFromParent();
this.node.destroy();
// 通知移除全部子弹、敌机飞机、暂停玩家飞机发射子弹后,
GameStateManager.instance().updateIsWin(true);
// 玩家飞机向上飞行后提示通关,继续创下一关
GameStateManager.instance().updateGameStatus(GameConstant.GameStatus.BOSSBOOMFINISH);
}
// 更新得分
updateScore() {
// 每个BOSS得分为血量
GameStateManager.instance().updateScore(this.bloodCount);
}
}
3.6 敌机BOSS来回移动并且发射导弹
// 左右移动
moveLeftRight() {
// 让节点左右来回移动并一直重复
var seq = cc.repeatForever(
cc.sequence(
cc.moveTo(5, cc.v2(-this.canvasWidth / 2, this.node.y)),
cc.moveTo(5, cc.v2(this.canvasWidth / 2, this.node.y))
));
this.node.runAction(seq);
}
// 每次创建一波Boss子弹
startCreateBossBullet() {
var time = 0.5;
this.schedule(this.onCreateBossBullet, time);
}
onCreateBossBullet() {
var bullet = cc.instantiate(this.getBossBullet());
this.node.parent.addChild(bullet);
var x = this.node.x;
var y = this.node.y - this.node.height + bullet.height;
bullet.setPosition(cc.v2(x, y));
}
stopSchedule() {
this.unschedule(this.onCreateDBullet);
this.unschedule(this.onCreateBossBullet);
}
onDestroy() {
this.stopSchedule();
}
四、最后可以扫码看下效果。
搜索微信小游戏:战击长空
五、下载地址
https://gitee.com/baibaime/plane-war.git