带有Physics的快速而肮脏的平台游戏在移动平台时出错

时间:2010-11-24 04:26:40

标签: java physics collision-detection

好吧,所以我正在尝试制作一个快速而肮脏的平台引擎,我在碰撞检测和移动平台方面遇到了一些问题。一方面,“玩家”似乎在移动平台上稍微反弹,当他击中右侧时,错误也会发生。我将上传一个jnlp演示,以便您可以尝试查找更多错误并查看发生了什么,但这里有来源:

import java.awt.Rectangle;
import java.util.Vector;

import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.BasicGame;
import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;


public class Platformer extends BasicGame{

 boolean keys[];
 int ALL_KEYS = 0xFF;
 Player player;
 Vector<Vector<Thing> > things;
 int level = 0;

 public Platformer() {
  super("You've met with a terrible fate, haven't you?");
 }

 public void init(GameContainer gc) throws SlickException {
  keys = new boolean[ALL_KEYS];
  for(int i = 0; i < ALL_KEYS; i++){
   keys[i] = false;
  }

  player = new Player();
  things = new Vector<Vector<Thing> >();
  Vector<Thing> temp = new Vector<Thing>();
  temp.add(new Thing(0, 440, 640, 40, 1));
  temp.add(new Thing(200, 300, 240, 50, 1));
  temp.add(new Thing(500, 200, 240, 50, 1));

  things.add(temp); 
 }

 public void update(GameContainer gc, int delta) throws SlickException{
  if(keys[Input.KEY_UP]){
   player.velo = player.maxJump;
   keys[Input.KEY_UP] = false;
  }

  if(keys[Input.KEY_DOWN]){
   keys[Input.KEY_DOWN] = false;
  }

  if(keys[Input.KEY_LEFT]){
   player.delta -= player.speed;

   if(player.delta < -player.maxSpeed)
    player.delta = -player.maxSpeed;
  }

  else if(keys[Input.KEY_RIGHT]){
   player.delta += player.speed;

   if(player.delta > player.maxSpeed)
    player.delta = player.maxSpeed;
  }

  else{
   if(player.delta < -0.5){
    player.delta += player.speed;
   }

   else if(player.delta > 0.5){
    player.delta -= player.speed;
   }

   else if(player.delta > -0.5 && player.delta < 0.5){
    player.delta = 0; 
   }
  }

  if(player.delta < 0)
   player.moveLeft(things.get(level));

  else if(player.delta > 0)
   player.moveRight(things.get(level));

  if(player.velo < 0)
   player.moveUp(things.get(level));

  else
   player.moveDown(things.get(level));


  things.get(level).get(1).moveRight(player, things.get(level));

 }

 public void render(GameContainer gc, Graphics g) throws SlickException{
  g.setColor(new Color(0,55,55));
  g.fillRect(0, 0, 640, 480);

  g.setColor(new Color(255,0,0));
  g.fillRect(player.x, player.y, player.width, player.height);

  for(int i = 0; i < things.get(level).size(); i++){
   if(things.get(level).get(i).type == 1)
    g.setColor(new Color(0,100,100));

   g.fillRect(things.get(level).get(i).x, things.get(level).get(i).y,things.get(level).get(i).width, things.get(level).get(i).height);
  }
 }

 public void keyPressed(int key, char c) {
  keys[key] = true;
 }

 public void keyReleased(int key, char c) {
  keys[key] = false;
 }

 public static void main(String[] args) throws SlickException{
   AppGameContainer app =
   new AppGameContainer( new Platformer() );

   app.setShowFPS(false);
   app.setAlwaysRender(true);
   app.setTargetFrameRate(60);
   app.setDisplayMode(640, 480, false);
   app.start();
 }


 class Player{
  float x = 50;
  float y = 50;

  float delta = 0; // x momentum
  float velo = 0;
  int height = 50;
  int width = 30;
  float speed = 0.2f;
  int maxSpeed = 6;
  int maxFallSpeed = 5;
  int maxJump = -8;

  public void moveLeft(Vector<Thing> things){
   x += delta;

   if(x < 0)
    x = 0;

   for(int i = 0; i < things.size(); i++){
    if(new Rectangle((int) x, (int) y, width, height).intersects(new Rectangle((int) things.get(i).x, (int) things.get(i).y, things.get(i).width, things.get(i).height))){
     x += (things.get(i).x + things.get(i).width) - x;
     delta = 0;
    }
   }
  }

