How do I add a retry function to my Snake game? - java

I made a snake game following a youtube tutorial. The game has two states: either "RUNNING" when you start the game and play or "END" when you die. To play the game again you have to close the window and run the code again. I would like to make the game start again when i hit the ENTER key on the "END" screen. Ill attack some of the code and any help is appreciated.
this is the code for the GameUI
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import java.awt.Toolkit;
public class GameUI
// This is the code for the GameUI
implements KeyListener{
private Snake player;
private Food food;
private Drawing drawing;
private Superfood sfood;
private JFrame panel;
private ImageIcon icon;
public static final int width = 20;
public static final int height = 20;
public static final int dimension = 30;
public GameUI() {
// definde the Jframe within which the game is played
panel = new JFrame();
player = new Snake();
food = new Food(player);
sfood = new Superfood(player);
drawing = new Drawing(this);
panel.getContentPane().add(drawing);
panel.setTitle("Cryptic Snake v1");
panel.setSize(width * dimension + 2, height * dimension + dimension + 4);
panel.setVisible(true);
panel.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
icon = new ImageIcon("images/SNAKE.png");
panel.setIconImage(Toolkit.getDefaultToolkit().getImage(GameUI.class.getResource("/images/SNAKE.png")));
}
public void start() {
drawing.state = "RUNNING"; //set state to running and initiate the game
}
// with this if else loop we can manage the game
public void checker() {
if(drawing.state == "RUNNING") { // given that the game is running...
if(foodcrash()) {
player.grow(); // call grow-method when snake bumps into food
food.random_spawn(player); // and spawn new food
}
if(sfoodcrash()) {
player.grow();
player.grow();
player.grow();
// call grow-method when snake bumps into food
food.random_spawn(player); // and spawn new food
}
else if(wallcrash() || autocrash()) { //end the game if the snake bumps into itself or a wall
drawing.state = "END";
}
else {
player.move();
}
}
}
//here we check if the snake is bumping into a wall
private boolean wallcrash() {
if(player.getX() < 0 || player.getX() >= width * dimension
|| player.getY() < 0|| player.getY() >= height * dimension) {
return true;
}
return false;
}
// here we check if the snake is bumping into food
private boolean foodcrash() {
if(player.getX() == food.getX() * dimension && player.getY() == food.getY() * dimension) {
return true;
}
return false;
}
// here we check if the snake is bumping into food
private boolean sfoodcrash() {
if(player.getX() == sfood.getSx() * dimension && player.getY() == sfood.getSy() * dimension) {
return true;
}
return false;
}
// here we check has bumped into itself
private boolean autocrash() {
for(int i = 1; i < player.getSnk().size(); i++) {
if(player.getX() == player.getSnk().get(i).x &&
player.getY() == player.getSnk().get(i).y) {
return true;
}
}
return false;
}
// now we add a keylistener that listens to the inputs on our keyboard
#Override
public void keyTyped(KeyEvent e) { }
#Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if(drawing.state == "RUNNING") {
if(keyCode == KeyEvent.VK_UP && player.getMove() != "UP") { // up-arrow-key
player.up();
}
if(keyCode == KeyEvent.VK_DOWN && player.getMove() != "DOWN") { // down-arrow-key
player.down();
}
if(keyCode == KeyEvent.VK_LEFT && player.getMove() != "LEFT") { //left-arrow-key
player.left();
}
if(keyCode == KeyEvent.VK_RIGHT && player.getMove() != "RIGHT") {//right-arrow-key
player.right();
}
}
else {
this.start();}
}
#Override
public void keyReleased(KeyEvent e) { }
//auto-generated getters and setters
public Snake getPlayer() {
return player;
}
public void setPlayer(Snake player) {
this.player = player;
}
public Food getFood() {
return food;
}
public void setFood(Food food) {
this.food = food;
}
public JFrame getPanel() {
return panel;
}
public Superfood getSfood() {
return sfood;
}
public void setSfood(Superfood sfood) {
this.sfood = sfood;
}
public void setPanel(JFrame window) {
this.panel = window;
}
public Drawing getGraphics() {
return drawing;
}
public static int getWidth() {
return width;
}
public static int getHeight() {
return height;
}
public static int getDimension() {
return dimension;
}
public void setGraphics(Drawing drawing) {
this.drawing = drawing;
}
}
this is the code for the drawing class
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.awt.Font;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import java.awt.SystemColor;
//this code is responsible for the graphics, so everything you see on the screen
// we use a paint component that redraws everything within a given time interval
public class Drawing
extends JPanel
implements ActionListener {
private Timer t = new Timer(100, this); //we want to redraw the screen every 100 milliseconds, this defindes speed of snake
public String state; // we use states as there are two different situations: either the game is running or you died
private Superfood sf;
private Snake s;
private Food f;
private GameUI gameUI;
public Drawing(GameUI g) {
setBackground(SystemColor.activeCaptionBorder);
t.start();
state = "RUNNING";
gameUI = g;
s = g.getPlayer();
f = g.getFood();
sf= g.getSfood();
//add a keyListner
this.addKeyListener(g);
this.setFocusable(true);
this.setFocusTraversalKeysEnabled(false);
GroupLayout groupLayout = new GroupLayout(this);
groupLayout.setHorizontalGroup(
groupLayout.createParallelGroup(Alignment.LEADING)
.addGap(0, 450, Short.MAX_VALUE)
);
groupLayout.setVerticalGroup(
groupLayout.createParallelGroup(Alignment.LEADING)
.addGap(0, 300, Short.MAX_VALUE)
);
setLayout(groupLayout);
}
public void paintComponent(java.awt.Graphics g) {
super.paintComponent(g);
Font font = new Font("Playbill", 10,50);
Font sfont = new Font("Perpetua Titling MT", 10,30);
Graphics2D g2d = (Graphics2D) g; //make it 2D
//drawing the background
g2d.setColor(Color.gray);
g2d.fillRect(0, 0, GameUI.width * GameUI.dimension + 5, GameUI.height * GameUI.dimension + 5);
if(state == "RUNNING") { // drawing the food in the case that the game is running
g2d.setColor(Color.cyan);
g2d.fillOval(f.getX() * GameUI.dimension, f.getY() * GameUI.dimension, GameUI.dimension, GameUI.dimension);
g2d.setColor(Color.BLUE);
if (s.getSnk().size() % 5 == 0)
g2d.fillRoundRect(sf.getSx() * GameUI.dimension, sf.getSy() * GameUI.dimension, GameUI.dimension, GameUI.dimension,12,12);
g2d.setColor(Color.DARK_GRAY); //drawing the snake in the case the the game is runnng
for(Rectangle r : s.getSnk()) {
g2d.fill(r);
}
}
else { //if the game is not running display the score
g2d.setColor(Color.DARK_GRAY);
g2d.setFont(sfont);
g2d.drawString("Your score was", GameUI.width/2 * GameUI.dimension - 175, GameUI.height / 2 * GameUI.dimension - 25);
g2d.setFont(font);
g2d.drawString("" + (s.getSnk().size() ), GameUI.width/2 * GameUI.dimension + 117, GameUI.height / 2 * GameUI.dimension - 20);
}
}
#Override
public void actionPerformed(ActionEvent e) {
repaint();
gameUI.checker(); //check if the snake is bumping into a wall itself or food or nothing to determine what to draw next
}
}

