Menu in a simple java game [closed] - java

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.

Related

How do I paint multiple objetcs that move at different speeds in Java?

I am working on homework for class, and its late because I can't seem to understand the material despite all the research that I am doing. I am a beginner and do not know much in the way of java. Also, this is my first post so please be forgiving when you are reading this.
I am building on source code from my textbook, which I updated recently for past homework, but now I am trying to generate a class that draws multiple squares and moves those objects independently and at different speeds. They will all need to rebound off the walls as well. I followed the instructions and created two arrays that will hold the random x and y values between 1 and 10. However, I struggle with arrays and I am sure that I am not doing it correctly. So, I would love some feedback to see if I have it set up correctly.
I have a the jpanel pulling up and drawing, and as long as there is 1 square it is working fine bouncing off the walls, but things change when I draw more than one. The do not move independently and they also share the same speed. Some even disappear from time to time. This has really thrown me off. I appreciate any help!
In short, I am trying to paint new squares that all travel in different directions and at different speeds. Per the instructions we are suppose create and use a two arrays that handle the x and y values.
Here is what I have so far:
public class DotsPanel extends JPanel
{
private int delay = 15;
private final int SIZE = 7, IMAGE_SIZE = 3; // radius of each dot
private Timer timer;
private int x, y, i;
private ArrayList<Point> pointList;
static int [] xarray = new int [1000];
static int [] yarray = new int [1000];
Random rand = new Random();
//-----------------------------------------------------------------
// Constructor: Sets up this panel to listen for mouse events.
//-----------------------------------------------------------------
public DotsPanel()
{
pointList = new ArrayList<Point>();
int [] xarray = new int [1000];
int [] yarray = new int [1000];
timer = new Timer(delay, new ReboundListener());
addMouseListener (new DotsListener());
addMouseMotionListener (new DotsListener());
setBackground(Color.gray);
setPreferredSize(new Dimension(700, 500));
for(int i = 0; i < xarray.length; i++)
{
xarray[i] = rand.nextInt(7);
yarray[i] = rand.nextInt(7);
}
timer.start();
}
//-----------------------------------------------------------------
// Draws all of the dots stored in the list.
//-----------------------------------------------------------------
public void paintComponent(Graphics page)
{
super.paintComponent(page);
page.setColor(Color.BLUE);
for (Point spot : pointList)
{
page.fillRect(spot.x-SIZE, spot.y-SIZE, 25, 25);
page.drawString("Count: " + pointList.size(), 5, 15);
}
}
//*****************************************************************
// Represents the listener for mouse events.
//*****************************************************************
private class DotsListener implements MouseListener, MouseMotionListener
{
//--------------------------------------------------------------
// Adds the current point to the list of points and redraws
// the panel whenever the mouse button is pressed.
//--------------------------------------------------------------
public void mousePressed(MouseEvent event)
{
pointList.add(event.getPoint());
repaint();
}
public void mouseDragged(MouseEvent event)
{
// initially I had two xarray and yarray in here just like in
// mouseClicked
// but it did not change anything when removed
}
//--------------------------------------------------------------
// Provide empty definitions for unused event methods.
//--------------------------------------------------------------
public void mouseClicked(MouseEvent event)
{
xarray[i] = rand.nextInt(7);
yarray[i] = rand.nextInt(7);
}
public void mouseReleased(MouseEvent event) {}
public void mouseEntered(MouseEvent event) {}
public void mouseExited(MouseEvent event) {}
public void mouseMoved(MouseEvent e) {}
}
private class ReboundListener 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 (Point spot : pointList)
{
spot.x += xarray[i];
spot.y += yarray[i];
if (spot.x <= 0 || spot.x >= 700)
xarray[i] = xarray[i] * -1;
if (spot.y <= 0 || spot.y >= 500)
yarray[i] = yarray[i] * -1;
repaint();
}
}
}
}
However, I struggle with arrays and I am sure that I am not doing it correctly.
I wouldn't use Arrays.
Instead, have a Ball object manage its own state. Then you can have different color, speed, size etc for each Ball. Then when the Timer fires you just calculate the new position and repaint the Ball.
Here is an example to get you started:
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;
public class BallAnimation4
{
private static void createAndShowUI()
{
BallPanel panel = new BallPanel();
JFrame frame = new JFrame("BallAnimation4");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( panel );
frame.setSize(800, 600);
frame.setLocationRelativeTo( null );
//frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setVisible( true );
panel.addBalls(5);
panel.startAnimation();
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
class BallPanel extends JPanel implements ActionListener
{
private ArrayList<Ball> balls = new ArrayList<Ball>();
public BallPanel()
{
setLayout( null );
setBackground( Color.BLACK );
}
public void addBalls(int ballCount)
{
Random random = new Random();
for (int i = 0; i < ballCount; i++)
{
Ball ball = new Ball();
ball.setRandomColor(true);
ball.setLocation(random.nextInt(getWidth()), random.nextInt(getHeight()));
ball.setMoveRate(32, 32, 1, 1, true);
// ball.setMoveRate(16, 16, 1, 1, true);
ball.setSize(32, 32);
balls.add( ball );
}
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
for (Ball ball: balls)
{
ball.draw(g);
}
}
public void startAnimation()
{
Timer timer = new Timer(75, this);
timer.start();
}
public void actionPerformed(ActionEvent e)
{
move();
repaint();
}
private void move()
{
for (Ball ball : balls)
{
ball.move(this);
}
}
class Ball
{
public Color color = Color.BLACK;
public int x = 0;
public int y = 0;
public int width = 1;
public int height = 1;
private int moveX = 1;
private int moveY = 1;
private int directionX = 1;
private int directionY = 1;
private int xScale = moveX;
private int yScale = moveY;
private boolean randomMove = false;
private boolean randomColor = false;
private Random myRand = null;
public Ball()
{
myRand = new Random();
setRandomColor(randomColor);
}
public void move(JPanel parent)
{
int iRight = parent.getSize().width;
int iBottom = parent.getSize().height;
x += 5 + (xScale * directionX);
y += 5 + (yScale * directionY);
if (x <= 0)
{
x = 0;
directionX *= (-1);
xScale = randomMove ? myRand.nextInt(moveX) : moveX;
if (randomColor) setRandomColor(randomColor);
}
if (x >= iRight - width)
{
x = iRight - width;
directionX *= (-1);
xScale = randomMove ? myRand.nextInt(moveX) : moveX;
if (randomColor) setRandomColor(randomColor);
}
if (y <= 0)
{
y = 0;
directionY *= (-1);
yScale = randomMove ? myRand.nextInt(moveY) : moveY;
if (randomColor) setRandomColor(randomColor);
}
if (y >= iBottom - height)
{
y = iBottom - height;
directionY *= (-1);
yScale = randomMove ? myRand.nextInt(moveY) : moveY;
if (randomColor) setRandomColor(randomColor);
}
}
public void draw(Graphics g)
{
g.setColor(color);
g.fillOval(x, y, width, height);
}
public void setColor(Color c)
{
color = c;
}
public void setLocation(int x, int y)
{
this.x = x;
this.y = y;
}
public void setMoveRate(int xMove, int yMove, int xDir, int yDir, boolean randMove)
{
this.moveX = xMove;
this.moveY = yMove;
directionX = xDir;
directionY = yDir;
randomMove = randMove;
}
public void setRandomColor(boolean randomColor)
{
this.randomColor = randomColor;
switch (myRand.nextInt(3))
{
case 0: color = Color.BLUE;
break;
case 1: color = Color.GREEN;
break;
case 2: color = Color.RED;
break;
default: color = Color.BLACK;
break;
}
}
public void setSize(int width, int height)
{
this.width = width;
this.height = height;
}
}
}
Since your Arrays only contain the Point you want to paint you don't have any information about the speed each point should be moved at. The best you could do is create a random amount each point should be moved each time its location is changed. This would give erratic movement as each time you move a point the distance would be random.
If you want more constant speed then you would need to create a second Array to contain the distance each point should move every time.
This starts to get messy creating a new Array every time you want a new property to be unique for the object you want to paint. That is why the approach to create a custom Object with multiple properties is easier to manage.

Rectangle Intersect doesn't match what is drawn to screen

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?

Java Graphics image refresh rate

I am making a JFrame holding several images that refresh using repaint(). The problem, however, was that the more images I added (or as the area that was being rendered increased) the framerate drastically decreased.
I was initially attempting to reduce the lag that Swing's unpredictable Timer experiences, but was unsuccessful. This time, I tried to call
repaint()
every 10 milliseconds based on system time. (To bypass the timer, desktop.screenPaint.drawWindow(); is called instead of repaint())
while(true)
{
long starttime = System.currentTimeMillis();
while(System.currentTimeMillis()-starttime < 10)
{
}
desktop.screenPaint.drawWindow();
desktop2.screenPaint.drawWindow();
}
Each "desktop" is just one of the draggable windows that you see if you run the code below. I noticed that when only "desktop" is added to "frame," there is no flickering. However, when "desktop2" is also added, flickering does not go away until the time until each refresh is set to 20 or more milliseconds. It is extremely strange, because when I was still using the timer, even thought the wait was set to 10 milliseconds, the framerate would lower to a frame every 20 milliseconds! I tested a little and noticed a trend: you will get flickering until the wait time to the amount of time that the 10 millisecond timer lagged behind. My question: Why is this happening? And is there any way to prevent the flickering, other than going back to the timer?
import javax.swing.JFrame;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.SwingUtilities.*;
import static java.awt.GraphicsDevice.WindowTranslucency.*;
import java.io.File;
import java.io.IOException;
public class Display extends JPanel
{
public static int width, height;
public static JFrame frame = new JFrame("");
private static int rh = 10;
public static Display desktop = new Display();
public static Display desktop2 = new Display();
public static void main(String[] args)
{
Dimension screen = new Dimension();
screen = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
width = (int)screen.getWidth();
height = (int)screen.getHeight();
frame.setLayout(null);
frame.setLocation(0, 0);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(null);
desktop.setBounds(0, 0, 620, 500+rh);
desktop2.setBounds(1000, 200, 620, 500+rh);
frame.add(desktop);
frame.add(desktop2);
frame.setUndecorated(true);
frame.setSize(width, height);
frame.setVisible(true);
while(true)
{
long starttime = System.currentTimeMillis();
while(System.currentTimeMillis()-starttime < 10)
{
}
desktop.screenPaint.drawWindow();
//desktop2.screenPaint.drawWindow();
}
}
private BufferedImage image;
private Graphics2D g;
public Listener screenPaint = new Listener();
private Display identify;
public Display()
{
identify = this;
image = new BufferedImage(620, 500+rh, BufferedImage.TYPE_INT_RGB);
g = (Graphics2D)image.getGraphics();
Timer timer = new Timer(1, screenPaint);
timer.start();
addMouseListener(new mMouse());
addMouseWheelListener(new wWheel());
setFocusable(true);
}
private BufferedImage toCompatibleImage(BufferedImage image)
{
GraphicsConfiguration gfx_config = GraphicsEnvironment.
getLocalGraphicsEnvironment().getDefaultScreenDevice().
getDefaultConfiguration();
if (image.getColorModel().equals(gfx_config.getColorModel()))
return image;
BufferedImage new_image = gfx_config.createCompatibleImage(
image.getWidth(), image.getHeight(), image.getTransparency());
}
public void paint(Graphics view)
{
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
view.drawImage(toCompatibleImage(image), 0, 0, 620, 500+rh, null);
view.dispose();
}
private class Listener implements ActionListener
{
int y = 0;
int wy = 0;
int b = 500;
int c = 1500;
int iy = (int)(wy/(c/(double)b));
int a = -1;
int i = -1;
int j = -1;
boolean d = false;
boolean u = false;
int f = 0;
public void moveY(int sy)
{
f += sy;
}
public void actionPerformed(ActionEvent e)
{
//drawWindow();
}
public void drawWindow()
{
int lx = (int)(identify.getLocation().getX());
int ly = (int)(identify.getLocation().getY());
g.setColor(Color.white);
g.fillRect(0, 0, 620, 500+rh);
g.drawImage(new ImageIcon("image.png").getImage(), 0, wy+rh, 610, c, null);
if(c > b)
{
if(d || Mouse.withinRect(610+lx, (int)(-wy/(c/(double)b))+rh+ly, 10, (int)Math.ceil(Math.pow(b, 2)/(double)c)))
{
if(Mouse.pressLeft())
{
if(!d)d = true;
if(a == -1)a = Mouse.y()-(int)(-wy/(c/(double)b));
y = (int)((Mouse.y()-a)*(c/(double)b));
f = y;
g.setColor(Color.black);
}
else
{
if(d)d = false;
if(a != -1)a = -1;
g.setColor(new Color(60, 60, 60));
}
}
else
{
g.setColor(Color.gray);
if(a != -1)a = -1;
}
if(y == f){}
else if(y < f)
{
y += (int)((f-y)*0.1);
if(y < f)y++;
}
else
{
y -= (int)((y-f)*0.1);
if(y > f)y--;
}
if(y < 0)
{
y = 0;
f = 0;
}
else if(y > c-b)
{
y = c-b;
f = y;
}
wy = -y;
if(u || Mouse.withinRect(lx, ly, 620, 10))
{
if(Mouse.pressLeft())
{
if(!u)u = true;
if(i == -1)i = Mouse.x()-lx;
if(j == -1)j = Mouse.y()-ly;
identify.setLocation(Mouse.x()-i, Mouse.y()-j);
}
else
{
if(u)u = false;
if(i != -1)i = -1;
if(j != -1)j = -1;
}
}
else
{
if(u)u = false;
if(i != -1)i = -1;
if(j != -1)j = -1;
}
int scrollBarLength = (int)Math.ceil(Math.pow(b, 2)/(double)c);
g.fillRect(610, (int)(-wy/(c/(double)b))+rh, 10, scrollBarLength);
}
else
{
g.setColor(new Color(200, 200, 200));
g.fillRect(610, rh, 10, b);
}
g.setColor(new Color(50, 50, 50));
g.fillRect(0, 0, 620, rh);
if(identify == desktop)
repaint();
else if(false)
{}
}
}
}
public static boolean LMPress, LMRelease = false;
public static boolean LMRight, LMLeft = false;
private class mMouse extends MouseAdapter
{
public void mousePressed(MouseEvent e)
{
LMPress = true; LMRelease = false;
if(SwingUtilities.isRightMouseButton(e))
{
LMRight = true;
LMLeft = false;
}
else if(SwingUtilities.isLeftMouseButton(e))
{
LMLeft = true;
LMRight = false;
}
}
public void mouseReleased(MouseEvent e)
{
LMRelease = true; LMPress = false;
if(SwingUtilities.isRightMouseButton(e))
{
LMRight = true;
LMLeft = false;
}
else if(SwingUtilities.isLeftMouseButton(e))
{
LMLeft = true;
LMRight = false;
}
}
}
private class wWheel implements MouseWheelListener
{
public void mouseWheelMoved(MouseWheelEvent e)
{
int notches = e.getWheelRotation();
if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL) {}
e.getScrollAmount();
screenPaint.moveY(e.getUnitsToScroll()*60); //desired pixel jump: 120
}
}
}
Mouse class:
import java.awt.*;
import java.awt.event.*;
public class Mouse {
public static int x() {
PointerInfo a = MouseInfo.getPointerInfo();
Point b = a.getLocation();
return (int) b.getX();
}
public static int y() {
PointerInfo a = MouseInfo.getPointerInfo();
Point b = a.getLocation();
return (int) b.getY();
}
public static boolean withinRect(int x, int y, int w, int h) {
if (x() >= x && x() < x + w && y() >= y && y() < y + h) return true;
else return false;
}
public static boolean press() {
return Display.LMPress;
}
public static boolean release() {
return Display.LMRelease;
}
public static boolean pressLeft() {
if (Display.LMPress && Display.LMLeft)
return true;
else return false;
}
public static boolean releaseLeft() {
if (Display.LMRelease && Display.LMLeft)
return true;
else return false;
}
public static boolean pressRight() {
if (Display.LMPress && Display.LMRight)
return true;
else return false;
}
public static boolean releaseRight() {
if (Display.LMRelease && Display.LMRight)
return true;
else return false;
}
}
Updating the view at 1 kHz is unrealistic; instead, consider the alternatives cited here. See this AnimationTest for an example of self-timing to determine your animation budget.
Addendum: The while(true) loop at the top is running at 100 Hz.
The available resolution of System.currentTimeMillis() may vary by platform.
Addendum: I am reopening this question because I was not able to fix it. Any more help?
Absent a Minimal, Complete, Tested and Readable Example, it's hard to say. You appear to be overriding paint(); was noted in Painting in AWT and Swing: The Paint Methods, "Swing programs should override paintComponent()." Moreover, you need to invoke super.paintComponent(), as shown here, to avoid visual artifacts.

