活动介绍

Android平台Doom游戏开发:音频、接口与原生层实现

立即解锁
发布时间: 2025-08-26 00:32:33 阅读量: 3 订阅数: 9
PDF

Android游戏开发:从零开始构建经典射击游戏

# Android平台Doom游戏开发:音频、接口与原生层实现 ## 1. 音频处理 ### 1.1 音频方法 在Doom游戏的Android开发中,有两个重要的音频方法: - `stopMusic (String key)`:该方法用于停止由`key`指定的背景音乐。 - `setMusicVolume (int vol)`:此方法用于设置背景音乐的音量,`vol`的取值范围是0到100。 ### 1.2 音频类与文件处理 `AudioClip`类与Wolfenstein 3D的`AudioClip`类基本相同,只是包名被重命名了。由于音频文件(包括背景音乐)可能会占用超过5MB的空间,因此这些文件被打包成一个zip存档,并在运行时安装到SD卡中,这样可以节省主文件系统的宝贵磁盘空间。这个zip存档位于Doom项目的`assets`文件夹中。 ### 1.3 避免媒体扫描问题 Android具有自动媒体扫描服务,会在文件系统中搜索音频文件。这可能会导致媒体播放器突然显示数百个不需要的Doom音效和音乐。为了解决这个问题,可以在声音文件夹中添加一个名为`.nomedia`的空文件,这样媒体扫描器就会跳过该目录。 ## 2. 原生接口类 ### 2.1 概述 原生接口类是一个双向管道,它通过原生方法将消息从Java发送到Doom引擎,并使用C到Java的回调将消息从引擎发送回Java。该类由三部分组成:回调监听器、原生方法和C到Java的回调。 ### 2.2 回调监听器 回调监听器由`EventListener`接口实现,希望接收C到Java回调的客户端(在这种情况下是主活动`DoomClient.java`)必须实现该接口。C到Java的回调如下: - `OnMessage(String text, int level)`:主要是一个调试回调,用于发送消息,让Java了解原生端的情况。 - `OnInitGraphics(int w, int h)`:这是第一个回调,仅在图形初始化后触发一次,它会告诉Java视频缓冲区的宽度和高度。 - `OnImageUpdate(int[] pixels)`:每秒会触发多次,将Android打包的视频缓冲区发送到Java,Java将使用它来渲染游戏位图。 - `OnFatalError(String text)`:当引擎中出现不可恢复的错误时触发,接收者应显示消息并终止程序。 - `OnQuit(int code)`:当用户退出游戏时触发,将返回代码发送回接收者。 - `OnStartSound(String name, int vol)`:当原生引擎启动一个声音时触发,委托给接收者处理。 - `OnStartMusic(String name, int loop)`:在背景音乐启动时触发,委托给接收者处理。 - `OnStopMusic(String name)`:在停止背景音乐时触发,委托给接收者处理。 - `OnSetMusicVolume(int volume)`:当用户设置音乐音量时触发,委托给接收者处理。 ### 2.3 原生方法 原生方法用于调用原生Doom引擎,有三个基本的原生方法: - `static native int DoomMain(String[] argv)`:该方法调用Doom引擎的主游戏循环。 - `static native int keyEvent(int type, int key)`:该方法将按键事件发送到引擎,事件类型可以是`EV_KEYDOWN`或`EV_KEYUP`,参数`key`必须是ASCII符号,而不是Android键码,这意味着在发送到引擎之前必须对键码进行转换。 - `static native int motionEvent(int b, int x, int y)`:该方法将运动事件(如用户在显示屏上拖动手指)发送到引擎,第一个参数是鼠标按钮(在这种情况下始终为零),加上事件本身的x和y坐标。 `static native int DoomMain(String[] argv)`需要一个参数列表并会阻塞执行,因此必须在一个线程中运行。以下是一些重要的参数: - `width`:定义视频缓冲区的宽度。 - `height`:定义视频缓冲区的高度。 - `iwad`:定义要玩的游戏,引擎支持以下游戏文件: - `doom1.wad`:Doom的共享软件版本。 - `doom.wad`:零售版本。 - `doom2.wad`:Doom系列的第二集。 - `plutonia.wad`:Plutonia Experiment集,是终极Doom系列的一部分。 - `tnt.wad`:名为Evilution的一集,也是终极Doom系列的一部分。 - `file`:定义引擎要使用的额外游戏文件。 例如,要以横向模式玩Doom共享软件,必须作为`String`数组发送给`DoomMain`的参数列表将是`doom -width 480 -height 320 -iwad doom1.wad`。 ### 2.4 C到Java回调 C到Java回调用于将引擎消息委托给监听器活动。原生接口类使用一个私有监听器和一个静态设置方法: ```java private static EventListener listener; public static void setListener(EventListener l) { listener = l; } ``` 需要注意的是,只能有一个监听器。当Doom引擎发送消息时,原生接口类会将其委托给监听器来处理事件: ```java private static void OnMessage(String text, int level) { if (listener != null) listener.OnMessage(text, level); } ``` 以下是完整的原生接口类代码: ```java package doom.jni; import android.util.Log; public class Natives { public static final String TAG = "Natives"; private static EventListener listener; public static final int EV_KEYDOWN = 0; public static final int EV_KEYUP = 1; public static final int EV_MOUSE = 2; public static interface EventListener { void OnMessage(String text, int level); void OnInitGraphics(int w, int h); void OnImageUpdate(int[] pixels); void OnFatalError(String text); void OnQuit(int code); void OnStartSound(String name, int vol); void OnStartMusic(String name, int loop); void OnStopMusic(String name); void OnSetMusicVolume(int volume); } public static void setListener(EventListener l) { listener = l; } /** * Send a key event to the native layer * * @param type : key up down or mouse * @param sym: ASCII symbol */ public static void sendNativeKeyEvent(int type, int sym) { try { Natives.keyEvent(type, sym); } catch (UnsatisfiedLinkError e) { Log.e(TAG, e.toString()); } } // Native Main Doom Loop: @param argv: program arguments public static native int DoomMain(String[] argv); /** * Send a Key Event * @param type: event type: UP/DOWN * @param key: ASCII symbol */ public static native int keyEvent(int type, int key); /*********************************************************** * C to Java - Callbacks ***********************************************************/ /** * This fires on messages from the C layer */ private static void OnMessage(String text, int level) { if (listener != null) listener.OnMessage(text, level); } private static void OnInitGraphics(int w, int h) { if (listener != null) listener.OnInitGraphics(w, h); } private static void OnImageUpdate(int[] pixels) { if (listener != null) listener.OnImageUpdate(pixels); } private static void OnFatalError(String message) { if (listener != null) listener.OnFatalError(message); } private static void OnQuit(int code) { if (listener != null) listener.OnQuit(code); } /** * Fires when a sound is played in the C layer. */ private static void OnStartSound(byte[] name, int vol) { if (listener != null) listener.OnStartSound(new String(name), vol); } /** * Start background music callback */ private static void OnStartMusic(String name, int loop) { if (listener != null) listener.OnStartMusic(name, loop); } /** * Stop background music * @param name */ private static void OnStopMusic(String name) { if (listener != null) listener.OnStopMusic(name); } /** * Set background music volume * @param volume Range: (0-255) */ private static void OnSetMusicVolume(int volume) { if (listener != null) listener.OnSetMusicVolume((int) (volume * 100.0 / 15.0)); } } ``` ## 3. 原生层 ### 3.1 概述 原生层通过定义三种类型的任务将Java和C代码粘合在一起: - 原生方法实现:这是原生接口类定义的原生Java方法的C实现,代码位于`jni_doom.c`文件中。 - 原始游戏更改:需要对原始Doom引擎进行轻微修改,以适应JNI粘合,这包括在正确的文件中插入对C到Java回调的调用。 - 移除无效依赖:必须移除原始代码中的无效依赖,例如,必须删除PC代码使用的原始Simple DirectMedia Layer (SDL)依赖。 ### 3.2 原生方法实现 以下是Java原生方法签名及其在`jni_doom.c`中的C对应方法: | Java方法 | C方法 | | --- | --- | | `static native int DoomMain(String[] argv)` | `JNIEXPORT jint JNICALL Java_doom_jni_Natives_DoomMain(JNIEnv * env, jclass class, jobjectArray jargv)` | | `static native int keyEvent(int type, int key)` | `JNIEXPORT jint JNICALL Java_doom_jni_Natives_keyEvent(JNIEnv * env, jclass cls, jint type, jint key)` | | `static native int motionEvent(int btn, int x, int y)` | `JNIEXPORT jint JNICALL Java_doom_jni_Natives_motionEvent(JNIEnv * env, jclass cls, jint btn, jint x, jint y)` | 在进行实现之前,必须使用`javah`命令生成所需的头文件和签名: ```sh javah -jni -classpath PATH_TO_PROJECT_FOLDER/bin -d include doom.jni.Natives ``` 需要注意的是,`javah`需要一个指向`bin`文件夹的类路径才能找到`doom.jni.Natives`类。使用`-d`选项将输出文件`doom_jn
corwn 最低0.47元/天 解锁专栏
赠100次下载
继续阅读 点击查看下一篇
profit 400次 会员资源下载次数
profit 300万+ 优质博客文章
profit 1000万+ 优质下载资源
profit 1000万+ 优质文库回答
复制全文

