image 组件设置背景图 bg_png,并填充上下左右;
// 场景控制单例
private static shared: SceneManager;
// 实例化单例获取方法
public static Shared(): SceneManager {
if(!SceneManager.shared) {
SceneManager.shared = new SceneManager();
}
return SceneManager.shared;
}
// 开始场景
private beginScene: BeginScene;
// 游戏场景
private gameScene: GameScene;
class SceneManager extends egret.Sprite{}
protected createGameScene(): void {
this.addChild(SceneManager.Shared());
}
public constructor() {
super(); this.init();
}
/**
* 初始化
* */
private init() {
// 实例化两个场景
this.beginScene = new BeginScene();
this.gameScene = new GameScene();
// 默认添加开始场景
this.addChild(this.beginScene);
}
// 切换场景
public changeScene(type) {
if(type == 'gameScene') {
this.beginScene.release();
}
// 移除所有显示列表中的对象
this.removeChildren();
// 添加下一个场景
this.addChild(this.gameScene);
}
// 移除事件
public release() {
if(this.beginBtn.hasEventListener(egret.TouchEvent.TOUCH_TAP)) {
this.beginBtn.removeEventListener(
egret.TouchEvent.TOUCH_TAP,
this.tapHandler,
this);
}
}
// 开始按钮
public beginBtn:eui.Button;
protected childrenCreated():void {
super.childrenCreated();
// 页面加载完毕后,调用自定义初始化方法
this.init();
}
/**
* 初始化方法(给开始按钮绑定点击事件)
* */
private init() {
this.beginBtn.addEventListener(
egret.TouchEvent.TOUCH_TAP,
this.tapHandler,
this
);
}
// 点击按钮调用的方法
private tapHandler() {
// 切换场景
SceneManager.Shared().changeScene('gameScene');
}
// 游戏场景组
public blockPanel:eui.Group;
// 游戏场景中的积分
public scoreLabel:eui.Label;
// 小 i
public player:eui.Image;
/**************************工厂设计模式*****************************/
// 所有方块资源的数组
private blockSourceNames: Array<string> = [];
// 所有方块的数组
private blockArr: Array<eui.Image> = [];
// 所有回收方块的数组
private reBackBlockArr: Array<eui.Image> = [];
/**
* 工厂方法,创建一个方块
* */
private createBlock(): eui.Image {
// 定义一个方块盒子
var blockNode: eui.Image = null;
if(this.reBackBlockArr.length) {
// 回收池里有,则直接取
blockNode = this.reBackBlockArr.splice(0,1)[0];
}else {
// 回收池里面没有,则重新创建
blockNode = new eui.Image();
}
// 使用随机背景
let n = Math.floor(Math.random() * this.blockSourceNames.length);
blockNode.source = this.blockSourceNames[n];
this.blockPanel.addChild(blockNode);
// 设置方块的锚点
blockNode.anchorOffsetX = 222;
blockNode.anchorOffsetY = 78;
// 把新建的 block 添加进入 blockArr 里
this.blockArr.push(blockNode);
return blockNode;
}
/**************************音频*****************************/
// 按下的音频
private pushVoice: egret.Sound;
// 弹跳的音频
private jumpVoice: egret.Sound;
protected childrenCreated():void {
super.childrenCreated();
this.init();
}
/**
* 初始化
* */
private init() {
this.blockSourceNames = ['block1_png','block2_png','block3_png'];
// 初始化音频
this.pushVoice = RES.getRes('push_mp3');
this.jumpVoice = RES.getRes('jump_mp3');
// 打开 touchEnabled 属性
this.blockPanel.touchEnabled = true;
this.blockPanel.addEventListener(
egret.TouchEvent.TOUCH_TAP,
this.onKeyDown,
this
);
this.blockPanel.addEventListener(
egret.TouchEvent.TOUCH_END,
this.onKeyUp,
this
);
// 设置玩家锚点
this.player.anchorOffsetX = this.player.width / 2;
this.player.anchorOffsetY = this.player.height - 20;
}
// 下一个盒子方向(1 靠右侧出现 / -1 靠左侧出现)
public direction: number = 1;
// 重置游戏
public reset() {
// 清空舞台
this.blockPanel.removeChildren();
this.blockArr = [];
// 添加一个方块
let blockNode = this.createBlock();
blockNode.touchEnabled = false;
// 设置方块的起始位置
blockNode.x = 200;
blockNode.y = this.height / 2 + blockNode.height;
this.currentBlock = blockNode;
// 摆正小人的位置
this.player.x = this.currentBlock.x;
this.player.y = this.currentBlock.y;
this.blockPanel.addChild(this.player);
// 添加积分
this.blockPanel.addChild(this.scoreLabel);
// 重置盒子方向
this.direction = 1;
// 添加下一块方块
this.addBlock();
}
// tanθ 角度值
public tanAngle: number = 0.55604719640118;
// 落脚点
private targetPos: egret.Point;
/**
* 添加一个方块
* */
private addBlock() {
// 随机一个方块
let blockNode = this.createBlock();
// 设置位置
let distance = this.minDistance + Math.random()*(this.maxDistance - this.minDistance);
if(this.direction > 0) {
blockNode.x = this.currentBlock.x + distance;
blockNode.y = this.currentBlock.y - distance*this.tanAngle;
}else {
blockNode.x = this.currentBlock.x - distance;
blockNode.y = this.currentBlock.y - distance*this.tanAngle;
}
this.currentBlock = blockNode;
}
/**
* 按下的事件逻辑
* */
private onKeyDown() {
// 播放按下的音频
this.pushSoundChannel = this.pushVoice.play(0,1);
// 变形
egret.Tween.get(this.player).to({
scaleY: 0.5
}, 3000);
this.isReadyJump = true;
}
/**
* 放开的事件逻辑
* */
private onKeyUp() {
// 判断是否在按下状态
if(!this.isReadyJump) {
return;
}
// 声明落脚点坐标
if(!this.targetPos) {
this.targetPos = new egret.Point();
}
// 立即让屏幕不可点,等小人落下后重新可点
this.blockPanel.touchEnabled = false;
// 停止播放按压音频,并且播放跳跃音频
this.pushSoundChannel.stop();
this.jumpVoice.play(0,1);
// 清除所有动画
egret.Tween.removeAllTweens();
this.blockPanel.addChild(this.player);
// 结束跳跃状态
this.isReadyJump = false;
// 落脚点坐标
this.targetPos.x = this.player.x + this.jumpDistance * this.direction;
// 根据落点重新计算斜率,确保小人往目标中心跳跃
this.targetPos.y = this.player.y + this.jumpDistance * (this.currentBlock.y - this.player.y)/(this.currentBlock.x - this.player.x) * this.direction;
// 执行跳跃动画
egret.Tween.get(this).to({factor: 1}, 500).call(() => {
this.player.scaleY = 1;
this.jumpDistance = 0;
});
// 执行小人空翻动画
this.player.anchorOffsetY = this.player.height / 2;
egret.Tween.get(this.player).to({rotation: this.direction > 0 ? 360 : -360}, 200).call(() => {
this.player.rotation = 0;
}).call(() => {
this.player.anchorOffsetY = this.player.height - 20;
});
}
// 添加 factor 的 set,get 方法,注意使用 public
public get factor(): number {
return 0;
}
// 计算方法参考,二次贝塞尔曲线公式
public set factor(value: number) {
this.player.x = (1-value)*(1-value) * this.player.x + 2 * value * (1-value)*(this.player.x + this.targetPos.x) / 2 + value * value * (this.targetPos.x);
this.player.y = (1-value)*(1-value) * this.player.y + 2 * value * (1-value)*(this.player.y - 300) / 2 + value * value * (this.targetPos.y);
}
对应 onKeyUp方法里执行跳跃动画的变量 factro:
// 执行跳跃动画
egret.Tween.get(this).to({factor: 1}, 500).call(() => { …… });
// 根据 this.jumpDistance 来判断跳跃是否成功
private judgeResult(){
// pow 函数用于求幂
if(Math.pow(this.currentBlock.x - this.player.x, 2) + Math.pow(this.currentBlock.y - this.player.y, 2) <= 70*70) {
// 跳跃成功
// 更新积分
this.score++;
this.scoreLabel.text = this.score.toString();
// 随机下一个方块出现的位置
this.direction = Math.random() > 0.5 ? 1 : -1;
// 当前方块要移到相应的跳跃点的距离
var blockX, blockY;
blockX = this.direction > 0 ? this.leftOrigin.x : this.rightOrigin.x;
blockY = this.height / 2 + this.currentBlock.height;
// 小人要移动到的点
var playerX, playerY;
playerX = this.player.x - (this.currentBlock.x - blockX);
playerY = this.player.y - (this.currentBlock.y - blockY);
// 更新页面的位置
this.update(this.currentBlock.x - blockX, this.currentBlock.y - blockY);
// 更新小人的位置
egret.Tween.get(this.player).to({
x: playerX,
y: playerY
}, 1000).call(() => {
// 开始创建下一块方块
this.addBlock();
// 让屏幕重新可点
this.blockPanel.touchEnabled = true;
})
console.log("x" + this.currentBlock.x);
}else {
// 跳跃失败
console.log("游戏失败!");
this.overPanel.visible = true;
this.overScoreLabel.text = this.score.toString();
}
}
// 更新页面
private update(x, y) {
egret.Tween.removeAllTweens();
for(var i: number = this.blockArr.length - 1; i >= 0; i--) {
var blockNode = this.blockArr[i];
if(blockNode.x + (blockNode.width - 222) < 0 ||
blockNode.x - 222 > this.width || blockNode.y - 78 > this.height) {
// 方块超出屏幕,从显示列表中移除
this.blockPanel.removeChild(blockNode);
this.blockArr.splice(i,1);
// 添加到回收数组中
this.reBackBlockArr.push(blockNode);
}else {
// 没有超出屏幕的范围,则移动
egret.Tween.get(blockNode).to({
x: blockNode.x - x,
y: blockNode.y - y
}, 1000)
}
}
}
// 执行跳跃动画
egret.Tween.get(this).to({factor: 1}, 500).call(() => {
this.player.scaleY = 1;
this.jumpDistance = 0;
// 判断是否跳跃成功
this.judgeResult();
});
导入第三方库(使用 egret build -a 命令导入):
在项目编辑器的终端输入 egret build -e 命令,等待编译成功
使用第三方库 game 里的Ticker 心跳计时器,用来计时手指按下屏幕的时间长度,通过时间长度来计算跳跃的距离
// 心跳计时器
egret.Ticker.getInstance().register(function(dt){
dt /= 1000;
if(this.isReadyJump) {
this.jumpDistance += 300 * dt;
}
}, this)