外出旅行、冬季保暖得常备户外袜、速干袜、加厚袜子哦。

猛戳乐途驿站http://zhoupa1188.taobao.com抢购品牌男女式加厚户外袜子,coolmax、全棉、保暖、吸汗、速干、登山、徒步袜子。满10包邮


谢炜的cnblogs

CSDN上比较完整:http://hi.csdn.net/xiefeifeihu

导航

8、示例5:TestPong

1 示例5:TestPong

这是一个类似于弹球的游戏,开始让画面动起来了。效果图如下:

clip_image002

按数字键1、2或9、0分别移动两个绿色的弹板,球碰到板子或四周的墙壁就会反弹。

1.1 源代码

隐藏行号 复制代码 源代码
  1. package jmetest.TutorialGuide;
    
  2. 
    
  3. import com.jme.app.SimpleGame;
    
  4. import com.jme.bounding.BoundingBox;
    
  5. import com.jme.bounding.BoundingSphere;
    
  6. import com.jme.input.KeyBindingManager;
    
  7. import com.jme.input.KeyInput;
    
  8. import com.jme.math.FastMath;
    
  9. import com.jme.math.Vector3f;
    
  10. import com.jme.renderer.ColorRGBA;
    
  11. import com.jme.renderer.Renderer;
    
  12. import com.jme.scene.Node;
    
  13. import com.jme.scene.Spatial;
    
  14. import com.jme.scene.Text;
    
  15. import com.jme.scene.shape.Box;
    
  16. import com.jme.scene.shape.Sphere;
    
  17. import com.jme.scene.state.MaterialState;
    
  18. import com.jme.scene.state.MaterialState.ColorMaterial;
    
  19. 
    
  20. /**
    
  21.  * TestPong
    
  22.  */
    
  23. public class TestPong extends SimpleGame {
    
  24.     // Side walls and goal detectors
    
  25.     private Node sideWalls;
    
  26.     private Box player1GoalWall;
    
  27.     private Box player2GoalWall;
    
  28. 
    
  29.     // Ball
    
  30.     private Sphere ball;
    
  31.     private Vector3f ballVelocity;
    
  32. 
    
  33.     // Player 1
    
  34.     private Box player1;
    
  35.     private float player1Speed = 100.0f;
    
  36.     private int player1Score = 0;
    
  37.     private Text player1ScoreText;
    
  38. 
    
  39.     // Player 2
    
  40.     private Box player2;
    
  41.     private float player2Speed = 100.0f;
    
  42.     private int player2Score = 0;
    
  43.     private Text player2ScoreText;
    
  44. 
    
  45.     public static void main(String[] args) {
    
  46.         TestPong app = new TestPong();
    
  47.         app.setConfigShowMode(ConfigShowMode.AlwaysShow);
    
  48.         app.start();
    
  49.     }
    
  50. 
    
  51.     protected void simpleUpdate() {
    
  52.         // Player 1 movement
    
  53.         if (KeyBindingManager.getKeyBindingManager().isValidCommand("PLAYER1_MOVE_UP", true)) {
    
  54.             player1.getLocalTranslation().z -= player1Speed* timer.getTimePerFrame();
    
  55.         }
    
  56.         if (KeyBindingManager.getKeyBindingManager().isValidCommand("PLAYER1_MOVE_DOWN", true)) {
    
  57.             player1.getLocalTranslation().z += player1Speed* timer.getTimePerFrame();
    
  58.         }
    
  59.         player1.getLocalTranslation().z = FastMath.clamp(player1.getLocalTranslation().z, -38, 38);
    
  60. 
    
  61.         // Player 2 movement
    
  62.         if (KeyBindingManager.getKeyBindingManager().isValidCommand("PLAYER2_MOVE_UP", true)) {
    
  63.             player2.getLocalTranslation().z -= player2Speed* timer.getTimePerFrame();
    
  64.         }
    
  65.         if (KeyBindingManager.getKeyBindingManager().isValidCommand("PLAYER2_MOVE_DOWN", true)) {
    
  66.             player2.getLocalTranslation().z += player2Speed* timer.getTimePerFrame();
    
  67.         }
    
  68.         player2.getLocalTranslation().z = FastMath.clamp(player2.getLocalTranslation().z, -38, 38);
    
  69. 
    
  70.         // Collision with player pads
    
  71.         if (player1.hasCollision(ball, false) || player2.hasCollision(ball, false)) {
    
  72.             ballVelocity.x *= -1f;
    
  73.         }
    
  74.         // Collision with side walls
    
  75.         if (sideWalls.hasCollision(ball, false)) {
    
  76.             ballVelocity.z *= -1f;
    
  77.         }
    
  78. 
    
  79.         // Checking for goals (ie collision with back walls)
    
  80.         if (player1GoalWall.hasCollision(ball, false)) {
    
  81.             System.out.println("1 撞);
    
  82.             player1Score++;
    
  83.             player1ScoreText.getText().replace(0, player1ScoreText.getText().length(), "" + player1Score);
    
  84.             ball.getLocalTranslation().set(0,0,0);
    
  85.         } else if (player2GoalWall.hasCollision(ball, false)) {     
    
  86.             System.out.println("2 撞);       
    
  87.             player2Score++;
    
  88.             player2ScoreText.getText().replace(0, player2ScoreText.getText().length(), "" + player2Score);
    
  89.             ball.getLocalTranslation().set(0,0,0);
    
  90.         }
    
  91. 
    
  92.         // Move ball according to velocity
    
  93.         ball.getLocalTranslation().addLocal(ballVelocity.mult(timer.getTimePerFrame()));
    
  94.     }
    
  95. 
    
  96.     protected void simpleInitGame() {
    
  97.         display.setTitle("jME - Pong");
    
  98. 
    
  99.         // Initialize camera
    
  100.         cam.setFrustumPerspective(45.0f, (float) display.getWidth()
    
  101.                 / (float) display.getHeight(), 1f, 1000f);
    
  102.         cam.setLocation(new Vector3f(-150, 200, 80));
    
  103.         cam.lookAt(new Vector3f(-30, 0, 10), Vector3f.UNIT_Y);
    
  104.         cam.update();
    
  105. 
    
  106.         // Create ball
    
  107.         ball = new Sphere("Ball", 8, 8, 2);
    
  108.         ball.setModelBound(new BoundingSphere());
    
  109.         ball.updateModelBound();
    
  110.         ball.setDefaultColor(ColorRGBA.blue);
    
  111.         rootNode.attachChild(ball);
    
  112. 
    
  113.         // Initialize ball velocity
    
  114.         ballVelocity = new Vector3f(100f, 0f, 50f);
    
  115. 
    
  116.         // Create Player 1 pad
    
  117.         player1 = new Box("Player1", new Vector3f(), 2, 5, 10);
    
  118.         player1.setModelBound(new BoundingBox());
    
  119.         player1.updateModelBound();
    
  120.         player1.getLocalTranslation().set(-100, 0, 0);
    
  121.         player1.setDefaultColor(ColorRGBA.green);
    
  122.         rootNode.attachChild(player1);
    
  123. 
    
  124.         // Create Player 2 pad
    
  125.         player2 = new Box("Player2", new Vector3f(), 2, 5, 10);
    
  126.         player2.setModelBound(new BoundingBox());
    
  127.         player2.updateModelBound();
    
  128.         player2.getLocalTranslation().set(100, 0, 0);
    
  129.         player2.setDefaultColor(ColorRGBA.green);
    
  130.         rootNode.attachChild(player2);
    
  131. 
    
  132.         // Create side walls
    
  133.         sideWalls = new Node("Walls");
    
  134.         rootNode.attachChild(sideWalls);
    
  135. 
    
  136.         Box wall = new Box("Wall1", new Vector3f(), 112, 2, 2);
    
  137.         wall.setModelBound(new BoundingBox());
    
  138.         wall.updateModelBound();
    
  139.         wall.getLocalTranslation().set(0, 0, 50);
    
  140.         sideWalls.attachChild(wall);
    
  141. 
    
  142.         wall = new Box("Wall2", new Vector3f(), 112, 2, 2);
    
  143.         wall.setModelBound(new BoundingBox());
    
  144.         wall.updateModelBound();
    
  145.         wall.getLocalTranslation().set(0, 0, -50);
    
  146.         sideWalls.attachChild(wall);
    
  147. 
    
  148.         // Create back wall, goal detector for player 1
    
  149.         player1GoalWall = new Box("player1GoalWall", new Vector3f(), 2, 2, 50);
    
  150.         player1GoalWall.setModelBound(new BoundingBox());
    
  151.         player1GoalWall.updateModelBound();
    
  152.         player1GoalWall.getLocalTranslation().set(110, 0, 0);
    
  153.         rootNode.attachChild(player1GoalWall);
    
  154. 
    
  155.         // Create back wall, goal detector for player 2
    
  156.         player2GoalWall = new Box("player2GoalWall", new Vector3f(), 2, 2, 50);
    
  157.         player2GoalWall.setModelBound(new BoundingBox());
    
  158.         player2GoalWall.updateModelBound();
    
  159.         player2GoalWall.getLocalTranslation().set(-110, 0, 0);
    
  160.         rootNode.attachChild(player2GoalWall);
    
  161. 
    
  162.         // Assign key bindings
    
  163.         KeyBindingManager.getKeyBindingManager().set("PLAYER1_MOVE_UP", KeyInput.KEY_1);
    
  164.         KeyBindingManager.getKeyBindingManager().set("PLAYER1_MOVE_DOWN", KeyInput.KEY_2);
    
  165.         KeyBindingManager.getKeyBindingManager().set("PLAYER2_MOVE_UP", KeyInput.KEY_9);
    
  166.         KeyBindingManager.getKeyBindingManager().set("PLAYER2_MOVE_DOWN", KeyInput.KEY_0);
    
  167. 
    
  168.         // Create score showing items
    
  169.         player1ScoreText = Text.createDefaultTextLabel("player1ScoreText", "0");
    
  170.         player1ScoreText.setRenderQueueMode(Renderer.QUEUE_ORTHO);
    
  171.         player1ScoreText.setLightCombineMode(Spatial.LightCombineMode.Off);
    
  172.         player1ScoreText.setLocalTranslation(new Vector3f(0, display.getHeight()/2, 1));
    
  173.         rootNode.attachChild(player1ScoreText);
    
  174. 
    
  175.         player2ScoreText = Text.createDefaultTextLabel("player2ScoreText", "0");
    
  176.         player2ScoreText.setRenderQueueMode(Renderer.QUEUE_ORTHO);
    
  177.         player2ScoreText.setLightCombineMode(Spatial.LightCombineMode.Off);
    
  178.         player2ScoreText.setLocalTranslation(new Vector3f(display.getWidth() - 30, display.getHeight()/2, 1));
    
  179.         rootNode.attachChild(player2ScoreText);
    
  180. 
    
  181.         // Make the object default colors shine through
    
  182.         MaterialState ms = display.getRenderer().createMaterialState();
    
  183.         ms.setColorMaterial(ColorMaterial.AmbientAndDiffuse);
    
  184.         rootNode.setRenderState(ms);
    
  185.     }
    
  186. }
    

 

1.2 详细说明

// Initialize camera

cam.setFrustumPerspective(45.0f, (float) display.getWidth()

/ (float) display.getHeight(), 1f, 1000f);

cam.setLocation(new Vector3f(-150, 200, 80));

cam.lookAt(new Vector3f(-30, 0, 10), Vector3f.UNIT_Y);

cam.update();

首先初始化摄像头的角度,让我们从上到下看有一个很好的视角。如果不设置cam效果是怎样呢:

clip_image004

按w、a、s、d、q、z等按键调整一下角度再看:

clip_image006

要想调个好视角还得费一番功夫,上图的视角也很不理想。

后面一段分别定义了弹球及其速度、绿色弹板(player1和player2)、两边的围墙(wall、sideWalls)、和后墙(两个玩家的目标探测仪goal detector)。这里的wall绑定到sideWalls节点上。

下面来看看怎么让画面动起来。

我们需要重载simpleUpdate函数。因为在main函数中调用app.start()启动游戏,start函数里面有个while循环,一刻不停地更新状态。 update(-1.0f);这个update是在BaseSimpleGame类里实现的,它调用了simpleUpdate。所以要想小球动起来,只需要在simpleUpdate中修改它的位置坐标即可,让它产生一定规律的运动。

// Move ball according to velocity

ball.getLocalTranslation().addLocal(

ballVelocity.mult(timer.getTimePerFrame()));

这就让小球延一个方向跑过去。ballVelocity是个速度向量,它乘以一个标量仍然是个向量。如果要使用ball.getLocalTranslation().add,产生的新的向量并没有赋给ball的localTranslation,所以用add小球不动。

下面来看看碰撞检测的方法,用hasCollision函数即可:

if (ball.hasCollision(sideWalls, false)) {

System.out.println("撞上侧墙了");

}

撞上之后需要改变小球的运动方向(向量),可以参考光线反射原理:

if (ball.hasCollision(sideWalls, false)) {

ballVelocity.z *= -1f;

}

if (KeyBindingManager.getKeyBindingManager().isValidCommand(

"PLAYER1_MOVE_UP", true)) {

player1.getLocalTranslation().z -= player1Speed

* timer.getTimePerFrame();

}

这是移动挡板,只需修改位置向量即可。没有限制的话挡板就会移到围墙外面去。

player1.getLocalTranslation().z = FastMath.clamp(player1.getLocalTranslation().z, -38, 38);

就限制了z的移动范围。函数FastMath.clamp的源代码如下:

public static float clamp(float input, float min, float max) {

return (input < min) ? min : (input > max) ? max : input;

}

如果给定的input值小于min,则返回min;如果大于max,就返回max;如果在min和max之间就返回input自己。这样我们就把一个数组固定在某个范围之内了。

现在我们基本上把这个例子弄清楚了:要想使一个物体运动只需在重载函数simpleUpdate中修改位置向量即可。可以通过hasCollision函数检测两个物体是否发生碰撞。

我在调试的时候遇到一个问题:如果小球的速度向量设置不合理,有可能检测不到碰撞,这时小球会飞出界外。比如:ballVelocity = new Vector3f(100f, 0f, 50f);时就从后挡板飞出去了,ballVelocity = new Vector3f(50f, 0f, 50f);就能在围墙内自由弹跳。我想可能是jME时钟造成的,运动的两个位置跳跃过大使之检测不到碰撞。比如我把速率调小:ballVelocity.mult((float) 0.1)又能在范围内弹跳了。

posted on 2009-09-26 14:29  飞飞狐  阅读(276)  评论(0编辑  收藏  举报

外出旅行、冬季保暖得常备户外袜、速干袜、加厚袜子哦。

猛戳乐途驿站http://zhoupa1188.taobao.com抢购品牌男女式加厚户外袜子,coolmax、全棉、保暖、吸汗、速干、登山、徒步袜子。满10包邮