相关推荐

Big黄勇

硬件工程师
广州大学计算机硕士,硬件开发资深技术专家,拥有超过10多年的工作经验。曾就职于全球知名的大型科技公司,担任硬件工程师一职。任职期间负责产品的整体架构设计、电路设计、原型制作和测试验证工作。对硬件开发领域有着深入的理解和独到的见解。
最低0.47元/天 解锁专栏
赠100次下载
百万级 高质量VIP文章无限畅学
千万级 优质资源任意下载
千万级 优质文库回答免费看

最新推荐

从近似程度推导近似秩下界

# 从近似程度推导近似秩下界 ## 1. 近似秩下界与通信应用 ### 1.1 近似秩下界推导 通过一系列公式推导得出近似秩的下界。相关公式如下: - (10.34) - (10.37) 进行了不等式推导,其中 (10.35) 成立是因为对于所有 \(x,y \in \{ -1,1\}^{3n}\),有 \(R_{xy} \cdot (M_{\psi})_{x,y} > 0\);(10.36) 成立是由于 \(\psi\) 的平滑性,即对于所有 \(x,y \in \{ -1,1\}^{3n}\),\(|\psi(x, y)| > 2^d \cdot 2^{-6n}\);(10.37) 由

量子物理相关资源与概念解析

# 量子物理相关资源与概念解析 ## 1. 参考书籍 在量子物理的学习与研究中,有许多经典的参考书籍,以下是部分书籍的介绍: |序号|作者|书名|出版信息|ISBN| | ---- | ---- | ---- | ---- | ---- | |[1]| M. Abramowitz 和 I.A. Stegun| Handbook of Mathematical Functions| Dover, New York, 1972年第10次印刷| 0 - 486 - 61272 - 4| |[2]| D. Bouwmeester, A.K. Ekert, 和 A. Zeilinger| The Ph

