0

So I have been trying to get into making very simple games in Java. I have been having success when I make the entire program in one class, but whenever I try to add object oriented principles everything falls apart. What I want is for a bullet to launch from my good guy, which is more or less a turret. I can set up something like this with ease, but when I try to do so using classes to represent the good guy and the bullet everything falls apart. Here is what I have so far. Sets up the main program frame:

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

ShooterPanel class:

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

Our protagonist:

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

And his bullet:

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

What I would like to happen is for the space bar to be pressed, a bullet to appear by the good guy, and for it to move across the screen to the right. I can't get the bullet to draw at all. I have tried several things, all to no avail. I'm sure this is very easy. As I've said I could do this all in my ShooterPanel class using variables to draw the bullet rather than creating objects, but I want to go object-oriented. Does anyone have a solution for me? I would greatly appreciate some help, but am looking for a solution. Please, if you are just going to give a vague suggestion I would prefer no response. EDIT: Here's how I want my program to work:

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

The shooter class remains the same. This is what I want the program to do, but it's not precisely how I want it to do it. I would prefer if it were more object-oriented, and each class took care of itself. The ShooterPanel is already starting to get a little convoluted for my taste, and only gets worse as more is added to the program. One thing I would like to change would be for each bullet to have its own timer, with an ActionListener defined in the Bullet class. However, I cannot figure out how to do this in such a way that the bullet is redrawn every time the timer fires an event. If anyone knows a way to do so, please let me know.

  • See also examples [here](http://stackoverflow.com/q/9849950/230513) and [here](http://stackoverflow.com/q/3066590/230513). – trashgod Aug 05 '12 at 20:43

2 Answers2

0

You need to make your ShooterPanel focusable. Add:

    setFocusable(true);
    requestFocusInWindow();

Also the Graphics for BulletListener is never set. This paint(ing) should probably happen in the ShooterPanel itself.

Reimeus
  • 158,255
  • 15
  • 216
  • 276
  • Even with the focusable lines added my problems persist. Anyone know how to make the painting occur in ShooterPanel? I tried adding this to paintComponent: if (bulletOut) hero.getBullet().draw(page); bulletOut is a boolean variable which is set to true when the space bar is pressed and a bullet is instantiated. getBullet() is of course a method I added to the GoodGuy class which returns bullet. I also changed the BulletListener to simply increase x by 5. Unfortunately this did not work. – user1505612 Aug 05 '12 at 20:54
  • Of course with it set up this way there is no call to repaint() occurring every time the timer fires, so I don't think it would show the bullet moving even if it was working. Anyone have a solution? – user1505612 Aug 05 '12 at 21:01
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.

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366