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



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]  框架优化、简单的输入输出操作

 

5.1回家放假了~本来很想继续做,但是一回到家就变懒了T_T,回来后赶紧弄了0.5版本。修改了碰撞底层的实现。

 

这个DEMO和上一个DEMO 的区别:

1、从updateWorld里面的碰撞检测看到,这个检测很方便。


2、底层判断已经使用了SAT判断。

3、修改了按键部分的BUG。

4、增加了场景多层背景的支持

5、代码依然很少。

 

 

目前引用自制引擎做的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. import java.awt.Image;
  32. import java.awt.event.KeyEvent;
  33. import java.awt.event.KeyListener;
  34. import java.io.IOException;
  35. import javax.imageio.ImageIO;
  36. import org.ubird.app.SimpleGame;
  37. import org.ubird.collision.CollisionDetector;
  38. import org.ubird.collision.CollisionResult;
  39. import org.ubird.scene.node.ImageNode;
  40. import org.ubird.scene.node.Node;
  41. import org.ubird.scene.particle.ParticleNode;
  42. import org.ubird.scene.particle.ParticleSystem;
  43. import org.ubird.sound.SoundManager;
  44. /**
  45.  * 测试类2
  46.  * @author junhong.c
  47.  * @version 1.0
  48.  * @version 1.1 [2011-05-05] 调整了碰撞检测部分的代码
  49.  * @version 1.1 [2011-05-05] 增加了按V可以显示物体的轴的功能
  50.  * @version 1.1 [2011-05-05] 增加了按B可以显示物体的边界的功能
  51.  * @date 2011-4-23
  52.  */
  53. public class Demo2 extends SimpleGame{
  54.     private Node player;
  55.     private ParticleNode bombParticle = ParticleSystem.getParticles(500,15,15,10);
  56.     private ParticleNode hitParticle = ParticleSystem.getParticles(500,15,15,10);
  57.     private ImageNode[] bullets = new ImageNode[40];
  58.     private int currentBullet = 0;
  59.     private long delay;     //子弹延时
  60.     private boolean fire;
  61.     private boolean fire2;
  62.     private boolean fire3;
  63.     private boolean down;
  64.     private boolean up;
  65.     private boolean right;
  66.     private boolean left;
  67.     private Node[]  enemys = new ImageNode[7];
  68.     private Thread keyProcessThread;
  69.     public Demo2() {
  70.         super(“Java2D游戏引擎 V0.5.0 – By John.Cha”);
  71.     }
  72.     public static void main(String[] args) throws IOException {
  73.         SimpleGame game = new Demo2();
  74.         game.setFPS(60);
  75.         game.setStageBackground(“resources/bg.png”);
  76.         game.setStageSize(1000,600);
  77.         game.start();
  78.     }
  79.     @Override
  80.     public void initWorld() {
  81.         initScene();
  82.         initNode();
  83.         initEvent();
  84.     }
  85.     /**
  86.      * 事件
  87.      */
  88.     private void initEvent() {
  89.         addKeyListener(new MyKeyListener());
  90.     }
  91.     /**
  92.      * 定义自己的事件监听
  93.      * @author junhong.c
  94.      * @version 1.0
  95.      * @date 2011-4-22
  96.      */
  97.     private class MyKeyListener implements KeyListener{
  98.         @Override
  99.         public void keyTyped(KeyEvent e) {
  100.             if(e.getKeyChar()==’v'){
  101.                 setDrawAxes(!isDrawAxes());
  102.             }
  103.             if(e.getKeyChar()==’b'){
  104.                 setDrawBounds(!isDrawBounds());
  105.             }
  106.         }
  107.         @Override
  108.         public void keyReleased(KeyEvent e) {
  109.             switch(e.getKeyCode()){
  110.                 case KeyEvent.VK_W :
  111.                     up=false;
  112.                     break;
  113.                 case KeyEvent.VK_S:
  114.                     down=false;
  115.                     break;
  116.                 case KeyEvent.VK_D:
  117.                     right=false;
  118.                     break;
  119.                 case KeyEvent.VK_A:
  120.                     left=false;
  121.                     break;
  122.                 case KeyEvent.VK_J:
  123.                     fire=false;
  124.                     break;
  125.                 case KeyEvent.VK_K:
  126.                     fire2=false;
  127.                     break;
  128.                 case KeyEvent.VK_L:
  129.                     fire3=false;
  130.                     break;
  131.             }
  132.         }
  133.         @Override
  134.         public void keyPressed(KeyEvent e) {
  135.             if(fire && e.getKeyCode()==KeyEvent.VK_A) return;
  136.             if(fire2 && e.getKeyCode()==KeyEvent.VK_S) return;
  137.             if(fire3 && e.getKeyCode()==KeyEvent.VK_D) return;
  138.             if(up && e.getKeyCode()==KeyEvent.VK_UP) return;
  139.             if(down && e.getKeyCode()==KeyEvent.VK_DOWN) return;
  140.             if(left && e.getKeyCode()==KeyEvent.VK_LEFT) return;
  141.             if(right && e.getKeyCode()==KeyEvent.VK_RIGHT) return;
  142.             switch(e.getKeyCode()){
  143.                 case KeyEvent.VK_W :
  144.                     up=true;
  145.                     break;
  146.                 case KeyEvent.VK_S:
  147.                     down=true;
  148.                     break;
  149.                 case KeyEvent.VK_D:
  150.                     right=true;
  151.                     break;
  152.                 case KeyEvent.VK_A:
  153.                     left=true;
  154.                     break;
  155.                 case KeyEvent.VK_I:
  156.                     bombParticle.start(player.getLocation().getIntX()-player.getWidth()/2-3,player.getLocation().getIntY()-player.getHeight());
  157.                     break;
  158.                 case KeyEvent.VK_J:
  159.                     fire=true;
  160.                     break;
  161.                 case KeyEvent.VK_K:
  162.                     fire2=true;
  163.                     break;
  164.                 case KeyEvent.VK_L:
  165.                     fire3=true;
  166.                     break;
  167.             }
  168.             if(!getKeyProcessThread().isAlive())
  169.                 getKeyProcessThread().start();
  170.         }
  171.     }
  172.     /**
  173.      * 场景
  174.      */
  175.     private void initScene() {
  176.         add(bombParticle);
  177.         add(hitParticle);
  178.     }
  179.     /**
  180.      * 处理按键的线程
  181.      * @return
  182.      */
  183.     public Thread getKeyProcessThread(){
  184.         if(keyProcessThread==null){
  185.             keyProcessThread = new Thread(){
  186.                 public void run(){
  187.                     try {
  188.                         while(true){
  189.                             Thread.sleep(getSPF());
  190.                             float v = 0.2f;
  191.                             if(up)
  192.                                 player.getVelocity().setY(-v);
  193.                             else if(down)
  194.                                 player.getVelocity().setY(v);
  195.                             if(left)
  196.                                 player.getVelocity().setX(-v);
  197.                             else if(right)
  198.                                 player.getVelocity().setX(v);
  199.                             if(!(up||down))
  200.                                 player.getVelocity().setY(0);
  201.                             if(!(left||right))
  202.                                 player.getVelocity().setX(0);
  203.                             if( fire ){
  204.                                 if(delay <= System.currentTimeMillis()){
  205.                                     for(int i=0; i<2; i++){
  206.                                         bullets[currentBullet].getVelocity().setY(-v*2f);
  207.                                         bullets[currentBullet].getVelocity().setX(0);
  208.                                         int fix = i == 0 ? -15 : 15;
  209.                                         bullets[currentBullet].rotate(0);
  210.                                         float x = player.getLocation().getX()+(player.getWidth() - bullets[currentBullet].getWidth())*0.5f;
  211.                                         bullets[currentBullet].setLocation(fix+x, player.getLocation().getY()-bullets[currentBullet].getHeight());
  212.                                         bullets[currentBullet].rotate(0);
  213.                                         currentBullet = ++currentBullet%bullets.length;
  214.                                         SoundManager.play(“resources/sound/bullet.wav”);
  215.                                     }
  216.                                     delay = System.currentTimeMillis()+80;
  217.                                 }
  218.                             }
  219.                             if(fire2){
  220.                                 if(delay <= System.currentTimeMillis()){
  221.                                     for(int i=0; i<3; i++){
  222.                                         bullets[currentBullet].getVelocity().setY(-v*2f);
  223.                                         int fix = i == 0 ? -15 : i==2 ? 15 : 0;
  224.                                         float vx = i==0 ? -v/4 : i==1 ? 0 : v/4;
  225.                                         bullets[currentBullet].getVelocity().setX(vx);
  226.                                         bullets[currentBullet].rotate(0);
  227.                                         float x = player.getLocation().getX()+(player.getWidth() - bullets[currentBullet].getWidth())*0.5f;
  228.                                         bullets[currentBullet].setLocation(fix+x, player.getLocation().getY()-bullets[currentBullet].getHeight());
  229.                                         bullets[currentBullet].rotate(0);
  230.                                         currentBullet = ++currentBullet%bullets.length;
  231.                                         SoundManager.play(“resources/sound/bullet.wav”);
  232.                                     }
  233.                                     delay = System.currentTimeMillis()+100;
  234.                                 }
  235.                             }
  236.                             if(fire3){
  237.                                 for(int i=0; i<bullets.length; i++){
  238.                                     bullets[currentBullet].getVelocity().setY(-v*2f);
  239.                                     float shita = 6.28f*i/(bullets.length-1);
  240.                                     bullets[currentBullet].rotate(shita);
  241.                                     float vx = (float) (v*Math.cos(shita));
  242.                                     float vy = (float) (v*Math.sin(shita));
  243.                                     bullets[currentBullet].getVelocity().setX(vx);
  244.                                     bullets[currentBullet].getVelocity().setY(vy);
  245.                                     bullets[currentBullet].setLocation(
  246.                                             player.getLocation().getX()+(player.getWidth()-bullets[currentBullet].getWidth())/2,
  247.                                             player.getLocation().getY()+(player.getHeight()-bullets[currentBullet].getHeight())/2);
  248.                                     bullets[currentBullet].setDelay(currentBullet);
  249.                                     currentBullet = ++currentBullet%bullets.length;
  250.                                 }
  251.                                 SoundManager.play(“resources/sound/bomb.wav”);
  252.                                 fire3=false;
  253.                             }
  254.                         }
  255.                     } catch (InterruptedException e) {
  256.                         e.printStackTrace();
  257.                     }
  258.                 }
  259.             };
  260.         }
  261.         return keyProcessThread;
  262.     }
  263.     private void initNode() {
  264.         try {
  265.             Image bulletImage = ImageIO.read(getClass().getClassLoader().getResource(“resources/bullet.png”));
  266.             Image planeImage  = ImageIO.read(getClass().getClassLoader().getResource(“resources/planes.png”));
  267.             /*
  268.              * 初始化子弹
  269.              */
  270.             for(int i=0; i<bullets.length; i++){
  271.                 bullets[i] = new ImageNode(bulletImage,0,70,35,35);
  272.                 bullets[i].setSize(35,35);
  273.                 bullets[i].setLocation(-500,-500);
  274.                 bullets[i].setExtent(35/2, 0);
  275.                 add(bullets[i]);
  276.             }
  277.             /*
  278.              * 初始化玩家
  279.              */
  280.             player = new ImageNode(planeImage,100,0,100,120);   //平抛–图像结点
  281.             player.setSize(60,72);
  282.             player.setLocation((getStageWidth()-player.getWidth())/2,getStageHeight()-player.getHeight());
  283.             player.setMass(10);
  284.             add(player);
  285.             /*
  286.              * 初始化敌人
  287.              */
  288.             for(int i=0; i<enemys.length; i++){
  289.                 enemys[i] = new ImageNode(planeImage,0,0,100,120);
  290.                 enemys[i].setSize(60,72);
  291.                 enemys[i].rotate(6.28f*i/(enemys.length-1));
  292.                 enemys[i].setLocation(i*(enemys[i].getWidth()+70),100);
  293.                 add(enemys[i]);
  294.             }
  295.         } catch (IOException e1) {
  296.             e1.printStackTrace();
  297.         }
  298.     }
  299.     @Override
  300.     public void updateWorld(long time) {
  301.         player.update(time);
  302.         bombParticle.update(time);
  303.         hitParticle.update(time);
  304.         //更新子弹
  305.         for(int i=0; i<bullets.length; i++){
  306.             bullets[i].update(time);
  307.         }
  308.         //更新敌机
  309.         for(int i=0; i<enemys.length; i++){
  310.             if(enemys[i]!=null){
  311.                 enemys[i].update(time);
  312.             }
  313.         }
  314.         //子弹和敌机碰撞检测
  315.         for(int i=0; i<bullets.length; i++){
  316.             if(bullets[i]!=null){
  317.                 for(int j=0; j<enemys.length; j++){
  318.                     if(enemys[j]!=null){
  319.                         CollisionResult cr = CollisionDetector.obb(bullets[i], enemys[j]);
  320.                         if(cr.isCollision()){
  321.                             int x = bullets[i].getLocation().getIntX(); //TODO 其实应该是碰撞的位置
  322.                             int y = bullets[i].getLocation().getIntY(); //TODO 其实应该是碰撞的位置
  323.                             bullets[i].getLocation().setY(-500);
  324.                             hitParticle.start(x, y);
  325.                         }
  326.                     }
  327.                 }
  328.             }
  329.         }
  330.     }
  331. }