使用GameKit创建多人游戏

### 利用 GameKit 创建多人游戏 #### 1. 引言 在为游戏添加了 Game Center 的一些基本功能后,现在可以将游戏功能扩展到支持通过 Game Center 进行在线多人游戏。在线多人游戏可以让玩家与真实的人对战,增加游戏的受欢迎程度,同时也带来更多乐趣。Game Center 中有两种类型的多人游戏:实时游戏和回合制游戏,本文将重点介绍自动匹配的回合制游戏。 #### 2. 请求回合制匹配 在玩家开始或加入多人游戏之前,需要先发出请求。可以使用 `GKTurnBasedMatchmakerViewController` 类及其对应的 `GKTurnBasedMat

区块链集成供应链与医疗数据管理系统的优化研究

# 区块链集成供应链与医疗数据管理系统的优化研究 ## 1. 区块链集成供应链的优化工作 在供应链管理领域,区块链技术的集成带来了诸多优化方案。以下是近期相关优化工作的总结: | 应用 | 技术 | | --- | --- | | 数据清理过程 | 基于新交叉点更新的鲸鱼算法(WNU) | | 食品供应链 | 深度学习网络(长短期记忆网络,LSTM) | | 食品供应链溯源系统 | 循环神经网络和遗传算法 | | 多级供应链生产分配(碳税政策下) | 混合整数非线性规划和分布式账本区块链方法 | | 区块链安全供应链网络的路线优化 | 遗传算法 | | 药品供应链 | 深度学习 | 这些技

由于提供的内容仅为“以下”,没有具体的英文内容可供翻译和缩写创作博客,请你提供第38章的英文具体内容,以便我按照要求完成博客创作。

由于提供的内容仅为“以下”,没有具体的英文内容可供翻译和缩写创作博客,请你提供第38章的英文具体内容,以便我按照要求完成博客创作。 请你提供第38章的英文具体内容,同时给出上半部分的具体内容(目前仅为告知无具体英文内容需提供的提示),这样我才能按照要求输出下半部分。

