0

所以我一直在尝试用 Java 制作非常简单的游戏。当我在一个班级中制作整个程序时,我已经取得了成功,但是每当我尝试添加面向对象的原则时,一切都会崩溃。我想要的是从我的好人身上发射子弹,这或多或少是一个炮塔。我可以轻松地设置这样的东西,但是当我尝试使用类来代表好人和子弹时,一切都崩溃了。这是我到目前为止所拥有的。设置主程序框架:

import javax.swing.JFrame;

public class Shooter 
{
    public static void main (String[] args)
    {
        JFrame frame = new JFrame("Car");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        ShooterPanel panel = new ShooterPanel();

        frame.getContentPane().add(panel);
        frame.pack();
        frame.setVisible(true);
    }
}

射手面板类:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class ShooterPanel extends JPanel
{
    final int WIDTH = 200, HEIGHT = 100;
    GoodGuy hero;

    public ShooterPanel()
    {
        hero = new GoodGuy(0, HEIGHT-20, 20);
        addKeyListener(new MoveListener());
        setPreferredSize(new Dimension (WIDTH, HEIGHT));
        setFocusable(true); 
    }
    public void paintComponent(Graphics page)
    {
        super.paintComponent(page);
        hero.draw(page);
    }
    private class MoveListener implements KeyListener
    {

        public void keyPressed (KeyEvent event)
        {
            switch (event.getKeyCode())
            {
                case KeyEvent.VK_SPACE:
                    hero.shoot();
                    break;
            }
        }
        //--------------------------------------------------------------
        //Provide empty definitions for unused event methods.
        //--------------------------------------------------------------
        public void keyTyped (KeyEvent event) {}
        public void keyReleased (KeyEvent event) {}
    }
}

我们的主角:

import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class GoodGuy 
{
    private int x, y, size;
    private Bullet bullet;

    public GoodGuy(int x, int y, int height)
    {
        size = height;
        this.x = x;
        this.y = y;
    }
    public int getSize()
    {
        return size;
    }
    public void draw(Graphics page)
    {
        page.drawRect(x, y, size, size);
    }
    public void shoot()
    {
        bullet = new Bullet(x+size, y);
    }
}

还有他的子弹:

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;

public class Bullet 
{
    private int x, y;
    final int LENGTH = 5, DELAY =200;
    private Timer timer;
    Graphics page1;

    public Bullet(int x, int y)
    {
        this.x = x;
        this.y = y;
        timer = new Timer(DELAY, new BulletListener());
        timer.start();
    }
    public void draw(Graphics page)
    {
        page.drawLine (x, y, x+LENGTH, y);  
    }

    //*****************************************************************
    // Represents the action listener for the timer.
    //*****************************************************************
    private class BulletListener implements ActionListener
    {
        public void actionPerformed (ActionEvent event)
        {
            x +=5;  
            draw(page1);
        }
    }
}

我想要发生的是按下空格键,好人出现一颗子弹,并让它穿过屏幕向右移动。我根本无法画出子弹。我已经尝试了几件事,都无济于事。我相信这很容易。正如我所说,我可以在我的 ShooterPanel 类中使用变量来绘制子弹而不是创建对象来完成这一切,但我想面向对象。有人对我有解决方案吗?我将非常感谢一些帮助,但我正在寻找解决方案。拜托,如果你只是想给出一个模糊的建议,我宁愿没有回应。编辑:这是我希望我的程序工作的方式:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;

