LibGdx练习-像素鸟(二)
游戏资源管理
res包下创建接口Res对于资源路径和变量进行统一管理使项目零散,便于调试。
public interface Res {
/** 固定世界宽度为 480, 高度根据实际屏幕比例换算 */
public static final float FIX_WORLD_WIDTH = 600;
public static final float FIX_WORLD_HEIGHT = 900;
/** 帧率显示所需要的位图字体 文件路径 */
public static final String FPS_BITMAP_FONT_PATH = "fps/fps24px.fnt";
/**
* 相关物理参数(调节物理参数可改变游戏难度)
*/
public static interface Physics {
/** 水管和地板的移动速度, 单位: px/s */
public static final float MOVE_VELOCITY = -150.0F;
/** 点击屏幕时给小鸟的竖直方向上的速度, 单位: px/s */
public static final float JUMP_VELOCITY = 150.0F;
/** 小鸟竖直方向上的重力加速度, 单位: px/(s*s) */
public static final float GRAVITY = -200.0F;
/** 撞入深度, 小鸟撞入水管或地板该深度后才算碰撞 */
public static final float DEPTH = 0.0F;
/** 生成水管时间间隔, 单位: s */
public static final float GENERATE_BAR_TIME_INTERVAL = 2.2F;
/** 上下水管之间的间隔 */
public static final float BAR_INTERVAL = 180.0F;
}
/**
* 纹理图集
*/
public static interface Atlas {
/** 纹理图集 文件路径 */
public static final String ATLAS_PATH = "atlas/images.atlas";
/* 纹理图集中的小图名称 */
public static final String IMAGE_GAME_BG = "game_bg";
public static final String IMAGE_GAME_FLOOR = "game_floor";
public static final String IMAGE_GAME_RESULT_BG = "game_result_bg";
public static final String IMAGE_BAR_DOWN = "bar_down";
public static final String IMAGE_BAR_UP = "bar_up";
public static final String IMAGE_GAME_TAP_TIP = "game_tap_tip";
public static final String IMAGE_GAME_READY = "game_ready";
public static final String IMAGE_GAME_OVER = "game_over";
public static final String IMAGE_GAME_START_01_TO_02 = "game_start";
public static final String IMAGE_GAME_MEDAL_01_TO_04 = "game_medal";
public static final String IMAGE_NUM_BIG_00_TO_09 = "num_big";
public static final String IMAGE_NUM_SCORE_00_TO_09 = "num_score";
public static final String IMAGE_BIRD_YELLOW_01_TO_03 = "bird_yellow";
}
/**
* 音效
*/
public static interface Audios {
/** 音效资源文件夹路径 */
public static final String AUDIO_BASE_DIR = "audio/";
// 音效资源路径
public static final String AUDIO_DIE = AUDIO_BASE_DIR + "die.ogg";
public static final String AUDIO_HIT = AUDIO_BASE_DIR + "hit.ogg";
public static final String AUDIO_TOUCH = AUDIO_BASE_DIR + "touch.ogg";
public static final String AUDIO_RESTART = AUDIO_BASE_DIR + "restart.ogg";
public static final String AUDIO_SCORE = AUDIO_BASE_DIR + "score.ogg";
}
}
资源中主要包括
- 资源常量
- 图集和文字集
- 音频
三个部分来进行统一管理。
与此同时,在util包下对于游戏进行状态进行了枚举类型的封装。
public enum GameState {
/** 准备状态 */
ready,
/** 游戏状态(小鸟处于飞翔状态) */
fly,
/** 小鸟死亡状态(撞到水管, 掉落到地板前) */
die,
/** 游戏结束(撞到地板或撞到水管后掉落到地板) */
gameOver,
// 暂停状态
pause,
// 恢复状态
resume;
}
工具包
工具包下Assets主要完成了对于资源管理器的封装,配合Res接口完成资源的调用。
public class AssetsUtil {
private static AssetManager assetManager;
public static TextureAtlas atlas;
public static BitmapFont bitmapFont;
public static void init(){
assetManager = new AssetManager();
}
public static void load(){
// 加载资源
assetManager.load(Res.Atlas.ATLAS_PATH, TextureAtlas.class);
assetManager.load(Res.Audios.AUDIO_DIE, Sound.class);
assetManager.load(Res.Audios.AUDIO_HIT, Sound.class);
assetManager.load(Res.Audios.AUDIO_TOUCH, Sound.class);
assetManager.load(Res.Audios.AUDIO_RESTART, Sound.class);
assetManager.load(Res.Audios.AUDIO_SCORE, Sound.class);
assetManager.load(Res.FPS_BITMAP_FONT_PATH, BitmapFont.class);
}
public static boolean loadFinished(){
// 加载图集和文字集
atlas = assetManager.get(Res.Atlas.ATLAS_PATH);
bitmapFont = assetManager.get(Res.FPS_BITMAP_FONT_PATH);
return true;
}
/**
* 等待资源加载完毕
* @return
*/
public static boolean update(){
return assetManager.update();
}
public static AssetManager getAssetManager() {
return assetManager;
}
// 资源管理器需要手动释放
public static void dispose(){
assetManager.dispose();
assetManager = null;
atlas = null;
bitmapFont = null;
}
}
CollisionUtils类主要负责碰撞检测操作,调用其中的isCollision方法可以直接判断两个actor的碰撞情况,发生碰撞返回true,否则返回false。
public class CollisionUtils {
private static final Rectangle rect1 = new Rectangle();
private static final Rectangle rect2 = new Rectangle();
private static final Rectangle tempRect = new Rectangle();
/**
* 判断两个演员是否碰撞
*
* @param actor1
* @param actor2
* @param depth 碰撞深度, 两个演员的包围矩阵重叠部分的矩形宽高均超过 depth 才算碰撞
* @return
*/
public static synchronized boolean isCollision(Actor actor1, Actor actor2, float depth) {
if (actor1 == null || actor2 == null) {
return false;
}
// 获取 演员1 缩放后的包围矩阵
rect1.setSize(
actor1.getWidth() * actor1.getScaleX(),
actor1.getHeight() * actor1.getScaleY()
);
rect1.setPosition(
actor1.getX() - (actor1.getOriginX() * actor1.getScaleX() - actor1.getOriginX()),
actor1.getY() - (actor1.getOriginY() * actor1.getScaleY() - actor1.getOriginY())
);
// 获取 演员2 缩放后的包围矩阵
rect2.setSize(
actor2.getWidth() * actor2.getScaleX(),
actor2.getHeight() * actor2.getScaleY()
);
rect2.setPosition(
actor2.getX() - (actor2.getOriginX() * actor2.getScaleX() - actor2.getOriginX()),
actor2.getY() - (actor2.getOriginY() * actor2.getScaleY() - actor2.getOriginY())
);
return rect1.overlaps(rect2);
}
}
SoundPlayer类负责银盆播放。
public class SoundPlayer {
private boolean sound = true;
public SoundPlayer(boolean sound){
this.sound = sound;
}
public void playSound(String soundName){
if(!AssetsUtil.getAssetManager().isLoaded(soundName)) return;
if (!sound){
Gdx.app.error("myk","未获取音频权限");
return;
}
Sound sound = AssetsUtil.getAssetManager().get(soundName);
sound.play();
}
}
本处当没有获得音频播放权限的时候给出日志提示,实际操作时可以考虑弹出异常,对于异常进行捕获处理,弹窗提示等。