Java 命中检测/对象之间的碰撞

标签 java collision-detection

作为编码新手,我观看了有关如何创建 Pong 的视频。进展顺利,因此我想尝试使用 Pong 中使用的一些编码技术来重新创建 Brick Breaker。到目前为止,我已经有了球、 Racket 和游戏底座。然而,球并没有与 Racket 正确碰撞,而是弹跳穿过。

基础游戏代码:

import java.applet.Applet;
import java.awt.Color;
import java.awt.Image;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class Breaker extends Applet implements Runnable, KeyListener{
final int WIDTH = 600, HEIGHT= 400;
Thread thread;
Graphics gfx;
Image img;
Ball b1;
Player p1;

public void init() {
    this.resize(WIDTH, HEIGHT);
    this.addKeyListener(this);
    b1 = new Ball();
    p1 = new Player(1);
    img = createImage(WIDTH,HEIGHT);
    gfx = img.getGraphics();
    thread = new Thread(this);
    thread.start();
}

public void paint(Graphics g) {
    gfx.setColor(Color.black);
    gfx.fillRect(0, 0, WIDTH, HEIGHT);
    b1.draw(gfx);
    p1.draw(gfx);
    g.drawImage(img, 0, 0, this);
}

public void update (Graphics g) {
    paint(g);
}

@Override
public void keyPressed(KeyEvent e) {
    if(e.getKeyCode() == KeyEvent.VK_LEFT){
        p1.setLeftAccel(true);
    }
    else if(e.getKeyCode() == KeyEvent.VK_RIGHT){
        p1.setRightAccel(true);
    }

}

@Override
public void keyReleased(KeyEvent e) {
    if(e.getKeyCode() == KeyEvent.VK_LEFT){
        p1.setLeftAccel(false);
    }
    else if(e.getKeyCode() == KeyEvent.VK_RIGHT){
        p1.setRightAccel(false);
    }
}

@Override
public void run() {
    for(;;) {

        p1.move();
        b1.move();
        b1.checkPlayerCollision(p1);

        repaint();
        getToolkit().sync();
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

@Override
public void keyTyped(KeyEvent arg0) {   
}
}

球:

import java.awt.Graphics;
import java.awt.Color;

public class Ball {
int score;
double xVel, yVel, x, y;

public Ball() {
    x= 350;
    y = 250;
    xVel= 0;
    yVel = 1;
}

public void draw(Graphics g) {
    g.setColor(Color.white);
    g.fillOval((int)x - 10, (int)y - 10, 20, 20);
}

public void checkPlayerCollision(Player p1) {
    if (x <= 50) {
        if(x >= p1.getX() && x <= p1.getX() + 10)
            xVel = -xVel;
    }
    else if (x >= 680) {
        xVel = -xVel;
    }
}

public void move() {
    x += xVel;
    y += yVel;

    if (y < 10) //Bounce at top side of screen
        yVel = -yVel;
    if (x < 10) // Bounce at left side of screen
        xVel = -xVel;
}

public int getX() {
    return (int)x;
}

public int getY() {
    return (int)y;
}


}

玩家:

import java.awt.Color;
import java.awt.Graphics;

public class Player implements Paddle {
double x, xVel;
boolean leftAccel, rightAccel;
int player, y;

public Player(int player) {
    leftAccel = false; rightAccel = false;
    x=260; xVel=0;
}

@Override
public void draw(Graphics g) {
    g.setColor(Color.white);
    g.fillRect((int)x, 380, 80, 10);

}

@Override
public void move() {
    if(leftAccel){
        xVel -= 2;
    }
    else if (rightAccel) {
        xVel += 2;
    }
    else if (!leftAccel && !rightAccel) {
        xVel = 0;
    }
    if(xVel >= 5) {
        xVel = 5;
    }
    else if (xVel <= -5) {
        xVel = -5;
    }
    x += xVel;

    if(x < 0)
        x=0; //Collision with left wall
    if(x > 520)
        x = 520; //Collision with right wall

}

public void setLeftAccel(boolean input) {
    leftAccel = input;
}

public void setRightAccel(boolean input) {
    rightAccel = input;
}

@Override
public int getX() {
    return (int)x;

}
}

桨:

import java.awt.Graphics;

public interface Paddle {
public void draw(Graphics g);
public void move();
public int getX();

}

我还不完全理解命中检测,所以我只是搞乱了用于 pong 的内容,但是,这不起作用(而且我确信它可能看起来很奇怪)。

最佳答案

有时,碰撞检测可能很难理解。真正对我有帮助的是在一张纸上画出我需要检查的东西,并将检查一一写在代码中。牢记您的轴也是一个好主意,很容易混淆 xy,但它们会对游戏玩法产生重要影响。 我的眼睛被你的 checkPlayerCollision 函数吸引,因为它看起来有点不对劲,我改变了一些检查并评论了每个检查/函数正在做什么。

public void checkPlayerCollision(Player p1) {
    if (
        // Is the ball at or below paddle height?
        y <= 50
        // AND Is the ball right of the left side of the paddle?
        && x >= p1.getX()
        // AND Is the ball left of the right side of the paddle?
        && x <= p1.getX() + 10
    ) {
        // Collision with the paddle! 
        // (Ball is lower than y=50 and between left and right side of the paddle!)
        // As we want the ball to go back up, we will be changing its velocity
        // along the Y-axis.
        yVel -= yVel;
    } else if (x >= 680) {
        // This checks whether the ball went too far to the right..?
        xVel -= xVel;
    }
}

我可以给您的最佳提示:拿一张纸,画一个简单的网格或图表,然后用它来画出您需要检查的不同内容。请务必标记您的 (0,0) 点,以便在使用不同边框时,您知道哪些为 0(通常是顶部和左侧边框),哪些等于 width Canvas 的高度

关于Java 命中检测/对象之间的碰撞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45875500/

相关文章:

java - 执行程序服务每 x 秒运行一次

java - 使用 SMPP (CloudHopper) 检索其帐户的剩余积分

java - 如何在 libgdx-InputProcess 中使用缩放功能?

ios - 在 cocos2d 3.1 中拖放物理体?

Java 碰撞检测未按预期运行

animation - 在 xcode 中使用动画时如何找到相交/不相交的两个对象?

java - LibGdx - 平铺游戏碰撞检测

java - 直接访问静态字段而不是调用静态getter方法,是不是更快?

java - MyBatis - 使用自定义对象调用存储过程

ios - 为什么在 IOS 中无法使用 CGRectIntersectsRect 进行碰撞检测?