public class ShooterPanel extends JPanel
{
final int WIDTH = 200, HEIGHT = 100;
GoodGuy hero;
ArrayList<BadGuy> enemies = new ArrayList<BadGuy>();
ArrayList<Bullet> bullets = new ArrayList<Bullet>();
private Timer timer, bulletTimer;

final int DELAY = 200;
int count=0;
private boolean bulletOut = false;

public ShooterPanel()
{
    hero = new GoodGuy(0, HEIGHT-20, 20);
    addKeyListener(new MoveListener());
    timer = new Timer(DELAY, new EnemyListener());
    bulletTimer = new Timer(100, new BulletListener());
    setPreferredSize(new Dimension (WIDTH, HEIGHT));
    //enemies.add(new BadGuy(WIDTH-10, HEIGHT-10));
    setFocusable(true );
    timer.start();
}
public void paintComponent(Graphics page)
{
    super.paintComponent(page);
    hero.draw(page);
    for (int i = 0; i < enemies.size(); i++)
    {
        enemies.get(i).draw(page);
    }
    if (bulletOut)
        for(Bullet bullet: bullets)
            bullet.draw(page);

}
private class MoveListener implements KeyListener
{
    //--------------------------------------------------------------
    //Responds to the user pressing arrow keys by adjusting the
    //image and image location accordingly.
    //--------------------------------------------------------------
    public void keyPressed (KeyEvent event)
    {
        switch (event.getKeyCode())
        {
        case KeyEvent.VK_SPACE:
            bullets.add(new Bullet(20,95));
            bulletOut = true;
            bulletTimer.start();
            break;
        }

    }
    //--------------------------------------------------------------
    //Provide empty definitions for unused event methods.
    //--------------------------------------------------------------
    public void keyTyped (KeyEvent event) {}
    public void keyReleased (KeyEvent event) {}
}
//*****************************************************************
// Represents the action listener for the timer.
//*****************************************************************
private class EnemyListener implements ActionListener
{
    //--------------------------------------------------------------
    // Updates the position of the image and possibly the direction
    // of movement whenever the timer fires an action event.
    //--------------------------------------------------------------
    public void actionPerformed (ActionEvent event)
    {
        if (count%20==0)
            enemies.add(new BadGuy(WIDTH-10, HEIGHT-10));

        for (BadGuy enemy: enemies)
        {
            enemy.move();
        }

        count++;
        repaint();
    }
}
private class BulletListener implements ActionListener
{
    //--------------------------------------------------------------
    // Updates the position of the image and possibly the direction
    // of movement whenever the timer fires an action event.
    //--------------------------------------------------------------
    public void actionPerformed (ActionEvent event)
    {
        for(Bullet bullet: bullets)
            bullet.move();
        for(int i = 0; i < bullets.size(); i++)
        {

            if (enemies.size() != 0)
            {
                if (bullets.get(i).getX() > enemies.get(0).getX())
                {
                    bullets.remove(i);
                    enemies.remove(0);
                }
            }
            if (bullets.size() != 0)
            {
                if (bullets.get(i).getX()>WIDTH)
                    bullets.remove(i);
            }       
        }
        repaint();
    }
}
}
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class GoodGuy 
{
private int x, y, size;
private Bullet bullet;

public GoodGuy(int x, int y, int height)
{
    size = height;
    this.x = x;
    this.y = y;
}
public int getSize()
{
    return size;
}
public void draw(Graphics page)
{
    page.drawRect(x, y, size, size);
}
public void shoot()
{
    bullet = new Bullet(x+size, y);

}
}

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class BadGuy 
{
private int x, y;
final int RADIUS = 5;


public BadGuy(int x, int y)
{
    this.x = x;
    this.y = y;

}
public void move()
{
    x -= 5;

}
public void draw(Graphics page)
{
    page.drawOval(x, y, RADIUS*2, RADIUS*2);
}
public int getX()
{
    return x;
}

}
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.Timer;

public class Bullet 
{
private int x, y;
final int LENGTH = 5, DELAY =200;

public Bullet(int x, int y)
{
    this.x = x;
    this.y = y;
}
public void draw(Graphics page)
{
    page.drawLine (x, y, x+LENGTH, y);

}
public void move()
{
    x += 5;
}
public int getX()
{
    return x;
}   
}

射击类保持不变。这就是我希望程序做的事情,但这并不是我希望它做的事情。如果它更面向对象,并且每个类都照顾好自己,我会更喜欢它。根据我的口味,ShooterPanel 已经开始变得有些复杂,而且随着程序添加更多内容,它只会变得更糟。我想改变的一件事是每个子弹都有自己的计时器,并在 Bullet 类中定义了一个 ActionListener。但是,我无法弄清楚如何以每次计时器触发事件​​时重新绘制子弹的方式来执行此操作。如果有人知道这样做的方法,请告诉我。

4

2 回答 2

0

您需要使您的 ShooterPanel 可聚焦。添加:

    setFocusable(true);
    requestFocusInWindow();

BulletListener 的 Graphics 也从未设置。这种绘画(ing)可能应该发生在 ShooterPanel 本身中。

于 2012-08-05T20:44:11.390 回答
0

Try to take advantage of the KeyBindings API instead of a KeyListener, if setup correctly, it should over come the issues with the focus.

于 2012-08-05T21:03:22.887 回答