2 * Copyright (c) 2003-2005 jMonkeyEngine
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 package jmetest.TutorialGuide;
36 import java.util.Random;
38 import com.jme.app.SimpleGame;
39 import com.jme.bounding.BoundingSphere;
40 import com.jme.image.Texture;
41 import com.jme.input.KeyInput;
42 import com.jme.input.action.InputActionEvent;
43 import com.jme.input.action.KeyInputAction;
44 import com.jme.math.Vector3f;
45 import com.jme.renderer.ColorRGBA;
46 import com.jme.scene.Controller;
47 import com.jme.scene.Skybox;
48 import com.jme.scene.Text;
49 import com.jme.scene.TriMesh;
50 import com.jme.scene.shape.Sphere;
51 import com.jme.scene.state.MaterialState;
52 import com.jme.scene.state.TextureState;
53 import com.jme.util.TextureManager;
54 import com.jmex.sound.openAL.SoundSystem;
58 * Started Date: Jul 24, 2004 <br>
61 * Demonstrates intersection testing, sound, and making your own controller.
63 * @author Jack Lindamood
65 public class HelloIntersection extends SimpleGame {
66 /** Material for my bullet */
67 MaterialState bulletMaterial;
69 /** Target you're trying to hit */
72 /** Location of laser sound */
75 /** Location of hit sound */
78 /** Used to move target location on a hit */
79 Random r = new Random();
81 /** A sky box for our scene. */
85 * The programmable sound that will be in charge of maintaining our sound
92 /** The node where attached sounds will be propagated from */
96 * The ID of our laser shooting sound effect. The value is not important. It
97 * should just be unique in our game to this sound.
99 private int laserEventID = 1;
101 private int hitEventID = 2;
103 public static void main(String[] args) {
104 HelloIntersection app = new HelloIntersection();
105 app.setDialogBehaviour(SimpleGame.ALWAYS_SHOW_PROPS_DIALOG);
109 protected void simpleInitGame() {
112 /** Create a + for the middle of the screen */
113 Text cross = new Text("Crosshairs", "+");
115 // 8 is half the width of a font char
116 /** Move the + to the middle */
117 cross.setLocalTranslation(new Vector3f(display.getWidth() / 2f - 8f,
118 display.getHeight() / 2f - 8f, 0));
119 fpsNode.attachChild(cross);
120 target = new Sphere("my sphere", 15, 15, 1);
121 target.setModelBound(new BoundingSphere());
122 target.updateModelBound();
123 rootNode.attachChild(target);
125 /** Create a skybox to suround our world */
126 sb = new Skybox("skybox", 200, 200, 200);
127 URL monkeyLoc = HelloIntersection.class.getClassLoader().getResource(
128 "jmetest/data/texture/clouds.png");
129 TextureState ts = display.getRenderer().createTextureState();
130 ts.setTexture(TextureManager.loadTexture(monkeyLoc, Texture.MM_LINEAR,
132 sb.setRenderState(ts);
134 // Attach the skybox to our root node, and force the rootnode to show
135 // so that the skybox will always show
136 rootNode.attachChild(sb);
137 rootNode.setForceView(true);
140 * Set the action called "firebullet", bound to KEY_F, to performAction
143 input.addKeyboardAction("firebullet", KeyInput.KEY_F, new FireBullet());
145 /** Make bullet material */
146 bulletMaterial = display.getRenderer().createMaterialState();
147 bulletMaterial.setEmissive(ColorRGBA.green);
149 /** Make target material */
150 MaterialState redMaterial = display.getRenderer().createMaterialState();
151 redMaterial.setDiffuse(ColorRGBA.red);
152 target.setRenderState(redMaterial);
155 private void setupSound() {
156 /** Set the 'ears' for the sound API */
157 SoundSystem.init(display.getRenderer().getCamera(), SoundSystem.OUTPUT_DEFAULT);
159 snode = SoundSystem.createSoundNode();
160 /** Create program sound */
161 targetSound = SoundSystem.create3DSample( getClass().getResource( "/jmetest/data/sound/explosion.wav" ) );
162 laserSound = SoundSystem.create3DSample( getClass().getResource( "/jmetest/data/sound/laser.ogg" ) );
163 SoundSystem.setSampleMaxAudibleDistance(targetSound, 1000);
164 SoundSystem.setSampleMaxAudibleDistance(laserSound, 1000);
165 // Then we bind the programid we received to our laser event id.
166 SoundSystem.bindEventToSample(laserSound, laserEventID);
167 SoundSystem.bindEventToSample(targetSound, hitEventID);
168 SoundSystem.addSampleToNode(laserSound, snode);
169 SoundSystem.addSampleToNode(targetSound, snode);
172 class FireBullet extends KeyInputAction {
176 setAllowsRepeats(false);
179 public void performAction(InputActionEvent evt) {
180 System.out.println("BANG");
182 Sphere bullet = new Sphere("bullet" + numBullets++, 8, 8, .25f);
183 bullet.setModelBound(new BoundingSphere());
184 bullet.updateModelBound();
185 /** Move bullet to the camera location */
186 bullet.setLocalTranslation(new Vector3f(cam.getLocation()));
187 bullet.setRenderState(bulletMaterial);
189 * Update the new world locaion for the bullet before I add a
192 bullet.updateGeometricState(0, true);
194 * Add a movement controller to the bullet going in the camera's
197 bullet.addController(new BulletMover(bullet, new Vector3f(cam
199 rootNode.attachChild(bullet);
200 bullet.updateRenderState();
201 /** Signal our sound to play laser during rendering */
202 Vector3f v=cam.getLocation();
203 SoundSystem.setSamplePosition(laserSound, v.x, v.y, v.z);
204 SoundSystem.onEvent(snode, laserEventID);
208 class BulletMover extends Controller {
209 private static final long serialVersionUID = 1L;
210 /** Bullet that's moving */
213 /** Direciton of bullet */
216 /** speed of bullet */
219 /** Seconds it will last before going away */
222 BulletMover(TriMesh bullet, Vector3f direction) {
223 this.bullet = bullet;
224 this.direction = direction;
225 this.direction.normalizeLocal();
228 public void update(float time) {
230 /** If life is gone, remove it */
232 rootNode.detachChild(bullet);
233 bullet.removeController(this);
237 Vector3f bulletPos = bullet.getLocalTranslation();
238 bulletPos.addLocal(direction.mult(time * speed));
239 bullet.setLocalTranslation(bulletPos);
240 /** Does the bullet intersect with target? */
241 if (bullet.getWorldBound().intersects(target.getWorldBound())) {
242 System.out.println("OWCH!!!");
243 Vector3f v=target.getWorldTranslation();
244 SoundSystem.setSamplePosition(targetSound, v.x, v.y, v.z);
246 target.setLocalTranslation(new Vector3f(r.nextFloat() * 10, r
247 .nextFloat() * 10, r.nextFloat() * 10));
249 SoundSystem.onEvent(snode, hitEventID);
256 * Called every frame for rendering
258 protected void simpleRender() {
259 // Give control to the sound in case sound changes are needed.
264 * Called every frame for updating
266 protected void simpleUpdate() {
267 // Let the programmable sound update itself.
268 SoundSystem.update(tpf);