具有物理特性的快速而肮脏的平台游戏在移动平台时会出现错误

发布于 2024-10-03 22:50:56 字数 7089 浏览 2 评论 0原文

好吧,所以我正在尝试制作一个快速而肮脏的平台游戏引擎,但我的碰撞检测和移动平台遇到了一些问题。一方面,“玩家”似乎在移动平台上轻微弹跳,当他击中右侧时,错误也会发生。我将上传一个 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

Alright, so I'm trying to make a quick and dirty platformer engine, and I am having some problems with my collision detection and moving platforms. for one thing the "player" seems to bounce on top of moving platforms ever so slightly, and when he hits the right side errors happen as well. I'll upload a jnlp demo so you can try to find more errors and see whats happening, but here is the source:

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);
   }
  }
 }

}

And here is the demo: http://prime.programming-designs.com/java/platformer_demo/platdemo.jnlp

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

少年亿悲伤 2024-10-10 22:50:56

你之所以很难找到错误,是因为代码太糟糕了。

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

代码重复会产生引入错误的效果,因为当功能重复时,有可能在某个地方出错,而且还可能隐藏错误,因为代码量太大,更难发现它们。

无论如何,平台上的弹跳可能与以下事实有关:在 Player:moveDown 中,您使用的是偏移玩家高度一半的矩形,而在 Thing:moveRight 中> 您正在与未偏移的矩形碰撞。 (但这只是一个猜测。)

The reason why you are having trouble finding the error is that the code is ghastly.

  • Vast amounts of duplication of code: moveLeft, moveRight, moveUp and moveDown are all very similar.
  • Logic for acceleration due to gravity appears in two places.
  • Collision logic repeated all over the place.
  • Desperately poor choice of names. velo for velocity downwards, but delta for velocity rightwards (mislabelled as "momentum"): why not vy and vx? Also maxSpeed for maximum horizontal velocity but maxFallSpeed for maximum vertical velocity.
  • Acceleration/deceleration called speed.
  • Wasteful allocation, e.g. calling new Rectangle every time you want to test whether something has hit something else.
  • Positions are floating-point, but collision is based on integers.

Duplication of code has the effect of introducing bugs, because when functionality is duplicated there's the possibility of getting it wrong in one of the places, and also of hiding bugs, because the volume of code makes it harder to spot them.

Anyway, the bouncing on platforms may be something to do with the fact that in Player:moveDown you are using a rectangle that's offset by half the player's height, whereas in Thing:moveRight you are colliding with a rectangle that's not offset. (But that's just a guess.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文