使用普通数组和矩形的碰撞检测 - java

时间:2012-05-07 00:27:52

标签: java arrays collision-detection

我的第一个小java游戏几乎完成了我的最终项目。它是一个侧面滚动器,你必须射击/避免小行星。我的最后一个问题是弄清楚如何让我的小行星阵列与玩家的激光相撞。这就是我到目前为止,在第137行有一个“AWT-EventQueue-0”java.lang.NullPointerException,我无法处理。感谢任何帮助。

编辑:我在其他课程中添加了,我意识到如果我没有告诉你它的来源,就很难判断我的代码的功能。

package ShooterGame;

import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.Random;

import javax.swing.*;

public class Board extends JPanel implements ActionListener
{   
    Enemy[] baddies = new Enemy[10000];
    Player p;
    Image img;
    int y;
    Timer time;
    boolean lost = false;
    static Font font = new Font("SanSerif", Font.BOLD, 24);
    public AudioClip theme, bang, laser;    
    static ArrayList<Enemy> enemies;

    public static int score = 0;
    public static int lives = 5;

    public Board() 
    {           
        p = new Player();       
        addKeyListener(new ActionListener());
        setFocusable(true);
        ImageIcon i = new ImageIcon("images/background.png");
        img = i.getImage();

        time = new Timer(5, this);
        time.start();

        for(int j = 0; j < baddies.length; j++)
        {   
            Random ran = new Random();
            y = ran.nextInt(365)+1;
            baddies[j]= new Enemy((100*j + 700), y, "images/asteroid.gif");
        }

        theme = Applet.newAudioClip(getClass().getResource("theme.mid"));
        theme.play();

        bang = Applet.newAudioClip(getClass().getResource("bang.wav"));
    }

    public void actionPerformed(ActionEvent e)
    {
        checkCollisions();
        ArrayList<?> bullets = Player.getBullets();

        for(int i = 0; i < bullets.size(); i++)
        {
            Bullet b = (Bullet)bullets.get(i);

            if(b.isVisible() == true)
            {
                b.move();
            }
            else
            {
                bullets.remove(i);
            }
        }

        p.move();
        for(int i = 0; i < baddies.length; i++)
        {
            if(p.x > 400)
            {
                baddies[i].move(p.getdx());
            }
        }

        repaint();
    }

    public void paint(Graphics g)
    {   
        super.paint(g);
        Graphics2D g2d = (Graphics2D) g;

        if(lost)
        {
            g2d.drawString("You Lose!", 300, 300);
        }

        if((p.getX() - 590) % 2400 == 0 || (p.getX() - 590) % 2400 == 1)
        {
            p.nx = 0;
        }

        if((p.getX() - 1790) % 2400 == 0 ||(p.getX() - 1790) % 2400 == 1)
        {
            p.nx2 = 0;
        }

        g2d.drawImage(img, 685-p.nx2, 0, null);

        if(p.getX() >= 590)
        {
            g2d.drawImage(img, 685-p.nx, 0, null);
        }

        g2d.drawImage(p.getImage(), p.edge, p.getY(), null);

        ArrayList<?> bullets = Player.getBullets();
        for(int i = 0; i < bullets.size(); i++)
        {
            Bullet b = (Bullet)bullets.get(i);
            g2d.drawImage(b.getImg(), b.getX(), b.getY(), null);

        }
            for(int i = 0; i < baddies.length; i++)
            {
                if(baddies[i].isAlive == true)
                {
                    g2d.drawImage(baddies[i].getImg(), baddies[i].getX(), baddies[i].getY(), null);
                }
            }

        g2d.setColor(Color.white);
        g2d.drawString("Score: " + score, 0, 320);
        g2d.drawString("Lives: " + lives, 80, 320);
    }

    public void checkCollisions()
    {       
        Rectangle[] rect = new Rectangle[baddies.length];
        for(int i = 0; i < baddies.length; i++)
        {
            Enemy e = (Enemy)baddies[i];
            rect[i] = e.getBounds();
        }

        ArrayList<?> bullets = Player.getBullets();
        for (int i = 0; i < bullets.size(); i++)
        {
            Bullet b = (Bullet) bullets.get(i);
            Rectangle b1 = b.getBounds();

            if (rect[i].intersects(b1) && baddies[i].isAlive())
            {
                score++;
                baddies[i].isAlive = false;
                baddies[i].isVisible = false;
                bang.play();
             }

            Rectangle h = p.getBounds();
            if (h.intersects(rect[i]))
            {
                if(baddies[i].isAlive() == true)
                {
                    lives--;
                    if(lives < 0)
                    {
                        lost = true;
                        theme.stop();
                        System.exit(1);
                    }
                }
            }
        }
    }

    private class ActionListener extends KeyAdapter
    {
        public void keyReleased(KeyEvent e)
        {
            p.keyReleased(e);
        }

        public void keyPressed(KeyEvent e)
        {
            p.keyPressed(e);
        }
    }
}

敌人

package ShooterGame;

import java.awt.*;

import javax.swing.ImageIcon;

public class Enemy 
{
    int x, y;
    Image img;
    boolean isAlive = true;
    boolean isVisible = true;


    public Enemy(int startX, int startY, String location)
    {
        x = startX;
        y = startY;
        ImageIcon l = new ImageIcon(location);
        img = l.getImage();
    }

    public Rectangle getBounds()
    {
        return new Rectangle(x, y, 60, 60);
    }


    public int getX() 
    {
        return x;
    }

    public int getY() 
    {
        return y;
    }

