项目命名: JPhysicalEngine
项目目的: 自己爱好/毕业设计
项目人员:
运行机器: 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] 框架优化、简单的输入输出操作
目前引用自制引擎做的DEMO2:
代码只需200+行:
* org.ubird.demo.Demo2.java 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.scene.ImageNode; import org.ubird.scene.Node; import org.ubird.scene.particle.ParticleNode; import org.ubird.scene.particle.ParticleSystem; /** * 测试类2 * @author junhong.c * @version 1.0 * @date 2011-4-23 */ public class Demo2 extends SimpleGame{ private Node player; private ParticleNode bomb = ParticleSystem.getParticles(500,15,15,10); private Node[] 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; public Demo2() { super("Java2D游戏引擎 V0.4.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) {} @Override public void keyReleased(KeyEvent e) { switch(e.getKeyCode()){ case KeyEvent.VK_UP : up=false; break; case KeyEvent.VK_DOWN: down=false; break; case KeyEvent.VK_RIGHT: right=false; break; case KeyEvent.VK_LEFT: left=false; break; case KeyEvent.VK_A: fire=false; break; case KeyEvent.VK_S: fire2=false; break; case KeyEvent.VK_D: 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_UP : up=true; break; case KeyEvent.VK_DOWN: down=true; break; case KeyEvent.VK_RIGHT: right=true; break; case KeyEvent.VK_LEFT: left=true; break; case KeyEvent.VK_B: bomb.start(player.getLocation().getIntX()-player.getWidth()/2-3,player.getLocation().getIntY()-player.getHeight()); break; case KeyEvent.VK_A: fire=true; break; case KeyEvent.VK_S: fire2=true; break; case KeyEvent.VK_D: fire3=true; break; } getProcessThread().start(); } } /** * 场景 */ private void initScene() { add(bomb); } /** * 处理按键的线程 * @return */ public Thread getProcessThread(){ return new Thread(){ public void run(){ try { while(up||down||left||right||fire||fire2||fire3){ Thread.sleep(1000/60); 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(-v*2f); bullets[currentBullet].getVelocity().setX(0); int fix = i == 0 ? -15 : 15; float x = player.getLocation().getX()+(player.getWidth() - bullets[currentBullet].getWidth())*0.5f; bullets[currentBullet].setLocation(fix+x, player.getLocation().getY()-bullets[currentBullet].getHeight()); currentBullet = ++currentBullet%bullets.length; } delay = System.currentTimeMillis()+80; } } if(fire2){ if(delay <= System.currentTimeMillis()){ for(int i=0; i<3; i++){ bullets[currentBullet].getVelocity().setY(-v*2f); 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); float x = player.getLocation().getX()+(player.getWidth() - bullets[currentBullet].getWidth())*0.5f; bullets[currentBullet].setLocation(fix+x, player.getLocation().getY()-bullets[currentBullet].getHeight()); currentBullet = ++currentBullet%bullets.length; } delay = System.currentTimeMillis()+100; } } if(fire3){ for(int i=0; i<bullets.length; i++){ bullets[currentBullet].getVelocity().setY(-v*2f); int fix = i == 0 ? -15 : i==2 ? 15 : 0; float vx = (float) (v*Math.cos(6.28*i/bullets.length)); float vy = (float) (v*Math.sin(6.28*i/bullets.length)); bullets[currentBullet].getVelocity().setX(vx); bullets[currentBullet].getVelocity().setY(vy); bullets[currentBullet].setLocation(fix+player.getLocation().getX()-player.getWidth()/2+2,player.getLocation().getY()-player.getHeight()); bullets[currentBullet].setDelay(currentBullet); currentBullet = ++currentBullet%bullets.length; } fire3=false; } } } catch (InterruptedException e) { e.printStackTrace(); } } }; } /** * */ private void initNode() { /** * 初始化子弹 */ try { Image image = ImageIO.read(getClass().getClassLoader().getResource("resources/bullet.png")); for(int i=0; i<bullets.length; i++){ bullets[i] = new ImageNode(image,i%6*35,0,35,35); bullets[i].setSize(30,30); bullets[i].setLocation(-500,-500); add(bullets[i]); } player = new ImageNode(image,70,35,35,35); //平抛--图像结点 player.setSize(35,35); player.setLocation((getStageWidth()-player.getWidth())/2,getStageHeight()-player.getHeight()); player.setMass(10); add(player); } catch (IOException e1) { e1.printStackTrace(); } } @Override public void updateWorld(long time) { player.update(time); bomb.update(time); for(int i=0; i<bullets.length; i++){ if(bullets[i]!=null){ bullets[i].update(time); } } } }