NullPointerException Java Maze

basically i have been following a Java tutorial to make a basic maze game where i generate a random maze which is saved to a file then i print it out using Jpanel however i keep getting this error when i compile.
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at maze.Map.getMap(Map.java:43)
at maze.Board.paint(Board.java:40)
However i am not sure why, i believe it is something to do with my Y integer but if i set it to 0 it causes my program to print out wrong(just prints the same column instead of changing rows).
I need the Y value in Map.java:43 to increase like my x value does however it provides me with the Exception error.
Code:
Map Class
package maze;
import java.awt.Image;
import java.io.File;
import java.util.*;
import javax.swing.ImageIcon;
public class Map {
private Scanner m;
private Image wall, ground;
//number of columns
private String Map[] = new String[20];
public Map() {
//sets ground to a texture
ImageIcon img = new ImageIcon("C:\\MazeGraphics\\ground.png");
ground = img.getImage();
//sets wall texture
img = new ImageIcon("C:\\MazeGraphics\\wall.png");
wall = img.getImage();
openFile();
readFile();
closeFile();
}
public Image getGround() {
// gives grass texture for screen
return ground;
}
public Image getWall() {
// gives wall texture for screen
return wall;
}
public String getMap(int x, int y) {
//compares string to find graphic to use
String index= Map[y].substring(x, x+1);
return index;
}
public void openFile() {
try {
m = new Scanner(new File("C:\\MazeGraphics\\Maze.txt"));
} catch (Exception e) {
System.out.println("Error Loading Map");
}
}
public void readFile() {
for(int i = 0; i < 20; i++)
{
while(m.hasNext()){
Map[i] = m.next();
}
}
}
public void closeFile() {
m.close();
}
}
Board Class:
package maze;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Board extends JPanel implements ActionListener {
private Timer timer;
private Map m;
private Player p;
public Board()
{
MazeGeneration maz=new MazeGeneration();
//runs Map class
m = new Map();
p = new Player();
//listens for key presses
addKeyListener(new Al());
//knows to add key listener to the frame
setFocusable(true);
timer = new Timer(25, this);
timer.start();
}
public void actionPerformed(ActionEvent e) {
repaint();
}
public void paint(Graphics g) {
super.paint(g);
//paints the board row by row
for (int y = 0; y < 20; y++)
{
for (int x = 0; x < 20; x++)
{
//places graphic depending on the letter.
if (m.getMap(x, y).equals("g"))
{
g.drawImage(m.getGround(), y * 32, x * 32, null);
}
if (m.getMap(x, y).equals("w"))
{
g.drawImage(m.getWall(), y * 32,x * 32, null);
}
}
}
g.drawImage(p.getPlayer(), p.gettileX() * 32, p.gettileY() * 32, null);
}
public class Al extends KeyAdapter {
//moving the player
public void keyPressed(KeyEvent e, char maz[][], int r, int c) {
int keycode = e.getKeyCode();
if (keycode == KeyEvent.VK_W) {
//if not a wall can move
if (!m.getMap(p.gettileX(), p.gettileY() - 1).equals("w")) {
p.move(0, -1);
}
}
if (keycode == KeyEvent.VK_S) {
if (!m.getMap(p.gettileX(), p.gettileY() + 1).equals("w")) {
p.move(0, 1);
}
}
if (keycode == KeyEvent.VK_A) {
if (!m.getMap(p.gettileX() - 1, p.gettileY()).equals("w")) {
p.move(-1, 0);
}
}
if (keycode == KeyEvent.VK_D) {
if (!m.getMap(p.gettileX() + 1, p.gettileY() ).equals("w")) {
p.move(1, 0);
}
}
}
}
}
The issue is in this code: In your readFile() method, your issue arises during reading your file:
for(int i = 0; i < 20; i++)
{
while(m.hasNext()){
Map[i] = m.next();
}
}
You are assigning the value only to the 0'th index. To explain, for the first for loop, the index i is at zero. The inner loop "iterates" through the Scanner m until there is no element next. Therefore, Map[0] contains the last element on the file.
Your solution is as follows:
int i = 0;
while (m.hasNext()) {
Map[i++] = m.next();
}
I hope this helps.

