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

<

div id=”content” contentScore=”1293″>项目命名: 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代码:

<

ol>

  • /****************************************************************************  
  •   org.ubird.demo.Demo2.java  
  •    
  •   该类属于JPhysicalEngine游戏引擎中的一部分。JPhysicalEngine游戏引擎  
  •   使用Java开发,是一款可以免费学习使用的2D游戏引擎。  
  •  *  
  •  ****************************************************************************  
  •   Apache Licence 2.0  
  •  ****************************************************************************  
  •    
  •   Copyright 2011 蔡俊鸿  
  •    
  •   Licensed under the Apache License, Version 2.0 (the “License”);  
  •   you may not use this file except in compliance with the License.  
  •   You may obtain a copy of the License at  
  •    
  •       http://www.apache.org/licenses/LICENSE-2.0  
  •    
  •   Unless required by applicable law or agreed to in writing, software  
  •   distributed under the License is distributed on an “AS IS” BASIS,  
  •   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
  •   See the License for the specific language governing permissions and  
  •   limitations under the License.  
  •  ****************************************************************************   
  •     
  •   创建于:2011-4-23  
  •   @since JDK1.6  
  •  *  
  •  ****************************************************************************/  
  • package org.ubird.demo;   
  •   
  • import java.awt.Image;   
  • import java.awt.event.KeyEvent;   
  • import java.awt.event.KeyListener;   
  • import java.io.IOException;   
  • import javax.imageio.ImageIO;   
  •   
  • import org.ubird.app.SimpleGame;   
  • import org.ubird.collision.CollisionDetector;   
  • import org.ubird.collision.CollisionResult;   
  • import org.ubird.scene.node.ImageNode;   
  • import org.ubird.scene.node.Node;   
  • import org.ubird.scene.particle.ParticleNode;   
  • import org.ubird.scene.particle.ParticleSystem;   
  • import org.ubird.sound.SoundManager;   
  • /**  
  •   测试类2  
  •   @author junhong.c  
  •   @version 1.0  
  •   @version 1.1 [2011-05-05] 调整了碰撞检测部分的代码  
  •   @version 1.1 [2011-05-05] 增加了按V可以显示物体的轴的功能  
  •   @version 1.1 [2011-05-05] 增加了按B可以显示物体的边界的功能  
  •   @date 2011-4-23  
  •  /  
  • public class Demo2 extends SimpleGame{   
  •     private Node player;   
  •        
  •     private ParticleNode bombParticle = ParticleSystem.getParticles(500,15,15,10);   
  •     private ParticleNode hitParticle = ParticleSystem.getParticles(500,15,15,10);   
  •        
  •     private ImageNode[] bullets = new ImageNode[40];   
  •     private int currentBullet = 0;   
  •        
  •     private long delay;     //子弹延时   
  •     private boolean fire;   
  •     private boolean fire2;   
  •     private boolean fire3;   
  •     private boolean down;   
  •     private boolean up;   
  •     private boolean right;   
  •     private boolean left;   
  •     private Node[]  enemys = new ImageNode[7];   
  •     private Thread keyProcessThread;   
  •        
  •     public Demo2() {   
  •         super(“Java2D游戏引擎 V0.5.0 — By John.Cha”);   
  •     }   
  •     public static void main(String[] args) throws IOException {   
  •         SimpleGame game = new Demo2();   
  •         game.setFPS(60);   
  •         game.setStageBackground(“resources/bg.png”);   
  •         game.setStageSize(1000,600);   
  •         game.start();   
  •     }   
  •   
  •     @Override  
  •     public void initWorld() {   
  •         initScene();   
  •         initNode();   
  •         initEvent();   
  •     }   
  •        
  •     /**  
  •       事件  
  •      /  
  •     private void initEvent() {   
  •         addKeyListener(new MyKeyListener());   
  •     }   
  •     /**  
  •       定义自己的事件监听  
  •       @author junhong.c  
  •       @version 1.0  
  •       @date 2011-4-22  
  •      /  
  •     private class MyKeyListener implements KeyListener{   
  •         @Override  
  •         public void keyTyped(KeyEvent e) {   
  •             if(e.getKeyChar()==‘v’){   
  •                 setDrawAxes(!isDrawAxes());   
  •             }   
  •             if(e.getKeyChar()==‘b’){   
  •                 setDrawBounds(!isDrawBounds());   
  •             }   
  •         }   
  •         @Override  
  •         public void keyReleased(KeyEvent e) {   
  •             switch(e.getKeyCode()){   
  •                 case KeyEvent.VK_W :   
  •                     up=false;   
  •                     break;   
  •                 case KeyEvent.VK_S:   
  •                     down=false;   
  •                     break;   
  •                 case KeyEvent.VK_D:   
  •                     right=false;   
  •                     break;   
  •                 case KeyEvent.VK_A:   
  •                     left=false;   
  •                     break;   
  •                 case KeyEvent.VK_J:   
  •                     fire=false;   
  •                     break;   
  •                 case KeyEvent.VK_K:   
  •                     fire2=false;   
  •                     break;   
  •                 case KeyEvent.VK_L:   
  •                     fire3=false;   
  •                     break;   
  •             }   
  •         }   
  •         @Override  
  •         public void keyPressed(KeyEvent e) {   
  •             if(fire && e.getKeyCode()==KeyEvent.VK_A) return;   
  •             if(fire2 && e.getKeyCode()==KeyEvent.VK_S) return;   
  •             if(fire3 && e.getKeyCode()==KeyEvent.VK_D) return;   
  •             if(up && e.getKeyCode()==KeyEvent.VK_UP) return;   
  •             if(down && e.getKeyCode()==KeyEvent.VK_DOWN) return;   
  •             if(left && e.getKeyCode()==KeyEvent.VK_LEFT) return;   
  •             if(right && e.getKeyCode()==KeyEvent.VK_RIGHT) return;   
  •                
  •             switch(e.getKeyCode()){   
  •                 case KeyEvent.VK_W :   
  •                     up=true;   
  •                     break;   
  •                 case KeyEvent.VK_S:   
  •                     down=true;   
  •                     break;   
  •                 case KeyEvent.VK_D:   
  •                     right=true;   
  •                     break;   
  •                 case KeyEvent.VK_A:   
  •                     left=true;   
  •                     break;   
  •                 case KeyEvent.VK_I:   
  •                     bombParticle.start(player.getLocation().getIntX()-player.getWidth()/23,player.getLocation().getIntY()-player.getHeight());   
  •                     break;   
  •                 case KeyEvent.VK_J:   
  •                     fire=true;   
  •                     break;   
  •                 case KeyEvent.VK_K:   
  •                     fire2=true;   
  •                     break;   
  •                 case KeyEvent.VK_L:   
  •                     fire3=true;   
  •                     break;   
  •             }   
  •             if(!getKeyProcessThread().isAlive())   
  •                 getKeyProcessThread().start();   
  •         }   
  •     }   
  •     /**  
  •       场景   
  •      /  
  •     private void initScene() {   
  •         add(bombParticle);   
  •         add(hitParticle);   
  •     }   
  •        
  •     /**  
  •       处理按键的线程  
  •       @return  
  •      /  
  •     public Thread getKeyProcessThread(){   
  •         if(keyProcessThread==null){   
  •             keyProcessThread = new Thread(){   
  •                 public void run(){   
  •                     try {   
  •                         while(true){   
  •                             Thread.sleep(getSPF());   
  •                             float v = 0.2f;   
  •                             if(up)   
  •                                 player.getVelocity().setY(-v);   
  •                             else if(down)   
  •                                 player.getVelocity().setY(v);   
  •                                
  •                             if(left)   
  •                                 player.getVelocity().setX(-v);   
  •                             else if(right)   
  •                                 player.getVelocity().setX(v);   
  •                                
  •                             if(!(up||down))   
  •                                 player.getVelocity().setY(0);   
  •                                
  •                             if(!(left||right))   
  •                                 player.getVelocity().setX(0);   
  •                                
  •                             if( fire ){   
  •                                 if(delay <= System.currentTimeMillis()){   
  •                                     for(int i=0; i<2; i++){   
  •                                         bullets[currentBullet].getVelocity().setY(-v2f);   
  •                                         bullets[currentBullet].getVelocity().setX(0);   
  •                                         int fix = i == 0 ? –15 : 15;   
  •                                         bullets[currentBullet].rotate(0);   
  •                                         float x = player.getLocation().getX()+(player.getWidth() – bullets[currentBullet].getWidth())0.5f;   
  •                                         bullets[currentBullet].setLocation(fix+x, player.getLocation().getY()-bullets[currentBullet].getHeight());   
  •                                         bullets[currentBullet].rotate(0);   
  •                                            
  •                                         currentBullet = ++currentBullet%bullets.length;   
  •                                         SoundManager.play(“resources/sound/bullet.wav”);   
  •                                            
  •                                     }   
  •                                     delay = System.currentTimeMillis()+80;   
  •                                 }   
  •                             }   
  •                                
  •                             if(fire2){   
  •                                 if(delay <= System.currentTimeMillis()){   
  •                                     for(int i=0; i<3; i++){   
  •                                         bullets[currentBullet].getVelocity().setY(-v2f);   
  •                                         int fix = i == 0 ? –15 : i==2 ? 15 : 0;   
  •                                         float vx = i==0 ? -v/4 : i==1 ? 0 : v/4;   
  •                                         bullets[currentBullet].getVelocity().setX(vx);   
  •                                         bullets[currentBullet].rotate(0);   
  •                                            
  •                                         float x = player.getLocation().getX()+(player.getWidth() – bullets[currentBullet].getWidth())0.5f;   
  •                                         bullets[currentBullet].setLocation(fix+x, player.getLocation().getY()-bullets[currentBullet].getHeight());   
  •                                         bullets[currentBullet].rotate(0);   
  •                                            
  •                                         currentBullet = ++currentBullet%bullets.length;   
  •                                         SoundManager.play(“resources/sound/bullet.wav”);   
  •                                     }   
  •                                     delay = System.currentTimeMillis()+100;   
  •                                 }   
  •                             }   
  •                                
  •                             if(fire3){   
  •                                 for(int i=0; i<bullets.length; i++){   
  •                                     bullets[currentBullet].getVelocity().setY(-v2f);   
  •                                        
  •                                     float shita = 6.28fi/(bullets.length-1);   
  •                                     bullets[currentBullet].rotate(shita);   
  •                                        
  •                                     float vx = (float) (vMath.cos(shita));   
  •                                     float vy = (float) (vMath.sin(shita));   
  •                                        
  •                                     bullets[currentBullet].getVelocity().setX(vx);   
  •                                     bullets[currentBullet].getVelocity().setY(vy);   
  •                                        
  •                                     bullets[currentBullet].setLocation(   
  •                                             player.getLocation().getX()+(player.getWidth()-bullets[currentBullet].getWidth())/2,   
  •                                             player.getLocation().getY()+(player.getHeight()-bullets[currentBullet].getHeight())/2);   
  •                                        
  •                                     bullets[currentBullet].setDelay(currentBullet);   
  •                                        
  •                                     currentBullet = ++currentBullet%bullets.length;   
  •                                 }   
  •                                 SoundManager.play(“resources/sound/bomb.wav”);   
  •                                 fire3=false;   
  •                             }   
  •                         }   
  •                     } catch (InterruptedException e) {   
  •                         e.printStackTrace();   
  •                     }   
  •                 }   
  •             };   
  •         }   
  •         return keyProcessThread;   
  •     }   
  •     private void initNode() {   
  •            
  •         try {   
  •             Image bulletImage = ImageIO.read(getClass().getClassLoader().getResource(“resources/bullet.png”));   
  •             Image planeImage  = ImageIO.read(getClass().getClassLoader().getResource(“resources/planes.png”));   
  •                
  •             /*  
  •               初始化子弹  
  •              /  
  •             for(int i=0; i<bullets.length; i++){   
  •                 bullets[i] = new ImageNode(bulletImage,0,70,35,35);   
  •                 bullets[i].setSize(35,35);   
  •                 bullets[i].setLocation(-500,-500);   
  •                 bullets[i].setExtent(35/20);   
  •                 add(bullets[i]);   
  •             }   
  •             /*  
  •               初始化玩家  
  •              /  
  •             player = new ImageNode(planeImage,100,0,100,120);   //平抛–图像结点   
  •             player.setSize(60,72);   
  •             player.setLocation((getStageWidth()-player.getWidth())/2,getStageHeight()-player.getHeight());   
  •             player.setMass(10);   
  •             add(player);   
  •                
  •             /*  
  •               初始化敌人  
  •              /  
  •             for(int i=0; i<enemys.length; i++){   
  •                 enemys[i] = new ImageNode(planeImage,0,0,100,120);   
  •                 enemys[i].setSize(60,72);   
  •                 enemys[i].rotate(6.28fi/(enemys.length-1));   
  •                 enemys[i].setLocation(i(enemys[i].getWidth()+70),100);   
  •                 add(enemys[i]);   
  •             }   
  •         } catch (IOException e1) {   
  •             e1.printStackTrace();   
  •         }   
  •     }   
  •   
  •     @Override  
  •     public void updateWorld(long time) {   
  •         player.update(time);   
  •            
  •         bombParticle.update(time);   
  •         hitParticle.update(time);   
  •            
  •         //更新子弹   
  •         for(int i=0; i<bullets.length; i++){   
  •             bullets[i].update(time);   
  •         }   
  •            
  •         //更新敌机   
  •         for(int i=0; i<enemys.length; i++){   
  •             if(enemys[i]!=null){   
  •                 enemys[i].update(time);   
  •             }   
  •         }   
  •         //子弹和敌机碰撞检测   
  •         for(int i=0; i<bullets.length; i++){   
  •             if(bullets[i]!=null){   
  •                 for(int j=0; j<enemys.length; j++){   
  •                     if(enemys[j]!=null){   
  •                         CollisionResult cr = CollisionDetector.obb(bullets[i], enemys[j]);   
  •                         if(cr.isCollision()){   
  •                             int x = bullets[i].getLocation().getIntX(); //TODO 其实应该是碰撞的位置   
  •                             int y = bullets[i].getLocation().getIntY(); //TODO 其实应该是碰撞的位置   
  •                             bullets[i].getLocation().setY(-500);   
  •                             hitParticle.start(x, y);   
  •                         }   
  •                     }   
  •                 }   
  • <sp