I have the following program, it's a SubKiller game and I have one question. How do I make the boat launch the bomb anytime I press the down key? So far I have made to launch it multiple times. I can launch the first bomb but when I'm trying to launch the second one, the first one disappears and it doesn't continue it's way. I am stuck on this matter for almost two days, help me please.
I am going to provide you the SSCCE code.
This is the class called SubKillerPanel, basically everything is here, the boat is here, the bomb is here, the submarine is here.
import java.awt.event.*;
import javax.swing.*;
import java.awt.Graphics;
import java.awt.Color;
public class SubKillerPanel extends JPanel {
private static final long serialVersionUID = 1L;
private Timer timer;
private int width, height;
private Boat boat;
private Bomb bomb;
private Submarine sub;
public SubKillerPanel() {
setBackground(Color.WHITE);
ActionListener action = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (boat != null) {
boat.updateForNewFrame();
bomb.updateForNewFrame();
sub.updateForNewFrame();
}
repaint();
}
};
timer = new Timer( 20, action );
addMouseListener( new MouseAdapter() {
public void mousePressed(MouseEvent evt) {
requestFocus();
}
}
);
addFocusListener( new FocusListener() {
public void focusGained(FocusEvent evt) {
timer.start();
repaint();
}
public void focusLost(FocusEvent evt) {
timer.stop();
repaint();
}
}
);
addKeyListener( new KeyAdapter() {
public void keyPressed(KeyEvent evt) {
int code = evt.getKeyCode(); // ce tasta a fost apasata
if (code == KeyEvent.VK_LEFT) {
boat.centerX -= 15;
}
else
if (code == KeyEvent.VK_RIGHT) {
boat.centerX += 15;
}
else
if (code == KeyEvent.VK_DOWN) {
if (bomb.isFalling == false)
bomb.isFalling = true;
bomb.centerX = boat.centerX;
bomb.centerY = boat.centerY;
}
}
}
);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (boat == null) {
width = getWidth();
height = getHeight();
boat = new Boat();
sub = new Submarine();
bomb = new Bomb();
}
if (hasFocus())
g.setColor(Color.CYAN);
else {
g.setColor(Color.RED);
g.drawString("CLICK TO ACTIVATE", 20, 30);
g.setColor(Color.GRAY);
}
g.drawRect(0,0,width-1,height-1);
g.drawRect(1,1,width-3,height-3);
g.drawRect(2,2,width-5,height-5);
boat.draw(g);
sub.draw(g);
bomb.draw(g);
}
private class Boat {
int centerX, centerY;
Boat() {
centerX = width/2;
centerY = 80;
}
void updateForNewFrame() {
if (centerX < 0)
centerX = 0;
else
if (centerX > width)
centerX = width;
}
void draw(Graphics g) {
g.setColor(Color.blue);
g.fillRoundRect(centerX - 40, centerY - 20, 80, 40, 20, 20);
}
}
private class Bomb {
int centerX, centerY;
boolean isFalling;
Bomb() {
isFalling = false;
}
void updateForNewFrame() {
if (isFalling) {
if (centerY > height) {
isFalling = false;
}
else
if (Math.abs(centerX - sub.centerX) <= 36 && Math.abs(centerY - sub.centerY) <= 21) {
sub.isExploding = true;
sub.explosionFrameNumber = 1;
isFalling = false; // Bomba reapare in barca
}
else {
centerY += 10;
}
}
}
void draw(Graphics g) {
if ( !isFalling ) {
centerX = boat.centerX;
centerY = boat.centerY + 23;
}
g.setColor(Color.RED);
g.fillOval(centerX - 8, centerY - 8, 16, 16);
}
}
private class Submarine {
int centerX, centerY;
boolean isMovingLeft;
boolean isExploding;
int explosionFrameNumber;
Submarine() {
centerX = (int)(width*Math.random());
centerY = height - 40;
isExploding = false;
isMovingLeft = (Math.random() < 0.5);
}
void updateForNewFrame() {
if (isExploding) {
explosionFrameNumber++;
if (explosionFrameNumber == 30) {
centerX = (int)(width*Math.random());
centerY = height - 40;
isExploding = false;
isMovingLeft = (Math.random() < 0.5);
}
}
else {
if (Math.random() < 0.04) {
isMovingLeft = ! isMovingLeft;
}
if (isMovingLeft) {
centerX -= 5;
if (centerX <= 0) {
centerX = 0;
isMovingLeft = false;
}
}
else {
centerX += 5;
if (centerX > width) {
centerX = width;
isMovingLeft = true;
}
}
}
}
void draw(Graphics g) {
g.setColor(Color.BLACK);
g.fillOval(centerX - 30, centerY - 15, 60, 30);
if (isExploding) {
g.setColor(Color.YELLOW);
g.fillOval(centerX - 4*explosionFrameNumber, centerY - 2*explosionFrameNumber,
8*explosionFrameNumber, 4*explosionFrameNumber);
g.setColor(Color.RED);
g.fillOval(centerX - 2*explosionFrameNumber, centerY - explosionFrameNumber/2,
4*explosionFrameNumber, explosionFrameNumber);
}
}
}
}
The SubKiller class, where the main method is located.
import javax.swing.JFrame;
public class SubKiller {
public static void main(String[] args) {
JFrame window = new JFrame("Sub Killer Game");
SubKillerPanel content = new SubKillerPanel();
window.setContentPane(content);
window.setSize(700, 700);
window.setLocation(0,0);
window.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
window.setResizable(false);
window.setVisible(true);
}
}
You only have a single Bomb being tracked by the graphics at any time. You should build a collection of Bombs and instantiate a new one whenever the down key is pressed, then iterate through all the collection of Bombs and draw them as needed.
So, instead of private Bomb bomb;
You would have private List<Bomb> bombs;
Afterwards, anywhere you update the single bomb you can use a for loop to go through the list of bombs and have them all update, and then if they are no longer being drawn, remove them from the list.
Related
I am build a graph, with a while circle moving along a line, and stoping over for a few seconds at 3 points of the path.
I have managed to do it, however, it does not display the circle moving, it displays only when the circle stops...
I can't understand why.
Many thanks in advance for your help
Here is my code:
public class Robot0 extends JFrame implements ActionListener {
public Robot0(String nom, int larg, int haut) {
setTitle(nom);
setSize(larg, haut);
setLocationRelativeTo(null);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
Timer tm = new Timer(10, this);
private int posX = 0;
private int posY = 0;
private int velX = 1;
public int getPosX() {
return posX;
}
public void setPosX(int posX) {
this.posX = posX;
}
public int getPosY() {
return posY;
}
public void setPosY(int posY) {
this.posY = posY;
}
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.BLACK);
// Draw the pathway
int xt[] = { 50, 50, 250, 250, 350, 350 };
int yt[] = { 50, 150, 150, 50, 50, 150 };
g.drawPolyline(xt, yt, 6);
// On the pathway, draw 3 squares (the 3 rooms)
g.setColor(Color.GREEN);
g.drawRect(35, 135, 30, 30);
g.drawRect(235, 35, 30, 30);
g.drawRect(335, 135, 30, 30);
g.setColor(Color.WHITE);
g.fillOval(40 + posX, 40 + posY, 20, 20);
g.setColor(Color.RED);
g.drawLine(45 + posX, 50 + posY, 55 + posX, 50 + posY);
g.drawLine(50 + posX, 45 + posY, 50 + posX, 55 + posY);
tm.start();
}
int segment = 0;
public void actionPerformed(ActionEvent e) {
// move along the 1st segment
if (posY < 100 && segment == 0) {
setPosY(posY + velX);
}
if (posY == 100 && posX == 0) {
segment = 1;
try {
Thread.sleep(15000);
} catch (InterruptedException ex) {
Logger.getLogger(Robot0.class.getName()).log(Level.SEVERE, null, ex);
}
}
// move along the second segment
if (posX <= 200 && segment == 1) {
setPosX(posX + velX);
}
if (posX == 200 && posY == 100) {
segment = 2;
}
// move along the third segment
if (posY > 0 && segment == 2) {
setPosY(posY - velX);
}
if (posX == 200 && posY == 0) {
segment = 3;
try {
Thread.sleep(15000);
} catch (InterruptedException ex) {
Logger.getLogger(Robot0.class.getName()).log(Level.SEVERE, null, ex);
}
}
// move along the fourth segment
if (posX < 300 && segment == 3) {
setPosX(posX + velX);
}
if (posX == 300 && posY == 0) {
segment = 4;
}
// move along the fifth segment
if (posY < 100 && segment == 4) {
setPosY(posY + velX);
}
if (posX == 300 && posY == 100) {
segment = 6;
try {
Thread.sleep(15000);
} catch (InterruptedException ex) {
Logger.getLogger(Robot0.class.getName()).log(Level.SEVERE, null, ex);
}
}
repaint();
}
// Build the Panel
public static void main(String[] args) {
Robot0 r = new Robot0("Robot0", 800, 600);
}
}
Swing is a single Thread library. All painting tasks are executed in the Event Dispatcher Thread
(EDT).
As commented by Andrew Thompson, running long processes (such as sleep) on the EDT makes keeps this thread busy, so it does not do other things
like updating the gui.
The gui becomes unresponsive (freezes).
So the first thing to do is to remove all sleeping.
To park at each stop, use a second timer:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class Robot0 extends JFrame implements ActionListener {
private static final int PARKING_TIME = 15000;
Timer moveTimer , waitTimer;
private boolean isParking = false;
public Robot0(String nom, int larg, int haut) {
moveTimer = new Timer(10, this);
waitTimer = new Timer(PARKING_TIME, e-> isParking = false);
waitTimer.setRepeats(false);
setTitle(nom);
setSize(larg, haut);
setLocationRelativeTo(null);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
private int posX = 0;
private int posY = 0;
private final int velX = 1;
public int getPosX() {
return posX;
}
public void setPosX(int posX) {
this.posX = posX;
}
public int getPosY() {
return posY;
}
public void setPosY(int posY) {
this.posY = posY;
}
#Override
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.BLACK);
// Draw the pathway
int xt[] = { 50, 50, 250, 250, 350, 350 };
int yt[] = { 50, 150, 150, 50, 50, 150 };
g.drawPolyline(xt, yt, 6);
// On the pathway, draw 3 squares (the 3 rooms)
g.setColor(Color.GREEN);
g.drawRect(35, 135, 30, 30);
g.drawRect(235, 35, 30, 30);
g.drawRect(335, 135, 30, 30);
g.setColor(Color.WHITE);
g.fillOval(40 + posX, 40 + posY, 20, 20);
g.setColor(Color.RED);
g.drawLine(45 + posX, 50 + posY, 55 + posX, 50 + posY);
g.drawLine(50 + posX, 45 + posY, 50 + posX, 55 + posY);
moveTimer.start();
}
int segment = 0;
#Override
public void actionPerformed(ActionEvent e) {
if(isParking) return; //execute only when not parking
// move along the 1st segment
if (posY < 100 && segment == 0) {
setPosY(posY + velX);
}
if (posY == 100 && posX == 0 && segment != 1) { //!=1 so it will not be invoked again
segment = 1;
isParking = true; //flag that robot is parking
waitTimer.start();
return;
}
// move along the second segment
if (posX <= 200 && segment == 1) {
setPosX(posX + velX);
}
if (posX == 200 && posY == 100) {
segment = 2;
}
// move along the third segment
if (posY > 0 && segment == 2) {
setPosY(posY - velX);
}
if (posX == 200 && posY == 0 && segment !=3) {
segment = 3;
isParking = true;
waitTimer.start();
return;
}
// move along the fourth segment
if (posX < 300 && segment == 3) {
setPosX(posX + velX);
}
if (posX == 300 && posY == 0) {
segment = 4;
}
// move along the fifth segment
if (posY < 100 && segment == 4) {
setPosY(posY + velX);
}
if (posX == 300 && posY == 100 && segment !=6) {
segment = 6;
isParking = true;
waitTimer.start();
return;
}
repaint();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(()->new Robot0("Robot0", 800, 600));
}
}
TODO:
Implement custom painting on JPanel.
Simplify actionPerformed
logic
Edit: the following is an implementation with some improvements not necessarily related to question asked:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class Robot0 extends JFrame {
public Robot0(String nom) {
setTitle(nom);
setLocationRelativeTo(null);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(new Floor());
pack();
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(()->new Robot0("Robot0"));
}
}
class Floor extends JPanel implements ActionListener{
private static final int PARKING_TIME = 5000, REPAINT_TIME = 10, W = 400, H = 200;
private static final int ROOM_SIZE = 30, ROBOT_SIZE = 20, CROSS_SIZE = 10;
private final Timer moveTimer , waitTimer;
private boolean isParking = false;
private int posX = 0, posY = 0;
private final int velX = 1;
// pathway
private static final int PATH_X[] = { 50, 50, 250, 250, 350, 350 };
private static final int PATH_Y[] = { 50, 150, 150, 50, 50, 150 };
//rooms
private static final Point[] ROOM_CENTERS = {new Point(PATH_X[1],PATH_Y[1]),
new Point(PATH_X[3],PATH_Y[3]),
new Point(PATH_X[5],PATH_Y[5]) };
Floor() {
moveTimer = new Timer(REPAINT_TIME, this);
waitTimer = new Timer(PARKING_TIME, e-> isParking = false);
waitTimer.setRepeats(false);
posX = PATH_X[0]; posY = PATH_Y[0];
setPreferredSize(new Dimension(W, H));
moveTimer.start(); //no need to restart with every paint
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
g.drawPolyline(PATH_X, PATH_Y, 6);
// draw rooms
g.setColor(Color.GREEN);
for(Point center : ROOM_CENTERS){
drawSquareAround(center, g);
}
//robot
g.setColor(Color.WHITE);
g.fillOval( posX - ROBOT_SIZE/2 , posY - ROBOT_SIZE/2 , ROBOT_SIZE, ROBOT_SIZE);
//cross
g.setColor(Color.RED);
g.drawLine(posX - CROSS_SIZE/2, posY, posX + CROSS_SIZE/2, posY);
g.drawLine(posX, posY - CROSS_SIZE/2, posX, posY + CROSS_SIZE/2);
}
private void drawSquareAround(Point center, Graphics g) {
g.drawRect(center.x - ROOM_SIZE/2, center.y - ROOM_SIZE/2, ROOM_SIZE, ROOM_SIZE);
}
#Override
public void actionPerformed(ActionEvent e) {
if(isParking) return; //execute only when not parking
if (posX <= PATH_X[0] && posY < PATH_Y[1]) {// move along the 1st segment
setPosY(posY + velX);
}else if (posX < PATH_X[2] && posY == PATH_Y[1]) { //move along the second segment
setPosX(posX + velX);
}else if (posX == PATH_X[2] && posY > PATH_Y[3]) { //move along the third segment
setPosY(posY - velX);
}else if (posY == PATH_Y[3] && posX < PATH_X[4]) {// move along the fourth segment
setPosX(posX + velX);
}else if (posX == PATH_X[4] && posY < PATH_Y[5]){// move along the fifth segment
setPosY(posY + velX);
}else {
moveTimer.stop(); //move finished, stop repainting
return;
}
//park if at room center
if(isRoomCeter()){
park();
}
repaint();
}
private void park() {
isParking = true; //flag that robot is parking
waitTimer.start();
}
private boolean isRoomCeter() {
for (Point center : ROOM_CENTERS){
if(posX == center.x && posY == center.y) return true;
}
return false;
}
public int getPosX() {
return posX;
}
public void setPosX(int posX) {
this.posX = posX;
}
public int getPosY() {
return posY;
}
public void setPosY(int posY) {
this.posY = posY;
}
}
I want to add a simple menu to my Java Snake game which will contain three buttons (New Game, Difficulty and Quit). I have created a class for the menu and a class for the mouse input. I have used an enum to store the states of the game (MAIN_MENU, DIFFICULTY_MENU and GAME) and a variable called STATE which stores the current state.
The main problem is that although the state of the game is changed when the "New Game" button is pressed the game doesn't start. I have tried to add game state checks inside the methods that are involved in setting the gameplay and I have also tried calling those methods from the mousePressed() method of the MouseInput class but none of these worked.
I would greatly appreciate if you could give me some tips on how to solve this issue.
Here's my code:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class SnakeGame extends JFrame{
public SnakeGame() {
initGUI();
}
public void initGUI() {
add(new GamePlay());
setResizable(false);
pack();
setTitle("The Snake");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
JFrame frame = new SnakeGame();
frame.setVisible(true);
});
}
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.*;
public class GamePlay extends JPanel implements ActionListener {
public static final int HEIGHT = 600;
public static final int WIDTH = 600;
private final int TOTAL_DOTS = 3600;
private final int DOT_SIZE = 10;
private final int RAND_POSITION = 29;
//private final int DELAY = 140;
private final int[] X = new int[TOTAL_DOTS];// the dots on X axis
private final int[] Y = new int[TOTAL_DOTS];//the dots on Y axis
private int dots;
private int apple_X;
private int apple_Y;
private int score = 0;
private int DELAY = 140;
private boolean leftDirection = false;
private boolean rightDirection = true;
private boolean upDirection = false;
private boolean downDirection = false;
private boolean inGame = true;
private Timer timer;
private Image bodyPart;
private Image snakeHead;
private Image apple;
private Menu menu;
public static GameState STATE = GameState.MAIN_MENU;//current game state(it changes when menu buttons are pressed)
public static enum GameState{
MAIN_MENU,
DIFFICULTY_MENU,
GAME
}
public GamePlay() {
setGamePlay();
}
public void setGamePlay() {
addKeyListener(new KeyboardEvent());
addMouseListener(new MouseInput());
setBackground(Color.BLACK);
setFocusable(true);
setPreferredSize(new Dimension(WIDTH, HEIGHT));
if(STATE == GameState.GAME) {
loadImages();
startGame();
}
}
private void loadImages() {
ImageIcon img2 = new ImageIcon("src/images/dot.png");
bodyPart = img2.getImage();
ImageIcon img1 = new ImageIcon("src/images/head.png");
snakeHead = img1.getImage();
ImageIcon img3 = new ImageIcon("src/images/apple.png");
apple = img3.getImage();
}
//setting the starting snake length and the apple position on the board
public void startGame() {
dots = 3;
for(int i = 0 ; i < dots; i++) {
X[i] = 50 - i * 10;
Y[i] = 50;
}
locateApple();
timer = new Timer(DELAY,this);
//timer.start();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if(STATE == GameState.GAME) {
draw(g);
}else if(STATE == GameState.MAIN_MENU) {
new Menu().displayMainMenu(g);
}else if(STATE == GameState.DIFFICULTY_MENU) {
new Menu().displayDifficultyMenu(g);
}
System.out.println("End of paint component method");
}
public void draw(Graphics g) {
scoreDisplay(g);
if(inGame) {
g.drawImage(apple, apple_X, apple_Y,this);
for(int i = 0 ; i < dots; i++) {
if(i == 0) {
g.drawImage(snakeHead,X[i], Y[i], this);
}else {
g.drawImage(bodyPart, X[i], Y[i], this);
}
}
Toolkit.getDefaultToolkit().sync();
}else {
gameOver(g);
}
}
public void gameOver(Graphics g) {
String msg = "Game Over!";
String msg2 = "Score: " + score + " " + "Length: " + dots;
Font small = new Font("Comic Sans",Font.BOLD,14 );
FontMetrics messageSize = getFontMetrics(small);
g.setColor(Color.WHITE);
g.setFont(small);
g.drawString(msg, (WIDTH - messageSize.stringWidth(msg)) / 2, HEIGHT / 2);
g.drawString(msg2, (WIDTH - messageSize.stringWidth(msg2)) / 2, (HEIGHT / 2) + 20);
restartMessageDisplay(g);
}
public void scoreDisplay(Graphics g) {
String gameScore = "Score: " + score;
String snakeLength = "Snake length: " + dots;
Font small = new Font("Arial", Font.BOLD, 14);
g.setColor(Color.WHITE);
g.setFont(small);
g.drawString(gameScore,480, 20);
g.drawString(snakeLength, 480, 40);
}
public void restartMessageDisplay(Graphics g) {
String restartMessage = " Press Enter to restart";
Font small = new Font("Arial", Font.BOLD, 14);
FontMetrics metrics = getFontMetrics(small);
g.drawString(restartMessage, (WIDTH - metrics.stringWidth(restartMessage)) / 2, (HEIGHT / 2) + 40);
}
private void checkApple() {
if((X[0] == apple_X) && (Y[0] == apple_Y)) {
dots++;
locateApple();
score += 5;//score update
DELAY -= 5;// speed increase when snake eats the apple
if(DELAY >= 40) {
timer.setDelay(DELAY);
}
}
}
//snake move logic
private void move() {
for(int i = dots; i > 0; i--) {
X[i] = X[(i-1)];
Y[i] = Y[(i-1)];
}
if(leftDirection) {
X[0] -= DOT_SIZE;
}
if(rightDirection) {
X[0] += DOT_SIZE;
}
if(upDirection) {
Y[0] -= DOT_SIZE;
}
if(downDirection) {
Y[0] += DOT_SIZE;
}
}
//checking for collision with the walls or the snake itself
private void checkCollision() {
for(int i = dots; i > 0; i--) {
if((i > 4) && (X[0] == X[i]) && (Y[0] == Y[i])) {
inGame = false;
}
}
if(X[0] < 0) {
inGame = false;
}
if(X[0] > WIDTH) {
inGame = false;
}
if(Y[0] < 0) {
inGame = false;
}
if(Y[0] > HEIGHT) {
inGame = false;
}
if(!inGame) {
timer.stop();
}
}
//setting apple position on the board
public void locateApple() {
int random = (int) (Math.random() * RAND_POSITION);
apple_X = random * DOT_SIZE;
random = (int) (Math.random()* RAND_POSITION);
apple_Y = random * DOT_SIZE;
}
#Override
public void actionPerformed(ActionEvent e) {
if(inGame) {
checkApple();
checkCollision();
move();
}
repaint();
}
private class KeyboardEvent extends KeyAdapter {
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if((keyCode == KeyEvent.VK_LEFT) && (!rightDirection)) {
leftDirection = true;
upDirection = false;
downDirection = false;
}
if((keyCode == KeyEvent.VK_RIGHT) && (!leftDirection)) {
rightDirection = true;
upDirection = false;
downDirection = false;
}
if((keyCode == KeyEvent.VK_UP) && (!downDirection)) {
upDirection = true;
leftDirection = false;
rightDirection = false;
}
if((keyCode == KeyEvent.VK_DOWN) && (!upDirection)) {
downDirection = true;
leftDirection = false;
rightDirection = false;
}
if(keyCode == KeyEvent.VK_PAUSE) {
timer.stop();
}
if(keyCode == KeyEvent.VK_SPACE) {
timer.start();
}
//game restart
if(keyCode == KeyEvent.VK_ENTER) {
if(!inGame) {
inGame = true;
leftDirection = false;
rightDirection = true;
upDirection = false;
downDirection = false;
score = 0;
DELAY = 140;
setGamePlay();
repaint();
}
}
}
}
}
import java.awt.*;
import javax.swing.*;
public class Menu {
public Rectangle newGameButton;
public Rectangle gameDifficultyButton;
public Rectangle quitButton;
public Rectangle easyDifficultyButton;
public Rectangle mediumDifficultyButton;
public Rectangle hardDifficultyButton;
public Button button1;
public Menu() {
int buttonWidth = 150;
int buttonHeight = 50;
newGameButton = new Rectangle((GamePlay.WIDTH - buttonWidth) / 2, (GamePlay.HEIGHT / 2) - 50, buttonWidth, buttonHeight);
gameDifficultyButton = new Rectangle((GamePlay.WIDTH - buttonWidth) / 2, (GamePlay.HEIGHT / 2) + 50, buttonWidth, buttonHeight);
quitButton = new Rectangle((GamePlay.WIDTH - buttonWidth) / 2, (GamePlay.HEIGHT / 2) + 150, buttonWidth, buttonHeight);
easyDifficultyButton = new Rectangle((GamePlay.WIDTH - buttonWidth) / 2, (GamePlay.HEIGHT / 2) - 50, buttonWidth, buttonHeight);
mediumDifficultyButton = new Rectangle((GamePlay.WIDTH - buttonWidth) / 2, (GamePlay.HEIGHT / 2) + 50, buttonWidth, buttonHeight);
hardDifficultyButton = new Rectangle((GamePlay.WIDTH - buttonWidth) / 2, (GamePlay.HEIGHT / 2) + 150, buttonWidth, buttonHeight);
}
public void displayMainMenu(Graphics g) {
Graphics2D buttonGraphics =(Graphics2D) g;
String title = "THE SNAKE GAME";
Font font = new Font("Arial", Font.BOLD, 50);
FontMetrics size = g.getFontMetrics(font);
g.setFont(font);
g.setColor(Color.WHITE);
g.drawString(title,(GamePlay.WIDTH-size.stringWidth(title)) / 2, (GamePlay.HEIGHT / 2) - 130);
Font buttonFont = new Font("Arial", Font.BOLD, 28);
g.setFont(buttonFont);
g.drawString("New Game",newGameButton.x + 2, newGameButton.y + 35);
buttonGraphics.draw(newGameButton);
g.drawString("Difficulty",gameDifficultyButton.x + 15,gameDifficultyButton.y + 35);
buttonGraphics.draw(gameDifficultyButton);
g.drawString("Quit", quitButton.x + 45, quitButton.y + 35);
buttonGraphics.draw(quitButton);
}
public void displayDifficultyMenu(Graphics g) {
Graphics2D difficultyMenuGraphics = (Graphics2D) g;
String title = "Difficulty level";
Font difficultyMenuTitleFont = new Font("Arial", Font.BOLD,40);
FontMetrics size = g.getFontMetrics(difficultyMenuTitleFont);
g.setFont(difficultyMenuTitleFont);
g.setColor(Color.WHITE);
g.drawString(title, (GamePlay.WIDTH - size.stringWidth(title)) / 2, (GamePlay.HEIGHT / 2) - 100);
Font difficultyButtonFont = new Font("Arial", Font.BOLD, 28);
g.setFont(difficultyButtonFont);
g.drawString("Easy", easyDifficultyButton.x + 40 , easyDifficultyButton.y + 35);
difficultyMenuGraphics.draw(easyDifficultyButton);
g.drawString("Medium",mediumDifficultyButton.x + 20, mediumDifficultyButton.y + 35);
difficultyMenuGraphics.draw(mediumDifficultyButton);
g.drawString("Hard", hardDifficultyButton.x + 40, hardDifficultyButton.y + 35);
difficultyMenuGraphics.draw(hardDifficultyButton);
}
}
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.lang.Thread.State;
public class MouseInput extends MouseAdapter {
public Rectangle newGameButton;
public Rectangle gameDifficultyButton;
public Rectangle quitButton;
public Rectangle easyDifficultyButton;
public Rectangle mediumDifficultyButton;
public Rectangle hardDifficultyButton;
Graphics g;
public void mousePressed(MouseEvent e) {
int mouseX = e.getX();
int mouseY = e.getY();
//NewGame button
if(mouseX >= (GamePlay.WIDTH - 150) / 2 && mouseX <= ((GamePlay.WIDTH - 150) / 2) + 150) {
if(mouseY >= (GamePlay.HEIGHT / 2) - 50 && mouseY <= (GamePlay.HEIGHT/ 2)) {
GamePlay.STATE = GamePlay.GameState.GAME;
System.out.println(GamePlay.STATE);
}
}
//Difficulty button
if(mouseX >= (GamePlay.WIDTH - 150) / 2 && mouseX <= ((GamePlay.WIDTH - 150)/ 2 ) + 150) {
if(mouseY >= (GamePlay.HEIGHT / 2) + 50 && mouseY <= (GamePlay.HEIGHT/ 2) + 100) {
GamePlay.STATE = GamePlay.STATE.DIFFICULTY_MENU;
System.out.println("Game state = " + GamePlay.STATE)
}
}
//Quit button
if(mouseX >= (GamePlay.WIDTH - 150) / 2 && mouseX <= ((GamePlay.WIDTH - 150)/ 2 ) + 150) {
if(mouseY >= (GamePlay.HEIGHT / 2) + 150 && mouseY <= (GamePlay.HEIGHT/ 2) + 200) {
System.exit(0);
}
}
}
}
My program is throwing a NullPointerException error upon trying to call the paint method of a ship.
import java.awt.*;
import java.awt.event.*;
public class Ship extends Polygon implements ActionListener, KeyListener {
final static Point[] shape = new Point[4];
final static Point START_POSITION = new Point(400, 300);
private int windowX;
private int windowY;
Point pull;
public Ship(int maxX, int maxY) {
super(shape, START_POSITION, 0);
windowX = maxX;
windowY = maxY;
shipInit();
init(shape);
Point[] pointArray = getPoints();
pull = new Point(0, 0);
}
public void shipInit() {
shape[0] = new Point(0, 0);
shape[1] = new Point(30, 10);
shape[2] = new Point(0, 20);
shape[3] = new Point(10, 10);
}
public void paint(Graphics brush) {
brush.setColor(Color.white);
Point[] points = getPoints();
if (position.x > windowX) {
position.x -= windowX;
} else if (position.x < 0) {
position.x += windowX;
} else if (position.y > windowY) {
position.y -= windowY;
} else if (position.y < 0) {
position.x += windowY;
}
for (int i = 0; i < points.length; i++) {
int x1;
int y1;
int x2;
int y2;
if (i == points.length - 1) {
x1 = (int) points[i].x;
y1 = (int) points[i].y;
x2 = (int) points[0].x;
y2 = (int) points[0].y;
} else {
x1 = (int) points[i].x;
y1 = (int) points[i].y;
x2 = (int) points[i + 1].x;
y2 = (int) points[i + 1].y;
}
brush.drawLine(x1, y1, x2, y2);
}
}
public void move() {
position.x += 2;
position.y += 5;
// position.y += 1;
}
public void accelerate(double acceleration) {
pull.x += (acceleration * Math.cos(Math.toRadians(rotation)));
pull.y += (acceleration * Math.sin(Math.toRadians(rotation)));
}
public void keyPressed(KeyEvent e) {
int keyPressed = e.getKeyCode();
if (keyPressed == KeyEvent.VK_W)
System.out.println("Hi");
if (keyPressed == KeyEvent.VK_UP) {
accelerate(5);
position.x += pull.x;
position.y += pull.y;
}
if (keyPressed == KeyEvent.VK_RIGHT) {
rotation += 5;
}
if (keyPressed == KeyEvent.VK_LEFT) {
rotation -= 5;
}
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
}
And the class the calls the paint
import java.awt.*;
import java.awt.event.*;
class Asteroids extends Game {
private static int frameWidth = 800;
private static int frameHeight = 600;
Ship player;
public Asteroids() {
super("Asteroids!", frameWidth, frameHeight);
init();
}
public void init() {
player = new Ship(800, 600);
this.addKeyListener(player);
repaint();
}
public void paint(Graphics brush) {
brush.setColor(Color.black);
brush.fillRect(0, 0, width,height);
brush.setColor(Color.white);
String hi = "hi";
brush.drawString(hi, 299, 399);
player.paint(brush);
}
public static void main (String[] args) {
new Asteroids();
}
}
The error says that the error is thrown when calling player.paint(brush). Can anyone figure out why?
I have never coded in this before, but a quick trip to the universe of google explained to me that paint() and init() runs on 2 different threads.
That said, your paint() method gets called BEFORE the init() method.
A quick way to fix this would be to have a boolean that gets set inside init()
Like this:
import java.awt.*;
import java.awt.event.*;
class Asteroids extends Game {
private static int frameWidth = 800;
private static int frameHeight = 600;
Ship player;
private boolean hasInitialized; // Initialization check
public Asteroids() {
super("Asteroids!", frameWidth, frameHeight);
init();
}
public void init() {
player = new Ship(800, 600);
this.addKeyListener(player);
hasInitialized = true; // We set the boolean to true to indicate that we have initialized.
repaint();
}
public void paint(Graphics brush) {
if (!hasInitialized) return; // Nope, not ready yet, we'll stop here.
brush.setColor(Color.black);
brush.fillRect(0, 0, width,height);
brush.setColor(Color.white);
String hi = "hi";
brush.drawString(hi, 299, 399);
player.paint(brush);
}
public static void main (String[] args) {
new Asteroids();
}
}
I'm not 100% certain this will fix it, considering you already have init() inside the constructor.
But it's worth a try!
Source: Java, applet: How to block the activation of paint() before init() finishes it's work
I am trying to draw 7 random circles across a JPanel using an array. I managed to get the array to work but now I am having trouble spacing out the circles. When i run the program i see multiple circles being drawn but they are all on the same spot. All the circles are of different size and color. The other problem i have is making the circles move towards the bottom of the screen.
public class keyExample extends JPanel implements ActionListener, KeyListener{
private Circle[] circles = new Circle[7];
Timer t = new Timer(5,this);
//current x and y
double x = 150, y = 200;
double changeX = 0, changeY = 0;
private int circlex = 0,circley = 0; // makes initial starting point of circles 0
private javax.swing.Timer timer2;
public keyExample(){
t.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
NewCircle();
timer2 = new javax.swing.Timer(33,new MoveListener());
timer2.start();
}
public void NewCircle(){
Random colors = new Random();
Color color = new Color(colors.nextInt(256),colors.nextInt(256),colors.nextInt(256));
Random num= new Random();
int radius = num.nextInt(45);
for (int i = 0; i < circles.length; i++)
circles[i] = new Circle(circlex,circley,radius,color);
}
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.BLUE);
g2.fill(new Rectangle2D.Double(x,y,40,40));
for (int i = 0; i < circles.length; i++)
circles[i].fill(g);
}
public void actionPerformed(ActionEvent e){
repaint();
x += changeX;
y += changeY;
changeX = 0;
changeY = 0;
}
public void up() {
if (y != 0){
changeY = -3.5;
changeX = 0;
}
}
public void down() {
if (y <= 350){
changeY = 3.5;
changeX = 0;
}
}
public void left() {
if (x >= 0) {
changeX = -3.5;
changeY = 0;
}
}
public void right() {
if (x <= 550) {
changeX = 3.5;
changeY = 0;
}
}
private class MoveListener implements ActionListener{
public void actionPerformed(ActionEvent e){
repaint();
Random speed = new Random();
int s = speed.nextInt(8);
}
}
public void keyPressed(KeyEvent e){
int code = e.getKeyCode();
if (code == KeyEvent.VK_UP){
up();
}
if (code == KeyEvent.VK_DOWN){
down();
}
if (code == KeyEvent.VK_RIGHT){
right();
}
if (code == KeyEvent.VK_LEFT){
left();
}
}
public void keyTyped(KeyEvent e) { }
public void keyReleased(KeyEvent e) { }
}
Circle class
import java.awt.*;
public class Circle{
private int centerX, centerY, radius, coord;
private Color color;
public Circle(int x, int y, int r, Color c){
centerX = x;
centerY = y;
radius = r;
color = c;
}
public void draw(Graphics g){
Color oldColor = g.getColor();
g.setColor(color);
g.drawOval(centerX - radius, centerY - radius, radius * 2, radius * 2);
g.setColor(oldColor);
}
public void fill(Graphics g){
Color oldColor = g.getColor();
g.setColor(color);
g.fillOval(centerX - radius, centerY - radius, radius *2, radius * 2);
g.setColor(oldColor);
}
public boolean containsPoint(int x, int y){
int xSquared = (x - centerX) * (x - centerX);
int ySquared = (y - centerY) * (y - centerY);
int RadiusSquared = radius * radius;
return xSquared + ySquared - RadiusSquared <=0;
}
public void move(int xAmount, int yAmount){
centerX = centerX + xAmount;
centerY = centerY + yAmount;
}
}
This is one of the problems with relying on borrowed code that you don't understand...
Basically, all you need to do is change the creation of the circles, for example...
for (int i = 0; i < circles.length; i++) {
circles[i] = new Circle(circlex, circley, radius, color);
circlex += radius;
}
You may wish to re-consider the use of KeyListener, in favour of Key Bindings before you discover that KeyListener doesn't work the way you expect it to...
For some strange reason, you're calling NewCirlces from within the MoveListener's actionPerfomed method, meaning that the circles are simply being re-created on each trigger of the Timer...instead, call it first in the constructor
You're also calling within your paintComponent method...this should mean that the circles never move and instead, random change size...
Updated with runnable example...
I modified your paint code NewCircle and the MoveListener a little...
import java.awt.Color;
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.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Rectangle2D;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class CircleExample extends JPanel implements ActionListener, KeyListener {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new CircleExample());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
private Circle[] circles = new Circle[7];
Timer t = new Timer(5, this);
//current x and y
double x = 150, y = 200;
double changeX = 0, changeY = 0;
private int circlex = 0, circley = 0; // makes initial starting point of circles 0
private javax.swing.Timer timer2;
public CircleExample() {
NewCircle();
t.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
timer2 = new javax.swing.Timer(33, new MoveListener());
timer2.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
public void NewCircle() {
for (int i = 0; i < circles.length; i++) {
Random colors = new Random();
Color color = new Color(colors.nextInt(256), colors.nextInt(256), colors.nextInt(256));
Random num = new Random();
int radius = num.nextInt(90);
circles[i] = new Circle(circlex, circley, radius, color);
circlex += radius;
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.BLUE);
g2.fill(new Rectangle2D.Double(x, y, 40, 40));
for (int i = 0; i < circles.length; i++) {
circles[i].fill(g);
}
}
#Override
public void actionPerformed(ActionEvent e) {
repaint();
x += changeX;
y += changeY;
changeX = 0;
changeY = 0;
}
public void up() {
if (y != 0) {
changeY = -3.5;
changeX = 0;
}
}
public void down() {
if (y <= 350) {
changeY = 3.5;
changeX = 0;
}
}
public void left() {
if (x >= 0) {
changeX = -3.5;
changeY = 0;
}
}
public void right() {
if (x <= 550) {
changeX = 3.5;
changeY = 0;
}
}
private class MoveListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
Random speed = new Random();
for (Circle circle : circles) {
int s = speed.nextInt(8);
circle.move(0, s);
}
repaint();
}
}
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if (code == KeyEvent.VK_UP) {
up();
}
if (code == KeyEvent.VK_DOWN) {
down();
}
if (code == KeyEvent.VK_RIGHT) {
right();
}
if (code == KeyEvent.VK_LEFT) {
left();
}
}
public void keyTyped(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
}
public class Circle {
private int centerX, centerY, radius, coord;
private Color color;
public Circle(int x, int y, int r, Color c) {
centerX = x;
centerY = y;
radius = r;
color = c;
}
public void draw(Graphics g) {
Color oldColor = g.getColor();
g.setColor(color);
g.drawOval(centerX, centerY, radius, radius);
g.setColor(oldColor);
}
public void fill(Graphics g) {
Color oldColor = g.getColor();
g.setColor(color);
g.fillOval(centerX, centerY, radius, radius);
g.setColor(oldColor);
}
public boolean containsPoint(int x, int y) {
int xSquared = (x - centerX) * (x - centerX);
int ySquared = (y - centerY) * (y - centerY);
int RadiusSquared = radius * radius;
return xSquared + ySquared - RadiusSquared <= 0;
}
public void move(int xAmount, int yAmount) {
centerX = centerX + xAmount;
centerY = centerY + yAmount;
}
}
}
I know I have asked a question like this before, but none of the answers in the old question worked for me. I am trying to make a little single-player pong game (It is in a Java applet). I already have a moveBall() function, as you can see below. But I don't know where to call it. I can't call it in the paint() method because it is double buffered.
public class Main extends Applet implements KeyListener, MouseListener {
private Rectangle paddle;
private Rectangle ball;
private ArrayList<Integer> keysDown;
private Image dbImage;
private Graphics dbg;
public int time = 300000;
Random randomGenerator = new Random();
int speed = 10;
int level = 1; // change to 0 once start menu works
int xpos, ypos;
int ballx, bally;
int width = 1024;
int height = 768;
int paddleWidth = 96;
int ballSize = 16;
String version = "0.0.1";
public static final int START_X_POS = 160;
public static final int START_Y_POS = 160;
public static final int START_WIDTH = 256;
public static final int START_HEIGHT = 64;
boolean startClicked;
boolean falling = true;
public void init() {
setSize(width, height);
addKeyListener(this);
addMouseListener(this);
setBackground(Color.black);
Frame c = (Frame)getParent().getParent();
c.setTitle("Asteroid Attack - Version " + version);
keysDown = new ArrayList<Integer>();
paddle = new Rectangle(getWidth()/2-paddleWidth, getHeight()-96, paddleWidth, 12);
ball = new Rectangle(getWidth()/2-ballSize, 96, ballSize, ballSize);
}
public void update(Graphics g) {
dbImage = createImage(getSize().width, getSize().height);
dbg = dbImage.getGraphics ();
if (dbImage == null) {}
dbg.setColor(getBackground ());
dbg.fillRect(0, 0, getSize().width, getSize().height);
dbg.setColor(getForeground());
paint(dbg);
g.drawImage(dbImage, 0, 0, this);
}
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
if (level != 0) {
g2.setPaint(Color.gray);
g2.fill(paddle);
g2.setPaint(Color.darkGray);
g2.fill(ball);
moveBall();
}
}
public void moveBall() {
bally = ball.y;
ballx = ball.x;
if (bally < paddle.y-32 && falling) {
bally += 12;
}
if (bally < paddle.y-32 && falling && paddle.x <= ballx && paddle.getMaxX() >= ball.x) { // collides with paddle
falling = false;
}
else { // does not collide with paddle
}
ball.setLocation(ballx, bally);
}
#Override
public void keyPressed(KeyEvent e) {
if (!keysDown.contains(e.getKeyCode()))
keysDown.add(new Integer(e.getKeyCode()));
key();
}
#Override
public void keyReleased(KeyEvent e) {
keysDown.remove(new Integer(e.getKeyCode()));
}
public void key() {
if (level != 0) {
int x = paddle.x;
int y = paddle.y;
if (keysDown.contains(KeyEvent.VK_ESCAPE)) {System.exit(0);}
if (x > 0 && x+paddleWidth < this.getWidth()) {
if (keysDown.contains(KeyEvent.VK_LEFT)) {x -= speed;}
if (keysDown.contains(KeyEvent.VK_RIGHT)) {x += speed;}
}
else { // so paddle doesn't exit room
if (x <= 0) {x += 4;}
else {x -= 4;}
}
paddle.setLocation(x, y);
repaint();
}
}
#Override
public void keyTyped(KeyEvent e) {}
#Override
public void mouseClicked(MouseEvent me) {
if (level == 0) {
xpos = me.getX();
ypos = me.getY();
if (xpos >= START_X_POS && ypos >= START_Y_POS && xpos <= START_X_POS + START_WIDTH && ypos <= START_X_POS + START_HEIGHT ) {
level = 1;
}
}
}
#Override
public void mouseEntered(MouseEvent me) {}
#Override
public void mouseExited(MouseEvent me) {}
#Override
public void mouseReleased(MouseEvent me) {}
#Override
public void mousePressed(MouseEvent me) {}
}
Any help would be greatly appreciated!
You'll probably want a separate Thread to move the ball which keeps track of time while in a in a loop - that way if frame rates drop, or speed up, you can try ensure consistency in the ball movement speed.
e.g. here on using a thread in a applet http://www.realapplets.com/tutorial/threadexample.html