- 作者:老汪软件技巧
- 发表时间:2024-09-12 00:02
- 浏览量:
A. 项目描述
《奔跑吧武士》是一款集动作与策略于一体的Android游戏,旨在为玩家提供一场激动人心的武侠冒险之旅。游戏的功能设计,需确保游戏的流畅体验和高度的娱乐性。
1. 核心玩法: 游戏的核心玩法围绕武士角色的冒险和战斗展开。玩家需要操控武士在各种场景中完成任务,包括击败敌人、收集资源。游戏场景设计需要富有挑战性,包含多样化的敌人类型和障碍物,以测试玩家的策略和反应能力。
2. 战斗与策略: 战斗系统需要平衡动作与策略。玩家可以使用武器和战术来应对敌人,合理运用技能和战术是取胜的关键。战斗中的敌人应具有不同的攻击模式和策略,挑战玩家的应变能力。
3. 图形与音效: 高质量的图形和音效对游戏体验至关重要。游戏应具备精美的武侠风格图形,细致的角色和环境设计,以及动感的音效和背景音乐,以增强沉浸感。
4. 得分成就: 游戏应支持玩家的成绩排行榜和成就系统。这些功能可以激励玩家进行更高水平的挑战,增加玩家的粘性和参与度。
5. 用户界面与体验: 界面设计应简洁直观,确保玩家可以轻松导航并快速上手。游戏操作需要流畅,控制按钮应根据触摸屏进行优化,以提升玩家的操作体验。
这些功能需求将确保《奔跑吧武士》成为一款受玩家喜爱的动作冒险游戏,并为其提供持久的娱乐价值。
B. 开发工具C. 代码设计
模块化设计:结构: 将游戏代码分成不同的模块,如角色控制、敌人行为、UI管理、音效处理等。每个模块负责游戏的一个特定功能,便于维护和扩展。
数据存储与管理:实现: 使用本地存储(SharedPreferences)来保存游戏数据,如游戏等分和成就。
游戏中包含多种角色和对象:主角是武士(Player),还有各种敌人,包括强大的大Boss、巡逻士兵以及具有威胁的乌鸦。此外,游戏还设有食物(如苹果)和武器等道具。游戏的主要显示由 DashSurfaceView 处理,它继承自 SurfaceView,负责游戏界面的渲染和用户操作的响应。通过 DashSurfaceView,游戏能够实现平滑的图形绘制和实时的用户输入处理,确保流畅的游戏体验。
在DashSurfaceView 中,执行了游戏线程,代码如下:
public void run() {
while (flag) {
long start = System.currentTimeMillis();
if (pageResume) {
myDraw();// 绘制游戏画面
logic();// 执行游戏逻辑
}
long end = System.currentTimeMillis();
try {
if (end - start <= 100)
Thread.sleep(100 - end + start);
} catch (Exception e) {
e.printStackTrace();
}
}
}
实现了定时刷新游戏画面、执行游戏逻辑。
绘制游戏画面定义在 myDraw函数中,通过Canvas绘制游戏画面,同时针对不通的绘制对象进行了代码封装,便于维护和扩展,代码如下:
private void myDraw() {
try {
canvas = holder.lockCanvas();
if (canvas != null) {
switch (status) {
// 绘制loading界面
case Tools.GAME_LOADING:
loading.draw(canvas, paint);
break;
// 绘制 GAME_MENU 界面
case Tools.GAME_MENU:
gameMenu.draw(canvas, paint);
break;
// 绘制GAME_PLAYING 界面
case Tools.GAME_PLAYING:
gameing_bg.draw(canvas, paint);
for (int i = 0; i < veEnemy.size(); i++) {
veEnemy.elementAt(i).onDraw(canvas, paint);
}
mapDraw();
mybutton.draw(canvas, paint);
player.draw(canvas, paint);
// 子弹
for (int i = 0; i < vetorBullet.size(); i++) {
vetorBullet.elementAt(i).onDraw(canvas, paint);
}
// 死亡效果
for (int i = 0; i < veDead.size(); i++) {
veDead.elementAt(i).onDraw(canvas, paint);
}
// 食物
for (int i = 0; i < vcFood.size(); i++) {
vcFood.elementAt(i).onDraw(canvas, paint);
}
// 绘制Boss
if (boss != null) {
if (boss.isDead() == false) {
boss.draw(canvas, paint);
}
}
// boss子弹
if (boss != null) {
for (int i = 0; i < vetorBulletBoss.size(); i++) {
vetorBulletBoss.elementAt(i).onDraw(canvas, paint);
}
}
break;
// 绘制GAME_OVER 界面
case Tools.GAME_OVER:
// 将最后的米数给gameover界面
Game_Over.latestmeter = gameing_bg.getMeter();
gameover.draw(canvas, paint);
break;
// 绘制 GAME_PAUSE 界面
case Tools.GAME_PAUSE:
gameing_bg.draw(canvas, paint);
mapDraw();
pause.draw(canvas, paint);
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
finally {
if (canvas != null && null!=holder) {
if (holder.getSurface().isValid()) {
holder.unlockCanvasAndPost(canvas);
}
}
}
}
游戏的主要逻辑定义在 logic 函数中,针对不通的场景、功能界面分别做了明确定义,同时对相应的代码进行了封装,代码实现如下:
public void logic() {
switch (status) {
// loading界面逻辑
case Tools.GAME_LOADING:
if (isFirstLoadLoading) {
initImage(); // 初始化图片
isFirstLoadLoading = false;
}
init(); // 初始化游戏
status = Tools.GAME_PLAYING;
if (countMusic++ == 0) {
GameMusic.startMusic();// 播放 GAME_PLAYING 界面 背景音乐;
GameMusic.playSound(R.raw.land, 0);// 播放一次落地 音效
} else {
GameMusic.nextMusic(R.raw.bg);
GameMusic.playSound(R.raw.land, 0);// 播放一次落地 音效
}
break;
// GAME_MENU 界面 逻辑
case Tools.GAME_MENU:
gameMenu.logic();
break;
// GAME_PLAYING 界面逻辑
case Tools.GAME_PLAYING:
gameing_bg.logic();
// ……
// 设置地图速度
for (int i = 0; i < vcMap.size(); i++) {
// ……
}
// 设置敌人速度
for (int i = 0; i < veEnemy.size(); i++) {
// ……
// 设置食物速度
for (int j = 0; j < vcFood.size(); j++) {
// ……
}
}
//设置子弹偏移量
for (int i = 0; i < vetorBullet.size(); i++) {
// ……
}
for (int i = 0; i < vetorBulletBoss.size(); i++) {
// ……
}
// // ////////
// 主角的逻辑处理-----------------------------------------------------------------------------------------------------
player.logic();
// 判断主角与木桩的碰撞
for (GameMap e : vcMap) {
// 判断主角是否在地上的桥之上
// ……
// 判断主角是否在天上的桥之下
// ……
// 判断主角与左突起的碰撞
// ……
// 判断主角与桥桩子的碰撞
// ……
// 如果屏幕停止了,但是忍者跳到了木桩之上,则要让屏幕继续移动
// ……
}
if (player.getIsPlayerDead()) {
// 播放死亡声效
// 暂停游戏中背景音乐
// ……
status = Tools.GAME_OVER;
}
// 主角的逻辑处理--------------------------------------------------------------------------------------
// 人物子弹
if (player.getIsShootMore()) {
// ……
}
// 人物子弹移除方法及逻辑及打到boss
for (int i = 0; i < vetorBullet.size(); i++) {
// ……
}
// 乌鸦
if (gameing_bg.getMeter() % 100 == 0) {
Enemy enemy = new Enemy(Tools.ENEMY_CROW, bmpCrow);
veEnemy.add(enemy);
enemy = null;
}
for (int i = 0; i < veEnemy.size(); i++) {
Enemy c = veEnemy.elementAt(i);
// ……
}
// 碰撞
for (int j = 0; j < veEnemy.size(); j++) {
// 子弹
for (int i = 0; i < vetorBullet.size(); i++) {
// ……
}
}
// 人物无敌与敌人
if (player.getIsUndead()) {
// ……
}
}
// 死亡效果
for (int i = 0; i < veDead.size(); i++) {
// ……
}
// 食物
if (gameing_bg.getMeter() %250 == 0) {
// ……
}
if (gameing_bg.getMeter() % 150 == 0) {
// ……
}
for (int i = 0; i < vcFood.size(); i++) {
// ……
}
// 敌人与主角碰撞
for (Enemy e : veEnemy) {
// ……
}
// 食物与主角碰撞
for (Food f : vcFood) {
// ……
}
// Boss逻辑
if (gameing_bg.getMeter() % 1000 == 0) {
boss = new Boss(vcboss);
}
if (boss != null) {
boss.logic();
// ……
}
}
// boss子弹与主角碰撞
for (int i = 0; i < vetorBulletBoss.size(); i++) {
// ……
}
break;
// GAME_OVER 界面逻辑
case Tools.GAME_OVER:
gameover.logic();
break;
// GAME_PAUSE 界面逻辑
case Tools.GAME_PAUSE:
break;
}
}
触屏事件定义在 DashSurfaceView 类的 onTouchEvent函数中,分别处理了在菜单页面、游戏进行时页面、游戏暂停页面以及游戏结束页面的触控事件,代码如下:
public boolean onTouchEvent(MotionEvent event) {
switch (status) {
case Tools.GAME_MENU:
gameMenu.onTouchEvent(event);// GameMenu 界面 触屏事件
break;
case Tools.GAME_PLAYING:
if (!mybutton.onTouchEvent(event) && !player.getIsJumpTwice()
&& !player.getIsScreenDown()) {
// Log.e("",
// !mybutton.onTouchEvent(event)+","+!player.getIsJumpTwice()+","+!player.getIsDrawRope()+"");
gameing_bg.onTouchEvent(event, player.getPosition()[1]);
}
// 将当前的米数传给暂停界面用于显示
Pause.currentmeter = gameing_bg.getMeter();
mybutton.onTouchEvent(event);// 暂停,,,发表按钮触屏事件
player.ontouch(event, mybutton.getPosition(),
mybutton.getPositionLeftRound());
// //////33333开火
if (inRect((int) event.getX(), (int) event.getY(), rect)) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
bulletFire = true;
} else {
bulletFire = false;
}
if (event.getAction() == MotionEvent.ACTION_UP) {
bulletFire = false;
}
}
break;
case Tools.GAME_OVER:
gameover.onTouchEvent(event);
break;
case Tools.GAME_PAUSE:
pause.onTouchEvent(event);// GamePause 界面 触屏事件
break;
}
return true;
}
D. 项目演示
E. 项目源码
关注公众号『数字森林』,后台发送关键字:武士,获取项目源码。