纯Java开发的游戏引擎V0.5--DEMO2 -- 物理引擎


项目命名: JPhysicalEngine
项目目的: 自己爱好/毕业设计
项目人员: http://blog.csdn.net/kakashi8841
运行机器: Intel P8600 2.4GHz、2G内存、Intel GMA X4500 HD
开发环境: Linux Ubuntu 10.10
开发语言: Java
开发工具: Eclipse
项目描述: 使用Java开发的2D游戏物理引擎,可以使得以后开发类似愤怒的小鸟、雷电等物理、碰撞、动作类游戏可以更快速、更方便。

项目进度:
【已实现】
版本  完成日期       实现功能
V0.1 [2011-04-07]  大致框架
V0.2 [2011-04-11]  基本动画
V0.3 [2011-04-15]  恒力和AABB碰撞检测
V0.4 [2011-04-22]  框架优化、简单粒子系统
V0.5 [2011-05-05]  更精确的OBB碰撞检测

【待实现】
版本  计划完成日期    实现功能
V0.6 [2011-05-10]  变力
V0.7 [2011-05-12]  更完善的粒子系统
V0.8 [2011-05-17]  弹力、引力
V0.9 [2011-05-20]  框架优化、简单的输入输出操作

赶紧弄了0.5版本。修改了碰撞底层的实现。
这个DEMO和上一个DEMO 的区别:

1、从updateWorld里面的碰撞检测看到,这个检测很方便。
2、底层判断已经使用了SAT判断。
3、修改了按键部分的BUG。
4、代码依然很少。
目前引用自制引擎做的DEMO2:

