ActionScript
TypeScript
JavaScript

六、子弹升级与敌军难度升级的逻辑实现

发布时间:2016-05-14

 

难度升级

上节实现了飞行射击,碰撞销毁等效果,游戏的样子已经有了,但是还不够有趣,这节增加一些游戏的趣味性。

我们增加了血瓶和子弹升级道具资源,并且重新打包为图集。

图片1.png 

子弹升级

设计目标:击毁boss飞机,有机会获得子弹升级道具,积攒后可以提高子弹发射数量,提高发射速度,提高飞行速度。

 Game.ts里面,修改了子弹发射相关代码。

//根据不同子弹类型,设置不同的数量及位置
                    var pos: Array = this.bulletPos[role.shootType - 1];
                    for (var index: number = 0; index < pos.length; index++) {
                        //从对象池里面创建一个子弹
                        var bullet: Role = Laya.Pool.getItemByClass("role", Role);
                        //初始化子弹信息,根据不同子弹类型,设置不同的飞行速度
                        bullet.init("bullet1", role.camp, 1, -4 - role.shootType - Math.floor(this.level / 15), 1, 1);
                        //设置子弹发射初始化位置
                        bullet.pos(role.x + pos[index], role.y - role.hitRadius - 10);
                        //添加到舞台上
                        Laya.stage.addChild(bullet);
                    }

 

修改lostHp掉血代码,增加打死boss掉血瓶和子弹升级道具的逻辑

//打死boss掉落血瓶或子弹升级道具
                if (role.type == "enemy3") {
                    //随机是子弹升级道具还是血瓶
                    var type: number = Math.random() < 0.7 ? 2 : 3;
                    //掉落血瓶或者加速器                     
                    var item: Role = Laya.Pool.getItemByClass("role", Role);
                    //初始化信息
                    item.init("ufo" + (type - 1), role.camp, 1, 1, 15, type);
                    //初始化位置
                    item.pos(role.x, role.y);
                    //添加到舞台上
                    Laya.stage.addChild(item);
                }

 

增加吃子弹升级道具升级逻辑。

 //每吃一个子弹升级道具,子弹升级+1
            this.bulletLevel++;
            //子弹每升2级,子弹数量增加1,最大数量限制在4个
            this.hero.shootType = Math.min(Math.floor(this.bulletLevel / 2) + 1,4);
            //子弹级别越高,发射频率越快
            this.hero.shootInterval = 500 - 20 * (this.bulletLevel > 20 ? 20 : this.bulletLevel);
            //隐藏道具
            role.visible = false;


增加吃血瓶,恢复血量的逻辑。

//每吃一个血瓶,血量增加1
            this.hero.hp++;
            //设置最大血量不超过10
            if (this.hero.hp > 10) this.hero.hp = 10;
            //隐藏道具
            role.visible = false;


敌人升级

设计目标:增加积分属性,增加关卡等级,积累积分,则关卡等级提升,关卡越高,敌人数量越多,速度越快,血量越高。

修改onLoop函数内的碰撞逻辑。

 //碰撞后掉血
                        this.lostHp(role1, 1);
                        this.lostHp(role2, 1);
                        //每掉一滴血,积分+1
                        this.score++;
                        //积分大于升级积分,则升级
                        if (this.score > this.levelUpScore) {
                            //升级关卡
                            this.level++;
                            //提高下一级的升级难道
                            this.levelUpScore += this.level * 5;
                        }

 

修改敌机出现逻辑。

 //关卡越高,创建敌机间隔越短
        var cutTime: number = this.level < 30 ? this.level * 2 : 60;
        //关卡越高,敌机飞行速度越高
        var speedUp: number = Math.floor(this.level / 6);
        //关卡越高,敌机血量越高
        var hpUp: number = Math.floor(this.level / 8);
        //关卡越高,敌机数量越多
        var numUp: number = Math.floor(this.level / 10);
 
        //生成小飞机
        if (Laya.timer.currFrame % (80 - cutTime) === 0) {
            this.createEnemy(0, 2 + numUp, 3 + speedUp, 1);
        }
 
        //生成中型飞机
        if (Laya.timer.currFrame % (150 - cutTime * 2) === 0) {
            this.createEnemy(1, 1 + numUp, 2 + speedUp, 2 + hpUp * 2);
        }
 
        //生成boss
        if (Laya.timer.currFrame % (900 - cutTime * 4) === 0) {
            this.createEnemy(2, 1, 1 + speedUp, 10 + hpUp * 6);
        }


最后我们看看效果:

图片1.png 

 

全部代码如下:

Game.ts

/**
* Game
*/
class Game {
    //定义英雄(主战斗机)
    private hero: Role
    //子弹发射偏移位置表
    private bulletPos: Array = [[0], [-15, 15], [-30, 0, 30], [-45, -15, 15, 45]];
    //关卡等级
    private level: number = 0;
    //积分成绩
    private score: number = 0;
    //升级等级所需的成绩数量
    private levelUpScore: number = 10;
    //子弹级别
    private bulletLevel: number = 0;
    //敌机被击半径表
    private radius: Array = [18, 33, 80];
 
