It's the same game that I'm working on and I've come to a problem that I can't understand again. I'm using Key Bindings to move my sprite and it's working great! but since it's a snake game I need the sprite to keep moving without stopping and change direction and keep moving after the player types a key. I know it's possible with KeyListener, but I really don't want to have to change my program entirely. I just need to know what code needs to change, if possible.
On top of that I'm also working on two arrays for the x and y co-ordinates for the snake body so that squares will follow behind the head, but I can't get it to paint. and how to display an integer for the score.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Random;
import java.util.ArrayList;
public class Snake2 extends JFrame {
/* Sprite: snake head co-ordinates */
int x = 400;
int y = 450;
int width = 10;
int height = 10;
/* Sprite: snake body */
int length = 0;
ArrayList <Integer> bodyX = new ArrayList <Integer>();
ArrayList <Integer> bodyY = new ArrayList <Integer>();
/* Score */
int point = 0;
/* Sprite: mouse co-ordinates */
Random rand = new Random();
int addx = (rand.nextInt(10))*10;
int addy = (rand.nextInt(10))*10;
int mx = ((rand.nextInt(5)+1)*100) + addx;
int my = ((rand.nextInt(6)+2)*100) + addy;
DrawPanel drawPanel = new DrawPanel();
public Snake2() {
addMouseListener(new MouseListener());
System.out.print(mx + " " + my);
/* move snake up */
Action upAction = new AbstractAction(){
public void actionPerformed(ActionEvent e) {
y -=10;
if (y >= my && y <= my+9 && x >= mx && x <= mx+9)
{
addx = (rand.nextInt(10))*10;
addy = (rand.nextInt(10))*10;
mx = ((rand.nextInt(5)+1)*100) + addx;
my = ((rand.nextInt(6)+1)*100) + addy;
point += 100;
length++;
bodyY.add(0, y);
}
if (y <99)
{
new GameOver();
dispose();
}
drawPanel.repaint();
}
};
/* move snake down */
Action downAction = new AbstractAction(){
public void actionPerformed(ActionEvent e) {
y +=10;
if (y >= my && y <= my+9 && x >= mx && x <= mx+9)
{
addx = (rand.nextInt(10))*10;
addy = (rand.nextInt(10))*10;
mx = ((rand.nextInt(5)+1)*100) + addx;
my = ((rand.nextInt(6)+1)*100) + addy;
point += 100;
length++;
bodyY.add(0, y);
}
if (y > 799)
{
new GameOver();
dispose();
}
drawPanel.repaint();
}
};
/* move snake left */
Action leftAction = new AbstractAction(){
public void actionPerformed(ActionEvent e) {
x -=10;
if (x >= mx && x <= mx+9 && y >= my && y <= my+9)
{
addx = (rand.nextInt(10))*10;
addy = (rand.nextInt(10))*10;
mx = ((rand.nextInt(5)+1)*100) + addx;
my = ((rand.nextInt(6)+1)*100) + addy;
point += 100;
length++;
bodyX.add(0, x);
}
if (x <99)
{
new GameOver();
dispose();
}
drawPanel.repaint();
}
};
/* move snake right */
Action rightAction = new AbstractAction(){
public void actionPerformed(ActionEvent e) {
x +=10;
if (x >= mx && x <= mx+9 && y >= my && y <= my+9)
{
addx = (rand.nextInt(10))*10;
addy = (rand.nextInt(10))*10;
mx = ((rand.nextInt(5)+1)*100) + addx;
my = ((rand.nextInt(6)+1)*100) + addy;
point += 100;
length++;
bodyX.add(0, x);
}
if (x > 699)
{
new GameOver();
dispose();
}
drawPanel.repaint();
}
};
InputMap inputMap = drawPanel.getInputMap(JPanel.WHEN_IN_FOCUSED_WINDOW);
ActionMap actionMap = drawPanel.getActionMap();
inputMap.put(KeyStroke.getKeyStroke("RIGHT"), "rightAction");
actionMap.put("rightAction", rightAction);
inputMap.put(KeyStroke.getKeyStroke("LEFT"), "leftAction");
actionMap.put("leftAction", leftAction);
inputMap.put(KeyStroke.getKeyStroke("DOWN"), "downAction");
actionMap.put("downAction", downAction);
inputMap.put(KeyStroke.getKeyStroke("UP"), "upAction");
actionMap.put("upAction", upAction);
add(drawPanel);
pack();
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
}//Snake2()
private class GameOver extends JFrame implements ActionListener{
JLabel answer = new JLabel("");
JPanel pane = new JPanel(); // create pane object
JButton pressme = new JButton("Quit");
JButton replay = new JButton("Replay?");
GameOver() // the constructor
{
super("Game Over"); setBounds(100,100,300,200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container con = this.getContentPane(); // inherit main frame
con.add(pane); pressme.setMnemonic('Q'); // associate hotkey
pressme.addActionListener(this); // register button listener
replay.addActionListener(this);
pane.add(answer); pane.add(pressme); pane.add(replay); pressme.requestFocus();
answer.setText("You Lose");
setVisible(true); // make frame visible
}//GameOver()
// here is the basic event handler
public void actionPerformed(ActionEvent event)
{
Object source = event.getSource();
if (source == pressme)
System.exit(0);
if (source == replay)
{
dispose();
EventQueue.invokeLater(new Runnable(){
public void run(){
new Snake2();
}
});
}
}//actionPreformed
}//GameOver
private class DrawPanel extends JPanel {
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Font ith = new Font("Ithornît", Font.BOLD, 78);
/* Background: Snake */
g.setColor(Color.darkGray);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.gray);
g.fillRect(100,100,600,700);
g.setColor(Color.white);
g.drawRect(99,99,601,701);
g.drawString("Quit",102,86);
g.drawRect(100,70,30,20);
g.drawString("Score: ", 602, 86);
g.setFont(ith);
g.drawString("SNAKE",350,60);
/* Sprite: Mouse */
g.setColor(Color.black);
g.fillRect(mx, my, width, height);
//System.out.print(mx + " " + my);
/* Sprite: Snake Body */
if (length != 0){
for(int i = 0; i >= length; i++)
{
g.setColor(Color.darkGray);
g.fillRect(bodyX.get(i), bodyY.get(i), width, height);
}
}
/* Sprite: Snake head */
g.setColor(Color.white);
g.fillRect(x, y, width, height);
}//Paint Component
public Dimension getPreferredSize() {
return new Dimension(800, 850);
}//Dimension
}//DrawPanel
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable(){
public void run(){
new Snake2();
}
});
}// main
}//Snake Class
/* Tracks where mouse is clicked */
class MouseListener extends MouseAdapter {
public void mouseReleased(MouseEvent me) {
if (me.getX() >= 101 && me.getX() <= 131 && me.getY() >= 94 && me.getY() <= 115){
System.exit(0);
}
String str="Mouse Released at "+me.getX()+","+me.getY();
System.out.println(str);
}
}//MouseAdapter
"but since it's a snake game I need the sprite to keep moving without stopping"
You need to use a javax.swing.Timer. The basic constructor is like this
Timer(int delay, ActionListener listener) // delay is in milliseconds
A basic implementation would be something like this
Timer timer = new Timer(100, new ActionListener(){
public void actionPerformed(ActionEvent e) {
// do something
}
});
timer.start();
Basically what the timer does, is fire an ActionEvent every so many milliseconds. This is how you work animation with swing. So without you pressing any keys, the sprite will move by itself. It works pretty much like a button does. When you press a button an event is fired. But in the case of the timer, the timer is the one that fires the event. You can specify any delay you want. You many even want to change the duration dynamically when a certain level is reached. timer.setDelay(someInt)
UPDATE
I made very few changes to your current code. I did pretty much what I stated in the comment below
Ok so I thought about it, and I would do something like this: Have a direction variable. For the actions, all you should do is change the direction. In the timer actionPerformed thats where all you logic should go. Check for the direction. If if equals "left" then continue going left like you would on a key press. And so on
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Random;
import java.util.ArrayList;
public class Snake2 extends JFrame {
String direction = "right";
//String duration =
/* Sprite: snake head co-ordinates */
int x = 400;
int y = 450;
int width = 10;
int height = 10;
/* Sprite: snake body */
int length = 0;
ArrayList<Integer> bodyX = new ArrayList<Integer>();
ArrayList<Integer> bodyY = new ArrayList<Integer>();
/* Score */
int point = 0;
/* Sprite: mouse co-ordinates */
Random rand = new Random();
int addx = (rand.nextInt(10)) * 10;
int addy = (rand.nextInt(10)) * 10;
int mx = ((rand.nextInt(5) + 1) * 100) + addx;
int my = ((rand.nextInt(6) + 2) * 100) + addy;
DrawPanel drawPanel = new DrawPanel();
Timer timer;
public Snake2() {
addMouseListener(new MouseListener());
timer = new Timer(50, new TimerListener()); ////////////// <<<<<<<<<<<<<<<<<< TIMER
timer.start();
System.out.print(mx + " " + my);
/* move snake up */
Action upAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
direction = "up"; ////////////// <<<<<<<<<<<<<<<<<< direction only change
}
};
/* move snake down */
Action downAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
direction = "down";
}
};
/* move snake left */
Action leftAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
direction = "left";
}
};
/* move snake right */
Action rightAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
direction = "right";
}
};
InputMap inputMap = drawPanel
.getInputMap(JPanel.WHEN_IN_FOCUSED_WINDOW);
ActionMap actionMap = drawPanel.getActionMap();
inputMap.put(KeyStroke.getKeyStroke("RIGHT"), "rightAction");
actionMap.put("rightAction", rightAction);
inputMap.put(KeyStroke.getKeyStroke("LEFT"), "leftAction");
actionMap.put("leftAction", leftAction);
inputMap.put(KeyStroke.getKeyStroke("DOWN"), "downAction");
actionMap.put("downAction", downAction);
inputMap.put(KeyStroke.getKeyStroke("UP"), "upAction");
actionMap.put("upAction", upAction);
add(drawPanel);
pack();
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
}// Snake2()
private class TimerListener implements ActionListener {
public void actionPerformed(ActionEvent e) { /////////////////// <<<<<<<<<<<<<< All logic here
if ("right".equals(direction)) {
x += 10;
if (x >= mx && x <= mx + 9 && y >= my && y <= my + 9) {
addx = (rand.nextInt(10)) * 10;
addy = (rand.nextInt(10)) * 10;
mx = ((rand.nextInt(5) + 1) * 100) + addx;
my = ((rand.nextInt(6) + 1) * 100) + addy;
point += 100;
length++;
bodyX.add(0, x);
}
if (x > 699) {
new GameOver();
dispose();
}
} else if ("left".equals(direction)) {
x -= 10;
if (x >= mx && x <= mx + 9 && y >= my && y <= my + 9) {
addx = (rand.nextInt(10)) * 10;
addy = (rand.nextInt(10)) * 10;
mx = ((rand.nextInt(5) + 1) * 100) + addx;
my = ((rand.nextInt(6) + 1) * 100) + addy;
point += 100;
length++;
bodyX.add(0, x);
}
if (x < 99) {
new GameOver();
dispose();
}
} else if ("up".equals(direction)) {
y -= 10;
if (y >= my && y <= my + 9 && x >= mx && x <= mx + 9) {
addx = (rand.nextInt(10)) * 10;
addy = (rand.nextInt(10)) * 10;
mx = ((rand.nextInt(5) + 1) * 100) + addx;
my = ((rand.nextInt(6) + 1) * 100) + addy;
point += 100;
length++;
bodyY.add(0, y);
}
if (y < 99) {
new GameOver();
dispose();
}
} else if ("down".equals(direction)) {
y += 10;
if (y >= my && y <= my + 9 && x >= mx && x <= mx + 9) {
addx = (rand.nextInt(10)) * 10;
addy = (rand.nextInt(10)) * 10;
mx = ((rand.nextInt(5) + 1) * 100) + addx;
my = ((rand.nextInt(6) + 1) * 100) + addy;
point += 100;
length++;
bodyY.add(0, y);
}
if (y > 799) {
new GameOver();
dispose();
}
}
drawPanel.repaint();
}
}
private class GameOver extends JFrame implements ActionListener {
JLabel answer = new JLabel("");
JPanel pane = new JPanel(); // create pane object
JButton pressme = new JButton("Quit");
JButton replay = new JButton("Replay?");
GameOver() // the constructor
{
super("Game Over");
timer.stop(); ////////////////////// <<<<<<<<<< Stop TIMER
setBounds(100, 100, 300, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container con = this.getContentPane(); // inherit main frame
con.add(pane);
pressme.setMnemonic('Q'); // associate hotkey
pressme.addActionListener(this); // register button listener
replay.addActionListener(this);
pane.add(answer);
pane.add(pressme);
pane.add(replay);
pressme.requestFocus();
answer.setText("You Lose");
setVisible(true); // make frame visible
}// GameOver()
// here is the basic event handler
public void actionPerformed(ActionEvent event) {
Object source = event.getSource();
if (source == pressme)
System.exit(0);
if (source == replay) {
dispose();
EventQueue.invokeLater(new Runnable() {
public void run() {
new Snake2();
}
});
}
}// actionPreformed
}// GameOver
private class DrawPanel extends JPanel {
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Font ith = new Font("Ithornît", Font.BOLD, 78);
/* Background: Snake */
g.setColor(Color.darkGray);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.gray);
g.fillRect(100, 100, 600, 700);
g.setColor(Color.white);
g.drawRect(99, 99, 601, 701);
g.drawString("Quit", 102, 86);
g.drawRect(100, 70, 30, 20);
g.drawString("Score: ", 602, 86);
g.setFont(ith);
g.drawString("SNAKE", 350, 60);
/* Sprite: Mouse */
g.setColor(Color.black);
g.fillRect(mx, my, width, height);
// System.out.print(mx + " " + my);
/* Sprite: Snake Body */
if (length != 0) {
for (int i = 0; i >= length; i++) {
g.setColor(Color.darkGray);
g.fillRect(bodyX.get(i), bodyY.get(i), width, height);
}
}
/* Sprite: Snake head */
g.setColor(Color.white);
g.fillRect(x, y, width, height);
}// Paint Component
public Dimension getPreferredSize() {
return new Dimension(800, 850);
}// Dimension
}// DrawPanel
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new Snake2();
}
});
}// main
}// Snake Class
/* Tracks where mouse is clicked */
class MouseListener extends MouseAdapter {
public void mouseReleased(MouseEvent me) {
if (me.getX() >= 101 && me.getX() <= 131 && me.getY() >= 94
&& me.getY() <= 115) {
System.exit(0);
}
String str = "Mouse Released at " + me.getX() + "," + me.getY();
System.out.println(str);
}
}// MouseAdapter
Related
I have a class called enemy and another class called "goal". The goal is that the enemy has to move towards the "goal". So I got the X and Y position of the "goal" but and when I implement that in the enemy class the enemy should move but it doesn't. Why is that?
Here is what I have done so far.
Main Class:
public class GameManager extends JFrame implements KeyListener {
private int canvasWidth;
private int canvasHeight;
private int borderLeft;
private int borderTop;
private BufferedImage canvas;
private Stage stage;
private Enemy[] enemies;
private Player player;
private Goal goal;
private Graphics gameGraphics;
private Graphics canvasGraphics;
private int numEnemies;
private boolean continueGame;
public static void main(String[] args) {
// During development, you can adjust the values provided in the brackets below
// as needed. However, your code must work with different/valid combinations
// of values.
GameManager managerObj = new GameManager(1980, 1280, 30);
}
public GameManager(int preferredWidth, int preferredHeight, int maxEnemies) {
this.borderLeft = getInsets().left;
this.borderTop = getInsets().top;
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
if (screenSize.width < preferredWidth)
this.canvasWidth = screenSize.width - getInsets().left - getInsets().right;
else
this.canvasWidth = preferredWidth - getInsets().left - getInsets().right;
if (screenSize.height < preferredHeight)
this.canvasHeight = screenSize.height - getInsets().top - getInsets().bottom;
else
this.canvasHeight = preferredHeight - getInsets().top - getInsets().bottom;
setSize(this.canvasWidth, this.canvasHeight);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
addKeyListener(this);
Random rng = new Random(2);
this.canvas = new BufferedImage(this.canvasWidth, this.canvasHeight, BufferedImage.TYPE_INT_RGB);
// Create a Stage object to hold the background images
this.stage = new Stage();
// Create a Goal object with its initial x and y coordinates
this.goal = new Goal(this.canvasWidth / 2, Math.abs(rng.nextInt()) % this.canvasHeight);
// Create a Player object with its initial x and y coordinates
this.player = new Player(this.canvasWidth - (Math.abs(rng.nextInt()) % (this.canvasWidth / 2)),
(Math.abs(rng.nextInt()) % this.canvasHeight));
// Create the Enemy objects, each with a reference to this (GameManager) object
// and their initial x and y coordinates.
this.numEnemies = maxEnemies;
this.enemies = new Enemy[this.numEnemies];
for (int i = 0; i < this.numEnemies; i++) {
this.enemies[i] = new Enemy(this, Math.abs(rng.nextInt()) % (this.canvasWidth / 4),
Math.abs(rng.nextInt()) % this.canvasHeight);
}
this.gameGraphics = getGraphics();
this.canvasGraphics = this.canvas.getGraphics();
this.continueGame = true;
while (this.continueGame) {
updateCanvas();
}
this.stage.setGameOverBackground();
updateCanvas();
}
public void updateCanvas() {
long start = System.nanoTime();
// If the player is alive, this should move the player in the direction of the
// key that has been pressed
// Note: See keyPressed and keyReleased methods in the GameManager class.
this.player.performAction();
// If the enemy is alive, the enemy must move towards the goal. The goal object
// is obtained via the GameManager object that is given at the time of creating
// an Enemy object.
// Note: The amount that the enemy moves must be much smaller than that of
// the player above or else the game becomes hard to play.
for (int i = 0; i < this.numEnemies; i++) {
this.enemies[i].performAction();
}
if ((Math.abs(this.goal.getX() - this.player.getX()) < (this.goal.getCurrentImage().getWidth() / 2))
&& (Math.abs(this.goal.getY() - this.player.getY()) < (this.goal.getCurrentImage().getWidth() / 2))) {
for (int i = 0; i < this.numEnemies; i++) {
// Sets the image of the enemy to the "dead" image and sets its status to
// indicate dead
this.enemies[i].die();
}
// Sets the image of the enemy to the "dead" image and sets its status to
// indicate dead
this.goal.die();
// Sets the background of the stage to the finished game background.
this.stage.setGameOverBackground();
this.continueGame = false;
}
// If an enemy is close to the goal, the player and goal die
int j = 0;
while (j < this.numEnemies) {
if ((Math.abs(this.goal.getX() - this.enemies[j].getX()) < (this.goal.getCurrentImage().getWidth() / 2))
&& (Math.abs(this.goal.getY() - this.enemies[j].getY()) < (this.goal.getCurrentImage().getWidth()
/ 2))) {
this.player.die();
this.goal.die();
this.stage.setGameOverBackground();
j = this.numEnemies;
this.continueGame = false;
}
j++;
}
try {
// Draw stage
this.canvasGraphics.drawImage(stage.getCurrentImage(), 0, 0, null);
// Draw player
this.canvasGraphics.drawImage(player.getCurrentImage(),
this.player.getX() - (this.player.getCurrentImage().getWidth() / 2),
this.player.getY() - (this.player.getCurrentImage().getHeight() / 2), null);
// Draw enemies
for (int i = 0; i < this.numEnemies; i++) {
this.canvasGraphics.drawImage(this.enemies[i].getCurrentImage(),
this.enemies[i].getX() - (this.enemies[i].getCurrentImage().getWidth() / 2),
this.enemies[i].getY() - (this.enemies[i].getCurrentImage().getHeight() / 2), null);
}
// Draw goal
this.canvasGraphics.drawImage(this.goal.getCurrentImage(),
this.goal.getX() - (this.goal.getCurrentImage().getWidth() / 2),
this.goal.getY() - (this.goal.getCurrentImage().getHeight() / 2), null);
} catch (Exception e) {
System.err.println(e.getMessage());
}
// Draw everything.
this.gameGraphics.drawImage(this.canvas, this.borderLeft, this.borderTop, this);
long end = System.nanoTime();
this.gameGraphics.drawString("FPS: " + String.format("%2d", (int) (1000000000.0 / (end - start))),
this.borderLeft + 50, this.borderTop + 50);
}
public Goal getGoal() {
return this.goal;
}
public void keyPressed(KeyEvent ke) {
// Below, the setKey method is used to tell the Player object which key is
// currently pressed.
// The Player object must keep track of the pressed key and use it for
// determining the direction
// to move.
if (ke.getKeyCode() == KeyEvent.VK_LEFT)
this.player.setKey('L', true);
if (ke.getKeyCode() == KeyEvent.VK_RIGHT)
this.player.setKey('R', true);
if (ke.getKeyCode() == KeyEvent.VK_UP)
this.player.setKey('U', true);
if (ke.getKeyCode() == KeyEvent.VK_DOWN)
this.player.setKey('D', true);
if (ke.getKeyCode() == KeyEvent.VK_ESCAPE)
this.continueGame = false;
}
#Override
public void keyReleased(KeyEvent ke) {
// Below, the setKey method is used to tell the Player object which key is
// currently released.
// The Player object must keep track of the pressed key and use it for
// determining the direction
// to move.
if (ke.getKeyCode() == KeyEvent.VK_LEFT)
this.player.setKey('L', false);
if (ke.getKeyCode() == KeyEvent.VK_RIGHT)
this.player.setKey('R', false);
if (ke.getKeyCode() == KeyEvent.VK_UP)
this.player.setKey('U', false);
if (ke.getKeyCode() == KeyEvent.VK_DOWN)
this.player.setKey('D', false);
}
#Override
public void keyTyped(KeyEvent ke) {
}
}
Player Class:
private int myX;
private int myY;
private char d;
public Player(int i, int j) {
// TODO Auto-generated constructor stub
try {
this.imageRunning = ImageIO.read(new File(
"/Users/Desktop/images/player-alive.png"));
this.imageOver = ImageIO.read(new File(
"/Users/Desktop/images/player-dead.png"));
} catch (IOException e) {
e.printStackTrace();
}
this.imageCurrent = this.imageRunning;
myX = i;
myY = j;
}
public void performAction() {
}
public int getX() {
return myX;
}
public int getY() {
return myY;
}
public BufferedImage getCurrentImage() {
return this.imageCurrent;
}
public void die() {
this.imageCurrent = this.imageOver;
}
public void setKey(char c, boolean b) {
}
That simply changes the variables gmX and gmY. Nothing more. You need to update the frame after setting the new gmX and gmY values. Assuming frameis your JFrame object, you need something like:
public void performAction() {
gmX += 40;
gmY += 40;
frame.repaint();
}
You need to redraw graphics on the component:
gmY += 40;
repaint(); /* add this where you want to redraw */
I am trying to have each brick in my game have a random color, however when I try to do this the whole set of bricks become the same color. How do I make each individual brick a random color? Any help is appreciated.
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class Game extends JoeApplet implements KeyListener
{
String status;
int ballx = 294; // ball spawn x coordinate
int bally = 640; // ball spawn y coordinate
int batx = 294;
int baty = 654;
int brickx = 32;
int bricky = 50;
double movex = -16; // x speed of ball
double movey = -16; //y speed of ball
int count = 0;
int currentLevel=0;
int score=0; //starts score at 0
int lives=3; //lives start at 3
static boolean right = false;
static boolean left = false;
boolean ballFallDown = false;
boolean bricksOver = false;
Rectangle Ball = new Rectangle(ballx, bally, 14, 14); //creates ball
Rectangle Bat = new Rectangle(batx, baty, 100, 12); //creates bat(paddle)
Rectangle[] Brick = new Rectangle[49]; //creates desired number of bricks
public void paint(Graphics art)
{
switch(currentLevel)
{
case 0:
menuScreen(art);
break;
case 1:
game(art);
break;
}
}
public void menuScreen(Graphics art)
{
setSize(700, 700);
art.setColor(Color.BLACK);
art.fillRect(0, 0, 698, 698);
Color ballcolor=new Color(0,0,66);
art.setColor(ballcolor);
art.fillOval(Ball.x, Ball.y, Ball.width, Ball.height);
Color batcolor=new Color(0,0,66);
art.setColor(batcolor);
art.fill3DRect(Bat.x, Bat.y, Bat.width, Bat.height, true);
art.setColor(Color.green);
art.drawRect(0, 0, 698, 698);
art.setColor(Color.yellow);
Font menu = new Font("Arial", Font.BOLD, 20);
art.setFont(menu);
art.drawString("Brick Breaker", 100,400);
art.drawString("Press P to Play", 100,425);
art.drawString("Press Q to Quit game", 100,450);
for (int i = 0; i < Brick.length; i++)
{
if (Brick[i] != null)
{
Color mycolor=new Color(100,0,0);
art.setColor(mycolor);
art.fill3DRect(Brick[i].x, Brick[i].y, Brick[i].width,
Brick[i].height, true);
}
}
art.setColor(Color.YELLOW);
if (ballFallDown || bricksOver)
{
Font f = new Font("Arial", Font.BOLD, 20);
art.setFont(f);
art.drawString(status, 294, 349);
ballFallDown = false;
bricksOver = false;
}
}
public void game(Graphics art)
{
setSize(700, 700);
art.setColor(Color.BLACK);
art.fillRect(0, 0, 698, 698);
Color ballcolor=new Color(0,0,225);
art.setColor(ballcolor);
art.fillOval(Ball.x, Ball.y, Ball.width, Ball.height);
Color batcolor=new Color(0,0,139);
art.setColor(batcolor);
art.fill3DRect(Bat.x, Bat.y, Bat.width, Bat.height, true);
art.setColor(Color.green);
art.drawRect(0, 0, 698, 698);
for (int i = 0; i < Brick.length; i++)
{
if (Brick[i] != null)
{
Color mycolor=new Color(200,0,0);
art.setColor(mycolor);
art.fill3DRect(Brick[i].x, Brick[i].y, Brick[i].width,
Brick[i].height, true);
}
}
if (ballFallDown || bricksOver)
{
Font f = new Font("Arial", Font.BOLD, 20);
art.setFont(f);
art.drawString(status, 100,425);
ballFallDown = false;
bricksOver = false;
}
for (int i = 0; i < Brick.length; i++)
{
if (Brick[i] != null)
{
if (Brick[i].intersects(Ball))
{
score=score+10;
Brick[i] = null;
movey = -movey;
count++;
}
}
}
if (count == Brick.length)
{
bricksOver = true;
movex=0;
movey=0;
art.setColor(Color.green);
status = "YOU BEAT THE LEVEL!!";
art.drawString("Press E to Exit", 100,450);
art.drawString("Press N for Next Level", 100,475);
repaint();
}
repaint();
Font f = new Font("Arial", Font.BOLD, 20);
art.setFont(f);
art.setColor(Color.white);
art.drawString("Score:"+score, 600, 684);
Ball.x += movex;
Ball.y += movey;
if (left == true)
{
Bat.x -= 18;
right = false;
}
if (right == true)
{
Bat.x += 18;
left = false;
}
if (Bat.x <= 4)
{
Bat.x = 4;
}
else if (Bat.x >= 586)
{
Bat.x = 596;
}
if (Ball.intersects(Bat))
{
movey = -movey-.1;
}
if (Ball.x <= 0 || Ball.x + Ball.height >= 698)
{
movex = -movex;
}
if (Ball.y <= 0)
{
movey = -movey;
}
Font f1 = new Font("Arial", Font.BOLD, 20);
art.setFont(f1);
art.setColor(Color.white);
art.drawString("Lives:"+ lives, 5, 684);
if (Ball.y >= 698 && (bricksOver==false) && lives>0)
{
ballFallDown = true;
art.setColor(Color.red);
status = "";
art.drawString("", 100,450);
lives=lives-1;
ballx = 294;
bally = 640;
Ball = new Rectangle(ballx, bally, 14, 14);
movex = -16;
movey = -16;
repaint();
}
if(lives==0 && Ball.y >= 698)
{
art.setColor(Color.red);
art.drawString("You lost!!", 100,425);
art.drawString("Press E to Exit", 100,450);
}
}
public void init()
{
addKeyListener(this);
for (int i = 0; i < Brick.length; i++) //creates bricks
{
Brick[i] = new Rectangle(brickx, bricky, 40, 20);
if (i == 12) //1st row of bricks
{
brickx = 32;
bricky = 84;
}
if (i == 23) //2nd row of bricks
{
brickx = 82;
bricky = 118;
}
if (i == 32) //3rd row of bricks
{
brickx = 132;
bricky = 152;
}
if (i == 39) //4th row of bricks
{
brickx = 182;
bricky = 186;
}
if (i == 44) //5th row of bricks
{
brickx = 232;
bricky = 220;
}
if (i == 47) //6th row of bricks
{
brickx = 282;
bricky = 254;
}
if (i == 48) //7th row of bricks
{
brickx = 144;
bricky = 132;
}
brickx += 50; //spacing between each brick
}
}
public void restart()
{
ballx = 294;
bally = 640;
batx = 294;
baty = 654;
brickx = 32;
bricky = 50;
Ball = new Rectangle(ballx, bally, 14, 14);
Bat = new Rectangle(batx, baty, 100, 12);
movex = -16;
movey = -16;
ballFallDown = false;
bricksOver = false;
count = 0;
status = null;
for (int i = 0; i < Brick.length; i++) //recreates bricks
{
Brick[i] = new Rectangle(brickx, bricky, 40, 20);
if (i == 12)
{
brickx = 32;
bricky = 84;
}
if (i == 23)
{
brickx = 82;
bricky = 118;
}
if (i == 32)
{
brickx = 132;
bricky = 152;
}
if (i == 39)
{
brickx = 182;
bricky = 186;
}
if (i == 44)
{
brickx = 232;
bricky = 220;
}
if (i == 47)
{
brickx = 282;
bricky = 254;
}
if (i == 48)
{
brickx = 144;
bricky = 132;
}
brickx += 50;
}
repaint();
}
#Override
public void keyPressed(KeyEvent e) //allows each key to do desired action
{
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_LEFT)
{
left = true;
}
if (keyCode == KeyEvent.VK_RIGHT)
{
right = true;
}
if (keyCode == e.VK_P && currentLevel == 0)
{
currentLevel = 1;
}
else if (keyCode == e.VK_E && currentLevel == 1)
{
currentLevel = 0;
score=0;
lives=3;
restart();
}
else if(keyCode == e.VK_Q)
{
System.exit(0);
}
}
#Override
public void keyReleased(KeyEvent e)
{
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_LEFT)
{
left = false;
}
if (keyCode == KeyEvent.VK_RIGHT)
{
right = false;
}
}
#Override
public void keyTyped(KeyEvent e)
{
}
public static void main(String[] args)
{
Game prog = new Game();
prog.init();
}
}
I'd throw that code out and start over as you've got both program logic and repaints within your painting methods, neither of which will help you, and your code appears to be one big huge "God" class, all of which will leave you with code that's a horrific nightmare to debug. Recommendations:
Create at least two separate JPanels to display your program with, a GamePanel and a MenuPanel.
Swap these JPanels using a CardLayout.
Do all graphics within a JPanel's paintComponent method and not within a JFrame's or JApplet's paint method.
Don't forget to call the super's painting method, the same method as your override within your override. This is to clean up any dirty pixels.
Separate your program logic from your GUI
This means that you should have a logical non-GUI representation of a single Brick class as well as a collection of these non-GUI bricks.
You can always give your Brick class a Color field, one that the view or gui uses to paint it with.
Create a game-loop, one that you can control, one that doesn't involve calling repaint() within a painting method, since this leads to a completely uncontrollable loop.
Favor use of Key Bindings over KeyListeners.
Try to avoid use of "magic" numbers, such as hard-coding your brick width and spacing in the class itself. Better to use constants as this too makes debugging and enhancing much easier.
For example, some code that's just to demonstrate showing random colors:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import javax.swing.*;
public class BrickBreak {
private static void createAndShowGui() {
GamePanel gamePanel = new GamePanel();
JFrame frame = new JFrame("Brick Break");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(gamePanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
// JPanel that draws the game
class GamePanel extends JPanel {
private static final long serialVersionUID = 1L;
private static final Color BACK_GRND = Color.BLACK;
private int prefW;
private int prefH;
private Bricks bricks = new Bricks();
public GamePanel() {
// wide enough to hold the complete top-row of Bricks
// using constants, so GUI automatically resizes if any sizes change
prefW = (Brick.WIDTH + Bricks.X_SPACING) * Bricks.ROW_COUNTS[0] + Bricks.X_SPACING;
prefH = prefW;
setBackground(BACK_GRND);
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(prefW, prefH);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
for (Brick brick : bricks) {
brick.draw(g2);
}
}
}
// non-GUI class that represents a logical Brick
class Brick {
public static final int WIDTH = 40;
public static final int HEIGHT = 20;
private int x;
private int y;
private Color color;
private Rectangle boundingRectangle;
public Brick(int x, int y, Color color) {
this.x = x;
this.y = y;
this.color = color;
boundingRectangle = new Rectangle(x, y, WIDTH, HEIGHT);
}
// yeah, I'm mixing some view with model here.
public void draw(Graphics2D g2) {
g2.setColor(color);
g2.fill3DRect(x, y, WIDTH, HEIGHT, true);
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public Color getColor() {
return color;
}
// use this to test for collisions
public boolean contains(Point p) {
return boundingRectangle.contains(p);
}
#Override
public String toString() {
return "Brick [x=" + x + ", y=" + y + ", color=" + color + "]";
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Brick other = (Brick) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
}
}
// logical class that holds all Bricks
// Have class implement Iterable<Brick> so we can easily iterate through its containing
// Brick objects in a for-each loop
class Bricks implements Iterable<Brick> {
public static final int X_SPACING = 10;
public static final int Y_SPACING = X_SPACING;
public static final int[] ROW_COUNTS = {13, 11, 9, 7, 5, 3, 1};
private static final float MIN_SAT = 0.8f;
private List<Brick> brickList;
private Random random = new Random();
public Bricks() {
init(); // safe to call since it's final
}
public final void init() {
// recreate the brickList ArrayList
brickList = new ArrayList<>();
int y = Y_SPACING;
// for each row of bricks
for (int row = 0; row < ROW_COUNTS.length; row++) {
int x = X_SPACING + ((ROW_COUNTS[0] - ROW_COUNTS[row]) / 2) * (X_SPACING + Brick.WIDTH);
// for each column
for (int j = 0; j < ROW_COUNTS[row]; j++) {
// create a random color
float hue = random.nextFloat();
float saturation = MIN_SAT + random.nextFloat() * (1f - MIN_SAT);
float brightness = MIN_SAT + random.nextFloat() * (1f - MIN_SAT);
Color color = Color.getHSBColor(hue, saturation, brightness);
Brick brick = new Brick(x, y, color); // create a new Brick with this Color
brickList.add(brick);
x += X_SPACING + Brick.WIDTH;
}
y += Y_SPACING + Brick.HEIGHT;
}
}
// returns null if no collision
public Brick collision(Point p) {
for (Brick brick : brickList) {
if (brick.contains(p)) {
return brick;
}
}
return null;
}
#Override
public Iterator<Brick> iterator() {
return brickList.iterator();
}
public boolean remove(Brick brick) {
// because Brick implements equals and hashCode, we can do this
return brickList.remove(brick);
}
}
Note that I like using Color's static getHSBColor(float h, float s, float b) method for creating random Colors as this helps me to avoid creating dull Colors, since I can guarantee that the saturation and brightness are above minimum values. All three parameters must be float values between 0f and 1.0f
float hue = random.nextFloat();
float saturation = MIN_SAT + random.nextFloat() * (1f - MIN_SAT);
float brightness = MIN_SAT + random.nextFloat() * (1f - MIN_SAT);
Color color = Color.getHSBColor(hue, saturation, brightness);
Your code has quite a lot of issues, which #HovercaftFullOfEels answer already points out.
As for why your code doesn't work:
for (int i = 0; i < Brick.length; i++)
{
if (Brick[i] != null)
{
Color mycolor=new Color(100,0,0);
art.setColor(mycolor);
art.fill3DRect(Brick[i].x, Brick[i].y, Brick[i].width,
Brick[i].height, true);
}
}
This is the part that renders the bricks. You never create a random-number, but use the same Color for each brick (new Color(100, 0, 0);). Instead introduce a new variable into Brick that specifies the color of each brick and is initialized once with a random color.
The Brick-class would afterwards look like this:
public class Brick{
public int x;
public int y;
...
public Color color;
...
}
The ... are just placeholders for other code that may be content of the class. Regarding public access of Class-variables: Encapsulation is a fundamental concept of OOP and should be used (on encapsulation). E.g. instead of giving direct access to Brick.x consider introducing a method Brick#getX().
I have three classes. The frame for menu of Game from which when play button,
is pressed the class of frame containing Game should play.And the main class creates the object of Menu class.But the problem is that when I pressed play button it become white and after some times it says your score is 0 and Game is over. Please help me solve this problem I have tried every thing.
public class GameFrame extends JFrame implements KeyListener {
protected int x;
protected int y;
private int a;
private int b;
protected int c;
protected int d;
protected int f;
protected int k;
private int h;
private int i;
private int s;
GameFrame() {
/*
* setSize(760,700);
* setLocation(200,25);
* setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
* setResizable(false);
* setVisible(true);
*/
setLayout(null);
c = 500;
d = 530;
a = 1;
b = 1;
x = 50;
y = 250;
f = 50;
k = 700;
h = 1;
i = -1;
s = 1;
addKeyListener(this);
setFocusable(true);
}
public void paint(Graphics g) {
super.paint(g);
Graphics g1 = (Graphics) g;
g1.setColor(Color.DARK_GRAY);
g1.fillRect(0, 0, 1200, getHeight());
/*
* g1.setColor(Color.blue);
* g1.fillRect(0, 0, 850, getHeight());
* g1.setColor(Color.green);
* g1.fillRect(0, 0, 845, getHeight());
* g1.setColor(Color.yellow);
* g1.fillRect(0, 0, 840, getHeight());
* g1.setColor(Color.red);
*/
g1.fillRect(0, 0, 835, getHeight());
g1.setColor(Color.gray);
g1.fillRect(0, 0, 830, getHeight());
g1.setColor(Color.BLACK);
g1.fillRect(0, 0, 825, getHeight());
g1.setColor(Color.red);
g1.fillOval(x, y, 20, 20);
g1.setColor(Color.GREEN);
g1.fillOval(k, f, 20, 20);
g1.setColor(Color.blue);
g1.fillRect(c, d, 100, 15);
g1.setColor(Color.red);
g1.fillRect(300, 300, 90, 20);
g1.setColor(Color.pink);
g1.drawRect(0, 80, 760, 3);
g1.setColor(Color.orange);
g1.setFont(new Font(null, Font.BOLD, 20));
g1.drawString("Your Score", 500, 60);
g1.setFont(new Font(null, Font.BOLD, 25));
g1.drawString("Credit:", 50, 60);
g1.setFont(new Font(null, Font.BOLD, 20));
g1.drawString("Mohsin Hussain", 150, 60);
g1.drawString(String.valueOf(points()), 650, 60);
}
// Here is Run Method. From This Method Ball Will Move in Different Direction After Collision
public void Run() {
if (c < 0)
c = 1;
if (c > 740)
c = 675;
if (k < 0)
i = s;
if (k > 700)
i = -s;
k = k + i;
if (f < 80)
h = s;
if ((f + 20 > d && k + 20 > c && f < d + 6 && k < c + 60))
h = -s;
f = f + h;
if (x < 0)
a = s;
if (x > 700)
a = -s;
x = x + a;
if (y < 80)
b = s;
if ((x > 300 && x < 380) && (y == 300) && b < 0) {
b = s;
}
if ((x > 300 && x < 380) && (y == 300) && b > 0) {
b = -s;
}
System.out.println(x);
if ((y + 20 > d && x + 20 > c && y < d + 6 && x < c + 60))// Control the Direction as well
// as Collision of the Grey Ball
// From Rectangle
b = -s;
y = y + b;
finish();// Call the Method of Finish
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
repaint();
Run();
} // End Bracket of Run Method
// Method of Points that Control the Score as well as Increase the Speed
public int points() {
if ((y + 20 > d && x + 20 > c && y < d + 6 && x < c + 60)
|| (f + 20 > d && k + 20 > c && f < d + 6 && k < c + 60))
s += 1;
return s - 1;
} // /End Bracket of Points Method
// Method of Finish that Control Game Over Logic
private void finish() {
if (y > getHeight() - 20 || f > getHeight() - 20) {
// Logic of Set Time at the End of the Game
/*
* GregorianCalendar date = new GregorianCalendar();
*
* int day = date.get(Calendar.DAY_OF_MONTH); int month = date.get(Calendar.MONTH); int
* year = date.get(Calendar.YEAR);
*
* int second = date.get(Calendar.SECOND); int minute = date.get(Calendar.MINUTE); int
* hour = date.get(Calendar.HOUR);
*
* System.out.println("Ending Date of Game is "+day+"/"+(month+1)+"/"+year);
* System.out.println("Ending Time of Game is "+hour+" : "+minute+" : "+second);
*/
JOptionPane.showMessageDialog(this, "your Score is " + points(), "Game Over",
JOptionPane.YES_NO_OPTION);
System.exit(ABORT);
}// End Bracket of If Statement
}
public void keyPressed(KeyEvent arg0) {
if (arg0.getKeyCode() == KeyEvent.VK_LEFT)
c -= 25;
if (arg0.getKeyCode() == KeyEvent.VK_RIGHT)
c += 25;
} // End of KeyPressed
public void keyReleased(KeyEvent arg0) {} // End of KeyReleased
public void keyTyped(KeyEvent arg0) {}// End of KeyTyped
}
The Frame containing the menu for the Game from where when we press play button the Game should start.
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class GameMenu extends JFrame {
private JButton play;
private JButton exit;
private JButton about;
private JButton credit;
private ImageIcon img;
private JLabel imgLabel;
private JPanel panel;
private float h = (float) 0.333;
private float b = (float) 0.600;
private float s = 1;
boolean runCheck = false;
public GameFrame frame;
GameMenu() {
setLayout(null);
setResizable(false);
panel = new JPanel();
panel.setLayout(null);
panel.setSize(760, 700);
panel.setBackground(Color.getHSBColor(h, s, b));
add(panel);
play = new JButton("PLAY");
play.setSize(100, 50);
play.setLocation(360, 400);
panel.add(play);
about = new JButton("ABOUT");
about.setSize(play.getSize());
about.setLocation(play.getX(), play.getY() + play.getHeight() + 50);
panel.add(about);
exit = new JButton("EXIT");
exit.setSize(play.getSize());
exit.setLocation(about.getX() + about.getWidth() + 50, about.getY());
panel.add(exit);
credit = new JButton("CREDIT");
credit.setSize(play.getSize());
credit.setLocation(about.getX() - about.getWidth() - 50, about.getY());
panel.add(credit);
img = new ImageIcon("C:\\Users\\Ghulam Haider\\Downloads\\b.jpg");
imgLabel = new JLabel(img);
imgLabel.setSize(imgLabel.getPreferredSize());
imgLabel.setLocation(230, 45);
panel.add(imgLabel);
mouseListener mouse = new mouseListener();
Action action = new Action();
play.addMouseListener(mouse);
}
private class Action implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {}
}
private class mouseListener implements MouseListener, Runnable {
#Override
public void mouseClicked(MouseEvent get) {}
#Override
public void mousePressed(MouseEvent e) {
if (e.getSource() == play) {
frame = new GameFrame();
frame.setSize(760, 700);
frame.setLocation(200, 25);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setVisible(true);
frame.Run();
// end of while
}
}
#Override
public void mouseReleased(MouseEvent e) {}
#Override
public void mouseEntered(MouseEvent e) {}
#Override
public void mouseExited(MouseEvent e) {}
#Override
public void run() {
frame.Run();
// end of while
}
}
}
and at last the main class which calls menu frame.
import javax.swing.JFrame;
public class RunGame {
public static void main(String args[]) {
GameMenu menu = new GameMenu();
menu.setSize(760, 700);
menu.setLocation(200, 25);
menu.setVisible(true);
menu.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
But the problem is that when I pressed play button it become white and after some times it says your score is 0 and Game is over.
You are calling the GameFrame.Run method on the EDT - Swing is single threaded, and all painting, events, etc.. run on the EDT. If you have something which blocks it (for instance calling Thread.sleep on the EDT as the GameFrame.Run method does) then none of these can occur. Instead, create a Thread or using a Timer
Some other suggestions:
Don't paint to a JFrame - paint to a JPanel by overriding the paintComponent method.
Avoid using null layouts. Choose the appropriate LayoutManager for the layout you seek.
If looking for button clicks, use an ActionListener rather than MouseListener
Class names should start with an uppercase (eg mouselistener), and method names with lowercase. Avoid any potential naming conflicts with API names
Your if statement that contains finish() is not surrounded by brackets. Therefore after the it sees the condition it simply moves along and runs finish()
if((y+20>d&&x+20>c&&y<d+6&&x<c+60))//Control the Direction as well as Collision of the Grey Ball From Rectangle
b=-s;
y=y+b;
finish();//Call the Method of Finish
so everytime the run method is called it will terminate because finish() is also always called.
Try surrounding your if statement so that it only calls finish() if the statement is true. Or write a separate if statement where when the condition is met finish() is called.
I have a little problem. I have searched the internet everywhere, and I can't find how to set an image in a rectangle. It seems fairly simple, but I am just getting into game programming, and I can't seem to find an explanation on this. I was referred to this site by somebody in Y! Ansers, and I think you guys might be able to help. I have this code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Racing extends JFrame {
private static final long serialVersionUID = -198172151996959655L;
//makes the screen size
final int WIDTH = 900, HEIGHT = 650;
//keeps track of player speed
double plSpeed = .5, p2Speed = .5;
//numbers that represent direction
final int UP = 0, RIGHT = 1, DOWN = 2, LEFT = 3, STOP = 5;
//keeps track of player direction
int p1Direction = STOP;
int p2Direction = STOP;
//create rectangles
Rectangle left = new Rectangle( 0, 0, WIDTH/9, HEIGHT );
Rectangle right = new Rectangle( ( WIDTH/9 )*8, 0, WIDTH/9, HEIGHT );
Rectangle top = new Rectangle ( 0, 0, WIDTH, HEIGHT/9 );
Rectangle bottom = new Rectangle( 0, ( HEIGHT/9 ) * 8, WIDTH, HEIGHT/9 );
Rectangle center = new Rectangle( (int) ((WIDTH/9) * 2.5), (int) ((HEIGHT/9) * 2.5), (int) ((WIDTH/9) * 5), (int) ((HEIGHT/9) * 4));
//makes the obstacles
Rectangle obstacle = new Rectangle ( WIDTH/2, (int) ((HEIGHT/9) * 7), WIDTH/10, HEIGHT/9 );
Rectangle obstacle2 = new Rectangle ( WIDTH/3, (int) ((HEIGHT/9 ) * 5), WIDTH/10, HEIGHT/4 );
Rectangle obstacle3 = new Rectangle ( 2 * (WIDTH/3), (int) ((HEIGHT/9) * 5),WIDTH/10, HEIGHT/4 );
Rectangle obstacle4 = new Rectangle ( WIDTH/3, HEIGHT/9, WIDTH/30, HEIGHT/9 );
Rectangle obstacle5 = new Rectangle ( WIDTH/2, (int) ((HEIGHT/9) * 1.5), WIDTH/30, HEIGHT/4 );
//makes the finish line
Rectangle finish = new Rectangle ( WIDTH/9, (HEIGHT/2)-HEIGHT/9, (int) ((WIDTH/9) * 1.5), HEIGHT/70 );
//makes player 1's car
Rectangle p1 = new Rectangle ( WIDTH/9, HEIGHT/2, WIDTH/30, WIDTH/30 );
//makes player 2's car
Rectangle p2 = new Rectangle ((( WIDTH/9 ) + ((int) ((WIDTH/9) * 1.5) /2)),(HEIGHT/2) + (HEIGHT/10), WIDTH/30, WIDTH/30);
//constructor
public Racing() {
//define defaults for the JFrame
super ("Racing");
setSize( WIDTH, HEIGHT );
setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
setBackground(Color.BLACK);
//start the inner class
Move2 m2 = new Move2();
m2.start();
Move1 m1 = new Move1();
m1.start();
}
//draws the cars and race track
public void paint(Graphics g) {
//make borders green
g.setColor(Color.GREEN);
//rectangles for start lines (lineO = outer player, lineI = inner player)
Rectangle lineO = new Rectangle( WIDTH/9, HEIGHT/2, (int) ((WIDTH/9) * 1.5)/2, HEIGHT/140 );
Rectangle lineI = new Rectangle( ((WIDTH/9)+((int) ((WIDTH/9) * 1.5)/2)), (HEIGHT/2) + (HEIGHT/10), (int) ((WIDTH/9) * 1.5)/2, HEIGHT/140 );
//fill the rectangles
g.fillRect(left.x,left.y,left.width,left.height);
g.fillRect(right.x,right.y,right.width,right.height);
g.fillRect(top.x,top.y,top.width,top.height);
g.fillRect(bottom.x,bottom.y,bottom.width,bottom.height);
g.fillRect(center.x,center.y,center.width,center.height);
g.fillRect(obstacle.x,obstacle.y,obstacle.width,obstacle.height);
g.fillRect(obstacle2.x,obstacle2.y,obstacle2.width,obstacle2.height);
g.fillRect(obstacle3.x,obstacle3.y,obstacle3.width,obstacle3.height);
g.fillRect(obstacle4.x,obstacle4.y,obstacle4.width,obstacle4.height);
g.fillRect(obstacle5.x,obstacle5.y,obstacle5.width,obstacle5.height);
//make the starting line color white
g.setColor(Color.WHITE);
//draw starting line
g.fillRect(lineO.x,lineO.y,lineO.width,lineO.height);
g.fillRect(lineI.x,lineI.y,lineI.width,lineI.height);
//make the finish line yellow
g.setColor(Color.YELLOW);
//draw the finish line
g.fillRect(finish.x,finish.y,finish.width,finish.height);
//make player one red
g.setColor(Color.RED);
//draw player 1
g.fill3DRect(p1.x,p1.y,p1.width,p2.height,true);
//make player two blue
g.setColor(Color.BLUE);
//now draw player two
g.fill3DRect(p2.x,p2.y,p2.width,p2.height,true);
}
private class Move1 extends Thread implements KeyListener {
public void run() {
//makes the key listener "wake up"
addKeyListener(this);
//should be done in an infinite loop, so it repeats
while (true) {
//make try block, so it can exit if it errors
try {
//refresh screen
repaint();
//check to see if car hits wall
//if so, slow down
if (p1.intersects(left) || p1.intersects(right) ||
p1.intersects(top) || p1.intersects(bottom) ||
p1.intersects(obstacle) || p1.intersects(obstacle2) ||
p1.intersects(obstacle3) || p1.intersects(obstacle4) ||
p1.intersects(obstacle5) || p1.intersects (center) ||
p1.intersects(p2)) {
plSpeed = -5;
Thread.sleep(128);
p1Direction = STOP;
}
//lets the car stop
if (plSpeed==0) {
p1Direction = STOP;
}
//moves player based on direction
if (p1Direction==UP) {
p1.y -= (int) plSpeed;
}
if (p1Direction==DOWN) {
p1.y += (int) plSpeed;
}
if (p1Direction==LEFT) {
p1.x -= (int) plSpeed;
}
if (p1Direction==RIGHT) {
p1.x += (int) plSpeed;
}
if (p1Direction==STOP) {
plSpeed = 0;
}
//delays refresh rate
Thread.sleep(75);
}
catch(Exception e) {
//if an error, exit
break;
}
}
}
//have to input these (so it will compile)
public void keyPressed(KeyEvent event) {
try {
//makes car increase speed a bit
if (event.getKeyChar()=='w' ||
event.getKeyChar()=='a' ||
event.getKeyChar()=='s' ||
event.getKeyChar()=='d') {
plSpeed += .2;
repaint();
}
} catch (Exception I) {}
}
public void keyReleased(KeyEvent event) {}
//now, to be able to set the direction
public void keyTyped(KeyEvent event) {
if (event.getKeyChar()=='a') {
if (p1Direction==RIGHT) {
p1Brake();
} else {
if (p1Direction==LEFT) {
} else {
plSpeed = .5;
p1Direction = LEFT;
}
}
}
if (event.getKeyChar()=='s') {
if (p1Direction==UP) {
p1Brake();
} else {
if (p1Direction==DOWN) {
} else {
plSpeed = .5;
p1Direction = DOWN;
}
}
}
if (event.getKeyChar()=='d') {
if (p1Direction==LEFT) {
p1Brake();
} else {
if (p1Direction==RIGHT) {
} else {
plSpeed = .5;
p1Direction = RIGHT;
}
}
}
if (event.getKeyChar()=='w') {
if (p1Direction==DOWN) {
p1Brake();
} else {
if (p1Direction==UP) {
} else {
plSpeed = .5;
p1Direction = UP;
}
}
}
if (event.getKeyChar()=='z') {
p1Brake();
}
}
public void p1Brake () {
try {
while (plSpeed != 0) {
plSpeed -= .2;
Thread.sleep(75);
}
} catch (Exception e) {
plSpeed = 0;
}
}
}
private class Move2 extends Thread implements KeyListener {
public void run() {
//makes the key listener "wake up"
addKeyListener(this);
//should be done in an infinite loop, so it repeats
while (true) {
//make try block, so it can exit if it errors
try {
//refresh screen
repaint();
//check to see if car hits outside wall
//if so, slow down
if (p2.intersects(left) || p2.intersects(right) ||
p2.intersects(top) || p2.intersects(bottom) ||
p2.intersects(obstacle) || p2.intersects(obstacle2) ||
p2.intersects(obstacle3) || p2.intersects(obstacle4) ||
p2.intersects(obstacle5) || p2.intersects(p1) ||
p2.intersects(center)) {
plSpeed = -.25;
Thread.sleep(128);
p2Direction = STOP;
}
//makes car increase speed a bit
if (p2Speed <= 5) {
plSpeed += .2;
}
//lets the car stop
if (p2Speed == 0) {
p2Direction = STOP;
}
//moves player based on direction
if (p2Direction==UP) {
p2.y -= (int) p2Speed;
}
if (p2Direction==DOWN) {
p2.y += (int) p2Speed;
}
if (p2Direction==LEFT) {
p2.x -= (int) p2Speed;
}
if (p2Direction==RIGHT) {
p2.x += (int) p2Speed;
}
if (p2Direction==STOP) {
p2Speed = 0;
}
//delays refresh rate
Thread.sleep(75);
}
catch(Exception e) {
//if an error, exit
break;
}
}
}
public void keyPressed(KeyEvent event) {
try {
//makes car increase speed a bit
if (event.getKeyChar()=='j' ||
event.getKeyChar()=='k' ||
event.getKeyChar()=='l' ||
event.getKeyChar()=='i') {
plSpeed += .2;
}
} catch (Exception I) {}
}
public void keyReleased(KeyEvent event) {}
//now, to be able to set the direction
public void keyTyped(KeyEvent event) {
if (event.getKeyChar()=='j') {
if (p2Direction==RIGHT) {
p2Brake();
} else {
p2Direction = LEFT;
p2Speed = .4;
}
}
if (event.getKeyChar()=='k') {
if (p2Direction==UP) {
p2Brake();
} else {
p2Direction = DOWN;
p2Speed = .4;
}
}
if (event.getKeyChar()=='l') {
if (p2Direction==LEFT) {
p2Brake();
} else {
p2Direction = RIGHT;
p2Speed = .4;
}
}
if (event.getKeyChar()=='i') {
if (p2Direction==DOWN) {
p2Brake();
} else {
p2Direction = UP;
p2Speed = .4;
}
}
if (event.getKeyChar()=='m') {
p2Brake();
}
}
public void p2Brake () {
try {
while (p2Speed != 0) {
p2Speed -= .5;
Thread.sleep(75);
}
} catch (Exception i) {
p2Speed = 0;
}
}
}
//finally, to start the program
public static void main(String[] args) {
Racing frame = new Racing();
frame.setVisible( true );
frame.setLocationRelativeTo( null );
frame.setResizable( false );
}
}
Currently I am just filling the p1 rectangle with the color red. I have an image of a car, and want to replace the red with the car. Any notes on how to do this?
** EDIT **
I found my answer. Using isah's g.drawImage, combined with the toolkit for getting the image, I was able to do this. I am leaving this up for anybody who wants to know.
How about drawImage. Take a look at this tutorial.
package puzzle;
import java.awt.Color;
import javax.swing.*;
import java.util.*;
public class Puzzle {
Integer x = 50;
Integer y = 50;
int x2 = 100;
int y2 = 100;
int vnotx = 0;
int vnoty = 0;
float t = 0;
float t2 = 0;
JFrame frame = new JFrame();
Move m = new Move(x, y,Color.GREEN);
Move n = new Move(x,y,Color.ORANGE);
java.util.Timer timer = new java.util.Timer();
java.util.Timer timer2 = new java.util.Timer();
public Puzzle() {
frame.setUndecorated(true);
frame.setSize(400, 400);
frame.add(m);
frame.add(n);
frame.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyPressed(java.awt.event.KeyEvent evt) {
formKeyPressed(evt);
}
});
com.sun.awt.AWTUtilities.setWindowOpacity(frame, 1f);
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
rD();
}
}, 0, 20);
timer2.scheduleAtFixedRate(new TimerTask() {
public void run() {
t2+=.01;
x2 =(int) ((Math.cos(t2)+1)*100);
y2 =(int) ((Math.sin(t2)+1)*100);
System.out.println(x2+", "+y2);
}
}, 0, 2);
}
int z = 0;
public void rD() {
z++;
m = new Move(x, y, Color.GREEN);
n = new Move(x2, y2, Color.ORANGE);
frame.add(n);
frame.add(m);
frame.validate();
}
private void formKeyPressed(java.awt.event.KeyEvent evt) {
int id = evt.getID();
int kC = evt.getKeyCode();
if (kC == 39) {
final java.util.Timer right = new java.util.Timer();
right.scheduleAtFixedRate(new TimerTask() {
public void run() {
t += .01;
int x1 = x;
if (x + 51 < 400) {
x = x1 + (int) (10 * t) + (-1 * ((int) (20 * t * t)));
}
if (t > .5) {
t = 0;
right.cancel();
}
}
}, 0, 10);
}
if (kC == 37) {
final java.util.Timer left = new java.util.Timer();
left.scheduleAtFixedRate(new TimerTask() {
public void run() {
t += .01;
int x1 = x;
if (x - 1 >= 0) {
x = x1 + (int) (-10 * t) - (-1 * ((int) (20 * t * t)));
}
if (t > .5) {
t = 0;
left.cancel();
}
}
}, 0, 10);
}
if (kC == 40) {
final java.util.Timer right = new java.util.Timer();
right.scheduleAtFixedRate(new TimerTask() {
public void run() {
t += .01;
int y1 = y;
if (y + 51 < 400) {
y = y1 + (int) (10 * t) + (-1 * ((int) (20 * t * t)));
}
if (t > .5) {
t = 0;
right.cancel();
}
}
}, 0, 10);
}
if (kC == 38) {
final java.util.Timer left = new java.util.Timer();
left.scheduleAtFixedRate(new TimerTask() {
public void run() {
t += .01;
int y1 = y;
if (y-1 >= 0)
{
y = y1 + (int) (-10 * t) - (-1 * ((int) (20 * t * t)));
}
if (t > .5) {
t = 0;
left.cancel();
}
}
}, 0, 10);
}
if (kC == 32) {
}
if (kC == 67) {
}
if (kC == 77) {
}
}
public static void main(String[] args) {
new Puzzle().frame.setVisible(true);
}
}
why is this not adding both instances of the move class. it only adds the last one called. the class paint is below what should i change in order for it paint both instances of move
package puzzle;
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
public class Move extends JPanel{
int x;
int y;
Color kk;
public Move(int x1, int y1, Color k)
{
x=x1;
y=y1;
kk = k;
}
public void paintComponent(Graphics g)
{Graphics2D g2 = (Graphics2D)g;
super.paintComponent(g2);
g2.setColor(kk);
g2.fill(new RoundRectangle2D.Float(x, y, 50, 50,10,10));
g2.drawString(x+", "+y, 200, 200);
}
}
the class move paints a rectangle with the position and color passed from the puzzle class
Are you taking layout managers into consideration? Do you know about JFrame's contentPane using BorderLayout as its default layout manager, and if you add components to this without constants, they are added BorderLayout.CENTER, and only one of these can be visible at a time (the last added).
I think that you might do better disassociating Move from JPanel, yes making it paintable, but making it more of a logical object rather than a gui component and instead of having it extend JPanel, allow a single drawing JPanel to hold one or more Move objects and then draw the Move objects in this JPanel's paintComponent method.
Also, you seem to be using several java.util.Timers in your code, but since it is a Swing application, it would likely be better served by using javax.swing.Timers instead, in fact perhaps just one Swing Timer that functioned as a game loop.
if (kC == 39) {
Don't use magic numbers.
Instead you should be using:
KeyEvent.VK_???