I'm using the Java AWT class to make a wall made up of rectangles on both sides. The wall class extends rectangles, and uses the same variables to draw to the screen.
Walls Class:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
public class Walls extends Rectangle {
public Walls(int startX, int startY, int width, int height ){
//super(startX, startY, width, height);
//
//Checking with this way for the collision detection
this.x = startX;
this.y = startY;
this.width = width;
this.height = height;
//this.wallStartX = startX;
//this.wallStartY = startY;
//this.wallWidth = width;
//this.wallHeight = height;
}
public void draw(Graphics g){
g.setColor(Color.GRAY);
//g.fillRect( this.wallStartX, this.wallStartY, this.wallWidth, this.wallHeight);
//Trying with the rectangle methods
g.fillRect( this.x, this.y, this.width, this.height);
}
I used the rectangle.intersects method to check for collision prediction. It works with the left wall, but it seems to collide with the right wall all the time, even when the player square is not touching. I've used the same code for the left and right wall, and I made sure that the arguments for the wall are the same for the rectangle in the class above.
Based on Worms game from Killer Code Programming in Java
RacerPanel:
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.text.DecimalFormat;
import java.util.Random;
import java.awt.event.KeyEvent; //Should be for Key Usage
import java.awt.event.KeyListener;
public class RacingPanel extends GamePanel implements KeyListener {
///KeyListener from https://www.youtube.com/watch?v=5UaEUrbpDPE
//Q: Serial ID? http://stackoverflow.com/questions/285793/what-is-a- serialversionuid-and-why-should-i-use-it
private static final long serialVersionUID = 1825086766957972644L;
private DecimalFormat df = new DecimalFormat("0.##"); // 2 dp
private Main_Racer mrTop;
private Racer bob;
private Walls josephine;
private Walls jeremy;
private static Random randomGenerator = new Random();
boolean wallBuilder;
int leftCreateorDestroy = 100;
int rightCreateorDestroy = 100;
//private ArrayList()[] Walls kinderland;
//Q
private Font font;
private FontMetrics metrics;
//Q: definitely find out what this method is doing
public RacingPanel( Main_Racer rc, long period) {
super(period);
mrTop = rc;
this.addKeyListener(this);
}
//In case we want to integrate mice
//Q: Why void? Why protected?
protected void mousePress( int x, int y){
}
//Q: in the worm game, it calls
//fred.move(), presumably to move the worm
//wcTop.setTimeSpent(timeSpentInGame);
//Probably a counter
protected void simpleUpdate(){
}
//Q: Assuming that this should be things the
//game starts off with, like the block,
//the course. Also, font
protected void simpleInitialize(){
//T: Maybe I need to initialize the racer
bob = new Racer(PWIDTH, PHEIGHT);
josephine = new Walls(0, 35, 100, 1);
jeremy = new Walls(PWIDTH-100, 35, 100,1);
//That did it!
// so the arguments to the racer update change
//where the square was rendered
//TJ: I need to loop in such a way that will draw random variables
// set up message font
font = new Font("SansSerif", Font.BOLD, 24);
metrics = this.getFontMetrics(font);
}
protected void simpleRender(Graphics dbg) {
if(!gameOver){
//These two seem pretty straight forward
dbg.setColor(Color.blue);
dbg.setFont(font);
// report frame count & average FPS and UPS at top left
// dbg.drawString("Frame Count " + frameCount, 10, 25);
dbg.drawString("Average FPS/UPS: " + df.format(averageFPS) + ", "
+ df.format(averageUPS), 20, 25); // was (10,55)
dbg.setColor(Color.black);
// draw game elements: the obstacles and the worm
//This'll probably be the block and the
//course instead
//obs.draw(dbg);
//fred.draw(dbg);
bob.draw(dbg);
//jeremy.draw(dbg);
//See if we can draw this thing over and over
for(int i = 35; i < PHEIGHT; i++){
wallBuilder = randomGenerator.nextBoolean();
if(wallBuilder == false){
if ( leftCreateorDestroy < PWIDTH/2 - 50)
leftCreateorDestroy++;
}
else{
if(leftCreateorDestroy > 0){
leftCreateorDestroy--;
}
}
josephine = new Walls(0, i, leftCreateorDestroy, 1);
josephine.draw(dbg);
wallBuilder = randomGenerator.nextBoolean();
//This wall keeps colliding with the other wall
//Also, it isn't set to the other side of the screen due to conventions
if(wallBuilder == false){
//if ( (PWIDTH - rightCreateorDestroy) > (PWIDTH/2-150))
if ( rightCreateorDestroy > 0)
rightCreateorDestroy--;
}
else{
if((PWIDTH/2 + 50) < PWIDTH - rightCreateorDestroy){
rightCreateorDestroy++;
}
}
//PWIDTH - rightCreateorDestroy is the length of the
jeremy = new Walls((PWIDTH - rightCreateorDestroy), i, rightCreateorDestroy, 1);
//jeremy = new Walls((PWIDTH - rightCreateorDestroy), i, 100, 1);
//Let's see if it will draw negative; will not;
jeremy.draw(dbg);
//Now to put up collision detection
if(bob.intersects(josephine) ){
System.out.println("Ouch!");
gameOver = true;
}
//System.out.println(bob.);
else if( bob.intersects(jeremy) ){
Rectangle Sektor = bob.intersection(jeremy);
System.out.println(Sektor);
System.out.println(jeremy);
}
//System.out.println("Yow!");
//Problems seem to be with the right side; let's take out the right and check.
//For some reason, intersecting all of the time.
}
}
//1msecond is too long. Starts clipping;
/* try{
Thread.sleep(1000);
}catch ( InterruptedException exc ){
System.out.println("No work");
} */
}
//So this does draw over and over again
//FPS/UPS Still good
//Pretty straight forward as well. Just need
//to see when it is called
protected void gameOverMessage(Graphics g)
// center the game-over message in the panel
{
//Keeps updating after death...
String msg = "Game Over. Your Score: " + timeSpentInGame;
int x = (PWIDTH - metrics.stringWidth(msg)) / 2;
int y = (PHEIGHT - metrics.getHeight()) / 2;
g.setColor(Color.red);
g.setFont(font);
g.drawString(msg, x, y);
} // end of gameOverMessage()
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_RIGHT){
//System.out.println("Right");
//Should set x position to current position plus 1
bob.setRacerPositionX(bob.getRacerPositionX() + 1);
}
if (e.getKeyCode() == KeyEvent.VK_LEFT){
// System.out.println("Left");
bob.setRacerPositionX(bob.getRacerPositionX() - 1);
}
if (e.getKeyCode() == KeyEvent.VK_UP){
//System.out.println("Up");
bob.setRacerPositionY(bob.getRacerPositionY() - 1);
}
if (e.getKeyCode() == KeyEvent.VK_DOWN){
//System.out.println("Down");
bob.setRacerPositionY(bob.getRacerPositionY() + 1);
}
}
Game Panel Class:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.text.DecimalFormat;
import javax.swing.JPanel;
public abstract class GamePanel extends JPanel implements Runnable {
private static final long serialVersionUID = 1863596360846514344L;
private static long MAX_STATS_INTERVAL = 1000000000L;
// private static long MAX_STATS_INTERVAL = 1000L;
// record stats every 1 second (roughly)
private static int NUM_FPS = 10;
// number of FPS values stored to get an average
protected static final int PWIDTH = 500; // size of panel
protected static final int PHEIGHT = 400;
protected static final int NO_DELAYS_PER_YIELD = 16;
/*
* Number of frames with a delay of 0 ms before the animation thread yields
* to other running threads.
*/
protected static int MAX_FRAME_SKIPS = 5; // was 2;
// no. of frames that can be skipped in any one animation loop
// i.e the games state is updated but not rendered
private Thread animator; // the thread that performs the animation
protected boolean running = false; // used to stop the animation thread
protected boolean isPaused = false;
protected long period; // period between drawing in _nanosecs_
// used for gathering statistics
private long statsInterval = 0L; // in ns
private long prevStatsTime;
private long totalElapsedTime = 0L;
private long gameStartTime;
protected int timeSpentInGame = 0; // in seconds
private long frameCount = 0;
private double fpsStore[];
private long statsCount = 0;
protected double averageFPS = 0.0;
private long framesSkipped = 0L;
private long totalFramesSkipped = 0L;
private double upsStore[];
protected double averageUPS = 0.0;
private DecimalFormat df = new DecimalFormat("0.##"); // 2 dp
// used at game termination
protected boolean gameOver = false;
// off screen rendering
private Graphics dbg;
private Image dbImage = null;
public GamePanel(long period) {
this.period = period;
setBackground(Color.white);
setPreferredSize(new Dimension(PWIDTH, PHEIGHT));
setFocusable(true);
requestFocus(); // the JPanel now has focus, so receives key events
readyForTermination();
simpleInitialize();
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
mousePress(e.getX(), e.getY());
}
});
// initialise timing elements
fpsStore = new double[NUM_FPS];
upsStore = new double[NUM_FPS];
for (int i = 0; i < NUM_FPS; i++) {
fpsStore[i] = 0.0;
upsStore[i] = 0.0;
}
} // end of GamePanel()
/**
* Sets up a listener to kill the game loop if the user attempts to quit
*/
private void readyForTermination() {
addKeyListener(new KeyAdapter() {
// listen for esc, q, end, ctrl-c on the canvas to
// allow a convenient exit from the full screen configuration
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if ((keyCode == KeyEvent.VK_ESCAPE)
|| (keyCode == KeyEvent.VK_Q)
|| (keyCode == KeyEvent.VK_END)
|| ((keyCode == KeyEvent.VK_C) && e.isControlDown())) {
running = false;
}
}
});
} // end of readyForTermination()
/**
* Triggers the animation loop to start
*/
public void addNotify()
// wait for the JPanel to be added to the JFrame before starting
{
super.addNotify(); // creates the peer
startGame(); // start the thread
}
/**
* Starts the animation loop
*/
private void startGame()
// initialise and start the thread
{
if (animator == null || !running) {
animator = new Thread(this);
animator.start();
}
} // end of startGame()
// ------------- game life cycle methods ------------
// called by the JFrame's window listener methods
public void resumeGame()
// called when the JFrame is activated / deiconified
{
isPaused = false;
}
public void pauseGame()
// called when the JFrame is deactivated / iconified
{
isPaused = true;
}
public void stopGame()
// called when the JFrame is closing
{
running = false;
}
// ----------------------------------------------
public void run()
/* The frames of the animation are drawn inside the while loop. */
{
long beforeTime, afterTime, timeDiff, sleepTime;
long overSleepTime = 0L;
int noDelays = 0;
long excess = 0L;
gameStartTime = System.nanoTime();
prevStatsTime = gameStartTime;
beforeTime = gameStartTime;
running = true;
while (running) {
gameUpdate();
//T Entering Game Render
System.out.println("Entering Game Render");
gameRender();
paintScreen();
afterTime = System.nanoTime();
timeDiff = afterTime - beforeTime;
sleepTime = (period - timeDiff) - overSleepTime;
if (sleepTime > 0) { // some time left in this cycle
try {
Thread.sleep(sleepTime / 1000000L); // nano -> ms
} catch (InterruptedException ex) {
}
overSleepTime = (System.nanoTime() - afterTime) - sleepTime;
} else { // sleepTime <= 0; the frame took longer than the period
excess -= sleepTime; // store excess time value
overSleepTime = 0L;
if (++noDelays >= NO_DELAYS_PER_YIELD) {
Thread.yield(); // give another thread a chance to run
noDelays = 0;
}
}
beforeTime = System.nanoTime();
/*
* If frame animation is taking too long, update the game state
* without rendering it, to get the updates/sec nearer to the
* required FPS.
*/
int skips = 0;
while ((excess > period) && (skips < MAX_FRAME_SKIPS)) {
excess -= period;
gameUpdate(); // update state but don't render
skips++;
}
framesSkipped += skips;
storeStats();
}
printStats();
System.exit(0); // so window disappears
} // end of run()
/**
* Renders to the backbuffer
*/
private void gameRender() {
if (dbImage == null) {
dbImage = createImage(PWIDTH, PHEIGHT);
if (dbImage == null) {
System.out.println("dbImage is null");
return;
} else
dbg = dbImage.getGraphics();
//T
System.out.println("dbg set");
}
// clear the background
dbg.setColor(Color.white);
dbg.fillRect(0, 0, PWIDTH, PHEIGHT);
//T
simpleRender(dbg);
if (gameOver)
gameOverMessage(dbg);
} // end of gameRender()
/**
* Paints the back buffer
*/
private void paintScreen()
// use active rendering to put the buffered image on-screen
{
Graphics g;
try {
g = this.getGraphics();
if ((g != null) && (dbImage != null))
g.drawImage(dbImage, 0, 0, null);
g.dispose();
} catch (Exception e) {
System.out.println("Graphics context error: " + e);
}
} // end of paintScreen()
/**
* Should be update the game state
*/
private void gameUpdate() {
if (!isPaused && !gameOver)
simpleUpdate();
} // end of gameUpdate()
private void storeStats() {
frameCount++;
statsInterval += period;
if (statsInterval >= MAX_STATS_INTERVAL) { // record stats every
// MAX_STATS_INTERVAL
long timeNow = System.nanoTime();
timeSpentInGame = (int) ((timeNow - gameStartTime) / 1000000000L);
long realElapsedTime = timeNow - prevStatsTime; // time since last
// stats collection
totalElapsedTime += realElapsedTime;
totalFramesSkipped += framesSkipped;
double actualFPS = 0; // calculate the latest FPS and UPS
double actualUPS = 0;
if (totalElapsedTime > 0) {
actualFPS = (((double) frameCount / totalElapsedTime) * 1000000000L);
actualUPS = (((double) (frameCount + totalFramesSkipped) / totalElapsedTime) * 1000000000L);
}
// store the latest FPS and UPS
fpsStore[(int) statsCount % NUM_FPS] = actualFPS;
upsStore[(int) statsCount % NUM_FPS] = actualUPS;
statsCount = statsCount + 1;
double totalFPS = 0.0; // total the stored FPSs and UPSs
double totalUPS = 0.0;
for (int i = 0; i < NUM_FPS; i++) {
totalFPS += fpsStore[i];
totalUPS += upsStore[i];
}
if (statsCount < NUM_FPS) { // obtain the average FPS and UPS
averageFPS = totalFPS / statsCount;
averageUPS = totalUPS / statsCount;
} else {
averageFPS = totalFPS / NUM_FPS;
averageUPS = totalUPS / NUM_FPS;
}
framesSkipped = 0;
prevStatsTime = timeNow;
statsInterval = 0L; // reset
}
} // end of storeStats()
private void printStats() {
System.out.println("Frame Count/Loss: " + frameCount + " / "
+ totalFramesSkipped);
System.out.println("Average FPS: " + df.format(averageFPS));
System.out.println("Average UPS: " + df.format(averageUPS));
System.out.println("Time Spent: " + timeSpentInGame + " secs");
} // end of printStats()
/**
* Should implement game specific rendering
*
* #param g
*/
protected abstract void simpleRender(Graphics g);
/**
* Should display a game specific game over message
*
* #param g
*/
protected abstract void gameOverMessage(Graphics g);
protected abstract void simpleUpdate();
/**
* This just gets called when a click occurs, no default behavior
*/
protected abstract void mousePress(int x, int y);
/**
* Should be overridden to initialize the game specific components
*/
protected abstract void simpleInitialize();
} // end of GamePanel class
Racer Class:
import java.awt.*;
import java.awt.geom.*;
public class Racer extends Rectangle {
//Only method that will likely be common between
//the two areas. This presumably draws to screen
//Size of Car
private static final int carSize = 20;
//Changing racer position from array to x and y coordinates
private int pWidth, pHeight; // panel dimensions
private long startTime; // in ms
public Racer (int pW, int pH){
this.width = pW;
this.height = pH;
//Meant to start racer in the center of the screen
//But it does not
this.x = pW/2;
this.y = pW/2;
}
public void draw(Graphics g){
g.setColor(Color.blue);
g.fillRect( x, y, carSize, carSize);
}
public int getRacerPositionX() {
return x;
}
public void setRacerPositionX(int x) {
this.x = x;
}
public int getRacerPositionY() {
return y;
}
public void setRacerPositionY(int y) {
this.y = y;
}
}
Main Racer:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Main_Racer extends JFrame implements WindowListener
{
private static int DEFAULT_FPS = 80;
private RacingPanel rp;
//Let's leave now and make the panel
//Q: Just a value; why JTextField instead of int?
private JTextField jtfBox;
//Q: Just a value; why JTextField instead of int?
private JTextField jtfTime;
//Main_Racer Constructor
public Main_Racer(long period)
{
//Q: Gotta find this constructor
super("The Main Racder");
//Q:What does the argument do?
makeGUI(period);
addWindowListener( this);
pack();
setResizable(false);
setVisible(true);
}
//Q: Warrants an in depth look
private void makeGUI(long period)
{
Container c = getContentPane(); // default BorderLayout used
rp = new RacingPanel(this, period);
c.add(rp, "Center");
JPanel ctrls = new JPanel(); // a row of textfields
ctrls.setLayout( new BoxLayout(ctrls, BoxLayout.X_AXIS));
//Keeps track of time. Might still be useful
jtfTime = new JTextField("Time Spent: 0 secs");
jtfTime.setEditable(false);
ctrls.add(jtfTime);
c.add(ctrls, "South");
} // end of makeGUI()
//Pretty straing forward
public void setTimeSpent(long t)
{ jtfTime.setText("Time Spent: " + t + " secs"); }
// QQQ -----------------Going to copy the window listening methods, as probably n
//need em all
public void windowActivated(WindowEvent e)
{ rp.resumeGame(); }
public void windowDeactivated(WindowEvent e)
{ rp.pauseGame(); }
public void windowDeiconified(WindowEvent e)
{ rp.resumeGame(); }
public void windowIconified(WindowEvent e)
{ rp.pauseGame(); }
public void windowClosing(WindowEvent e)
{ rp.stopGame(); }
public void windowClosed(WindowEvent e) {}
public void windowOpened(WindowEvent e) {}
//=================================================================================
public static void main(String args[])
{
int fps = DEFAULT_FPS;
if (args.length != 0)
fps = Integer.parseInt(args[0]);
long period = (long) 1000.0/fps;
System.out.println("fps: " + fps + "; period: " + period + " ms");
new Main_Racer(period*1000000L); // ms --> nanosecs
}
} // end of WormChase class
Any reason why collision detection only works on one side?
Related
Look I'm going to be up front about this. My assignment is due soon and i've spent way too many hours trying to fix this problem with no success at all. I'm essentially clueless at what the issue is and I really dont know where to look. I have 5 classes, I will try and post them all to ensure I get the answer, I am unable to change GameManager or Goal but I am allowed to change any other class.
The problem lines are this.canvasGraphics.drawImage(player.getCurrentImage() where drawImage says it isnt applicable for the arguments
and
this.enemies[i].getX() - (this.enemies[i].getCurrentImage().getWidth() / 2),
this.enemies[i].getY() - (this.enemies[i].getCurrentImage().getHeight() / 2), null);
where getWidth and getHeight show an almost identical error
thanks in advance
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.awt.Font;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
public class GameManager extends JFrame implements KeyListener {
private int canvasWidth;
private int canvasHeight;
private int borderLeft;
private int borderTop;
private BufferedImage canvas;
private Stage stage;
private Enemy[] enemies;
private Player player;
private Goal goal;
private Graphics gameGraphics;
private Graphics canvasGraphics;
private int numEnemies;
private boolean continueGame;
public static void main(String[] args) {
// During development, you can adjust the values provided in the brackets below
// as needed. However, your code must work with different/valid combinations
// of values.
int choice;
do{
GameManager managerObj = new GameManager(1920, 1080);
choice=JOptionPane.showConfirmDialog(null,"Play again?", "", JOptionPane.OK_CANCEL_OPTION);
}while(choice==JOptionPane.OK_OPTION);
System.exit(0);
}
public GameManager(int preferredWidth, int preferredHeight) {
int maxEnemies;
try{
maxEnemies=Integer.parseInt(JOptionPane.showInputDialog("How many enemies? (Default is 5)"));
if (maxEnemies<0)
maxEnemies=5;
}
catch (Exception e){
maxEnemies=5;
}
this.borderLeft = getInsets().left;
this.borderTop = getInsets().top;
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
if (screenSize.width < preferredWidth)
this.canvasWidth = screenSize.width - getInsets().left - getInsets().right;
else
this.canvasWidth = preferredWidth - getInsets().left - getInsets().right;
if (screenSize.height < preferredHeight)
this.canvasHeight = screenSize.height - getInsets().top - getInsets().bottom;
else
this.canvasHeight = preferredHeight - getInsets().top - getInsets().bottom;
setSize(this.canvasWidth, this.canvasHeight);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
addKeyListener(this);
Random rng = new Random();
this.canvas = new BufferedImage(this.canvasWidth, this.canvasHeight, BufferedImage.TYPE_INT_RGB);
// Create a Stage object to hold the background images
this.stage = new Stage();
// Create a Goal object with its initial x and y coordinates
this.goal = new Goal((Math.abs(rng.nextInt()) % (this.canvasWidth)),
(Math.abs(rng.nextInt()) % this.canvasHeight));
// Create a Player object with its initial x and y coordinates
this.player = new Player((Math.abs(rng.nextInt()) % (this.canvasWidth)),
(Math.abs(rng.nextInt()) % this.canvasHeight));
// Create the Enemy objects, each with a reference to this (GameManager) object
// and their initial x and y coordinates.
this.numEnemies = maxEnemies;
this.enemies = new Enemy[this.numEnemies];
for (int i = 0; i < this.numEnemies; i++) {
this.enemies[i] = new Enemy(this, Math.abs(rng.nextInt()) % (this.canvasWidth),
Math.abs(rng.nextInt()) % this.canvasHeight);
}
this.gameGraphics = getGraphics();
this.canvasGraphics = this.canvas.getGraphics();
this.continueGame = true;
long gameStartTime=System.nanoTime();
while (this.continueGame) {
updateCanvas();
}
this.stage.setGameOverBackground();
double gameTime=(System.nanoTime()-gameStartTime)/1000000000.0;
updateCanvas();
this.gameGraphics.setFont(new Font(this.gameGraphics.getFont().getFontName(), Font.PLAIN, 50));
if (gameTime<1)
this.gameGraphics.drawString("Oops! Better luck next time...", this.canvasWidth/3, this.canvasHeight/2 - 50);
else
this.gameGraphics.drawString("You survived " + String.format("%.1f", gameTime)+ " seconds with "+this.numEnemies+" enemies!",
this.canvasWidth/4, this.canvasHeight/2 - 50);
return;
}
public void updateCanvas() {
long start = System.nanoTime();
this.goal.performAction();
// If the player is alive, this should move the player in the direction of the
// key that has been pressed
// Note: See keyPressed and keyReleased methods in the GameManager class.
this.player.performAction();
// If the enemy is alive, the enemy must move towards the Player. The Player object
// is obtained via the GameManager object that is given at the time of creating an Enemy
// object.
// Note: The amount that the enemy moves by must be much smaller than that of
// the player above or else the game becomes too hard to play.
for (int i = 0; i < this.numEnemies; i++) {
this.enemies[i].performAction();
}
if ((Math.abs(this.goal.getX() - this.player.getX()) < (this.goal.getCurrentImage().getWidth() / 2))
&& (Math.abs(this.goal.getY() - this.player.getY()) < (this.goal.getCurrentImage().getWidth() / 2))) {
for (int i = 0; i < this.numEnemies; i++) {
// Sets the image of the enemy to the "dead" image and sets its status to
// indicate dead
this.enemies[i].die();
}
// Sets the background of the stage to the finished game background.
this.stage.setGameOverBackground();
this.continueGame = false;
}
// If an enemy is close to the player or the goal, the player and goal die
int j = 0;
while (j < this.numEnemies) {
if ((Math.abs(this.player.getX() - this.enemies[j].getX()) < (this.player.getCurrentImage().getWidth() / 2))
&& (Math.abs(this.player.getY() - this.enemies[j].getY()) < (this.player.getCurrentImage().getWidth()
/ 2))) {
this.player.die();
this.goal.die();
this.stage.setGameOverBackground();
j = this.numEnemies;
this.continueGame = false;
}
else if ((Math.abs(this.goal.getX() - this.enemies[j].getX()) < (this.goal.getCurrentImage().getWidth() / 2))
&& (Math.abs(this.goal.getY() - this.enemies[j].getY()) < (this.goal.getCurrentImage().getWidth()
/ 2))) {
this.player.die();
this.goal.die();
this.stage.setGameOverBackground();
j = this.numEnemies;
this.continueGame = false;
}
j++;
}
try {
// Draw stage
this.canvasGraphics.drawImage(stage.getCurrentImage(), 0, 0, null);
// Draw goal
this.canvasGraphics.drawImage(this.goal.getCurrentImage(),
this.goal.getX() - (this.goal.getCurrentImage().getWidth() / 2),
this.goal.getY() - (this.goal.getCurrentImage().getHeight() / 2), null);
// Draw player
this.canvasGraphics.drawImage(player.getCurrentImage(),
this.player.getX() - (this.player.getCurrentImage().getWidth() / 2),
this.player.getY() - (this.player.getCurrentImage().getHeight() / 2), null);
// Draw enemies
for (int i = 0; i < this.numEnemies; i++) {
this.canvasGraphics.drawImage(this.enemies[i].getCurrentImage(),
this.enemies[i].getX() - (this.enemies[i].getCurrentImage().getWidth() / 2),
this.enemies[i].getY() - (this.enemies[i].getCurrentImage().getHeight() / 2), null);
}
} catch (Exception e) {
System.err.println(e.getMessage());
}
// Draw everything.
this.gameGraphics.drawImage(this.canvas, this.borderLeft, this.borderTop, this);
long end = System.nanoTime();
this.gameGraphics.setFont(new Font(this.gameGraphics.getFont().getFontName(), Font.PLAIN, 15));
this.gameGraphics.drawString("FPS: " + String.format("%2d", (int) (1000000000.0 / (end - start))),
this.borderLeft + 50, this.borderTop + 75);
return;
}
public Player getPlayer() {
return this.player;
}
public void keyPressed(KeyEvent ke) {
// Below, the setKey method is used to tell the Player object which key is
// currently pressed.
// The Player object must keep track of the pressed key and use it for
// determining the direction
// to move.
// Important: The setKey method in Player must not move the Player.
if (ke.getKeyCode() == KeyEvent.VK_LEFT)
this.player.setKey('L', true);
if (ke.getKeyCode() == KeyEvent.VK_RIGHT)
this.player.setKey('R', true);
if (ke.getKeyCode() == KeyEvent.VK_UP)
this.player.setKey('U', true);
if (ke.getKeyCode() == KeyEvent.VK_DOWN)
this.player.setKey('D', true);
if (ke.getKeyCode() == KeyEvent.VK_ESCAPE)
this.continueGame = false;
return;
}
#Override
public void keyReleased(KeyEvent ke) {
// Below, the setKey method is used to tell the Player object which key is
// currently released.
// The Player object must keep track of the pressed key and use it for
// determining the direction
// to move.
// Important: The setKey method in Player must not move the Player.
if (ke.getKeyCode() == KeyEvent.VK_LEFT)
this.player.setKey('L', false);
if (ke.getKeyCode() == KeyEvent.VK_RIGHT)
this.player.setKey('R', false);
if (ke.getKeyCode() == KeyEvent.VK_UP)
this.player.setKey('U', false);
if (ke.getKeyCode() == KeyEvent.VK_DOWN)
this.player.setKey('D', false);
return;
}
#Override
public void keyTyped(KeyEvent ke) {
return;
}
}
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import java.util.*;
public class Goal {
private int x;
private int y;
private BufferedImage imageCurrent;
private BufferedImage imageRunning;
private BufferedImage imageOver;
private int stepSize;
private Random rng; // Tip: Code that students write must not use randomness
public Goal(int x, int y) {
try {
this.imageRunning = ImageIO.read(new File("goal-alive.png"));
this.imageOver = ImageIO.read(new File("goal-dead.png"));
} catch (IOException e) {
e.printStackTrace();
}
this.x = x;
this.y = y;
this.stepSize = 10;
this.rng = new Random(x + y); // Tip: Code that students write (elsewhere) must not use any randomness.
this.imageCurrent = this.imageRunning;
return;
}
public void performAction() {
// The code below shows how the Goal can be moved by manipulating its x and y
// coordinates.
// Tip: Code that students write (elsewhere) must not use any randomness.
this.x += this.rng.nextInt() % stepSize;
this.y += this.rng.nextInt() % stepSize;
return;
}
public int getY() {
return this.y;
}
public int getX() {
return this.x;
}
public BufferedImage getCurrentImage() {
return this.imageCurrent;
}
public void die() {
this.imageCurrent = this.imageOver;
return;
}
}
import java.awt.Image;
public class Enemy {
private Image CurrentImage;
private int x;
private int y;
public Enemy(GameManager gameManager, int x, int y) {
}
public void performAction() {
}
public void die() {
}
public int getX() {
return this.x;
}
public int getY() {
return this.y;
}
public Image getCurrentImage() {
return CurrentImage;
}
}
import java.awt.Dimension;
public class Player {
private Dimension CurrentImage;
private int x;
private int y;
public Player(int x1, int y1) {
}
public void performAction() {
}
public int getX() {
return this.x;
}
public int getY() {
return this.y;
}
public Dimension getCurrentImage() {
return CurrentImage;
}
public void die() {
}
public void setKey(char c, boolean b) {
}
}
import java.awt.Image;
public class Stage {
public void setGameOverBackground() {
}
public Image getCurrentImage() {
return null;
}
}
Player.getCurrentImage() returns a Dimension, not an Image.
I'm developing a Java game just for study purposes.
I want the player to select the object. The selected object can move, but the others (non-selected objects) must not move.
Game.java:
import javax.swing.JFrame;
public class Game {
public static void main(String[] args) {
JFrame frame = new JFrame("Kibe");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(new GamePanel());
frame.pack();
frame.setVisible(true);
}
}
GamePanel.java:
import javax.swing.JPanel;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import java.util.*;
public class GamePanel extends JPanel implements Runnable, KeyListener {
// fields
public static final int WIDTH = 640, HEIGHT = 480;
private Thread thread;
private boolean running;
private int FPS = 30;
private double averageFPS;
private BufferedImage image;
private Graphics2D g;
public ArrayList<Circle> circles;
private int selectedCircle;
// constructor
public GamePanel(){
super();
setPreferredSize(new Dimension(WIDTH, HEIGHT));
setFocusable(true);
requestFocus();
}
// functions
public void addNotify(){
super.addNotify();
if(thread == null){
thread = new Thread(this);
thread.start();
}
addKeyListener(this);
}
public void run(){
running = true;
image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
g = (Graphics2D) image.getGraphics();
circles = new ArrayList<Circle>();
long startTime;
gameUpdate();
gameRender();
gameDraw();
long URDTimeMillis;
long waitTime;
long totalTime = 0;
int frameCount = 0;
int maxFrameCount = 30;
long targetTime = 1000 / FPS;
while(running){ // the game loop
startTime = System.nanoTime();
gameUpdate();
gameRender();
gameDraw();
URDTimeMillis = (System.nanoTime() - startTime) / 1000000;
waitTime = targetTime - URDTimeMillis;
try{
Thread.sleep(waitTime);
}catch(Exception e){
e.printStackTrace();
}
frameCount++;
if(frameCount == maxFrameCount){
averageFPS = 1000.0 / ((totalTime / frameCount) / 1000000);
frameCount = 0;
totalTime = 0;
}
}
}
private void gameUpdate(){
circles.get(selectedCircle).update();
}
private void gameRender(){
g.setColor(Color.BLACK);
g.fillRect(0, 0, WIDTH, HEIGHT);
for(int i = 0; i < circles.size(); i++){
circles.get(i).draw(g);
}
}
private void gameDraw(){
Graphics g2 = this.getGraphics();
g2.drawImage(image, 0, 0, null);
g2.dispose();
}
// key functions
public void keyTyped(KeyEvent e){
int keyCode = e.getKeyCode();
}
public void keyPressed(KeyEvent e){
int keyCode = e.getKeyCode();
if(keyCode == KeyEvent.VK_SPACE){
circles.add(new Circle());
}
else if(keyCode == KeyEvent.VK_Z){
selectedCircle = (selectedCircle + 1) % circles.size();
}
}
public void keyReleased(KeyEvent e){
int keyCode = e.getKeyCode();
}
}
Circle.java:
import java.awt.*;
public class Circle {
// fields
private double x;
private double y;
private int speed;
private int dx;
private int dy;
private int r;
private boolean up;
private boolean down;
private boolean left;
private boolean right;
private Color color;
// constructor
public Circle(){
x = Math.random() * GamePanel.WIDTH / 2 + GamePanel.HEIGHT / 4;
y = -r;
speed = 5;
dx = 0;
dy = 0;
r = 5;
color = Color.WHITE;
}
// functions
public void setUp(boolean b) { up = b; }
public void setDown(boolean b) { down = b; }
public void setLeft(boolean b) { left = b; }
public void setRight(boolean b ) { right = b; }
public void update(){
if(up)
dy = -speed;
else
dy = 0;
if(down)
dy = speed;
if(left)
dx = -speed;
else
dx = 0;
if(right)
dx = speed;
color = Color.RED;
}
public void draw(Graphics2D g){
g.setColor(Color.WHITE);
g.fillOval((int) x - r, (int) y - r, 2 * r, 2 * r);
}
}
The error when I try to run:
Exception in thread "Thread-2" java.lang.IndexOutOfBoundsException: Index: 0, Si
ze: 0
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at GamePanel.gameUpdate(GamePanel.java:102)
at GamePanel.run(GamePanel.java:51)
at java.lang.Thread.run(Unknown Source)
The error message is clear:
IndexOutOfBoundsException: Index: 0, Size: 0
You're trying to get the 0th item out of an ArrayList whose size is 0, meaning there is no 0th item (first item).
This line:
private void gameUpdate(){
circles.get(selectedCircle).update(); // here ****
}
This is happening at game start before the circles ArrayList holds any Circle objects.
One solution is to do a validity check before trying to extract something that doesn't exist, e.g.,
private void gameUpdate() {
if (selectedCircle < circles.size()) {
circles.get(selectedCircle).update();
}
}
Of course this won't prevent the other problems that you will soon encounter with this code including
negative Thread.sleep times
Drawing with a Graphics object obtained by calling getGraphics() on a Swing component
Making Swing calls directly from a background thread
As you can see I added the a mouse listener to the game.
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
public class Game implements Runnable
{
private Display display;
public int width, height;
public String title;
private boolean running = false;
private Thread thread;
private BufferStrategy bs;
private Graphics g;
// States
public static State gameState;
// Input
private InputManager inputManager;
private MouseHandler mouseHandler;
public Game(String title, int width, int height)
{
this.width = width;
this.height = height;
this.title = title;
inputManager = new InputManager();
mouseHandler = new MouseHandler();
}
/**
* Initializes all of the graphics
*/
private void initialize()
{
display = new Display(title, width, height);
display.getFrame().addKeyListener(inputManager);
display.getFrame().addMouseListener(mouseHandler);
Assets.loadAssets();
gameState = new GameState(this, 1);
State.setState(gameState);
}
/**
* Updates everything in the game loop
*/
private void update()
{
if (State.getState() != null)
State.getState().update();
}
private void render()
{
bs = display.getCanvas().getBufferStrategy();
// If this is the first time running initialize the buffer strategy
if (bs == null)
{
display.getCanvas().createBufferStrategy(3);
return;
}
g = bs.getDrawGraphics();
// Clear the screen
g.clearRect(0, 0, width, height);
// Drawing
if (State.getState() != null)
State.getState().render(g);
// End drawing
bs.show();
g.dispose();
}
public void run()
{
initialize();
// Updates the game loop 60 times every 1 second = 1,000,000,000
// nanoseconds
int fps = 60;
double timePerUpdate = 1000000000 / fps;
double timeElapsed = 0;
long now;
// Current time of computer in nanoseconds
long lastTime = System.nanoTime();
// Game loop
while (running)
{
now = System.nanoTime();
timeElapsed += (now - lastTime) / timePerUpdate;
lastTime = now;
if (timeElapsed >= 1)
{
update();
render();
timeElapsed--;
}
}
stop();
}
public synchronized void start()
{
// Do not make a new thread if it is already running
if (running)
return;
// Starts the game
running = true;
thread = new Thread(this); // this = Game class
thread.start(); // Goes to run
}
public synchronized void stop()
{
// In case stop gets called and it is already not running
if (!running)
return;
// Stops the game
running = false;
try
{
thread.join();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
public InputManager getInputManager()
{
return inputManager;
}
public MouseHandler getMouseHandler()
{
return mouseHandler;
}
public static void main(String[] args)
{
Game game = new Game("Game", 1024, 768);
game.start();
}
}
This is my mouse adapter class, basically all I want is the x,y coordinates of where the mouse is pressed
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class MouseHandler extends MouseAdapter
{
public int x, y;
public MouseHandler()
{
}
public void MousePressed(MouseEvent e)
{
x = e.getX();
y = e.getY();
}
}
When I try to get the X, and Y coordinates they are always 0 instead of where the mouse actually clicked. I have no clue why.
public int x, y;
int variables are always initialized to 0.
public void MousePressed(MouseEvent e)
Method names are case sensitive.
Your code is never executed since the method to override should be mousePressed(...). Fix the typo in your code.
Always use code like:
#Override
public void mousePressed(MouseEvent e)
Then if you make a typo the compiler will tell you.
When I try to get the X, and Y coordinates they are always 0
Since your code is never executed the default value is returned.
I have it set up so all it does is draw a light gray background and some rectangles to create a grid. My next goal was to assign two images so I can default the grid to load as one, and then eventually add some listeners to let me change them to the other.
However, when I assign the image (png format) to the Image object through an ImageIcon (created and assigned previously and creating a new one on the spot were tested) it causes the default background color to be shown, and nothing drawn.
This occurs no matter where I move the assignments to except if I put the assignment into the draw method itself.
The image that I'm trying to use works fine, I pulled it straight from a previously working project, the location hadn't changed. But to be sure, I copied the address and put it in again.
Here is the code (The assignment causing the issue is in Block):
Main:
package BLURGpackage;
import javax.swing.JFrame;
public class Main extends JFrame
{
private final int FRAME_WIDTH = 1200, FRAME_HEIGHT = 1034; // add 34 onto height
//to show all of the panel
public Main()
{
setSize(FRAME_WIDTH, FRAME_HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
setVisible(true);
Panel panel = new Panel();
add(panel);
}
public static void main(String[] args)
{
Main m = new Main();
}
}
Panel:
package BLURGpackage;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
public class Panel extends JPanel implements Runnable
{
public final static int PANEL_WIDTH = 1200, PANEL_HEIGHT = 1000;
private Dimension panelDimension = new Dimension(PANEL_WIDTH, PANEL_HEIGHT);
private Thread panelThread = null;
private boolean threadRunning = false;
private Image dbi = null;
private Graphics dbg = null;
Grid grid;
private int mouseX = 0, mouseY = 0;
// ============ CHANGE THESE TO CHANGE THE LOCATION OF WHERE THE X AND Y COORDS ARE PRINTED ON THE SCREEN =============
private int printXCoordsX = 10; // X-Coordinate for where to print the current mouse X location
private int printXCoordsY = 855; // Y-Coordinate for where to print the current mouse X location
private int printYCoordsX = printXCoordsX; // X-Coordinate for where to print the current mouse Y location
private int printYCoordsY = printXCoordsY + 15; // Y-Coordinate for where to print the current mouse Y location
// ====================================================================================================================
public Panel()
{
grid = new Grid();
setPreferredSize(panelDimension);
setBackground(Color.LIGHT_GRAY);
// ===== Listeners ==========
addMouseMotionListener(new MouseMotionAdapter()
{
public void mouseMoved(MouseEvent e)
{
mouseX = e.getX();
mouseY = e.getY();
}
});
// ====== Start ============= (if startPanel is before listeners, dbi is null... dunno why)
startPanel();
}
private void startPanel()
{
if(panelThread == null || threadRunning == false)
{
panelThread = new Thread(this);
threadRunning = true;
panelThread.start();
}
else
System.out.println("panelThread is NOT null on startup");
}
#Override
public void run()
{
while(threadRunning)
{
update();
render();
paintScreen();
}
}
public void update()
{
// Logic here
}
public void render()
{
if(dbi == null)
{
dbi = createImage(PANEL_WIDTH, PANEL_HEIGHT);
if(dbi == null)
System.err.println("dbi is NULL");
else
{
dbg = dbi.getGraphics();
}
}
dbg.setColor(Color.LIGHT_GRAY);
dbg.fillRect(0, 0, PANEL_WIDTH, PANEL_HEIGHT);
draw(dbg);
}
public void paintScreen()
{
Graphics g;
try
{
g = this.getGraphics();
if(dbi != null && g != null)
{
g.drawImage(dbi, 0, 0, null);
}
Toolkit.getDefaultToolkit().sync();
g.dispose();
}catch(Exception e)
{
e.printStackTrace();
}
}
public void draw(Graphics g)
{
g.setColor(Color.BLACK);
g.drawString("X: "+mouseX, printXCoordsX, printXCoordsY);
g.drawString("Y: "+mouseY, printYCoordsX, printYCoordsY);
// Allow the Grid to draw
grid.draw(g);
}
}
Grid:
package BLURGpackage;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
public class Grid
{
// ======== CHANGE THESE VARIABLES TO CHANGE THE SIZE OF THE GRID =============
public final static int GRID_ROWS = 21, GRID_COLUMNS = 25;
private final int RECT_WIDTH = 48, RECT_HEIGHT = 40;
private final int NUM_BLOCKS = GRID_ROWS*GRID_COLUMNS;
/*public final static int GRID_ROWS = 25, GRID_COLUMNS = 25;
private final int RECT_WIDTH = Panel.PANEL_WIDTH / GRID_ROWS; // 1200 / 25 = 48 px width per rect
private final int RECT_HEIGHT = Panel.PANEL_HEIGHT / GRID_COLUMNS; // 1000 / 25 = 40 px height per rect
private final int NUM_BLOCKS = GRID_ROWS*GRID_COLUMNS;*/
// ============================================================================
private Block[] blockArray;
private int[] blockSelectArray; // numbers for which block is selected. Feed in through file reader
public Grid()
{
// ===== FOR TESTING ONLY======
blockArray = new Block[NUM_BLOCKS];
blockSelectArray = new int[NUM_BLOCKS];
for(int i=0; i < NUM_BLOCKS; i++)
{
blockSelectArray[i] = 0;
}
// ============================
loadBlocks();
}
private void loadBlocks()
{
int x, y;
x = y = 0;
for(int i = 0; i < NUM_BLOCKS; i++)
{
if(x >= Panel.PANEL_WIDTH) // if x hits right boundary, reset x and increment y by the px height of a single block
{
x = 0;
y += RECT_HEIGHT;
}
blockArray[i] = new Block(blockSelectArray[i], x, y);
x += RECT_WIDTH;
}
}
public void draw(Graphics g)
{
g.setColor(Color.BLACK);
for(int i=0;i<NUM_BLOCKS;i++)
{
g.drawRect(blockArray[i].getBlockX(), blockArray[i].getBlockY(), RECT_WIDTH, RECT_HEIGHT);
blockArray[i].draw(g);
}
}
}
Block:
package BLURGpackage;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import javax.swing.ImageIcon;
public class Block
{
private Image blockImage = null;
private Image DIRT_IMG = new ImageIcon("C:/Users/Tyler/workspace/IntTut1/src/thejavahub/images/dirt.png").getImage();
// ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ Problem assignment
private Rectangle blockRect = null;
private boolean solid;
private final int RECT_WIDTH = Panel.PANEL_WIDTH / Grid.GRID_ROWS; // 1200 / 25 = 48 px width per rect
private final int RECT_HEIGHT = Panel.PANEL_HEIGHT / Grid.GRID_COLUMNS; // 1000 / 25 = 40 px height per rect
public Block(int blockNum, int x, int y)
{
// switch statement on blockNum for what block
switch(blockNum)
{
default:
System.out.println("Default of switch in Block constrcutor hit");
break;
case 0: // background block
solid = false;
break;
case 1: // dirt block
blockImage = DIRT_IMG; // <---- uses the assigned image --------
solid = true;
break;
}
// set the coordinates of the block
blockRect = new Rectangle(x, y, RECT_WIDTH, RECT_HEIGHT);
}
public void draw(Graphics g)
{
// draw the image here (.... g.drawImage(blockImage, blockRect.x, blockRect.y, null); )
g.drawImage(blockImage, blockRect.x, blockRect.y, null);
}
// ==== GETTERS AND SETTERS ===
public int getBlockX()
{
return this.blockRect.x;
}
public void setBlockX(int x)
{
this.blockRect.x = x;
}
public int getBlockY()
{
return this.blockRect.y;
}
public void setBlockY(int y)
{
this.blockRect.y = y;
}
public boolean isSolid() {
return solid;
}
public void setSolid(boolean solid) {
this.solid = solid;
}
}
Some Points:
Call frame.setVisible(true) in the end after adding all the components.
Use frame.pack() instead of frame.setSize() that fits the components as per component's preferred size.
Override getPreferredSize() to set the preferred size of the JPanel in case of custom painting.
Use Swing Timer instead of Thread that is most suitable for swing application in two ways:
To perform a task once, after a delay.
To perform a task repeatedly.
Read more How to Use Swing Timers
Use SwingUtilities.invokeLater() or EventQueue.invokeLater() to make sure that EDT is initialized properly.
Read more
Why to use SwingUtilities.invokeLater in main method?
SwingUtilities.invokeLater
Should we use EventQueue.invokeLater for any GUI update in a Java desktop application?
sample code:
private Timer timer;
...
// 1 second delay
timer = new javax.swing.Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
// next call
}
});
timer.setRepeats(true);
timer.start();
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Main m = new Main();
}
});
}
class MyRoll extends JPanel {
// override paintComponent in case of custom painting
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
...
}
#Override
public Dimension getPreferredSize() {
return new Dimension(..., ...);
}
}
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 9 years ago.
Improve this question
I created a GUI named Menu class for my Start, Help and Exit button. my problem is my game won't start, it hangs everytime I press the Start button. Can someone check my error and explain it to me because its my case study at school.
package spaceSip;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
public class Menu extends JFrame implements ActionListener
{
private JLabel titleL;
private JButton startB, helpB, exitB;
static JFrame frame1 = new JFrame();
public Menu()
{
frame1.setSize(500,250);
Container mainP = frame1.getContentPane();
mainP.setLayout(null);
titleL = new JLabel("WELCOME");
startB = new JButton("Start");
helpB = new JButton("Help");
exitB = new JButton("Exit");
mainP.add(titleL);
titleL.setFont(new Font("Chiller",Font.BOLD,50));
titleL.setBounds(100, 30, 200, 50);
mainP.add(startB);
startB.setMnemonic(KeyEvent.VK_S);
startB.setBounds(200, 80, 100, 20);
mainP.add(helpB);
helpB.setMnemonic(KeyEvent.VK_H);
helpB.setBounds(200, 100, 100, 20);
mainP.add(exitB);
exitB.setMnemonic(KeyEvent.VK_E);
exitB.setBounds(200, 120, 100, 20);
startB.addActionListener(this);
helpB.addActionListener(this);
exitB.addActionListener(this);
frame1.setVisible(true);
frame1.setResizable(false);
}
public void actionPerformed(ActionEvent e)
{
String key = e.getActionCommand();
if(key == "Start")
{
frame1.dispose();
new SpaceShipMain();
}
else if(key == "Help")
{
}
else
System.exit(0);
}
public static void main(String[]args)
{
new Menu();
}
}
package spaceSip;
import javax.swing.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public class SpaceShipMain implements MouseListener
{
private JFrame background;
private SpaceShipPanel back;
public static boolean paused;
public static boolean crashed;
public static boolean started;
public static boolean playedOnce;
public boolean goingUp;
private double upCount;
public static int distance;
public static int maxDistance;
public final int XPOS;
public final int NUMRECS;
public final int RECHEIGHT;
public final int RECWIDTH;
private int moveIncrement;
private int numSmoke;
private ArrayList<SpaceShipImage> toprecs;
private ArrayList<SpaceShipImage> bottomrecs;
private ArrayList<SpaceShipImage> middlerecs;
private ArrayList<SpaceShipImage> smoke;
private SpaceShipImage helicopter;
public SpaceShipMain()
{
NUMRECS = 100;
RECHEIGHT = 70;
RECWIDTH = 30;
XPOS = 200;
playedOnce = false;
maxDistance = 0;
load(new File("C:\\Users/Travelmate/workspace/GAME/src/spaceSip/Best.txt"));
initiate();
}
public void load(File file)
{
try
{
Scanner reader = new Scanner(file);
while(reader.hasNext())
{
int value = reader.nextInt();
if(value > maxDistance)
maxDistance = value;
}
}
catch(IOException i )
{
System.out.println("Error. "+i);
}
}
public void save()
{
FileWriter out;
try
{
out = new FileWriter("C:\\Users/Travelmate/workspace/GAME/src/spaceSip/Best.txt");
out.write("" + maxDistance);
out.close();
}
catch(IOException i)
{
System.out.println("Error: "+i.getMessage());
}
}
public void initiate()
{
if(!playedOnce)
{
background = new JFrame("Space Ship Game");
background.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //closes the program when the window is closed
background.setResizable(false); //don't allow the user to resize the window
background.setSize(new Dimension(800,500));
background.setVisible(true);
back = new SpaceShipPanel("C:\\Users/Travelmate/workspace/GAME/src/spaceSip/starfield.jpg");
background.add(back);
back.addMouseListener(this);
}
playedOnce = true;
goingUp = false;
paused = false;
crashed = false;
started = false;
distance = 0;
upCount = 0;
moveIncrement = 2;
numSmoke = 15;
toprecs = new ArrayList<SpaceShipImage>();
middlerecs = new ArrayList<SpaceShipImage>();
bottomrecs = new ArrayList<SpaceShipImage>();
smoke = new ArrayList<SpaceShipImage>();
helicopter = new SpaceShipImage("C:\\Users/Travelmate/workspace/GAME/src/spaceSip/rocketship.GIF",XPOS,200);
for(int x = 0; x < NUMRECS; x++)
toprecs.add(new SpaceShipImage("C:\\Users/Travelmate/workspace/GAME/src/spaceSip/rec2.JPG",RECWIDTH*x,5));
for(int x = 0; x < NUMRECS; x++)
bottomrecs.add(new SpaceShipImage("C:\\Users/Travelmate/workspace/GAME/src/spaceSip/rec2.JPG",RECWIDTH*x,410));
middlerecs.add(new SpaceShipImage("C:\\Users/Travelmate/workspace/GAME/src/spaceSip/asteroid2.jpg",1392,randomMidHeight()));
middlerecs.add(new SpaceShipImage("C:\\Users/Travelmate/workspace/GAME/src/spaceSip/asteroid2.jpg",1972,randomMidHeight()));
drawRectangles();
}
public void drawRectangles()
{
long last = System.currentTimeMillis();
long lastCopter = System.currentTimeMillis();
long lastSmoke = System.currentTimeMillis();
long lastSound = System.currentTimeMillis();
int firstUpdates = 0;
double lastDistance = (double)System.currentTimeMillis();
while(true)
{
if(!paused && !crashed && started && (double)System.currentTimeMillis() - (double)(2900/40) > lastDistance)
{
lastDistance = System.currentTimeMillis();
distance++;
}
if(!paused && !crashed && started && System.currentTimeMillis() - 10 > lastCopter)
{
lastCopter = System.currentTimeMillis();
updateCopter();
updateMiddle();
}
if(!paused && !crashed && started && System.currentTimeMillis() - 100 > last)
{
last = System.currentTimeMillis();
updateRecs();
}
if(!paused && !crashed && started && System.currentTimeMillis() - 75 > lastSmoke)
{
lastSmoke = System.currentTimeMillis();
if (firstUpdates < numSmoke)
{
firstUpdates++;
smoke.add(new SpaceShipImage("C:\\Users/Travelmate/workspace/GAME/src/spaceSip/smoke.GIF",187,helicopter.getY()));
for(int x = 0; x < firstUpdates; x++)
smoke.set(x,new SpaceShipImage("C:\\Users/Travelmate/workspace/GAME/src/spaceSip/smoke.GIF",smoke.get(x).getX() - 12, smoke.get(x).getY()));
}
else
{
for(int x = 0; x < numSmoke - 1; x++)
smoke.get(x).setY(smoke.get(x+1).getY());
smoke.set(numSmoke - 1,new SpaceShipImage("C:\\Users/Travelmate/workspace/GAME/src/spaceSip/smoke.GIF",187,helicopter.getY()));
}
}
back.updateImages(middlerecs,helicopter,smoke);
}
}
public void updateRecs()
{
for(int x = 0; x < (NUMRECS - 1); x++) //move all but the last rectangle 1 spot to the left
{
toprecs.set(x,new SpaceShipImage("C:\\Users/Travelmate/workspace/GAME/src/spaceSip/rec2.JPG",RECWIDTH*x,toprecs.get(x+1).getY()));
bottomrecs.set(x,new SpaceShipImage("C:\\Users/Travelmate/workspace/GAME/src/spaceSip/rec2.JPG",RECWIDTH*x,bottomrecs.get(x+1).getY()));
}
}
public void randomDrop()
{
toprecs.get(26).setY(toprecs.get(26).getY() + (463 - bottomrecs.get(26).getY()));
bottomrecs.get(26).setY(463);
}
public int randomMidHeight()
{
int max = 10000;
int min = 0;
for(int x = 0; x < NUMRECS; x++)
{
if(toprecs.get(x).getY() > min)
min = (int)toprecs.get(x).getY();
if(bottomrecs.get(x).getY() < max)
max = (int)bottomrecs.get(x).getY();
}
min += RECHEIGHT;
max -= (RECHEIGHT + min);
return min + (int)(Math.random() * max);
}
//moves the randomly generated middle rectangles
public void updateMiddle()
{
if(middlerecs.get(0).getX() > -1 * RECWIDTH)
{
middlerecs.set(0,new SpaceShipImage("C:\\Users/Travelmate/workspace/GAME/src/spaceSip/asteroid.gif",middlerecs.get(0).getX() - (RECWIDTH/5), middlerecs.get(0).getY()));
middlerecs.set(1,new SpaceShipImage("C:\\Users/Travelmate/workspace/GAME/src/spaceSip/asteroid.gif",middlerecs.get(1).getX() - (RECWIDTH/5), middlerecs.get(1).getY()));
}
else
{
middlerecs.set(0,new SpaceShipImage("C:\\Users/Travelmate/workspace/GAME/src/spaceSip/asteroid.gif",middlerecs.get(1).getX() - (RECWIDTH/5), middlerecs.get(1).getY()));
middlerecs.set(1,new SpaceShipImage("C:\\Users/Travelmate/workspace/GAME/src/spaceSip/asteroid.gif",middlerecs.get(0).getX() + 580,randomMidHeight()));
}
}
public boolean shoot()
{
for(int x = 3; x <= 7; x++)
if(helicopter.getY() >= bottomrecs.get(x).getY())
return true;
for(int y = 3; y <= 7; y++)
if(helicopter.getY() <= toprecs.get(y).getY())
return true;
for(int z = 0; z <= 1; z++)
if(isInMidRange(z))
return true;
return false;
}
public boolean isInMidRange(int num)
{
Rectangle middlecheck = new Rectangle((int)middlerecs.get(num).getX(),(int)middlerecs.get(num).getY(),RECWIDTH,RECHEIGHT);
Rectangle coptercheck = new Rectangle((int)helicopter.getX(),(int)helicopter.getY(),70,48); //asteroid X and y bump
return middlecheck.intersects(coptercheck);
}
public void crash()
{
crashed = true;
if(distance > maxDistance)
{
maxDistance = distance;
save();
}
int reply = JOptionPane.showConfirmDialog(null, " RESTART ?", "GAME OVER", JOptionPane.YES_NO_OPTION);
if(reply == JOptionPane.YES_OPTION)
initiate();
else
System.exit(0);
initiate();
}
//moves the spaceship
public void updateCopter()
{
upCount += .10;
if(goingUp)
{
if(upCount < 3.5)
helicopter.setPosition(XPOS,(double)(helicopter.getY() - (.3 + upCount)));
else
helicopter.setPosition(XPOS,(double)(helicopter.getY() - (1.2 + upCount)));
helicopter.setImage("C:\\Users/Travelmate/workspace/GAME/src/spaceSip/rocketship.GIF");
}
else
{
if(upCount < 1)
helicopter.setPosition(XPOS,(double)(helicopter.getY() + upCount));
else
helicopter.setPosition(XPOS,(double)(helicopter.getY() + (1.2 + upCount)));
helicopter.setImage("C:\\Users/Travelmate/workspace/GAME/src/spaceSip/rocketship.GIF");
}
if(shoot())
crash();
}
//Called when the mouse exits the game window
public void mouseExited(MouseEvent e)
{
paused = true;
}
//Called when the mouse enters the game window
public void mouseEntered(MouseEvent e)
{
}
//Called when the mouse is released
public void mouseReleased(MouseEvent e)
{
goingUp = false;
upCount = -1;
if(paused)
paused = false;
}
//Called when the mouse is pressed
public void mousePressed(MouseEvent e)
{
if (!started)
started = true;
goingUp = true;
upCount = 0;
}
//Called when the mouse is released
public void mouseClicked(MouseEvent e)
{
}
}
package spaceSip;
import java.awt.Image;
import javax.swing.ImageIcon;
public class SpaceShipImage
{
private Image image; //The picture
private double x; //X position
private double y; //Y position
//Construct a new Moving Image with image, x position, and y position given
public SpaceShipImage(Image img, double xPos, double yPos)
{
image = img;
x = xPos;
y = yPos;
}
//Construct a new Moving Image with image (from file path), x position, and y position given
public SpaceShipImage(String path, double xPos, double yPos)
{
this(new ImageIcon(path).getImage(), xPos, yPos);
//easiest way to make an image from a file path in Swing
}
//They are set methods. I don't feel like commenting them.
public void setPosition(double xPos, double yPos)
{
x = xPos;
y = yPos;
}
public void setImage(String path)
{
image = new ImageIcon(path).getImage();
}
public void setY(double newY)
{
y = newY;
}
public void setX(double newX)
{
x = newX;
}
//Get methods which I'm also not commenting
public double getX()
{
return x;
}
public double getY()
{
return y;
}
public Image getImage()
{
return image;
}
}
package spaceSip;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.util.ArrayList;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
class SpaceShipPanel extends JPanel
{
private Image background;
private ArrayList<SpaceShipImage> middle;
private SpaceShipImage copter;
private ArrayList<SpaceShipImage> smoke;
//Constructs a new ImagePanel with the background image specified by the file path given
public SpaceShipPanel(String img)
{
this(new ImageIcon(img).getImage());
//The easiest way to make images from file paths in Swing
}
//Constructs a new ImagePanel with the background image given
public SpaceShipPanel(Image img)
{
background = img;
Dimension size = new Dimension(img.getWidth(null), img.getHeight(null));
//Get the size of the image
//Thoroughly make the size of the panel equal to the size of the image
//(Various layout managers will try to mess with the size of things to fit everything)
setPreferredSize(size);
setMinimumSize(size);
setMaximumSize(size);
setSize(size);
middle = new ArrayList<SpaceShipImage>();
smoke = new ArrayList<SpaceShipImage>();
}
//This is called whenever the computer decides to repaint the window
//It's a method in JPanel that I've overwritten to paint the background and foreground images
public void paintComponent(Graphics g)
{
//Paint the background with its upper left corner at the upper left corner of the panel
g.drawImage(background, 0, 0, null);
//Paint each image in the foreground where it should go
for(SpaceShipImage img : middle)
g.drawImage(img.getImage(), (int)(img.getX()), (int)(img.getY()), null);
for(SpaceShipImage img : smoke)
g.drawImage(img.getImage(), (int)(img.getX()), (int)(img.getY()), null);
if(copter != null)
g.drawImage(copter.getImage(), (int)(copter.getX()), (int)(copter.getY()), null);
drawStrings(g);
}
public void drawStrings(Graphics g)
{
g.setColor(Color.WHITE);
g.setFont(new Font("Arial",Font.BOLD,20));
g.drawString("Distance: " + SpaceShipMain.distance,30,440);
g.setFont(new Font("Arial",Font.BOLD,20));
if (SpaceShipMain.distance > SpaceShipMain.maxDistance)
g.drawString("Best: " + SpaceShipMain.distance,650,440);
else
g.drawString("Best: " + SpaceShipMain.maxDistance,650,440);
if(SpaceShipMain.paused)
{
g.setFont(new Font("Chiller",Font.BOLD,72));
g.drawString("Paused",325,290);
g.setFont(new Font("Chiller",Font.BOLD,30));
g.drawString("Click to unpause.",320,340);
}
}
//Replaces the list of foreground images with the one given, and repaints the panel
public void updateImages(ArrayList<SpaceShipImage> newMiddle,SpaceShipImage newCopter,ArrayList<SpaceShipImage> newSmoke)
{
copter = newCopter;
middle = newMiddle;
smoke = newSmoke;
repaint(); //This repaints stuff... you don't need to know how it works
}
}
You compare Strings with equals(value equality) not with ==(reference equality). For more information read this previous question How do I compare strings in Java?
As #AndrewThompson always advice don't use NullLayout
Java GUIs might have to work on a number of platforms, on different
screen resolutions & using different PLAFs. As such they are not
conducive to exact placement of components. To organize the
components for a robust GUI, instead use layout managers, or
combinations of
them1, along
with layout padding & borders for white
space2.
As you say that your gui is blocked, that may be cause some of your execution code takes too more time and it's executed in the same thread as gui stuff (The Event Dispatch Thread). As you have a while(true) that's block the gui so use a SwingTimer for execute repeatidly task or if that code that takes long time execute it in a background thread using a Swing Worker. Here you have a complete example. When you perform custom painting you should override paintComponent and in first line you have to call super.paintComponent(..) to follow correct chaining. Read more in Painting in AWT-Swing.
Another error i see is that you are adding components after calling setVisible(true) without calling revalidate() repaint(). So i recommend to first add components to container then call setVisible(true) at final step.