  public void moveRight(Vector<Thing> things){
   x += delta;

   if(x + width > 640)
    x = (640 - width);

   for(int i = 0; i < things.size(); i++){
    if(new Rectangle((int) x, (int) y, width, height).intersects(new Rectangle((int) things.get(i).x, (int) things.get(i).y, things.get(i).width, things.get(i).height))){
     x -= (x + width) - things.get(i).x;
     delta = 0;
    }
   }
  }

  public void moveLeftWithThing(Vector<Thing> things, float thingSpeed){
   x -= thingSpeed;

   if(x < 0)
    x = 0;

   for(int i = 0; i < things.size(); i++){
    if(new Rectangle((int) x, (int) y, width, height).intersects(new Rectangle((int) things.get(i).x, (int) things.get(i).y, things.get(i).width, things.get(i).height))){
     x += (things.get(i).x + things.get(i).width) - x;
     delta = 0;
    }
   }
  }

  public void moveRightWithThing(Vector<Thing> things, float thingSpeed){
   x += thingSpeed;

   if(x + width > 640)
    x = (640 - width);

   for(int i = 0; i < things.size(); i++){
    if(new Rectangle((int) x, (int) y, width, height).intersects(new Rectangle((int) things.get(i).x, (int) things.get(i).y, things.get(i).width, things.get(i).height))){
     x -= (x + width) - things.get(i).x;
     delta = 0;
    }
   }
  }

  public void moveUp(Vector<Thing> things){
   y += velo;

   velo += speed;

   if(velo > maxFallSpeed)
    velo = maxFallSpeed;

   for(int i = 0; i < things.size(); i++){
    if(new Rectangle((int) x, (int) y, width, height/2).intersects(new Rectangle((int) things.get(i).x, (int) things.get(i).y, things.get(i).width, things.get(i).height))){
     y += (things.get(i).y + things.get(i).height) - y;
     velo = 0;
    }
   }
  }

  public void moveDown(Vector<Thing> things){
   y += velo;

   velo += speed;

   if(velo > maxFallSpeed)
    velo = maxFallSpeed;


   boolean b = false;
   for(int i = 0; i < things.size(); i++){
    if(!b && new Rectangle((int) x, (int) y + (height/2), width, height).intersects(new Rectangle((int) things.get(i).x, (int) things.get(i).y, things.get(i).width, things.get(i).height))){
     y -= (y + height) - things.get(i).y;
     velo = 0;
    }
   }
  }

 }

 class Thing{
  float x = 50;
  float y = 50;
  int height = 50;
  int width = 30;
  int type = -1;
  float speed = 0.5f;

  public Thing(float x, float y, int width, int height, int type){
   this.x = x;
   this.y = y;
   this.width = width;
   this.height = height;
   this.type = type;
  }

  public void moveUp(Player player){
   y -= 0.5f;

   if(new Rectangle((int) x,(int) y, width, height).intersects(new Rectangle((int) player.x, (int) player.y, player.width, player.height))){
    player.y -= (player.y + player.height) - y;
    player.velo = 0;
   }
  }

  public void moveRight(Player player, Vector<Thing> things){
   x += speed;

   if(new Rectangle((int) x,(int) y - 1, width, height).intersects(new Rectangle((int) player.x, (int) player.y, player.width, player.height))){
    player.moveRightWithThing(things, speed);
   }
  }
 }

}

以下是演示:http://prime.programming-designs.com/java/platformer_demo/platdemo.jnlp

1 个答案:

答案 0 :(得分:7)

您无法找到错误的原因是代码可怕。

  • 大量重复的代码:moveLeftmoveRightmoveUpmoveDown都非常相似。
  • 由于重力引起的加速逻辑出现在两个地方。
  • 碰撞逻辑遍布整个地方。
  • 名字选择极其糟糕。 velo表示速度向下,delta表示速度向右(错误标记为“动量”):为什么不vyvx?另外maxSpeed表示最大水平速度,maxFallSpeed表示最大垂直速度。
  • 加速/减速称为speed
  • 浪费分配,例如每当你想测试是否有什么东西碰到其他东西时调用new Rectangle
  • 位置是浮点数,但碰撞基于整数。

重复代码会产生错误,因为当复制功能时,可能会在其中一个地方出错,并且还会隐藏错误,因为代码量使得发现它们变得更加困难。 / p>

无论如何,平台上的弹跳可能与Player:moveDown中使用的矩形偏移了玩家身高的一半,而Thing:moveRight中你正在与一个矩形相撞的事实有关。这不是抵消。 (但这只是猜测。)