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

Wil*_*iam 0 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);
   }
  }
 }

}
Run Code Online (Sandbox Code Playgroud)

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

Gar*_*ees 7

你找不到错误的原因是代码是可怕的.

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

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

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