I had something similar and I did this:
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
Main.frame.dispose();
new Main();
}
});
where the Main is a class you initializing the frame in it.

Related

How do I make a top down view with the ability to rotate with built in java graphics?

I'm trying to make a racing game with the top down view on a static player in the middle of the screen, so instead of moving the player through the map, the map would move around the player. Since it's a racing game, I wanted it to also be somewhat similar to a car, but I've been having trouble with rotating the map around the player and having that work with translations.
I've tried keeping track of the center by adding or subtracting from it, which is what I did for the translations, but it doesn't work with the rotate method. The rotate function wouldn't rotate about the player and instead would rotate the player around some other point, and the translations would snap to a different location from the rotations. I'm sure my approach is flawed, and I have read about layers and such, but I'm not sure what I can do with them or how to use them. Also, any recommendations as to how to use java graphics in general would be greatly appreciated!
This is what I have in my main:
import javax.swing.JFrame;
import java.awt.BorderLayout;
public class game
{
public static void main(String []args)
{
JFrame frame = new JFrame();
final int FRAME_WIDTH = 1000;
final int FRAME_HEIGHT = 600;
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final Map b = new Map();
frame.add(b,BorderLayout.CENTER);
frame.setVisible(true);
b.startAnimation();
}
}
And this is the class that handles all the graphics
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JComponent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class Map extends JComponent implements Runnable, KeyListener
{
private int speed = 5;
private int xcenter = 500; // starts on player
private int ycenter = 300;
private double angle = 0.0;
private int[] xcords = {xcenter+10, xcenter, xcenter+20};
private int[] ycords = {ycenter-10, ycenter+20, ycenter+20};
private boolean moveNorth = false;
private boolean moveEast = false;
private boolean moveSouth = false;
private boolean moveWest = false;
public Map()
{
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public void startAnimation()
{
Thread t = new Thread(this);
t.start();
}
public void paintComponent(Graphics g)
{
g.fillPolygon(xcords, ycords, 3);
// move screen
if(moveNorth)
{
ycenter += speed;
g.translate(xcenter, ycenter);
}
else if(moveEast)
{
angle += ((1 * Math.PI/180) % (2 * Math.PI));
((Graphics2D) g).rotate(angle, 0, 0);
}
else if(moveSouth)
{
System.out.println(xcenter + ", " + ycenter);
ycenter -= speed;
((Graphics2D) g).rotate(angle, 0, 0);
g.translate(xcenter, ycenter);
}
else if(moveWest)
{
angle -= Math.toRadians(1) % (2 * Math.PI);
((Graphics2D) g).rotate(angle, 0, 0);
}
for(int i = -10; i < 21; i++)
{
g.drawLine(i * 50, -1000, i * 50, 1000);
g.drawLine(-1000, i * 50, 1000, i * 50);
}
g.drawOval(0, 0, 35, 35);
}
public void run()
{
while (true)
{
try
{
if(moveNorth || moveEast || moveSouth || moveWest)
{
repaint();
}
Thread.sleep(10);
}
catch (InterruptedException e)
{
}
}
}
public void keyPressed(KeyEvent e)
{
if(e.getExtendedKeyCode() == 68) // d
{
moveEast = true;
}
else if(e.getExtendedKeyCode() == 87) // w
{
moveNorth = true;
}
else if(e.getExtendedKeyCode() == 65) // a
{
moveWest = true;
}
else if(e.getExtendedKeyCode() == 83) // s
{
moveSouth = true;
}
}
public void keyReleased(KeyEvent e)
{
moveNorth = false;
moveEast = false;
moveSouth = false;
moveWest = false;
}
public void keyTyped(KeyEvent e)
{
}
}
You have to keep in mind that transformations are compounding, so if you rotate the Graphics context by 45 degrees, everything painted after it will be rotated 45 degrees (around the point of rotation), if you rotate it again by 45 degrees, everything painted after it will be rotated a total of 90 degrees.
If you want to paint additional content after a transformation, then you either need to undo the transformation, or, preferably, take a snapshot of the Graphics context and dispose of it (the snapshot) when you're done.
You also need to beware of the point of rotation, Graphics2D#rotate(double) will rotate the Graphics around the point of origin (ie 0x0), which may not be desirable. You can change this by either changing the origin point (ie translate) or using Graphics2D#rotate(double, double, double), which allows you to define the point of rotation.
For example...
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Set;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
public class TestPane extends JPanel {
enum Direction {
LEFT, RIGHT;
}
protected enum InputAction {
PRESSED_LEFT, PRESSED_RIGHT, RELEASED_LEFT, RELEASED_RIGHT
}
private BufferedImage car;
private BufferedImage road;
private Set<Direction> directions = new TreeSet<>();
private double directionOfRotation = 0;
public TestPane() throws IOException {
car = ImageIO.read(getClass().getResource("/images/Car.png"));
road = ImageIO.read(getClass().getResource("/images/Road.png"));
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), InputAction.PRESSED_LEFT);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, true), InputAction.RELEASED_LEFT);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), InputAction.PRESSED_RIGHT);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, true), InputAction.RELEASED_RIGHT);
am.put(InputAction.PRESSED_LEFT, new DirectionAction(Direction.LEFT, true));
am.put(InputAction.RELEASED_LEFT, new DirectionAction(Direction.LEFT, false));
am.put(InputAction.PRESSED_RIGHT, new DirectionAction(Direction.RIGHT, true));
am.put(InputAction.RELEASED_RIGHT, new DirectionAction(Direction.RIGHT, false));
Timer timer = new Timer(5, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (directions.contains(Direction.RIGHT)) {
directionOfRotation += 1;
} else if (directions.contains(Direction.LEFT)) {
directionOfRotation -= 1;
}
// No doughnuts for you :P
if (directionOfRotation > 180) {
directionOfRotation = 180;
} else if (directionOfRotation < -180) {
directionOfRotation = -180;
}
repaint();
}
});
timer.start();
}
protected void setDirectionActive(Direction direction, boolean active) {
if (active) {
directions.add(direction);
} else {
directions.remove(direction);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(213, 216);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
drawRoadSurface(g2d);
drawCar(g2d);
g2d.dispose();
}
protected void drawCar(Graphics2D g2d) {
g2d = (Graphics2D) g2d.create();
int x = (getWidth() - car.getWidth()) / 2;
int y = (getHeight() - car.getHeight()) / 2;
g2d.drawImage(car, x, y, this);
g2d.dispose();
}
protected void drawRoadSurface(Graphics2D g2d) {
g2d = (Graphics2D) g2d.create();
// This sets the point of rotation at the center of the window
int midX = getWidth() / 2;
int midY = getHeight() / 2;
g2d.rotate(Math.toRadians(directionOfRotation), midX, midY);
// We then need to offset the top/left corner so that what
// we want draw appears to be in the center of the window,
// and thus will be rotated around it's center
int x = midX - (road.getWidth() / 2);
int y = midY - (road.getHeight() / 2);
g2d.drawImage(road, x, y, this);
g2d.dispose();
}
protected class DirectionAction extends AbstractAction {
private Direction direction;
private boolean active;
public DirectionAction(Direction direction, boolean active) {
this.direction = direction;
this.active = active;
}
#Override
public void actionPerformed(ActionEvent e) {
setDirectionActive(direction, active);
}
}
}
}