    public boolean isAlive() 
    {
        return isAlive;
    }

    public boolean isVisible() 
    {
        return isVisible;
    }

    public Image getImg() 
    {
        return img;
    }   

    public void move(int dx)
    {
        x = x - dx;
    }

}

子弹

package ShooterGame;

import java.applet.Applet;
import java.awt.*;
import javax.swing.ImageIcon;
import java.applet.AudioClip;

public class Bullet 
{   
    int x, y;
    Image img;
    boolean visible;

    public Bullet(int startX, int startY)
    {
        x = startX;
        y = startY;

        ImageIcon newBullet = new ImageIcon("images/bullet.gif");
        img = newBullet.getImage();
        visible = true;
    }

    public Rectangle getBounds()
    {
        return new Rectangle(x, y, 9, 5);
    }

    public int getX() 
    {
        return x;
    }

    public int getY() 
    {
        return y;
    }

    public Image getImg() 
    {
        return img;
    }

    public boolean isVisible() 
    {
        return visible;
    }

    public void move()
    {
        x = x + 2;
        if(x > 700)
        {
            visible = false;
        }
    }

    public void setVisible(boolean isVisible)
    {
        visible = isVisible;
    }
}

播放器

package ShooterGame;

import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.util.ArrayList;

import javax.swing.ImageIcon;

public class Player 
{

    int x, dx, y, dy, nx2, nx, edge, ceiling; 
    Image player;
    ImageIcon ib = new ImageIcon("images/player1back.gif");
    ImageIcon i = new ImageIcon("images/playerstill.gif");
    ImageIcon f = new ImageIcon("images/playerforward.gif");
    ImageIcon up = new ImageIcon("images/playerup.gif");
    ImageIcon down = new ImageIcon("images/playerdown.gif");
    public AudioClip laser;
    static ArrayList<Bullet> bullets;

    public Player()
    {laser = Applet.newAudioClip(getClass().getResource("laser.wav"));
        player = ib.getImage();
        x = 75;
        nx = 0;
        nx2 = 685;
        y = 172;
        edge = 150;
        ceiling = 0;
        bullets = new ArrayList<Bullet>();
    }

    public static ArrayList<Bullet> getBullets()
    {
        return bullets;
    }

    public void fire()
    {
        Bullet z = new Bullet((edge + 60), (y+17));
        bullets.add(z); 
    }

    public Rectangle getBounds()
    {
        return new Rectangle(edge, y, 43, 39);
    }

    public void move()
    {
        y = y + dy;
        if(y < ceiling)
        {
            y = ceiling;
        }

        if(y > 290)
        {
            y = 290;
        }

        if(dx != -1)
        {
            if(edge + dx <= 151)
            {
                edge = edge + dx;
            }
            else
            {
                x = x + dx;
                nx2 = nx2 + dx;
                nx = nx + dx;
            }
        }
        else
            {
            if(edge + dx > 0)
            {
                edge = edge + dx;
            }
        }   

    }

    public int getX()
    {
        return x;
    }

    public int getdx()
    {
        return dx;
    }

    public int getY()
    {
        return y;
    }

    public Image getImage()
    {
        return player;
    }

    public void keyPressed(KeyEvent e)
    {
        int key = e.getKeyCode();

        if(key == KeyEvent.VK_RIGHT)
        {
            dx = 2;
            player = f.getImage();
        }
        if(key == KeyEvent.VK_UP)
        {
            dy = -1;
            player = up.getImage();
        }
        if(key == KeyEvent.VK_DOWN)
        {
            dy = 1;
            player = down.getImage();
        }
        if(key == KeyEvent.VK_SPACE)
        {
            fire();
            laser.play();
        }
    }

    public void keyReleased(KeyEvent e)
    {
        int key = e.getKeyCode();

        if(key == KeyEvent.VK_RIGHT)
        {
            dx = 1;
            player = ib.getImage();
        }

        if(key == KeyEvent.VK_UP)
        {
            dy = 0;
            player = ib.getImage();
        }

        if(key == KeyEvent.VK_DOWN)
        {
            dy = 0;
            player = ib.getImage();
        }
    }
}

package ShooterGame;

import javax.swing.*;

public class Frame 
{
    public AudioClip theme;

        public Frame()
        {
                JFrame frame = new JFrame();
                frame.add(new Board());
                frame.setTitle("SideShooter");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setSize(700,365);
                frame.setVisible(true);
                frame.setLocationRelativeTo(null);

        }

        public static void main(String[] args)
        {
                new Frame();

        }
}

2 个答案:

答案 0 :(得分:0)

错误在行

rect[i] = e.getBounds();

您是否未正确初始化Enemy班级的界限?或者,你从数组中撤出的敌人可能为空。

答案 1 :(得分:0)

好的,所以问题是另一个答案中提到的那条线,但我相信所有的敌人在检查碰撞之前可能都没有被初始化。因为你开始使用它们中的10000个,我认为你的动作执行方法可能是在它们全部被创建之前检查碰撞。

尝试的一件事可能是降低你拥有的敌人数量,看看它是否仍在继续发生,尝试100或1000,但这仍然无法解决问题。

你真的想要改变你的游戏以在它自己的循环中运行,此时你只是在玩家执行动作时检查碰撞。所以如果玩家停止移动,没有碰撞检测...

我建议您找一本名为“Java中的杀手游戏编程”的书,有免费的电子书版本,只需阅读前两章关于制作游戏循环的内容。这本书有点陈旧,但循环的基础非常好。

question here还包含一个非常简单的循环,以及评论中有关如何使其更好的一些建议。