引入了引擎的DEMO代码:

  1. /****************************************************************************  
  2.  * org.ubird.demo.Demo2.java  
  3.  *  
  4.  * 该类属于JPhysicalEngine游戏引擎中的一部分。JPhysicalEngine游戏引擎  
  5.  * 使用Java开发,是一款可以免费学习使用的2D游戏引擎。  
  6.  *  
  7.  ****************************************************************************  
  8.  * Apache Licence 2.0  
  9.  ****************************************************************************  
  10.  *  
  11.  * Copyright 2011 蔡俊鸿  
  12.  *  
  13.  * Licensed under the Apache License, Version 2.0 (the "License");  
  14.  * you may not use this file except in compliance with the License.  
  15.  * You may obtain a copy of the License at  
  16.  *  
  17.  *     http://www.apache.org/licenses/LICENSE-2.0  
  18.  *  
  19.  * Unless required by applicable law or agreed to in writing, software  
  20.  * distributed under the License is distributed on an "AS IS" BASIS,  
  21.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
  22.  * See the License for the specific language governing permissions and  
  23.  * limitations under the License.  
  24.  ****************************************************************************   
  25.  *   
  26.  * 创建于:2011-4-23  
  27.  * @since JDK1.6  
  28.  *  
  29.  ****************************************************************************/  
  30. package org.ubird.demo;   
  31.   
  32. import java.awt.Image;   
  33. import java.awt.event.KeyEvent;   
  34. import java.awt.event.KeyListener;   
  35. import java.io.IOException;   
  36. import javax.imageio.ImageIO;   
  37.   
  38. import org.ubird.app.SimpleGame;   
  39. import org.ubird.collision.CollisionDetector;   
  40. import org.ubird.collision.CollisionResult;   
  41. import org.ubird.scene.node.ImageNode;   
  42. import org.ubird.scene.node.Node;   
  43. import org.ubird.scene.particle.ParticleNode;   
  44. import org.ubird.scene.particle.ParticleSystem;   
  45. import org.ubird.sound.SoundManager;   
  46. /**  
  47.  * 测试类2  
  48.  * @author junhong.c  
  49.  * @version 1.0  
  50.  * @version 1.1 [2011-05-05] 调整了碰撞检测部分的代码  
  51.  * @version 1.1 [2011-05-05] 增加了按V可以显示物体的轴的功能  
  52.  * @version 1.1 [2011-05-05] 增加了按B可以显示物体的边界的功能  
  53.  * @date 2011-4-23  
  54.  */  
  55. public class Demo2 extends SimpleGame{   
  56.     private Node player;   
  57.        
  58.     private ParticleNode bombParticle = ParticleSystem.getParticles(500,15,15,10);   
  59.     private ParticleNode hitParticle = ParticleSystem.getParticles(500,15,15,10);   
  60.        
  61.     private ImageNode[] bullets = new ImageNode[40];   
  62.     private int currentBullet = 0;   
  63.        
  64.     private long delay;     //子弹延时   
  65.     private boolean fire;   
  66.     private boolean fire2;   
  67.     private boolean fire3;   
  68.     private boolean down;   
  69.     private boolean up;   
  70.     private boolean right;   
  71.     private boolean left;   
  72.     private Node[]  enemys = new ImageNode[7];   
  73.     private Thread keyProcessThread;   
  74.        
  75.     public Demo2() {   
  76.         super("Java2D游戏引擎 V0.5.0 -- By John.Cha");   
  77.     }   
  78.     public static void main(String[] args) throws IOException {   
  79.         SimpleGame game = new Demo2();   
  80.         game.setFPS(60);   
  81.         game.setStageBackground("resources/bg.png");   
  82.         game.setStageSize(1000,600);   
  83.         game.start();   
  84.     }   
  85.   
  86.     @Override  
  87.     public void initWorld() {   
  88.         initScene();   
  89.         initNode();   
  90.         initEvent();   
  91.     }   
  92.        
  93.     /**  
  94.      * 事件  
  95.      */  
  96.     private void initEvent() {   
  97.         addKeyListener(new MyKeyListener());   
  98.     }   
  99.     /**  
  100.      * 定义自己的事件监听  
  101.      * @author junhong.c  
  102.      * @version 1.0  
  103.      * @date 2011-4-22  
  104.      */  
  105.     private class MyKeyListener implements KeyListener{   
  106.         @Override  
  107.         public void keyTyped(KeyEvent e) {   
  108.             if(e.getKeyChar()=='v'){   
  109.                 setDrawAxes(!isDrawAxes());   
  110.             }   
  111.             if(e.getKeyChar()=='b'){   
  112.                 setDrawBounds(!isDrawBounds());   
  113.             }   
  114.         }   
  115.         @Override  
  116.         public void keyReleased(KeyEvent e) {   
  117.             switch(e.getKeyCode()){   
  118.                 case KeyEvent.VK_W :   
  119.                     up=false;   
  120.                     break;   
  121.                 case KeyEvent.VK_S:   
  122.                     down=false;   
  123.                     break;   
  124.                 case KeyEvent.VK_D:   
  125.                     right=false;   
  126.                     break;   
  127.                 case KeyEvent.VK_A:   
  128.                     left=false;   
  129.                     break;   
  130.                 case KeyEvent.VK_J:   
  131.                     fire=false;   
  132.                     break;   
  133.                 case KeyEvent.VK_K:   
  134.                     fire2=false;   
  135.                     break;   
  136.                 case KeyEvent.VK_L:   
  137.                     fire3=false;   
  138.                     break;   
  139.             }   
  140.         }   
  141.         @Override  
  142.         public void keyPressed(KeyEvent e) {   
  143.             if(fire && e.getKeyCode()==KeyEvent.VK_A) return;   
  144.             if(fire2 && e.getKeyCode()==KeyEvent.VK_S) return;   
  145.             if(fire3 && e.getKeyCode()==KeyEvent.VK_D) return;   
  146.             if(up && e.getKeyCode()==KeyEvent.VK_UP) return;   
  147.             if(down && e.getKeyCode()==KeyEvent.VK_DOWN) return;   
  148.             if(left && e.getKeyCode()==KeyEvent.VK_LEFT) return;   
  149.             if(right && e.getKeyCode()==KeyEvent.VK_RIGHT) return;   
  150.                
  151.             switch(e.getKeyCode()){   
  152.                 case KeyEvent.VK_W :   
  153.                     up=true;   
  154.                     break;   
  155.                 case KeyEvent.VK_S:   
  156.                     down=true;   
  157.                     break;   
  158.                 case KeyEvent.VK_D:   
  159.                     right=true;   
  160.                     break;   
  161.                 case KeyEvent.VK_A:   
  162.                     left=true;   
  163.                     break;   
  164.                 case KeyEvent.VK_I:   
  165.                     bombParticle.start(player.getLocation().getIntX()-player.getWidth()/2-3,player.getLocation().getIntY()-player.getHeight());   
  166.                     break;   
  167.                 case KeyEvent.VK_J:   
  168.                     fire=true;   
  169.                     break;   
  170.                 case KeyEvent.VK_K:   
  171.                     fire2=true;   
  172.                     break;   
  173.                 case KeyEvent.VK_L:   
  174.                     fire3=true;   
  175.                     break;   
  176.             }   
  177.             if(!getKeyProcessThread().isAlive())   
  178.                 getKeyProcessThread().start();   
  179.         }   
  180.     }   
  181.     /**  
  182.      * 场景   
  183.      */  
  184.     private void initScene() {   
  185.         add(bombParticle);   
  186.         add(hitParticle);   
  187.     }   
  188.        
  189.     /**  
  190.      * 处理按键的线程  
  191.      * @return  
  192.      */  
  193.     public Thread getKeyProcessThread(){   
  194.         if(keyProcessThread==null){   
  195.             keyProcessThread = new Thread(){   
  196.                 public void run(){   
  197.                     try {   
  198.                         while(true){   
  199.                             Thread.sleep(getSPF());   
  200.                             float v = 0.2f;   
  201.                             if(up)   
  202.                                 player.getVelocity().setY(-v);   
  203.                             else if(down)   
  204.                                 player.getVelocity().setY(v);   
  205.                                
  206.                             if(left)   
  207.                                 player.getVelocity().setX(-v);   
  208.                             else if(right)   
  209.                                 player.getVelocity().setX(v);   
  210.                                
  211.                             if(!(up||down))   
  212.                                 player.getVelocity().setY(0);   
  213.                                
  214.                             if(!(left||right))   
  215.                                 player.getVelocity().setX(0);   
  216.                                
  217.                             if( fire ){   
  218.                                 if(delay <= System.currentTimeMillis()){   
  219.                                     for(int i=0; i<2; i++){   
  220.                                         bullets[currentBullet].getVelocity().setY(-v*2f);   
  221.                                         bullets[currentBullet].getVelocity().setX(0);   
  222.                                         int fix = i == 0 ? -15 : 15;   
  223.                                         bullets[currentBullet].rotate(0);   
  224.                                         float x = player.getLocation().getX()+(player.getWidth() - bullets[currentBullet].getWidth())*0.5f;   
  225.                                         bullets[currentBullet].setLocation(fix+x, player.getLocation().getY()-bullets[currentBullet].getHeight());   
  226.                                         bullets[currentBullet].rotate(0);   
  227.                                            
  228.                                         currentBullet = ++currentBullet%bullets.length;   
  229.                                         SoundManager.play("resources/sound/bullet.wav");   
  230.                                            
  231.                                     }   
  232.                                     delay = System.currentTimeMillis()+80;   
  233.                                 }   
  234.                             }   
  235.                                
  236.                             if(fire2){   
  237.                                 if(delay <= System.currentTimeMillis()){   
  238.                                     for(int i=0; i<3; i++){   
  239.                                         bullets[currentBullet].getVelocity().setY(-v*2f);   
  240.                                         int fix = i == 0 ? -15 : i==2 ? 15 : 0;   
  241.                                         float vx = i==0 ? -v/4 : i==1 ? 0 : v/4;   
  242.                                         bullets[currentBullet].getVelocity().setX(vx);   
  243.                                         bullets[currentBullet].rotate(0);   
  244.                                            
  245.                                         float x = player.getLocation().getX()+(player.getWidth() - bullets[currentBullet].getWidth())*0.5f;   
  246.                                         bullets[currentBullet].setLocation(fix+x, player.getLocation().getY()-bullets[currentBullet].getHeight());   
  247.                                         bullets[currentBullet].rotate(0);   
  248.                                            
  249.                                         currentBullet = ++currentBullet%bullets.length;   
  250.                                         SoundManager.play("resources/sound/bullet.wav");   
  251.                                     }   
  252.                                     delay = System.currentTimeMillis()+100;   
  253.                                 }   
  254.                             }   
  255.                                
  256.                             if(fire3){   
  257.                                 for(int i=0; i<bullets.length; i++){   
  258.                                     bullets[currentBullet].getVelocity().setY(-v*2f);   
  259.                                        
  260.                                     float shita = 6.28f*i/(bullets.length-1);   
  261.                                     bullets[currentBullet].rotate(shita);   
  262.                                        
  263.                                     float vx = (float) (v*Math.cos(shita));   
  264.                                     float vy = (float) (v*Math.sin(shita));   
  265.                                        
  266.                                     bullets[currentBullet].getVelocity().setX(vx);   
  267.                                     bullets[currentBullet].getVelocity().setY(vy);   
  268.                                        
  269.                                     bullets[currentBullet].setLocation(   
  270.                                             player.getLocation().getX()+(player.getWidth()-bullets[currentBullet].getWidth())/2,   
  271.                                             player.getLocation().getY()+(player.getHeight()-bullets[currentBullet].getHeight())/2);   
  272.                                        
  273.                                     bullets[currentBullet].setDelay(currentBullet);   
  274.                                        
  275.                                     currentBullet = ++currentBullet%bullets.length;   
  276.                                 }   
  277.                                 SoundManager.play("resources/sound/bomb.wav");   
  278.                                 fire3=false;   
  279.                             }   
  280.                         }   
  281.                     } catch (InterruptedException e) {   
  282.                         e.printStackTrace();   
  283.                     }   
  284.                 }   
  285.             };   
  286.         }   
  287.         return keyProcessThread;   
  288.     }   
  289.     private void initNode() {   
  290.            
  291.         try {   
  292.             Image bulletImage = ImageIO.read(getClass().getClassLoader().getResource("resources/bullet.png"));   
  293.             Image planeImage  = ImageIO.read(getClass().getClassLoader().getResource("resources/planes.png"));   
  294.                
  295.             /*  
  296.              * 初始化子弹  
  297.              */  
  298.             for(int i=0; i<bullets.length; i++){   
  299.                 bullets[i] = new ImageNode(bulletImage,0,70,35,35);   
  300.                 bullets[i].setSize(35,35);   
  301.                 bullets[i].setLocation(-500,-500);   
  302.                 bullets[i].setExtent(35/20);   
  303.                 add(bullets[i]);   
  304.             }   
  305.             /*  
  306.              * 初始化玩家  
  307.              */  
  308.             player = new ImageNode(planeImage,100,0,100,120);   //平抛--图像结点   
  309.             player.setSize(60,72);   
  310.             player.setLocation((getStageWidth()-player.getWidth())/2,getStageHeight()-player.getHeight());   
  311.             player.setMass(10);   
  312.             add(player);   
  313.                
  314.             /*  
  315.              * 初始化敌人  
  316.              */  
  317.             for(int i=0; i<enemys.length; i++){   
  318.                 enemys[i] = new ImageNode(planeImage,0,0,100,120);   
  319.                 enemys[i].setSize(60,72);   
  320.                 enemys[i].rotate(6.28f*i/(enemys.length-1));   
  321.                 enemys[i].setLocation(i*(enemys[i].getWidth()+70),100);   
  322.                 add(enemys[i]);   
  323.             }   
  324.         } catch (IOException e1) {   
  325.             e1.printStackTrace();   
  326.         }   
  327.     }   
  328.   
  329.     @Override  
  330.     public void updateWorld(long time) {   
  331.         player.update(time);   
  332.            
  333.         bombParticle.update(time);   
  334.         hitParticle.update(time);   
  335.            
  336.         //更新子弹   
  337.         for(int i=0; i<bullets.length; i++){   
  338.             bullets[i].update(time);   
  339.         }   
  340.            
  341.         //更新敌机   
  342.         for(int i=0; i<enemys.length; i++){   
  343.             if(enemys[i]!=null){   
  344.                 enemys[i].update(time);   
  345.             }   
  346.         }   
  347.         //子弹和敌机碰撞检测   
  348.         for(int i=0; i<bullets.length; i++){   
  349.             if(bullets[i]!=null){   
  350.                 for(int j=0; j<enemys.length; j++){   
  351.                     if(enemys[j]!=null){   
  352.                         CollisionResult cr = CollisionDetector.obb(bullets[i], enemys[j]);   
  353.                         if(cr.isCollision()){   
  354.                             int x = bullets[i].getLocation().getIntX(); //TODO 其实应该是碰撞的位置   
  355.                             int y = bullets[i].getLocation().getIntY(); //TODO 其实应该是碰撞的位置   
  356.                             bullets[i].getLocation().setY(-500);   
  357.                             hitParticle.start(x, y);   
  358.                         }   
  359.                     }   
  360.                 }   
  361.             }   
  362.         }   
  363.     }   
  364. }  

相关内容