    constructor() {
        //初始化引擎,设置游戏设计宽高
        Laya.init(480, 852);
 
        //创建循环滚动的背景
        var bg: BackGround = new BackGround();
        //把背景添加到舞台上显示出来
        Laya.stage.addChild(bg);
 
        //加载图集资源
        Laya.loader.load("res/atlas/war.json", Laya.Handler.create(this, this.onLoaded), null, Laya.Loader.ATLAS);
 
        //显示FPS
        Laya.Stat.show();
    }
 
    onLoaded() {
        //创建一个主角(主战斗机)
        this.hero = new Role();
        //初始化角色
        this.hero.init("hero", 0, 5, 0, 30);
        //设置角色位置
        this.hero.pos(240, 700);
        //设置射击类型
        this.hero.shootType = 1;
        //把主角添加到舞台上
        Laya.stage.addChild(this.hero);
 
        //监听舞台的鼠标移动事件
        Laya.stage.on("mousemove", this, this.onMouseMove);
 
        //创建主循环
        Laya.timer.frameLoop(1, this, this.onLoop);
    }
 
    onLoop(): void {
         //遍历所有飞机,更改飞机状态
        for (var i: number = Laya.stage.numChildren - 1; i > 0; i--) {
            var role: Role = Laya.stage.getChildAt(i) as Role;
            if (role && role.speed) {
                //根据飞机速度更改位置
                role.y += role.speed;
                //如果敌人移动到显示区域以外,则移除
                if (role.y > 1000 || !role.visible || (role.heroType === 1 && role.y  0) {
                //获取当前时间
                var time: number = Laya.Browser.now();
                //如果当前时间大于下次射击时间
                if (time > role.shootTime) {
                    //更新下次射击时间
                    role.shootTime = time + role.shootInterval;
                    //根据不同子弹类型,设置不同的数量及位置
                    var pos: Array = this.bulletPos[role.shootType - 1];
                    for (var index: number = 0; index  0; i--) {
            //获取角色对象1
            var role1: Role = Laya.stage.getChildAt(i) as Role;
            //如果角色已经死亡,则忽略
            if (role1.hp  0; j--) {
                //如果角色已经死亡,则忽略
                if (!role1.visible) continue;
                //获取角色对象2
                var role2: Role = Laya.stage.getChildAt(j) as Role;
               //如果角色未死亡,并且阵营不同,才进行碰撞
                if (role2.hp > 0 && role1.camp != role2.camp) {
                    //计算碰撞区域
                    var hitRadius: number = role1.hitRadius + role2.hitRadius;
                    //根据距离判断是否碰撞
                    if (Math.abs(role1.x - role2.x) < hitRadius && Math.abs(role1.y - role2.y)  this.levelUpScore) {
                            //升级关卡
                            this.level++;
                            //提高下一级的升级难道
                            this.levelUpScore += this.level * 5;
                        }
                    }
                }
            }
        } 
        //如果主角死亡,则停止游戏循环
        if (this.hero.hp < 1) {
            Laya.timer.clear(this, this.onLoop);
        }
        //关卡越高,创建敌机间隔越短
        var cutTime: number = this.level  20 ? 20 : this.bulletLevel);
            //隐藏道具
            role.visible = false;
        } else if (role.heroType === 3) {
            //每吃一个血瓶,血量增加1
            this.hero.hp++;
            //设置最大血量不超过10
            if (this.hero.hp > 10) this.hero.hp = 10;
            //隐藏道具
            role.visible = false;
        } else if (role.hp > 0) {
            //如果未死亡,则播放受击动画
            role.playAction("hit");
        } else {
            //如果死亡,则播放爆炸动画
            if (role.heroType > 0) {
                //如果是子弹,则直接隐藏,下次回收
                role.visible = false;
            } else {
                role.playAction("down");
                //打死boss掉落血瓶或子弹升级道具
                if (role.type == "enemy3") {
                    //随机是子弹升级道具还是血瓶
                    var type: number = Math.random() < 0.7 ? 2 : 3;
                    //掉落血瓶或者加速器                     
                    var item: Role = Laya.Pool.getItemByClass("role", Role);
                    //初始化信息
                    item.init("ufo" + (type - 1), role.camp, 1, 1, 15, type);
                    //初始化位置
                    item.pos(role.x, role.y);
                    //添加到舞台上
                    Laya.stage.addChild(item);
                }
            }
        }
    }
    onMouseMove(e: Laya.Event): void {
        //始终保持影响和鼠标位置一致
        this.hero.pos(Laya.stage.mouseX, Laya.stage.mouseY);
    }
 
    createEnemy(type: number, num: number, speed: number, hp: number): void {
        for (var i: number = 0; i < num; i++) {
            //创建敌人,从对象池创建
            var enemy: Role = Laya.Pool.getItemByClass("role", Role);
            //初始化角色
            enemy.init("enemy" + (type + 1), 1, hp, speed, this.radius[type]);
            //随机位置
            enemy.pos(Math.random() * 400 + 40, -Math.random() * 200 - 100);
            //添加到舞台上
            Laya.stage.addChild(enemy);
        }
    }
}
 
//启动游戏
new Game();

 

 

Role.ts


/**
 * 角色类
 */
class Role extends Laya.Sprite {
    //是否缓存了动画
    private static cached: boolean = false;
    //定义飞机的身体
    private body: Laya.Animation;
    //定义飞机类型
    public type: string;
    //阵营,0:我方,1:敌方
    public camp: number;
    //血量
    public hp: number;
    //飞行速度
    public speed: number;
    //攻击半径
    public hitRadius: number = 0;
    //射击类型
    public shootType: number = 0;
    //射击间隔
    public shootInterval: number = 500;
    //下次射击时间
    public shootTime: number = Laya.Browser.now() + 100;
    //当前动作
    public action: string;
    /**0:普通,1:子弹,2:弹药,3:补给品 */
    public heroType: number = 0;
 
    constructor() {
        super();
    }
 
    public init(type: string, camp: number, hp: number, speed: number, hitRadius: number, heroType: number = 0): void {
        //初始化角色属性
        this.type = type;
        this.camp = camp;
        this.hp = hp;
        this.speed = speed;
        this.hitRadius = hitRadius;
        this.heroType = heroType;
 
        //显示碰撞区域
        //this.graphics.clear();
        //this.graphics.drawCircle(0, 0, hitRadius, null, "#ff0000")
 
        //缓存公用动画模板,减少对象创建开销
        if (!Role.cached) {
            Role.cached = true;
            //缓存hero_fly动画
            Laya.Animation.createFrames(["war/hero_fly1.png", "war/hero_fly2.png"], "hero_fly");
            //缓存hero_down动画
            Laya.Animation.createFrames(["war/hero_down1.png", "war/hero_down2.png", "war/hero_down3.png", "war/hero_down4.png"], "hero_down");
 
            //缓存enemy1_fly动画
            Laya.Animation.createFrames(["war/enemy1_fly1.png"], "enemy1_fly");
            //缓存enemy1_down动画
            Laya.Animation.createFrames(["war/enemy1_down1.png", "war/enemy1_down2.png", "war/enemy1_down3.png", "war/enemy1_down4.png"], "enemy1_down");
 
            //缓存enemy2_fly动画
            Laya.Animation.createFrames(["war/enemy2_fly1.png"], "enemy2_fly");
            //缓存enemy2_down动画
            Laya.Animation.createFrames(["war/enemy2_down1.png", "war/enemy2_down2.png", "war/enemy2_down3.png", "war/enemy2_down4.png"], "enemy2_down");
            //缓存enemy2_hit动画
            Laya.Animation.createFrames(["war/enemy2_hit.png"], "enemy2_hit");
 
            //缓存enemy3_fly动画
            Laya.Animation.createFrames(["war/enemy3_fly1.png", "war/enemy3_fly2.png"], "enemy3_fly");
            //缓存enemy3_down动画
            Laya.Animation.createFrames(["war/enemy3_down1.png", "war/enemy3_down2.png", "war/enemy3_down3.png", "war/enemy3_down4.png", "war/enemy3_down5.png", "war/enemy3_down6.png"], "enemy3_down");
            //缓存enemy3_hit动画
            Laya.Animation.createFrames(["war/enemy3_hit.png"], "enemy3_hit");
 
            //缓存子弹动画
            Laya.Animation.createFrames(["war/bullet1.png"], "bullet1_fly");
            //缓存UFO1
            Laya.Animation.createFrames(["war/ufo1.png"], "ufo1_fly");
            //缓存UFO2
            Laya.Animation.createFrames(["war/ufo2.png"], "ufo2_fly");
        }
 
        if (!this.body) {
            //创建一个动画作为飞机的身体
            this.body = new Laya.Animation();
            //动画播放时间间隔
            this.body.interval = 50;
            //把机体添加到容器内
            this.addChild(this.body);
 
            //增加动画播放完成监听
            this.body.on("complete", this, this.onPlayComplete);
        }
        //播放飞行动画
        this.playAction("fly");
    }
 
    onPlayComplete(): void {
        //如果是击毁动画,则隐藏对象
        if (this.action === "down") {
            //停止动画播放
            this.body.stop();
            //隐藏显示,通过此标记,在下帧进行回收
            this.visible = false;
        } else if (this.action === "hit") {
            //如果是被击动画播放完毕,则接着播放飞行动画
            this.playAction("fly");
        }
    }
 
    playAction(action: string): void {
        //纪录当前播放动画类型
        this.action = action;
        //根据类型播放动画
        this.body.play(0, true, this.type + "_" + action);
        //获取动画大小区域
        var bound: Laya.Rectangle = this.body.getBounds();
        //设置机身剧中
        this.body.pos(-bound.width / 2, -bound.height / 2);
    }
}

游戏到目前为止,已经有趣味性了,但是还有很多其他功能可以添加,比如增加不同轨迹的子弹,增加跟踪弹,增加敌机反击等,我在此不再过多的深入,更多有趣功能留给开发者自己去尝试。

 

本节课程源码下载