话说上回游戏背景和音效成功的动起来了,接下来就是在背景上添加更多的模块来让游戏感体现出来,期待主角上场吧。。。
1.新建父类Role角色管理模块
class Role extends egret.DisplayObjectContainer{
/**
* 屏幕高宽
*/
private mStageW:number=0;
private mStageH:number=0;
/**
* 角色的血量
*/
private mBlood:number=0;
public constructor() {
super();
this.addEventListener(egret.Event.ADDED_TO_STAGE,this.createAirplane,this);
}
/**
* 创建角色
*/
public createAirplane():void{
this.mStageW = this.stage.stageWidth;
this.mStageH = this.stage.stageHeight;
}
/**
* 检测敌机之间碰撞
*/
public checkCollosion(x:number,y:number,obj:egret.DisplayObjectContainer):boolean{
return false;
}
/**
* 更新角色的血量
*/
public updateBlood():void{
}
public setBlood(blood:number){
if(blood<=0){
blood = 0;
}
this.mBlood = blood;
}
public getBlood():number{
return this.mBlood
}
/**
* 获取屏幕高宽
*/
public getStageW() : number{
return this.mStageW;
}
public getStageH() : number{
return this.mStageH;
}
/**
* 获取角色位置
*/
public getX():number{
return 0;
}
public getY():number{
return 0;
}
/**
* 角色高宽
*/
public getWidth():number{
return 0;
}
public getHeight():number{
return 0;
}
}
角色基本信息,比如位置x,y;角色的高宽;血量等信息;每种角色的血量肯定都不一样的。
2.新建主角类Lead继承Role。
class Lead extends Role{
/**
* 角色
*/
private mLead: egret.Bitmap;
/**
* 血量,主角血量默认为100
*/
private mBloodShape:egret.Shape;
/**
* 主角分数
*/
private mScore:egret.TextField;
private mScoreNumber:number=0;
/**
* 主角控制器
*/
private mCollect: egret.Bitmap;
private mTouchStatus: boolean = false;
private mDistance:egret.Point = new egret.Point();
/**
* 尾部喷气
*/
private mPlayblow : egret.Bitmap;
private mPlayblowH : number;
private mSpeedAngle : number;
/**
* 主角出场完成
*/
private mTweenComplete: Function;
private mLevel:Level;
public constructor(tweenComplete:Function,level:Level) {
super();
this.mTweenComplete = tweenComplete;
this.mLevel = level;
}
public createAirplane():void{
super.createAirplane();
this.setBlood(100);
this.mSpeedAngle = 5;
var stageW = this.getStageW();
var stageH = this.getStageH();
//主角
this.mLead = ImageResUtils.createBitmapByName("lead_png");
this.addChild(this.mLead);
this.mLead.width = 68;
this.mLead.height = 68;
this.mLead.x = (stageW) / 2;
this.mLead.y = stageH+this.mLead.height*2;
//尾部火焰
this.mPlayblow = ImageResUtils.createBitmapByName("playblow_png");
this.addChildAt(this.mPlayblow,0);
this.mPlayblowH = 65;
this.mPlayblow.width = 68;
this.mPlayblow.height =this.mPlayblowH;
this.mPlayblow.x = this.mLead.x;
this.mPlayblow.y = this.mLead.y + this.mLead.height / 1.5;
var timer = new egret.Timer(5,0);
timer.addEventListener(egret.TimerEvent.TIMER,this.startBlowAnimation,this);
timer.start();
//手指触摸位置控制器
this.mCollect = ImageResUtils.createBitmapByName("playerunmatched_png");
this.addChild(this.mCollect);
this.mCollect.width = 68;
this.mCollect.height = 68;
this.mCollect.anchorOffsetX = this.mCollect.width / 2;
this.mCollect.anchorOffsetY = this.mCollect.height / 2
this.mCollect.x = this.mLead.x + this.mCollect.width/2;
this.mCollect.y = this.mPlayblow.y+this.mPlayblow.height * 1.2;
this.addEventListener(egret.Event.ENTER_FRAME,(evt:egret.Event)=>{
this.mCollect.rotation+=10;
},this);
//进场动画
var leadY = stageH - this.mLead.height * 3;
egret.Tween.get(this.mLead).to({y:leadY},2500,egret.Ease.backInOut).call(this.mTweenComplete,this.mLevel);
var playblowY = leadY + this.mLead.height / 1.5;
egret.Tween.get(this.mPlayblow).to({y:playblowY},2500,egret.Ease.backInOut);
egret.Tween.get(this.mCollect).to({y:playblowY+this.mPlayblow.height * 1.2},2500,egret.Ease.backInOut);
//移动主角
this.mCollect.touchEnabled = true;
this.mCollect.addEventListener(egret.TouchEvent.TOUCH_BEGIN,this.mouseDown,this);
this.mCollect.addEventListener(egret.TouchEvent.TOUCH_END,this.mouseUp,this);
//初始化血量
this.mBloodShape = new egret.Shape();
this.addChild(this.mBloodShape);
this.updateBlood();
//分数
this.mScore = new egret.TextField();
this.mScore.textColor = 0xfffffff;
this.mScore.width = 200;
this.mScore.height = 100;
this.mScore.textAlign = "center";
this.mScore.x = 0;
this.mScore.y = 30;
this.addChild(this.mScore);
this.updateScore();
}
/**
* 刷新主角血量
*/
public updateBlood():void{
this.mBloodShape.graphics.clear();
var blood:number = this.getBlood();
if(blood==0){
Level.GAME_STATE = Level.GAME_END;
}
if(blood>100){
blood=100;
}
if(blood<=20){
this.mBloodShape.graphics.beginFill(0xdc143c);
}else{
this.mBloodShape.graphics.beginFill(0xfffffff);
}
this.mBloodShape.graphics.drawRect(240,40,blood * 4,10);
this.mBloodShape.graphics.endFill();
}
/**
* 刷新分数
*/
private updateScore():void{
this.mScore.text = this.mScoreNumber.toString();
}
/**
* 按下
*/
private mouseDown(event: egret.TouchEvent) : void{
this.mTouchStatus = true;
this.mDistance.x = event.stageX - this.mLead.x;
this.mDistance.y = event.stageY - this.mLead.y;
this.stage.addEventListener(egret.TouchEvent.TOUCH_MOVE,this.mouseMove,this);
};
/**
* 移动
*/
private mouseMove(event: egret.TouchEvent) : void{
if(this.mTouchStatus && this.getBlood()>0){
var leadX:number = event.stageX - this.mDistance.x;
var leadY:number = event.stageY - this.mDistance.y;
leadX = leadX<0?0:leadX;
leadX = leadX>this.getStageW()-this.mLead.width?this.getStageW()-this.mLead.width:leadX;
leadY = leadY<0?0:leadY;
leadY = leadY>this.getStageH()-this.mLead.height-this.mCollect.height?this.getStageH()-this.mLead.height-this.mCollect.height:leadY;
this.mLead.x = leadX;
this.mLead.y = leadY;
//尾气火焰移动
this.mPlayblow.x = this.mLead.x;
this.mPlayblow.y = this.mLead.y + this.mLead.height / 1.5;
//控制器
this.mCollect.x = this.mLead.x + this.mCollect.width/2;
this.mCollect.y = this.mPlayblow.y+this.mPlayblow.height * 1.2;
this.mCollect.alpha = 0;
}
}
/**
* 松开
*/
private mouseUp(event: egret.TouchEvent){
this.mTouchStatus = false;
this.stage.removeEventListener(egret.TouchEvent.TOUCH_MOVE,this.mouseMove,this);
this.mCollect.alpha = 1;
}
/**
* 火焰喷射动画
*/
private startBlowAnimation() : void{
this.mPlayblowH += this.mSpeedAngle;
if(this.mPlayblowH>=75 || this.mPlayblowH<55){
this.mSpeedAngle = -this.mSpeedAngle;
}
this.mPlayblow.height = this.mPlayblowH;
}
public getX():number{
return this.mLead.x;
}
public getY():number{
return this.mLead.y;
}
public getWidth():number{
return this.mLead.width;
}
public getHeight():number{
return this.mLead.height;
}
}
主角类的每一个地方我都写了注释,很明确,主要说一下主角组成部分和在容器体现出的地方:
- 容器顶部多了一个数字和一个矩形条,分别代表的是游戏的分数以及血量。
1.分数核心代码:
//分数
this.mScore = new egret.TextField();
this.mScore.textColor = 0xfffffff;
this.mScore.width = 200;
this.mScore.height = 100;
this.mScore.textAlign = "center";
this.mScore.x = 0;
this.mScore.y = 30;
this.addChild(this.mScore);
this.updateScore();
/**
* 刷新分数
*/
private updateScore():void{
this.mScore.text = this.mScoreNumber.toString();
}
2.血量核心代码:
//设置血量为100
this.setBlood(100);
this.mBloodShape = new egret.Shape();
this.addChild(this.mBloodShape);
this.updateBlood();
/**
* 刷新主角血量
*/
public updateBlood():void{
this.mBloodShape.graphics.clear();
var blood:number = this.getBlood();
if(blood==0){
Level.GAME_STATE = Level.GAME_END;
}
if(blood>100){
blood=100;
}
if(blood<=20){
this.mBloodShape.graphics.beginFill(0xdc143c);
}else{
this.mBloodShape.graphics.beginFill(0xfffffff);
}
this.mBloodShape.graphics.drawRect(240,40,blood * 4,10);
this.mBloodShape.graphics.endFill();
}
这里出现了一个新的东西egret.Shape,可以做很多事情,类似于Android的Canvas可以绘制各种各样的形状,做游戏必学的。传送门
- 战机由三个部分组成:
1.飞机主体
//主角
this.mLead = ImageResUtils.createBitmapByName("lead_png");
this.addChild(this.mLead);
this.mLead.width = 68;
this.mLead.height = 68;
this.mLead.x = (stageW) / 2;
this.mLead.y = stageH+this.mLead.height*2;
2.主体尾部喷气式火焰
//尾部火焰
this.mPlayblow = ImageResUtils.createBitmapByName("playblow_png");
this.addChildAt(this.mPlayblow,0);
this.mPlayblowH = 65;
this.mPlayblow.width = 68;
this.mPlayblow.height =this.mPlayblowH;
this.mPlayblow.x = this.mLead.x;
this.mPlayblow.y = this.mLead.y + this.mLead.heisght / 1.5;
注意:引擎是不支持GIF的,所以动效你要么帧动画,要么自己代码实现。我这里是把火焰图片高度做不停的改变来实现喷射式效果。利用Timer定时器
var timer = new egret.Timer(5,0);
timer.addEventListener(egret.TimerEvent.TIMER,this.startBlowAnimation,this);
timer.start();
意思是每隔5秒执行一次回调方法startBlowAnimation;在回调函数来不停的改变火焰高度
/**
* 火焰喷射动画
*/
private startBlowAnimation() : void{
this.mPlayblowH += this.mSpeedAngle;
if(this.mPlayblowH>=75 || this.mPlayblowH<55){
this.mSpeedAngle = -this.mSpeedAngle;
}
this.mPlayblow.height = this.mPlayblowH;
}
3.看见主角战机下有一个在旋转的按钮没有?没错,那就是让玩家来触摸控制主角的地方,为什么需要这个设计呢?这就是体验问题,自己思考一下吧。
//手指触摸位置控制器
this.mCollect = ImageResUtils.createBitmapByName("playerunmatched_png");
this.addChild(this.mCollect);
this.mCollect.width = 68;
this.mCollect.height = 68;
this.mCollect.anchorOffsetX = this.mCollect.width / 2;
this.mCollect.anchorOffsetY = this.mCollect.height / 2
this.mCollect.x = this.mLead.x + this.mCollect.width/2;
this.mCollect.y = this.mPlayblow.y+this.mPlayblow.height * 1.2;
this.addEventListener(egret.Event.ENTER_FRAME,(evt:egret.Event)=>{
this.mCollect.rotation+=10;
},this);
这里一定要写上anchorOffsetX ,anchorOffsetY 的参数赋值,这样才能让控制器围绕自己中心点旋转。
通过addEventListener监听帧动画来维持持续旋转。
- 主角组合完成,怎么在容器中自由移动呢?
1.通过按住旋转控制器来上下左右移动主角,
//移动主角
this.mCollect.touchEnabled = true;
this.mCollect.addEventListener(egret.TouchEvent.TOUCH_BEGIN,this.mouseDown,this);
this.mCollect.addEventListener(egret.TouchEvent.TOUCH_END,this.mouseUp,this);
后面两个监听我能理解,手指按下和离开,第一行this.mCollect.touchEnabled = true;真不理解引擎为什么这样设计的,必须要给需要触摸事情的对象设置此参数,如果你不小心忽略了这一行,后面所有的触摸监听没有任何作用。
2.按下的时候除了记录位置,还需要添加监听整个屏幕的移动事件,这样才能知道手指移动的位置。
/**
* 按下
*/
private mouseDown(event: egret.TouchEvent) : void{
this.mTouchStatus = true;
this.mDistance.x = event.stageX - this.mLead.x;
this.mDistance.y = event.stageY - this.mLead.y;
this.stage.addEventListener(egret.TouchEvent.TOUCH_MOVE,this.mouseMove,this);
};
3.上面说了主角是多个部分组成,所以移动的时候组合部位需要跟着移动,不然就解体了,移动的时候做了边缘判断,保证随便怎么移动都只能在容器可见位置,并且隐藏控制器,表示主角已经受到玩家控制。
/**
* 移动
*/
private mouseMove(event: egret.TouchEvent) : void{
if(this.mTouchStatus && this.getBlood()>0){
var leadX:number = event.stageX - this.mDistance.x;
var leadY:number = event.stageY - this.mDistance.y;
leadX = leadX<0?0:leadX;
leadX = leadX>this.getStageW()-this.mLead.width?this.getStageW()-this.mLead.width:leadX;
leadY = leadY<0?0:leadY;
leadY = leadY>this.getStageH()-this.mLead.height-this.mCollect.height?this.getStageH()-this.mLead.height-this.mCollect.height:leadY;
this.mLead.x = leadX;
this.mLead.y = leadY;
//尾气火焰移动
this.mPlayblow.x = this.mLead.x;
this.mPlayblow.y = this.mLead.y + this.mLead.height / 1.5;
//控制器
this.mCollect.x = this.mLead.x + this.mCollect.width/2;
this.mCollect.y = this.mPlayblow.y+this.mPlayblow.height * 1.2;
this.mCollect.alpha = 0;
}
}
4.手指离开的时候,移除监听屏幕移动事件,显示控制器。
/**
* 松开
*/
private mouseUp(event: egret.TouchEvent){
this.mTouchStatus = false;
this.stage.removeEventListener(egret.TouchEvent.TOUCH_MOVE,this.mouseMove,this);
this.mCollect.alpha = 1;
}
3.回到我们的关卡类TheFirstPass修改startGame方法,添加主角类进场。
public startGame(){
super.startGame();
//加载背景
this.mBgGame = new BackgroundGame();
this.addChild(this.mBgGame);
//主角进场
var lead = new Lead(function(){
this.mBgGame.startAnimationBg();
},this);
this.addChild(lead);
//加载游戏音乐
this.mBgSoundMusic = new BgSoundMusic();
this.mBgSoundMusic.playMusic();
//游戏结束提示
this.mGameTextMessage = new egret.TextField();
this.mGameTextMessage.textColor = 0xfffffff;
this.mGameTextMessage.size = 40;
this.mGameTextMessage.textAlign = "center"
this.mGameTextMessage.x = 0;
//重新开始
this.mGameRestart = new egret.TextField();
this.mGameRestart.textColor = 0xfffffff;
this.mGameRestart.size = 40;
this.mGameRestart.textAlign = egret.HorizontalAlign.CENTER;
this.mGameRestart.verticalAlign = egret.VerticalAlign.MIDDLE;
this.mGameRestart.backgroundColor = 0x000000;
this.mGameRestart.text = "再来一次"
this.mGameRestart.touchEnabled = true;
this.mGameRestart.stroke = 1;
this.mGameRestart.strokeColor = 0xffffff;
}
相比上一章修改了一下出场逻辑,等主角出场动画完成后再开始执行游戏背景动画,这样看来好像更符合逻辑。
主角已经完美出场了,是不是感觉并不是很难呢,无非就是多看官方文档和亲自试验,期待下一篇吧,给主角配上武器。
在线体验
如果是电脑端记得先把浏览器缩小后再打开地址,不然是横过来的。
网友评论