这个程序介绍了声音节点,天空盒,声音API控制,你将学习
如何去播放声音,创建文本,制作你的controller和输入handler.而且介绍了简单的碰撞检测.
可编译声音继承soundspatial extends objext
因此可编程声音不是一个在trimesh或者geometry或者node的"spatial",它不能被普通的渲染环境渲染,它由声音系统渲染,对象被显示系统渲染。在这个系统里,我们打算使用一个programmable 声音 一个programmable sound是一个有各自url连接的节点。每个url关联的声音可以被某个事件触发,我们的激光声音的事件id是1,这个数字不实很重要,我将在以后提及如何使用它,但我们首先了解如何建立声音:
/** init sound API acording to the rendering enviroment you're using
*/
SoundAPIController.getSoundSystem(properties.getRenderer());
/** Set the 'ears' for the sound API */
SoundAPIController.getRenderer().setCamera(cam);
第一行创建了声音系统,声音不能设置为默认,我们创建
一个具体要渲染的声音的系统。如果我们使用Lwjgl库那么它将创建lWJGL的声音系统。下一步我们设置“耳朵”来配置声音在摄像机的位置,随后我们创建我们的声音对象
snode = new SoundNode();
/** Create program sound */
targetSound = new ProgrammableSound();
/** Make the sound softer */
targetSound .setLooping(false);
targetSound.setMaxDistance(140f);
在这里设置了一个距离我们140单位远的不会循环播放的声音对象。同样我们设置激光的声音对象,但不需要给他一个距离:
laserSound = new ProgrammableSound();
laserSound.setLooping(false);
下一步。我们把声音对象绑定到声音节点:
/** locate laser and register it with the prog sound. */
laserURL = HelloIntersection.class.getClassLoader().getResource(
"jmetest/data/sound/laser.ogg");
hitURL = HelloIntersection.class.getClassLoader().getResource(
"jmetest/data/sound/explosion.ogg");
// Ask the system for a program id for this resource
int programid = SoundPool.compile(new URL[] { laserURL });
int hitid = SoundPool.compile(new URL[] { hitURL });
// Then we bind the programid we received to our laser event id.
laserSound.bindEvent(laserEventID, programid);
targetSound.bindEvent(hitEventID, hitid);
snode.attachChild(laserSound);
snode.attachChild(targetSound);
SoundPool.compile 接收一个url数组并编译到一个soundpool,这些声音由整数指定,在编译后,我们告诉snode是否lasereventid事件被调用,它将播放在soundpool中的指定programid的声音,无论何时hitevetnid事件被触发,就会播放hitid指定的声音,我们只使用一个声音,但我们能容易制造一个激光声音邦定到我们的programid通过使用2个url数组,在制造了声音之后,我们把十字光标放到屏幕上
/** Create a + for the middle of the screen */
Text cross = new Text("Crosshairs", "+");
// 8 is half the width of a font char
/** Move the + to the middle */
cross.setLocalTranslation(new Vector3f(display.getWidth() / 2f - 8f,
display.getHeight() / 2f - 8f, 0));
fpsNode.attachChild(cross);
text扩展了geometry,这意味着text需要一个名字,我们叫它“crosshairs”,text就显示到屏幕上,这里显示一个“+”,这个转换的text不是真实世界的坐标像其他时候,
这个坐标是实际的屏幕坐标,setLocalTranslation 方法的Z轴被忽略因此是0,设置我们的+到屏幕的中间,
你将注意我没有分配到rootnode而是fpsnode,fpsnode是被simplegame创建并有一个默认的孩子节点,这个孩子节点就是你看见的在屏幕的底部,我分配我的cross到fpsnode因为fpsnode有一个特定的纹理,让我们看这个纹理:
text exttext将把ascII匹配到图片的一个位置,显示每个字母,把握这一点,你可以容易地更改一个图片文件获取任何text你想要得到的,在创建+后,我创建skybox到我的世界:
/** Create a skybox to suround our world */
sb = new Skybox("skybox", 200, 200, 200);
URL monkeyLoc = HelloIntersection.class.getClassLoader().getResource(
"jmetest/data/texture/clouds.png");
TextureState ts = display.getRenderer().createTextureState();
59
ts.setTexture(TextureManager.loadTexture(monkeyLoc,
Texture.MM_LINEAR,
Texture.FM_LINEAR, true));
sb.setRenderState(ts);
这样简单地创建一个200x200x200单位的框。这个箱子出现这样的纹理。我分配云到纹理中,最后我们绑定按键到action中
input.addKeyboardAction("firebullet", KeyInput.KEY_F,
new FireBullet());
输入创建一个简单的游戏,它是一个inputhandler类,
默认地,游戏给输入信息需要去做鼠标和键盘的处理,这里,我增加key_F去绑定到AWT,这个简单的状态当你压了F key,FireBullet.performAction将被调用,让我们看
子弹的构造器:
FireBullet() {
setAllowsRepeats(false);
}
这个功能是如果我们按下F,你不会看到上千个子弹在屏幕中交在一起,如果你要变成自动发射,你设置true就可以了,注意FireBullet extends AbstractInputAction,这样允许我们绑定键盘的action,下面介绍performaction:
System.out.println("BANG");
/** Create bullet */
Sphere bullet = new Sphere("bullet" + numBullets++, 8, 8, .25f);
bullet.setModelBound(new BoundingSphere());
bullet.updateModelBound();
/** Move bullet to the camera location */
bullet.setLocalTranslation(new Vector3f(cam.getLocation()));
bullet.setRenderState(bulletMaterial);
无论什么时候按下f,首先创建子弹,紧接着我移动它到摄像机的位置(就是子弹初始的位置),然后把子弹设成绿色
bullet.updateGeometricState(0, true);
调用这个方法因为我需要更新几何信息(重要的是他的包裹体),这给子弹正确的世界绑定使它能够立即被bulletmover()更新,子弹开始与updateGeometricState 被调用,因为这个方法是子弹的孩子,方法的背后是每个simplegame的帧调用rootNode.updateGeometricState(time_per_frame,true)去移动和更新全部的子节点,下面,我给移动子弹的controller:
/**
* Add a movement controller to the bullet going in the camera's
* direction
*/
bullet.addController(new BulletMover(bullet, new Vector3f(cam
.getDirection())));
移动这个子弹沿着摄像机的方向,我们得到子弹的下一位置,但先让我们完成F的按键
rootNode.attachChild(bullet);
bullet.updateRenderState();
下面我们分配到这个节点和调用 updateRenderState(),
再一次 updateRenderState() 被调用在simpleInitGame()之后,这个方法将全部的渲染状态应用到spatial,
包括所有的子状态,如果没有更新渲染状态子弹将是红色的,最后,我通知programsound初始化lasereventid,记住邦定到laser sound
/** Signal our sound to play laser during rendering */
laserSound.setPosition(cam.getLocation());
snode.onEvent(laserEventID);
现在,让我们看下BulletMover(),注意 它是一个controller像KeyframeController 和SpatialController
一样,他移动spatial在给定的方向,每次updateGeometricState()被调用或者子弹的根节点,这个方法起更新全部的子弹状态,让我们看update()
public void update(float time) {
更新时间是在相连帧之间的时间,为什么?因为那是updateGeometricState()给出的浮点值,下面我们可以移动子弹
lifeTime -= time;
/** If life is gone, remove it */
if (lifeTime < 0) {
rootNode.detachChild(bullet);
bullet.removeController(this);
return;
}
如果子弹的存在超过5秒,我把它干掉,很简单对吧?
下面,我移动子弹沿着它的方向
/** Move bullet */
Vector3f bulletPos = bullet.getLocalTranslation();
bulletPos.addLocal(direction.mult(time * speed));
bullet.setLocalTranslation(bulletPos);
这个时间的浮点值是update()给予的,速度是常量,下面,我检查子弹有无射到他的目标
/** Does the bullet intersect with target? */
if (Intersection.intersection(bullet.getWorldBound(), target
.getWorldBound())) {
注意那是检查子弹的世界约束边界和目标的边界
约束量可以比实际的网的边界更大,这意味着两个边界
可以相交,我将增加更复杂的方法在两个trimesh对象相交,但现在我们要保持简单,我简单地移动目标和干掉子弹,这是 simpleRender 和 simpleUpdate要做的
/**
* Called every frame for rendering
*/
protected void simpleRender() {
// Give control to the sound in case sound changes are needed.
SoundAPIController.getRenderer().draw(snode);
}
/**
* Called every frame for updating
*/
protected void simpleUpdate() {
// Let the programmable sound update itself.
snode.updateGeometricState(tpf, true);
}
我还要更新和渲染声音象一个简单的游戏,这就是我要做的,变量tpf被simplegame创建,它是每帧的次数
它更新每一帧
分享到:
相关推荐
### JME3游戏开发引擎中文学习指南 #### 引言 JME3,全称jMonkeyEngine3,是一款开源的3D游戏开发引擎,专为Java开发者设计,旨在简化3D游戏和应用程序的开发过程。本文档将详细介绍如何在Netbeans6.x环境下搭建...
com.jme3.animation com.jme3.app com.jme3.app.state com.jme3.asset com.jme3.asset.pack com.jme3.asset.plugins com.jme3.audio com.jme3.audio.joal ...jme3tools.preview
这份"JME学习文档—中文版"压缩包文件,显然是为了帮助初学者或有经验的Java开发者掌握JME的使用和开发技巧。 JME的核心在于它的可移植性,它允许开发者编写一次代码,就能在多个平台上运行,这得益于其“Write ...
Java Micro Edition(JME,前身为...通过深入学习和实践这些知识点,你将能够利用JME的强大功能,开发出富有创新性的移动和嵌入式应用。在阅读本教程时,建议同时进行实际编码练习,以便更好地理解和掌握JME的精髓。
标题中的“联想的JME2207P键盘驱动”是指专门为联想品牌的一款键盘型号为JME2207P的设备设计的驱动程序。在计算机硬件系统中,驱动程序是连接操作系统与硬件设备的关键软件,它使得操作系统能够识别并控制特定硬件,...
**JME程序设计实例教程详解** Java Micro Edition(JME),又称为Java 2 Micro Edition...通过学习,开发者不仅能够理解JME的编程模型,还能熟练运用其API,解决实际问题,为移动和嵌入式领域的软件开发打下坚实基础。
该引擎不仅功能全面,其API设计简洁明了,易于学习掌握。 - **应用场景**:主要应用于3D游戏开发领域,包括但不限于桌面应用、Android及iOS平台游戏的开发。 - **核心功能**: - 场景管理:用于构建和管理复杂的...
【Java学习笔记整理】 Java是一种广泛使用的编程语言,它不仅是一种语言,还是一个软件开发平台和运行环境。Java分为三个主要版本:Java标准版(JSE)、Java缩微版(JME)和Java企业版(JEE)。JSE主要用于桌面应用...
通过深入学习《2015jme3指南》,开发者不仅可以了解JME3的使用,还能掌握3D游戏开发的基本流程和技巧,为今后的项目开发打下坚实基础。同时,结合博主的博客文章,可以得到更全面的开发经验,解决实际遇到的问题。
标题中的“联想FN功能键 jme2207p键盘驱动. XP windows7”表明这是一个针对联想笔记本电脑的FN功能键以及JME2207P型号键盘的驱动程序,适用于Windows XP和Windows 7操作系统。FN键是许多笔记本电脑上常见的辅助功能...
jme8002b蓝牙键盘驱动
JME Molecular Editor结构式在线编辑器
2. **简洁的API**:JME3的API设计清晰,易于学习和使用,开发者可以快速上手进行游戏开发。 3. **物理引擎集成**:通过与Bullet物理引擎的集成,JME3提供了真实的物理模拟,使游戏中的物体运动更加逼真。 4. **跨...
游戏引擎是开发电子游戏的核心工具,它为游戏开发者提供了一个集成环境,用于创建、管理和优化游戏...通过学习和掌握游戏引擎的相关技术,开发者可以更高效地实现游戏创意,提高开发效率,同时保证游戏的性能和质量。
标题“ant-jme.jar.zip”指的是一个压缩文件,其中包含了两个关键元素:ant-jme.jar和ant.license.txt。这个文件主要与Java开发工具有关,特别是Apache Ant和Java Micro Edition (JME)。 Apache Ant是一个Java库和...
**10. 性能优化** 为了确保游戏在不同设备上的流畅运行,jme3提供了性能优化工具,如帧率控制、资源管理、内存优化等。开发者需要考虑硬件兼容性和资源的合理分配。 通过“Rise of Mutants”这款游戏Demo,我们...
本文档是JME 的javadoc 文档 JME是一个高性能的3D图形API,采用LWJGL作为底层支持。它的后续版本将支持JOGL。JME和Java 3D具有类似的场景结构,开发者必须以树状方式组织自己的场景。JME有一套很好的优化机制,这...
《JME商业游戏进阶二 (地表层的神秘面纱1)...通过深入研究这个"ditu_example"的源代码,开发者不仅能学习到JME的用法,还能掌握游戏开发中的许多核心概念和技术,这对于提升游戏开发技能和理解游戏架构有着极大的帮助。
### JME试题及答案知识点详解 #### 一、选择题知识点解析 ...这些知识点涵盖了JME中的多个方面,包括网络通信、图形处理、游戏开发等,旨在帮助中级水平的学习者深入理解JME的相关概念和技术细节。
**JMonkeyEngine 3 (JME3) 文件格式详解** JMonkeyEngine 3(简称JME3)是一款开源的游戏开发引擎,专为构建3D游戏和应用而设计。它支持多种文件格式,使得开发者能够方便地导入和管理游戏资源。以下是对JME3支持的...