我创造了一个射出子弹(矩形)的椭圆形,如果它碰到红色矩形,碰撞就会发现子弹击中了矩形。然而,当我运行程序时,碰撞已经完成,我甚至没有按空格键进行拍摄。我想要发生的是,当我射击并且子弹击中矩形时,那就是当它发现碰撞时。我试图分析它并做一些事情,但我无法得到它。这是我的源代码:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class JavaGame2 extends JPanel implements KeyListener,Runnable{
//variables
JFrame frame;
int x, y, xDir, yDir,bx,by;
Rectangle bullet;
boolean readyTofire, shot = false;
//constructor for game
public JavaGame2(){
frame = new JFrame("Java Game");
int x=150;
int y=150;
}
//drawings
public void paintComponent(Graphics g){
super.paintComponent(g);
this.setBackground(Color.WHITE);
Rectangle rec = new Rectangle(50, 20, 50, 50);
g.setColor(Color.BLUE);
g.fillOval(x, y, 55, 55);
g.fillRect(x+23, y-15, 10, 20);
g.setColor(Color.RED);
g.fillRect(rec.x, rec.y, rec.width, rec.height);
bullet = new Rectangle(bx, by, 5, 3);
if(shot){
g.setColor(Color.BLACK);
g.fillRect(bullet.x, bullet.y, bullet.width, bullet.height);
}
if(bullet.intersects(rec));
g.drawString("collision!", 50, 20);
repaint();
}
public void setxDir(int xdir){
xDir = xdir;
}
public void setyDir(int ydir){
yDir = ydir;
}
//key event listener keypressed
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if(code == KeyEvent.VK_UP){
setyDir(-1);
}
if(code == KeyEvent.VK_DOWN){
setyDir(+1);
}
if(code == KeyEvent.VK_LEFT){
setxDir(-1);
}
if(code == KeyEvent.VK_RIGHT){
setxDir(+1);
}
if(code == KeyEvent.VK_SPACE){
if(bullet == null ){
readyTofire = true;
if(readyTofire){
bx = x+26;
by = y-15;
bullet = new Rectangle(bx, by, 5, 3);
shot = true;
}
}
}
}
//key event listener for key released
public void keyReleased(KeyEvent e) {
int code = e.getKeyCode();
if(code == KeyEvent.VK_UP){
setyDir(0);
}
if(code == KeyEvent.VK_DOWN){
setyDir(0);
}
if(code == KeyEvent.VK_LEFT){
setxDir(0);
}
if(code == KeyEvent.VK_RIGHT){
setxDir(0);
}
if(code == KeyEvent.VK_SPACE){
readyTofire = false;
if(bullet.y <= -5){
bullet = new Rectangle(0, 0, 0, 0);
shot = false;
readyTofire = true;
}
}
}
public void keyTyped(KeyEvent e) {
}
//shot of bullet
public void shoot(){
if(shot){
bullet.y--;
}
}
//movement of the oval
public void move(){
x += xDir;
y += yDir;
if(x <= 0){
x = 0;
}
else if(x >= 500){
x = 500;
}
else if(y <= 0){
y = 0;
}
else if(y >= 500){
y = 500;
}
}
//thread
public void run() {
try{
while(true){
shoot();
move();
Thread.sleep(5);
}
}
catch(Exception e){
System.out.println("error!");
}
}
}
答案 0 :(得分:2)
花点时间看看你的碰撞检测声明......
if (bullet.intersects(rec));
g.drawString("collision!", 50, 20);
问题是,您已使用if
;
声明
if (bullet.intersects(rec));
^---
这意味着该语句被有效忽略,它将与......相同。
if (bullet.intersects(rec)) {
}
g.drawString("collision!", 50, 20);
首先会提醒您注意这个问题
相反,请尝试使用
if (bullet.intersects(rec)) {
g.drawString("collision!", 50, 20);
}
现在,请勿使用任何repaint
方法调用repaint
或任何可能调用setBackground
的方法(如paint
)。这将设置一个重复绘制事件的循环,最终消耗你的CPU。
我认为你真的不需要200fps而且大约40的Thread.sleep
会给你25fps,并且通常会超出你的目的。
您还应该考虑使用key bindings,这样您就可以解决与KeyListener
相关的焦点问题。
我还鼓励您探索Swing Timer
的使用,这将减少模型和视图之间未同步更新的可能性,这可能导致随机且难以解决的问题或其他问题。 ..
拍摄问题
存在许多逻辑问题和错误使用变量......
首先......
bx
和by
,您不需要它们。你实际上并不需要x
和y
,但随着我们的到来,这可能会更加明显...... bullet
,这会造成一些混淆...... paintComponent
进行keyReleased
检查,但如果您这样做,则应将VK_SPACE
设为shot
,将false
设为bullet
} ... null
是否readyToFire
之前将true
设置为true
但是,当您在VK_SPACE
中检测到keyPressed
时检查bullet
是否为null
,如果不是,则bullet
已经存在,不知道这是否是一个问题,但是如果您要使用{ {1}},您可以同时触发多个子弹......任何方式,创建新的List
并分配给Rectangle
bullet
if (code == KeyEvent.VK_SPACE) {
readyTofire = true;
if (readyTofire) {
int bx = x + 26;
int by = y - 15;
bullet = new Rectangle(bx, by, 5, 3);
shot = true;
}
}
方法中,忘记进行边界检查......
shoot
public void shoot() {
if (shot) {
bullet.y--;
// Have we past the edge of the screen
if (bullet.y < 0) {
shot = false;
bullet = null;
}
}
}
如果我错过了什么,这就是我测试的代码......
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
Rectangle rec = new Rectangle(50, 20, 50, 50);
g.setColor(Color.BLUE);
g.fillOval(x, y, 55, 55);
g.fillRect(x + 23, y - 15, 10, 20);
g.setColor(Color.RED);
g.fillRect(rec.x, rec.y, rec.width, rec.height);
if (shot && bullet != null) {
g2d.setColor(Color.BLACK);
g2d.fill(bullet);
if (bullet.intersects(rec)) {
g2d.drawString("collision!", 50, 20);
}
}
g2d.dispose();
}
没有冒犯,但你的方法有点原始。您不应该将整个游戏模型包含在尝试显示它的同一个类中,而应该将游戏“逻辑”分离为模型并更新模型状态,然后让您的视图绘制模型...恕我直言