Eclipse is not running Java method: public void paint (Graphics g)

I'm new to Eclipse, recently swapped from Bluej which ran my codes reliably. In Eclipse, it sometimes runs and sometimes just doesn't run the paint method and I'm not sure why. The same code was running this morning and now it decides to not run and I'm not sure what to do.
Main method:
import java.awt.Container;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;
import Asset.Paddle;
import Asset.Puck;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseEvent;
import java.awt.BorderLayout;
public class setup implements KeyListener, MouseListener, MouseMotionListener, Runnable {
int width = 100;
int height = 100;
int scale = 8;
public static setup setup;
JFrame frame;
JPanel main;
Graphic graphic;
Puck puck;
Paddle paddle1,paddle2;
boolean running, up = true, up2 = true;
boolean menu = false, b1, b2, b3;
int winSize;
public setup() {
puck = new Puck((width*scale)/2,(width*scale)/2,20,20);
paddle1 = new Paddle(width*scale/8-20,height*scale/2,20,100);
paddle2 = new Paddle(width*scale/8*7,height*scale/2,20,100);
frame();
}
public void frame() { //Frame setup
frame = new JFrame("Pong");
frame.setSize(width * scale,height * scale);
frame.setLayout(new BorderLayout());
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container c1 = frame.getContentPane();
Dimension winSize = frame.getSize();
System.out.println(winSize);
graphic = new Graphic(puck,paddle1,paddle2);
graphic.addKeyListener(this);
graphic.addMouseListener(this);
graphic.addMouseMotionListener(this);
main = new JPanel();
main.setLayout(new BorderLayout());
main.setSize(width * scale,height * scale);
main.add(graphic,BorderLayout.CENTER);
start();
c1.add(main);
graphic.requestFocus();
}
public void start() { //running = true
new Thread(this).start();
running = true;
menu = true;
RENDER();
}
public void stop() {
running = false;
}
public void run() { //Game
while(running == true) {
try {
Thread.sleep(10);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
if(puck.getY() < 0 || puck.getY() > height * scale) {
puck.reverseY();
}
paddle1.run();
paddle2.run();
puck.run();
RENDER();
}
}
public void RENDER() {
graphic.UPDATEPADDLE(paddle1,paddle2);
graphic.UPDATEPUCK(puck);
graphic.repaint();
}
public void keyPressed(KeyEvent evt) {
if(evt.getKeyCode() == 81) { // Q
paddle1.setYVel(-2);
up = true;
}
if(evt.getKeyCode() == 65) { // A
paddle1.setYVel(2);
up = false;
}
if(evt.getKeyCode() == 80) { // P
paddle2.setYVel(-2);
up2 = true;
}
if(evt.getKeyCode() == 76) {
paddle2.setYVel(2);
up2 = false;
}
}
public void keyReleased(KeyEvent evt) {
if(evt.getKeyCode() == 81 && up ) { // Q
paddle1.setYVel(0);
}
if(evt.getKeyCode() == 65 && !up) { // A
paddle1.setYVel(0);
}
if(evt.getKeyCode() == 80 && up2) { // P
paddle2.setYVel(0);
}
if(evt.getKeyCode() == 76 && !up2) { // L
paddle2.setYVel(0);
}
}
public void keyTyped(KeyEvent evt) {}
public void mouseClicked(MouseEvent e) {
// if(e.getX() > 375 && e.getX() < 375 + 200 && e.getY() > 400 && e.getY() < 400 + 50) {
// menu = false;
// System.out.println("clicked");
// graphic.UPDATEBUTTON(b1,b2,b3);
// graphic.UPDATEMENU(menu);
// start();
// graphic.repaint();
// }
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
public static void main(String[] args) {
setup = new setup();
}
public void mouseDragged(MouseEvent e) {
}
public void mouseMoved(MouseEvent e) {
if(e.getX() > 375 && e.getX() < 375 + 200 && e.getY() > 400 && e.getY() < 400 + 50) {
b1 = true;
graphic.UPDATEBUTTON(b1,b2,b3);
graphic.repaint();
}
else {
b1 = false;
graphic.UPDATEBUTTON(b1,b2,b3);
graphic.repaint();
}
}
}
Paddle:
package Asset;
public class Paddle {
double x, y, yVel, h, w;
public Paddle(double xx, double yy, int width, int height) {
x = xx;
y = yy;
h = height;
w = width;
}
public int getX() {
return (int)x;
}
public int getY() {
return (int)y;
}
public int getH() {
return (int)h;
}
public int getW() {
return (int)w;
}
public void setYVel(int yVelocity) {
yVel = yVelocity;
}
public void run() {
y += yVel;
if(y < 0) {
yVel = 0;
y = 0;
}
}
}
Puck:
package Asset;
public class Puck {
double x,y,w,h;
double xVel = 0;
double yVel = 3;
public Puck(double xx, double yy,int width,int height) {
x = xx;
y = yy;
w = width;
h = height;
x++;
}
public void reverseY() {
yVel *= -1;
}
public void reverseX() {
xVel *= -1;
}
public int getX() {
return (int)x;
}
public int getY() {
return (int)y;
}
public int getW() {
return (int)w;
}
public int getH() {
return (int)h;
}
public void run() {
x += xVel;
y += yVel;
}
}
Setup:
import java.awt.*;
import javax.swing.*;
import Asset.Paddle;
import Asset.Puck;
public class Graphic extends JPanel {
private static final long serialVersionUID = 2273791975624707192L;
Puck ppuck;
Paddle ppaddle1,ppaddle2;
boolean mmenu = true;
boolean bb1,bb2,bb3;
public Graphic(Puck puck,Paddle paddle1,Paddle paddle2) {
ppuck = puck;
ppaddle1 = paddle1;
ppaddle2 = paddle2;
}
public void UPDATEMENU(boolean menu) {
mmenu = menu;
}
public void UPDATEPADDLE(Paddle paddle1, Paddle paddle2) {
ppaddle1 = paddle1;
ppaddle2 = paddle2;
}
public void UPDATEPUCK(Puck puck) {
ppuck = puck;
}
public void UPDATEBUTTON(boolean b1,boolean b2, boolean b3) {
bb1 = b1;
bb2 = b2;
bb3 = b3;
}
public void paint (Graphics g) {
super.paint(g);
g.setColor(Color.black);
g.fillRect(0, 0, 1000, 1000);
if (mmenu) { //menu
if(bb1) {
g.setColor(Color.blue);
g.setFont(new Font("TimesRoman", Font.PLAIN, 50));
g.drawString("START", 390, 440);
}
else {
g.setColor(Color.white);
g.setFont(new Font("TimesRoman", Font.PLAIN, 50));
g.drawString("START", 390, 440);
}
}
else {
g.setColor(Color.white);
g.fillOval(ppuck.getX(), ppuck.getY(), ppuck.getW(), ppuck.getH());
g.fillRect(ppaddle1.getX(), ppaddle1.getY(), ppaddle1.getW(), ppaddle1.getH());
g.fillRect(ppaddle2.getX(), ppaddle2.getY(), ppaddle2.getW(), ppaddle2.getH());
}
}
}
So, two "basic" problems...
One, if you modify the UI after the frame is visible, you must call revalidate and repaint too trigger a layout and paint pass. A simpler solution, in your case, would be to call setVisible AFTER you've established the UI
public void frame() { //Frame setup
frame = new JFrame("Pong");
frame.setSize(width * scale, height * scale);
frame.setLayout(new BorderLayout());
frame.setLocationRelativeTo(null);
//frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container c1 = frame.getContentPane();
//...
start();
c1.add(main);
graphic.requestFocus();
frame.setVisible(true);
}
Second...
This one's a little more complicated, but, you start your Thread and then update the state which it relies on to keep running
public void start() { //running = true
new Thread(this).start();
running = true;
menu = true;
RENDER();
}
While very, very unlikely, it's possible that the thread will inspect the state before you change it ... or because of the way the memory model works, won't see the change.
Better to set it before hand...
public void start() { //running = true
running = true;
new Thread(this).start();
menu = true;
RENDER();
}
You should also consider making it volatile
Having said that...
You're going around it all the wrong way.
To start with, don't try and do all the rendering for all the states in the single view, instead, use seperate views to different states (such as the start screen and the game screen).
You could then make use of CardLayout or simply overlay the containers onto of each other when you want to switch between them.
Next, you should avoid using KeyListener, it's troublesome at the best of times. Instead, make us of the key bindings API, then you won't need to post another question about why KeyListener has stopped working.
Next, Swing is single threaded and not thread safe. This means you should not be performing blocking or long running operations within the context of the Event Dispatching Thread or updating the UI or a state the UI depends on from outside of it.
Take a look at Concurrency in Swing for more details.
The simple solution in this case is probably to use a Swing Timer, see How to use Swing Timers for more details.
I would, personally, make the "game" panel responsible for setting up the input and rendering management, but that's me.

JFrame.dispose(); isn't doing anything

I've tried every solution I could find here and on forums but I cannot close the wind JFrame no matter what I do and I have no idea why. I need to dispose of the JFrame and launch a different one by creating a WarioWareGUI object.
Right now, the best I seem to be able to do is stop the ball from moving and just leave the old JFrame in the background, but that's not quite good enough. I need the wind JFrame to close
I've tried infinitely disposing, I've tried setting the JFrame as public static and initializing it as an object of BallGame so that I can dispose from anywhere. I've tried simply disposing it immediately after creating it. Nothing seems to get rid of it.
I even tried just setting the ball speed to 0 and making the frame invisible but wind.setVisible(false); doesn't do anything either.
package GameProject;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.Timer;
import javax.swing.WindowConstants;
public final class BallGame extends JComponent implements ActionListener, MouseMotionListener, KeyListener {
private int ballx = 150;
private int bally = 30;
private int paddlex = 0;
private static int ballySpeed = 7;
private static int ballxSpeed = 5;
private int score = 0;
private int round = 1;
private int bounces = 0;
private static int delay = 20;
public static boolean gameOver = false;
public static boolean gameOverFlag = false;
public boolean started;
public static void main(int round) {
//only true the first time the game is run
if ((gameOver == false) && (gameOverFlag == false)) {
gameMake(round);
}
//only true after the game has resulted in a loss
if ((gameOver == true) && (gameOverFlag==true)) {
gameOver = false;
//gameMake(round);
WarioWareGUI gui = new WarioWareGUI();
}
//only true after the game has resulted in a loss and
//returned to main menu
if ((gameOver == false) && (gameOverFlag==true)) {
}
}
public static void gameMake(int round) {
JFrame wind = new JFrame("RedBall/GamePinfo");
BallGame g = new BallGame();
wind.add(g);
wind.pack();
wind.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
wind.setLocationRelativeTo(null);
wind.setVisible(true);
wind.addMouseMotionListener(g);
wind.dispose();
//speed up the timer each round
Timer tt = new Timer(delay, g);
tt.start();
}
public void newball(int ballx, int bally, int ballxspeed, int ballyspeed) {
ballx = 150;
bally = 30;
ballxspeed = 5;
ballyspeed = 7;
JOptionPane.showMessageDialog(null, "new ball !");
return;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(800, 600);
}
#Override
protected void paintComponent(Graphics g) {
//draw the sky
g.setColor(Color.cyan);
g.fillRect(0, 0, 800, 600);
g.setColor(Color.GREEN);
g.fillRect(0, 550, 800, 100);
//draw the paddel
g.setColor(Color.black);
g.fillRect(paddlex, 500, 100, 20);
//draw the ball
g.setColor(Color.RED);
g.fillOval(ballx, bally, 30, 30);
g.setColor(Color.white);
g.setFont(new Font("Arial", 8, 50));
g.drawString(String.valueOf(score), 30, 80);
}
#Override
public void actionPerformed(ActionEvent e) {
//Manages ball movement
ballx = ballx + ballxSpeed;
bally = bally + ballySpeed;
if (gameOverFlag) {
round = 1;
BallGame.main(round);
}
else if (gameOver) {
gameOverFlag = true;
//displays the dialog box indicating victory
JOptionPane.showMessageDialog(this, "You lost on round"
+ round + "!");
ballx = 150;
bally = 30;
}
else if (bounces==10) {
//reset score
bounces = 0;
round++;
JOptionPane.showMessageDialog(this,"You Win! You move on to"
+ " round " + round + "!");
}
// Sets ball speed upward if it hits the paddle
else if (ballx >= paddlex && ballx <= paddlex + 100 && bally >= 475) {
ballySpeed = -7 - (round*2);
//monitors the number of times the ball is successfully hit
score++;
bounces++;
}
// Handles loss condition
else if (bally >= 500 ) {
gameOver = true;
}
// Sets ball movement down if it hits the ceiling
else if (bally <= 0) {
ballySpeed = 7 + (round*2);
}
// Sets ball
else if (ballx >= 775) {
ballxSpeed = -5 - (round*2);
}
// Window left
else if (ballx <= 0) {
ballxSpeed = 5 + (round*2);
}
//**********************************************************************
repaint();
}
#Override
public void mouseMoved(MouseEvent e) {
//places paddle in middle of mouse
paddlex = e.getX() - 50;
repaint();
}
#Override
public void mouseDragged(MouseEvent e) {
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
}
}
I expect calling wind.dispose to shut down the GUI but it won't, no matter where I put it or how I declare the JFrame. I can't just make it invisible either.
The code right now is just where it was when I gave up, I'm not trying to just dispose of it right away of course, but once I can get it to just dispose once successfully, hopefully I can get it to do that at the right time.

How to restart the game in Java [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 6 years ago.
Im writing RiverRaidlike game, and i have a problem with restarting the game.
When Craft crashes i want to make it able to press space and restart the game.
Problem is that i have everything drawn on the JPanel.
My research:
When i try to pass a game object to the Panel class and dispose the last window there is a NullPointerException...
private void restart()
{
game.dispose();
new Game();
repaint();
}
I think it's a problem with calling constructors.. but im not sure...
When i try to reinitialize the JPanel it just repaints all but doesnt remove the old content
private void initBoard() {
addKeyListener(new TAdapter());
setFocusable(true);
setBackground(Color.PINK);
setLayout(new GridBagLayout());
craft = new Craft(ICRAFT_X, ICRAFT_Y);
setMinimumSize(new Dimension(WIDTH, HEIGHT));
initEnemiesAndAddThem();
czas = new Timer(delay, this);
czas.start();
}
private void initEnemiesAndAddThem() {
enemy = new EnemyJet(0, -600);
enemies.add(enemy);
fuel = new Fuel(0, 0);
fuels.add(fuel);
obstacle = new Obstacle(0, -600);
obst.add(obstacle);
}
private void restart()
{
initBoard();
}
Lastly, when i try to implement KeyListener to the JFrame it doesnt work at all... tried to print out a string when i press space, but nothing happens...
All i can do is to stop the Timer and start it again but it pausing the game but not restarting it.
Those are the JFrame class and JPanel class:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package riverraid2;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
*
* #author Michał
*/
public class Game extends JFrame implements KeyListener {
private final static int WIDTH = 1024;
private final static int HEIGHT = 768;
Plansza panel;
Game() {
initGame();
}
private void initGame() {
Plansza panel = new Plansza();
setTitle("Reeevah Raaid");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(WIDTH, HEIGHT);
setPreferredSize(new Dimension(WIDTH, HEIGHT));
setMinimumSize(new Dimension(800, 600));
setMaximumSize(new Dimension(1680, 1050));
setLocationRelativeTo(null);
// panel.setState(new StartScreen(panel));
this.add(panel, BorderLayout.CENTER);
pack();
setVisible(true);
//setExtendedState(JFrame.MAXIMIZED_BOTH);
//setResizable(false);
}
public static void main(String[] args) {
new Game();
//ex.setVisible(true);
// ex.pack();
}
#Override
public void keyTyped(KeyEvent e) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
System.out.print("Spacja!");
}
}
#Override
public void keyReleased(KeyEvent e) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package riverraid2;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.geom.AffineTransform;
import javax.swing.JPanel;
import javax.swing.Timer;
import java.util.ArrayList;
import javax.swing.Icon;
import javax.swing.JLabel;
/**
*
* #author Michał
*/
public class Plansza extends JPanel implements ActionListener {
private boolean paused = false;
private int ileWcisniec = 0;
private int slowDownSally = 0;
private int finalScore = 1;
private Game game;
private Timer czas;
private Thread thread;
private Craft craft;
private Fuel fuel;
private Obstacle obstacle;
private EnemyJet enemy;
private final int delay = 10;
private final int ICRAFT_X = 450;
private final int ICRAFT_Y = 600;
private final ArrayList<Fuel> fuels = new ArrayList<>();
private final ArrayList<EnemyJet> enemies = new ArrayList<>();
private final ArrayList<Obstacle> obst = new ArrayList<>();
boolean running = true;
long licznik = System.nanoTime();
public Plansza() {
// setBackground(Color.WHITE);
initBoard();
}
private void initBoard() {
addKeyListener(new TAdapter());
setFocusable(true);
setBackground(Color.PINK);
setLayout(new GridBagLayout());
craft = new Craft(ICRAFT_X, ICRAFT_Y);
setMinimumSize(new Dimension(WIDTH, HEIGHT));
initEnemiesAndAddThem();
czas = new Timer(delay, this);
czas.start();
}
private void initEnemiesAndAddThem() {
enemy = new EnemyJet(0, -600);
enemies.add(enemy);
fuel = new Fuel(0, 0);
fuels.add(fuel);
obstacle = new Obstacle(0, -600);
obst.add(obstacle);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
doDrawing(g);
if (!running) {
drawGameOver(g, "");
g.drawString("Press SPACE to restart the game!", getWidth()/4, getHeight()/2);
}
Toolkit.getDefaultToolkit().sync();
}
private void doDrawing(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
drawStrings(g2);
ArrayList ms = craft.getMissiles();
for (Object m1 : ms) {
Missile m = (Missile) m1;
g2.drawImage(m.getImage(), m.getX(), m.getY(), this);
}
g2.drawImage(craft.getImage(), craft.getX(), craft.getY(), this);
for (EnemyJet enemy : enemies) {
g2.drawImage(enemy.getImage(), enemy.getX(), enemy.getY(), this);
}
for (Fuel fuel : fuels) {
g2.drawImage(fuel.getImage(), fuel.getX(), fuel.getY(), fuel.getHeight(), fuel.getHeight(), this);
}
for (Obstacle o : obst) {
g2.drawImage(o.getImage(), o.getX(), o.getY(), this);
}
drawStrings(g2);
}
private void drawGameOver(Graphics g, String msg) {
Font small = new Font("Helvetica", Font.BOLD, 36);
FontMetrics fm = getFontMetrics(small);
g.setColor(Color.white);
g.setFont(small);
g.drawString("GAME OVER", getWidth()/4, (getHeight()/2)-50);
g.drawString(msg, (1024 - fm.stringWidth(msg)) / 2,
800 / 2);
}
public void drawStrings(Graphics2D g) {
String score;
String fuelString;
score = "Score: " + finalScore;
g.setColor(Color.WHITE);
g.setFont(new Font("Consolas", Font.PLAIN, 48));
g.drawString(score, 150, 48);
fuelString = "Fuel: " + craft.getFuel();
g.drawString(fuelString, 650, 48);
}
public String gameOver() {
String msg = "";
if (craft.getFuel() <= 0) {
running = false;
msg = "Zabrakło ci paliwa!";
}
if (finalScore == 1000000) {
running = false;
msg = "Gra ukończona, jesteś mistrzem River Raid, oto Twój medal Mistrza River Raid";
}
return msg;
}
private void restart()
{
initBoard();
}
#Override
public void actionPerformed(ActionEvent e) {
removeAll();
gameRunning();
updateMissiles();
updateCraft();
updateEnemy();
updateFuel();
updateObstacles();
checkCollision();
gameOver();
if (slowDownSally % 100 == 0) {
updateArrays();
}
if (finalScore % 2000 == 0) {
levelUpJets();
}
repaint();
slowDownSally++;
}
public boolean gameState()
{
return running;
}
private void updateMissiles() {
ArrayList ms = craft.getMissiles();
for (int i = 0; i < ms.size(); i++) {
Missile m = (Missile) ms.get(i);
if (m.isVisible()) {
m.move();
} else {
ms.remove(i);
}
}
}
private void updateArrays() {
EnemyJet e = new EnemyJet(0, -600);
enemies.add(e);
Fuel f = new Fuel(0, -500);
fuels.add(f);
Obstacle o = new Obstacle(0, -600);
obst.add(o);
}
private void updateEnemy() {
for (int i = 0; i < enemies.size(); i++) {
EnemyJet e = enemies.get(i);
if (e.isVisible()) {
e.move();
} else {
enemies.remove(i);
}
}
}
private void updateFuel() {
for (int i = 0; i < fuels.size(); i++) {
Fuel e = fuels.get(i);
if (e.isVisible()) {
e.move();
} else {
fuels.remove(i);
}
}
}
private void updateObstacles() {
for (int i = 0; i < obst.size(); i++) {
Obstacle o = obst.get(i);
if (o.isVisible()) {
o.move();
} else {
obst.remove(i);
}
}
}
private void updateCraft() {
craft.move();
}
public void gameRunning() {
if (running == false) {
czas.stop();
}
}
void checkCollision() {
Rectangle r3 = craft.getBounds();
for (EnemyJet enemy : enemies) {
Rectangle r2 = enemy.getBounds();
if (r3.intersects(r2)) {
craft.setVisible(false);
enemy.setVisible(false);
running = false;
}
}
ArrayList<Missile> ms = craft.getMissiles();
for (Missile m : ms) {
Rectangle r1 = m.getBounds();
for (EnemyJet enemy : enemies) {
Rectangle r2 = enemy.getBounds();
if (r1.intersects(r2)) {
m.setVisible(false);
enemy.setVisible(false);
enemy.vis = false;
finalScore += 100;
}
}
}
for (Fuel fuel : fuels) {
Rectangle r4 = fuel.getBounds();
if (r3.intersects(r4)) {
craft.addFuel(50);
fuel.setVisible(false);
}
}
for (Obstacle o : obst) {
Rectangle r5 = o.getBounds();
for (Missile m : ms) {
Rectangle r1 = m.getBounds();
if (r1.intersects(r5)) {
m.setVisible(false);
}
}
if(r5.intersects(r3))
{
running = false;
}
}
}
private void levelUpJets() {
for (EnemyJet e : enemies) {
e.levelUp();
}
}
private class TAdapter extends KeyAdapter {
#Override
public void keyReleased(KeyEvent e) {
craft.keyReleased(e);
}
#Override
public void keyPressed(KeyEvent e) {
craft.keyPressed(e);
restart();
}
}
}
It's not a problem of NullPointerException but i think more conceptional problem, about how to restart the game... I only suggested that one of my tries gave that error but I did it to show an effort in findin the solution.
I can't answer why you are getting a null pointer. I would suggest that you would just create a method that would reset the game instead of creating a new game object. As for the JPanel not resetting itself, it doesn't seem that you actually reset anything. Consider writing a method that would reset all your fields. Hope this is helpful!
There is no need to reinitialize everything, like you do in your initBoard (listener). Those are fine. Try to separate your functions. You are setting size and creating a craft and so on in the same method. All you need is to reinitialize your positions, some values, bool states, only stuffs that affects the game play. Make a separated method for these, and call them whenever you want, and don't forget to clear your arraylists.

Java help: make image move across the screen

I've been having trouble with this for quite a while now
I am trying to make a space shooter but to no avail, I'm trying to make the bullet move across the screen like in space invaders etc
when the player presses the space bar a bullet should appear where the player's X position is and move right across the screen.
import java.awt.Color;
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 javax.swing.ImageIcon;
import javax.swing.JFrame;
public class game extends JFrame{
boolean run = true;
boolean fired = false;
Image player;
Image bullet;
int playerX = 100;
int playerY = 200;
int bulletX;
int bulletY;
public game(){
//Load Images:
ImageIcon playerI = new ImageIcon("C:/Users/Dan/workspace/shooterProject/bin/shooterProject/ship.png");
player = playerI.getImage();
ImageIcon bulletI = new ImageIcon("C:/Users/Dan/workspace/shooterProject/bin/shooterProject/bullet.png");
bullet = bulletI.getImage();
//Set up game
addKeyListener(new AL());
addMouseListener(new Mouse());
init();
}
private Image dbImage;
private Graphics dbg;
public static void main(String[] args) {
new game();
}
//When the program runs, thins are initialised here
public void init(){
windowManager();
}
public void paintComponent(Graphics g){
if(run == true){
g.drawImage(player, playerX, playerY, this);
}
if(fired == true){
g.drawImage(bullet, bulletX, bulletY, this);
}
repaint();
}
public void paint(Graphics g){
dbImage = createImage(getWidth(), getHeight());
dbg = dbImage.getGraphics();
paintComponent(dbg);
g.drawImage(dbImage,0,0,this);
}
public void bullet(){
bulletX = playerX;
bulletY = playerY;
while(fired == true){
bulletX = bulletX + 10;
if(bulletX == 800){
bullet = null;
fired = false;
}
}
}
public void windowManager(){
JFrame f = new JFrame();
setTitle("Engine");
setVisible(true);
setResizable(false);
setSize(800,400);
setBackground(Color.BLACK);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public class AL extends KeyAdapter{
public void keyPressed(KeyEvent e){
int keyCode = e.getKeyCode();
if((keyCode == KeyEvent.VK_UP) && (run == true) && (playerY - 20 > 0)){
playerY = playerY - 10;
}else if((keyCode == KeyEvent.VK_DOWN) && (run == true) && (playerY + 20 < 400)){
playerY = playerY + 10;
}
if((keyCode == KeyEvent.VK_SPACE) && (fired == false)){
fired = true;
if(fired == true){
bullet();
}
}
}
public void keyReleased(KeyEvent e){
}
}
public class Mouse extends MouseAdapter {
public void mousePressed(MouseEvent e) {
double x = e.getX();
double y = e.getY();
}
}
}
HOWEVER
When I run the code without the while loop the bullet appears at the player's X position
but
When the while loop is there when the player presses the X button nothing happens, the bullet doesnt even appear!
would anybody be able to assist me in how i can make the bullet appear and move across the screen?
thanks
This is because you are not drawing the bullet until it's out of range, you should not use the while loop this way, you probably need to google for 'Game Loop' but until you do here is a snipet that may help, Note that very bad but should work:
public void paintComponent(Graphics g){
if(run == true){
g.drawImage(player, playerX, playerY, this);
if(fired == true) {
bulletX = bulletX + 10;
if(bulletX > 800 || bulletX < 0){
fired = false;
}
g.drawImage(bullet, bulletX, bulletY, this);
}
repaint();
}
}
public void bullet(){
bulletX = playerX;
bulletY = playerY;
}
one final note, move this code in the paint methode dbImage = createImage(getWidth(), getHeight()) to the constructor or the init() because you are creating a new image every frame.

Categories