Collision detection using plain arrays and rectangles--java

I am almost done with my first little java game for my final project. It is a sidescroller where you have to shoot/avoid asteroids. My last problem is figuring out how to make my array of asteroids collide with the player's lasers. Here's what I have so far, there's an "AWT-EventQueue-0" java.lang.NullPointerException" on line 137, that I can't deal with. Any help is appreciated.
Edit: I added in my other classes, I realize it would be hard to judge the functionality of my code if I didn't show you where it came from.
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);
}
}
}
Enemy
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;
}
}
Bullet
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;
}
}
Player
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();
}
}
}
Frame
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();
}
}
Ok, so the problem is the line mentioned in the other answer, but I believe it is that all the enemies may not be initialised before it checks collisions. Because you are making 10000 of them to start with, I think your action performed method may be checking collisions before they have all be created.
One thing to try could be to bring down the amount of enemies you have and see if it still keeps happening, try 100 or 1000, but this still won't fix the issue.
You really want to be change your game to run in it's own loop though, at the moment you are only checking collisions when the player performs an action. so if the player stops moving, no collision detection...
I would suggest that you find a book called 'Killer Game Programming in Java', there are free ebook version, and just read the first 2 chapters about making a game loop. The book is a bit old, but the basics of the loop are very good.
This question here also contains a very simple loop, and some suggestions in the comments about how to make it better.
The error is on the line
rect[i] = e.getBounds();
Are you not initializing the bounds of your Enemy class correctly? Alternatively, the Enemy you pulled out of the array could be null.

Categories