元宇宙与AR/VR在特殊教育中的应用及安全隐私问题

### 元宇宙与AR/VR在特殊教育中的应用及安全隐私问题 #### 元宇宙在特殊教育中的应用与挑战 元宇宙平台在特殊教育发展中具有独特的特性,旨在为残疾学生提供可定制、沉浸式、易获取且个性化的学习和发展体验,从而改善他们的学习成果。然而,在实际应用中,元宇宙技术面临着诸多挑战。 一方面,要确保基于元宇宙的技术在设计和实施过程中能够促进所有学生的公平和包容,避免加剧现有的不平等现象和强化学习发展中的偏见。另一方面,大规模实施基于元宇宙的特殊教育虚拟体验解决方案成本高昂且安全性较差。学校和教育机构需要采购新的基础设施、软件及VR设备,还会产生培训、维护和支持等持续成本。 解决这些关键技术挑

黎曼zeta函数与高斯乘性混沌

### 黎曼zeta函数与高斯乘性混沌 在数学领域中,黎曼zeta函数和高斯乘性混沌是两个重要的研究对象,它们之间存在着紧密的联系。下面我们将深入探讨相关内容。 #### 1. 对数相关高斯场 在研究中,我们发现协方差函数具有平移不变性,并且在对角线上存在对数奇异性。这种具有对数奇异性的随机广义函数在高斯过程的研究中被广泛关注,被称为高斯对数相关场。 有几个方面的证据表明临界线上$\log(\zeta)$的平移具有对数相关的统计性质: - 理论启发:从蒙哥马利 - 基廷 - 斯奈思的观点来看,在合适的尺度上,zeta函数可以建模为大型随机矩阵的特征多项式。 - 实际研究结果:布尔加德、布

探索人体与科技融合的前沿:从可穿戴设备到脑机接口

# 探索人体与科技融合的前沿:从可穿戴设备到脑机接口 ## 1. 耳部交互技术:EarPut的创新与潜力 在移动交互领域,减少界面的视觉需求,实现无视觉交互是一大挑战。EarPut便是应对这一挑战的创新成果,它支持单手和无视觉的移动交互。通过触摸耳部表面、拉扯耳垂、在耳部上下滑动手指或捂住耳朵等动作,就能实现不同的交互功能,例如通过拉扯耳垂实现开关命令,上下滑动耳朵调节音量,捂住耳朵实现静音。 EarPut的应用场景广泛,可作为移动设备的遥控器(特别是在播放音乐时)、控制家用电器(如电视或光源)以及用于移动游戏。不过,目前EarPut仍处于研究和原型阶段,尚未有商业化产品推出。 除了Ea

利用GeoGebra增强现实技术学习抛物面知识

### GeoGebra AR在数学学习中的应用与效果分析 #### 1. 符号学视角下的学生学习情况 在初步任务结束后的集体讨论中,学生们面临着一项挑战:在不使用任何动态几何软件,仅依靠纸和笔的情况下,将一些等高线和方程与对应的抛物面联系起来。从学生S1的发言“在第一个练习的图形表示中,我们做得非常粗略,即使现在,我们仍然不确定我们给出的答案……”可以看出,不借助GeoGebra AR或GeoGebra 3D,识别抛物面的特征对学生来说更为复杂。 而当提及GeoGebra时,学生S1表示“使用GeoGebra,你可以旋转图像,这很有帮助”。学生S3也指出“从上方看,抛物面与平面的切割已经

人工智能与混合现实技术在灾害预防中的应用与挑战

### 人工智能与混合现实在灾害预防中的应用 #### 1. 技术应用与可持续发展目标 在当今科技飞速发展的时代,人工智能(AI)和混合现实(如VR/AR)技术正逐渐展现出巨大的潜力。实施这些技术的应用,有望助力实现可持续发展目标11。该目标要求,依据2015 - 2030年仙台减少灾害风险框架(SFDRR),增加“采用并实施综合政策和计划,以实现包容、资源高效利用、缓解和适应气候变化、增强抗灾能力的城市和人类住区数量”,并在各级层面制定和实施全面的灾害风险管理。 这意味着,通过AI和VR/AR技术的应用,可以更好地规划城市和人类住区,提高资源利用效率,应对气候变化带来的挑战,增强对灾害的