I have been working on a simple Java game and have done so successfully using shapes, but the next big step is to do so using images. I was wondering whether there was a method where I could simply place an image over a shape such as a rectangle, which would make the process much easier and doesn't require me to re-write most of my code.
Here's the two classes of my game for reference:
The first class named "Flappy Bird"
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;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.Timer;
public class FlappyBird implements ActionListener, MouseListener, KeyListener {
public static FlappyBird flappyBird;
public final int WIDTH = 800, HEIGHT = 800;
public Renderer renderer;
public Rectangle bird;
public ArrayList<Rectangle> columns;
public int ticks, yMotion, score;
public boolean gameOver, started;
public Random rand;
public FlappyBird() {
JFrame jframe = new JFrame();
Timer timer = new Timer(20, this);
renderer = new Renderer();
rand = new Random();
jframe.add(renderer);
jframe.setTitle("Flappy Bird");
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jframe.setSize(WIDTH, HEIGHT);
jframe.addMouseListener(this);
jframe.addKeyListener(this);
jframe.setResizable(false);
jframe.setVisible(true);
bird = new Rectangle(WIDTH / 2 - 10, HEIGHT / 2 - 10, 20, 20);
columns = new ArrayList<Rectangle>();
addColumn(true);
addColumn(true);
addColumn(true);
addColumn(true);
timer.start();
}
public void addColumn(boolean start) {
int space = 300;
int width = 100;
int height = 50 + rand.nextInt(300);
if (start) {
columns.add(new Rectangle(WIDTH + width + columns.size() * 300, HEIGHT - height - 120, width, height));
columns.add(new Rectangle(WIDTH + width + (columns.size() - 1) * 300, 0, width, HEIGHT - height - space));
} else {
columns.add(new Rectangle(columns.get(columns.size() - 1).x + 600, HEIGHT - height - 120, width, height));
columns.add(new Rectangle(columns.get(columns.size() - 1).x, 0, width, HEIGHT - height - space));
}
}
public void paintColumn(Graphics g, Rectangle column) {
g.setColor(Color.green.darker());
g.fillRect(column.x, column.y, column.width, column.height);
}
public void jump() {
if (gameOver) {
bird = new Rectangle(WIDTH / 2 - 10, HEIGHT / 2 - 10, 20, 20);
columns.clear();
yMotion = 0;
score = 0;
addColumn(true);
addColumn(true);
addColumn(true);
addColumn(true);
gameOver = false;
}
if (!started)
started = true;
else if (!gameOver) {
if (yMotion > 0)
yMotion = 0;
yMotion -= 10;
}
}
#Override
public void actionPerformed(ActionEvent e) {
int speed = 10;
ticks++;
if (started) {
for (int i = 0; i < columns.size(); i++) {
Rectangle column = columns.get(i);
column.x -= speed;
}
if (ticks % 2 == 0 && yMotion < 15)
yMotion += 2;
for (int i = 0; i < columns.size(); i++) {
Rectangle column = columns.get(i);
if (column.x + column.width < 0) {
columns.remove(column);
if (column.y == 0)
addColumn(false);
}
}
bird.y += yMotion;
for (Rectangle column : columns) {
if (column.y == 0 && bird.x + bird.width / 2 > column.x + column.width / 2 - 10 && bird.x + bird.width / 2 < column.x + column.width / 2 + 10) {
score++;
}
if (column.intersects(bird)) {
gameOver = true;
if (bird.x <= column.x)
bird.x = column.x - bird.width;
else
if (column.y != 0)
bird.y = column.y - bird.height;
else if (bird.y < column.height)
bird.y = column.height;
}
}
if (bird.y > HEIGHT - 120 || bird.y < 0)
gameOver = true;
if (bird.y + yMotion >= HEIGHT - 120) {
bird.y = HEIGHT - 120 - bird.height;
gameOver = true;
}
}
renderer.repaint();
}
public void repaint(Graphics g) {
g.setColor(Color.cyan);
g.fillRect(0, 0, WIDTH, HEIGHT);
g.setColor(Color.orange);
g.fillRect(0, HEIGHT - 120, WIDTH, 120);
g.setColor(Color.green);
g.fillRect(0, HEIGHT - 120, WIDTH, 20);
g.setColor(Color.red);
g.fillRect(bird.x, bird.y, bird.width, bird.height);
for (Rectangle column : columns)
paintColumn(g, column);
g.setColor(Color.white);
g.setFont(new Font("Arial", 1, 100));
if (!started)
g.drawString("Click to start!", 75, HEIGHT / 2 - 50);
if (gameOver)
g.drawString("Game Over!", 100, HEIGHT / 2 - 50);
if (!gameOver && started)
g.drawString(String.valueOf(score), WIDTH / 2 - 25, 100);
}
public static void main(String[] args) {
flappyBird = new FlappyBird();
}
#Override
public void mouseClicked(MouseEvent e) {
jump();
}
#Override
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_SPACE)
jump();
}
#Override
public void mousePressed(MouseEvent e){
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e){
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
}
}
The second class named "Renderer":
import java.awt.Graphics;
import javax.swing.JPanel;
public class Renderer extends JPanel {
private static final long serialVersionUID = 1L;
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
FlappyBird.flappyBird.repaint(g);
}
}
I know this is a massive ask and I would like to give a HUGE thank you to everyone who replies and to the wonderful community here :-)
Related
I'm trying to make a Brick Breaker game where the ball which is initially on the paddle(referred to as BAR in the code below) is launched with a speed(approx 100) in some random direction, if it hits any brick on the screen the brick disappears and the ball changes direction accordingly.
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import java.awt.event.KeyEvent;
import java.awt.event.*;
public class Brick_Breaker extends Canvas implements KeyListener{
int BRICK_WIDTH=60,BRICK_HEIGHT=30,X=0,Y=0;
int BAR_X = 390,BAR_Y=560,BAR_WIDTH=120,BAR_HEIGHT=20,BAR_DX=10;
int BALL_X=440,BALL_Y=540,BALL_SIZE=20,BALL_DX=0,BALL_DY=0;
int LEFT_WALL=100,RIGHT_WALL=800,TOP_WALL=10;
boolean GAME_STATE=false;
int BAR_STATE=0;
static int[][] y = new int[10][5];
static int[][] x = new int[10][5];
static int[][] status = new int[10][5];
static Canvas canvas;
static JFrame frame;
#Override
public void keyReleased(KeyEvent ke){}
#Override
public void keyTyped(KeyEvent ke){}
public void STaRT(){
frame = new JFrame("My Drawing");
frame.addKeyListener(this);
canvas = new Brick_Breaker();
canvas.setSize(900, 600);
frame.add(canvas);
frame.pack();
frame.setVisible(true);
}
#Override
public void update(Graphics g){
BALL_X += BALL_DX;
BALL_Y += BALL_DY;
for(int i=0;i<10;i++){
for(int j=0;j<5;j++){
if(BALL_X>x[i][j]&&BALL_X<(x[i][j]+BRICK_WIDTH)&&BALL_Y<=y[i][j]+BAR_HEIGHT+BALL_SIZE && BALL_Y>y[i][j]&&BALL_DY<0){
BALL_DY=-BALL_DY;
status[i][j]-=1;
}else if(BALL_X>x[i][j]&&BALL_X<(x[i][j]+BRICK_WIDTH)&&BALL_Y>=y[i][j]-BALL_SIZE && BALL_Y<y[i][j]+BAR_HEIGHT&&BALL_DY>0){
BALL_DY=-BALL_DY;
status[i][j]-=1;
}else if(BALL_X+BALL_SIZE>=x[i][j]&&BALL_X<(x[i][j]+BRICK_WIDTH)&&BALL_Y>=y[i][j] && BALL_Y<y[i][j]+BAR_HEIGHT&&BALL_DY<0){
BALL_DX=-BALL_DX;
status[i][j]-=1;
}else if(BALL_X>x[i][j]&&BALL_X-BALL_SIZE<=(x[i][j]+BRICK_WIDTH)&&BALL_Y>=y[i][j] && BALL_Y<y[i][j]+BAR_HEIGHT&&BALL_DY<0){
BALL_DX=-BALL_DX;
status[i][j]-=1;
}else if(BALL_X-BALL_SIZE<LEFT_WALL||BALL_X+BALL_SIZE>RIGHT_WALL){
BALL_DX=-BALL_DX;
}else if(BALL_Y-BALL_SIZE<TOP_WALL){
BALL_DY=-BALL_DY;
}
}
}
BAR_X = BAR_X +BAR_STATE*BAR_DX;
repaint();
}
public static void main(String[] args) {
Brick_Breaker bb = new Brick_Breaker();
bb.STaRT();
for(int i=0;i<10;i++){
for(int j=0;j<5;j++){
x[i][j] = 300+60*j;
y[i][j] = 50+30*i;
status[i][j] = 1;
}
}
}
#Override
public void keyPressed(KeyEvent ke){
if(!GAME_STATE){
BALL_DX = (int)(100*Math.random());
BALL_DY = (int)(Math.sqrt(100*100-BALL_DX*BALL_DX));
GAME_STATE = true;
}else if(ke.getKeyCode() == KeyEvent.VK_LEFT){
BAR_STATE=-1;
}else if(ke.getKeyCode()==KeyEvent.VK_RIGHT){
BAR_STATE=1;
}
}
#Override
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.white);
g.drawLine(LEFT_WALL,600, LEFT_WALL, TOP_WALL);
g.drawLine(RIGHT_WALL, 600, RIGHT_WALL, TOP_WALL);
g.drawLine(LEFT_WALL,TOP_WALL,RIGHT_WALL,TOP_WALL);
g.fillRect(BAR_X,BAR_Y,BAR_WIDTH,BAR_HEIGHT);
g.setColor(Color.red);
g.fillOval(BALL_X, BALL_Y, BALL_SIZE, BALL_SIZE);
for(int i=0;i<10;i++){
for(int j=0;j<5;j++){
if(status[i][j]>0){
X = x[i][j];Y=y[i][j];
g.setColor(Color.white);
g.fillRect(X, Y, BRICK_WIDTH, BRICK_HEIGHT);
g.setColor(Color.red);
g.fillRect(X+3, Y+3, BRICK_WIDTH-6, BRICK_HEIGHT-6);
}
}
}
setBackground(Color.black);
}
}
Here the update function doesn't seem to update at all.
I'm not really sure on how the method works as well.
Any help would be appreciated
Canvas is a pretty low level component and one which I'd only consider using if I needed to use a BufferStrategy.
update is called as part of the paint phase and because you've overridden it without calling it's super implementation, you broke the paint workflow.
AWT and Swing generally employ a passive rendering system, this means that updates only occur when the system decides it needs to happen, so overriding update the way you have doesn't really make sense and isn't going to help you.
A better place to start is with a JPanel, the main reason is because it's double buffered and saves you hassles of trying to figure out how to eliminate flickering.
A good place to start is Performing Custom Painting and Painting in AWT and Swing to gain a better understanding of how painting works (and how you should work with it).
KeyListener is also a poor choice for input monitoring, seriously, just do some searching on SO for all the reasons why.
A better, and generally less problematic approach is to use key bindings as well.
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 javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
int BRICK_WIDTH = 60, BRICK_HEIGHT = 30, X = 0, Y = 0;
int BAR_X = 390, BAR_Y = 560, BAR_WIDTH = 120, BAR_HEIGHT = 20, BAR_DX = 1;
int BALL_X = 440, BALL_Y = 540, BALL_SIZE = 20, BALL_DX = 0, BALL_DY = 0;
int LEFT_WALL = 100, RIGHT_WALL = 800, TOP_WALL = 10;
boolean GAME_STATE = false;
int BAR_STATE = 0;
int[][] y = new int[10][5];
int[][] x = new int[10][5];
int[][] status = new int[10][5];
private Timer timer;
public TestPane() {
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 5; j++) {
x[i][j] = 300 + 60 * j;
y[i][j] = 50 + 30 * i;
status[i][j] = 1;
}
}
BALL_DX = 0; //(int) (100 * Math.random());
BALL_DY = -1;//(int) (Math.sqrt(100 * 100 - BALL_DX * BALL_DX));
setBackground(Color.BLACK);
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "left");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "right");
ActionMap am = getActionMap();
am.put("left", new KeyAction(this, -1));
am.put("right", new KeyAction(this, 1));
}
#Override
public void addNotify() {
super.addNotify(); //To change body of generated methods, choose Tools | Templates.
if (timer == null) {
timer = new Timer(5, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
tick();
}
});
timer.start();
}
}
#Override
public void removeNotify() {
super.removeNotify();
if (timer != null) {
timer.stop();
timer = null;
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(900, 600);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.white);
g2d.drawLine(LEFT_WALL, 600, LEFT_WALL, TOP_WALL);
g2d.drawLine(RIGHT_WALL, 600, RIGHT_WALL, TOP_WALL);
g2d.drawLine(LEFT_WALL, TOP_WALL, RIGHT_WALL, TOP_WALL);
g2d.fillRect(BAR_X, BAR_Y, BAR_WIDTH, BAR_HEIGHT);
g2d.setColor(Color.red);
g2d.fillOval(BALL_X, BALL_Y, BALL_SIZE, BALL_SIZE);
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 5; j++) {
if (status[i][j] > 0) {
X = x[i][j];
Y = y[i][j];
g2d.setColor(Color.white);
g2d.fillRect(X, Y, BRICK_WIDTH, BRICK_HEIGHT);
g2d.setColor(Color.red);
g2d.fillRect(X + 3, Y + 3, BRICK_WIDTH - 6, BRICK_HEIGHT - 6);
}
}
}
g2d.dispose();
}
protected void tick() {
BALL_X += BALL_DX;
BALL_Y += BALL_DY;
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 5; j++) {
if (BALL_X > x[i][j] && BALL_X < (x[i][j] + BRICK_WIDTH) && BALL_Y <= y[i][j] + BAR_HEIGHT + BALL_SIZE && BALL_Y > y[i][j] && BALL_DY < 0) {
BALL_DY = -BALL_DY;
status[i][j] -= 1;
} else if (BALL_X > x[i][j] && BALL_X < (x[i][j] + BRICK_WIDTH) && BALL_Y >= y[i][j] - BALL_SIZE && BALL_Y < y[i][j] + BAR_HEIGHT && BALL_DY > 0) {
BALL_DY = -BALL_DY;
status[i][j] -= 1;
} else if (BALL_X + BALL_SIZE >= x[i][j] && BALL_X < (x[i][j] + BRICK_WIDTH) && BALL_Y >= y[i][j] && BALL_Y < y[i][j] + BAR_HEIGHT && BALL_DY < 0) {
BALL_DX = -BALL_DX;
status[i][j] -= 1;
} else if (BALL_X > x[i][j] && BALL_X - BALL_SIZE <= (x[i][j] + BRICK_WIDTH) && BALL_Y >= y[i][j] && BALL_Y < y[i][j] + BAR_HEIGHT && BALL_DY < 0) {
BALL_DX = -BALL_DX;
status[i][j] -= 1;
} else if (BALL_X - BALL_SIZE < LEFT_WALL || BALL_X + BALL_SIZE > RIGHT_WALL) {
BALL_DX = -BALL_DX;
} else if (BALL_Y - BALL_SIZE < TOP_WALL) {
BALL_DY = -BALL_DY;
}
}
}
BAR_X = BAR_X + BAR_STATE * BAR_DX;
repaint();
}
class KeyAction extends AbstractAction {
private TestPane source;
private int delta;
public KeyAction(TestPane source, int delta) {
this.source = source;
this.delta = delta;
}
#Override
public void actionPerformed(ActionEvent e) {
source.BAR_STATE = delta;
}
}
}
}
I've messed with delta values, because the ball and bar disappeared real quick
So I'm new at java and need some help with my breakout game. My JFrame is just blank and i don't know how to fix it?
So I have a ball class, paddle class, canvas class and a brick class as well as a main class. In my canvas class I set all functions the ball, paddle and bricks has etc. In brick class I draw the bricks. And in my main I do the JFrame but it's blank
Main class :
public class Main {
public static void main(String[] args){
JFrame frame = new JFrame();
Canvas c = new Canvas();
frame.add(c);
frame.pack();
frame.setResizable(false);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
I expect the JFrame to show the game instead of just blank window
package breakout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import javax.swing.JPanel;
import javax.swing.Timer;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.KeyEvent;
import breakout.Bricks.Type;
public class Canvas extends JPanel implements ActionListener, MouseMotionListener, MouseListener, KeyListener {
/**
*
*/
private static final long serialVersionUID = 1L;
private static final int HEIGHT = 600;
public static final int WIDTH = 720;
private int horizontalCount;
private BufferedImage image;
private Graphics2D bufferedGraphics;
private Timer time;
private static final Font endFont = new Font(Font.SANS_SERIF, Font.BOLD, 20);
private static final Font scoreFont = new Font(Font.SANS_SERIF, Font.BOLD, 15);
private Paddle player;
private Ball ball;
ArrayList<ArrayList<Bricks>> bricks;
public Canvas() {
super();
setPreferredSize( new Dimension(WIDTH, HEIGHT));
image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
bufferedGraphics = image.createGraphics();
time = new Timer (15, this);
player = new Paddle((WIDTH/2)-(Paddle.PADDLE_WIDTH/2));
ball = new Ball (((player.getX() + (Paddle.PADDLE_WIDTH / 2 )) - (Ball.DIAMETER / 2)), (Paddle.Y_POS - (Ball.DIAMETER + 10 )), -5, -5);
bricks = new ArrayList<ArrayList<Bricks>>();
horizontalCount = WIDTH / Bricks.BRICK_WIDTH;
for(int i = 0; i < 8; ++i) {
ArrayList<Bricks> temp = new ArrayList<Bricks>();
#SuppressWarnings("unused")
Type rowColor = null;
switch(i) {
case 0 :
case 2:
rowColor = Type.LOW;
break;
case 1 :
case 3 :
case 5 :
rowColor = Type.MEDIUM;
break;
case 4 :
case 6 :
rowColor = Type.HIGH;
break;
case 7 :
default :
rowColor = Type.ULTRA;
break;
}
for(int j = 0; j < horizontalCount; ++j) {
Bricks tempBrick = new Bricks();
temp.add(tempBrick);
}
bricks.add(temp);
addMouseMotionListener(this);
addMouseListener(this);
addKeyListener(this);
requestFocus();
}
}
public void actionPerformed(ActionEvent e) {
checkCollisions();
ball.Move();
for(int i = 0; i < bricks.size(); ++i) {
ArrayList<Bricks> al = bricks.get(i);
for(int j = 0; j < al.size(); ++j) {
Bricks b = al.get(j);
if(b.dead()) {
al.remove(b);
}
}
}
repaint();
}
private void checkCollisions() {
if(player.hitPaddle(ball)) {
ball.setDY(ball.getDY() * -1);
return;
}
if(ball.getX() >= (WIDTH - Ball.DIAMETER) || ball.getX() <= 0) {
ball.setDX(ball.getDX() * -1);
}
if(ball.getY() > (Paddle.Y_POS + Paddle.PADDLE_HEIGHT + 10)) {
resetBall();
}
if(ball.getY() <= 0) {
ball.setDY(ball.getDY() * -1);
}
int brickRowActive = 0;
for(ArrayList<Bricks> alb : bricks) {
if(alb.size() == horizontalCount) {
++brickRowActive;
}
}
for(int i = (brickRowActive==0) ? 0 : (brickRowActive - 1); i < bricks.size(); ++i) {
for(Bricks b : bricks.get(i)) {
if(b.hitBy(ball)) {
player.setScore(player.getScore() + b.getBrickType().getPoints());
b.decrementType();
}
}
}
}
private void resetBall() {
if(gameOver()) {
time.stop();
return;
}
ball.setX(WIDTH/2);
ball.setDY((HEIGHT/2) + 80);
player.setLives(player.getLives() -1);
player.setScore(player.getScore() <= 1);
}
private boolean gameOver() {
if(player.getLives() <= 1) {
return true;
}
return false;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
bufferedGraphics.clearRect(0, 0, WIDTH, HEIGHT);
player.drawPaddle(bufferedGraphics);
player.drawBall(bufferedGraphics);
for(ArrayList<Bricks> row : bricks) {
for(Bricks b : row) {
b.drawBrick(bufferedGraphics);
}
}
bufferedGraphics.setFont(scoreFont);
bufferedGraphics.drawString("Score: " + player.getScore(), 10, 25);
if(gameOver() && ball.getY() >= HEIGHT) {
bufferedGraphics.setColor(Color.black);
bufferedGraphics.setFont(endFont);
bufferedGraphics.drawString("Game Over Score: " + player.getScore(), (WIDTH /2) -85, (HEIGHT/2));
}
if(empty()) {
bufferedGraphics.setColor(Color.black);
bufferedGraphics.setFont(endFont);
bufferedGraphics.drawString("You won. Score: " + player.getScore(), (WIDTH /2) -85, (HEIGHT /2));
time.stop();
}
g.drawImage(image, 0, 0, this);
Toolkit.getDefaultToolkit().sync();
}
private boolean empty() {
for(ArrayList<Bricks> al : bricks) {
if(al.size() != 0) {
return false;
}
}
return true;
}
#Override
public void mouseMoved(MouseEvent e) {
player.setX(e.getX() - (Paddle.PADDLE_WIDTH / 2));
}
#Override
public void mouseClicked(MouseEvent e) {
if(time.isRunning()) {
return;
}
time.start();
}
#Override
public void mouseDragged(MouseEvent e) { }
#Override
public void mouseEntered(MouseEvent arg0) {}
#Override
public void mouseExited(MouseEvent arg0) {}
#Override
public void mousePressed(MouseEvent arg0) {}
#Override
public void mouseReleased(MouseEvent arg0) {}
#Override
public void keyPressed(KeyEvent arg0) {}
#Override
public void keyReleased(KeyEvent arg0) {}
#Override
public void keyTyped(KeyEvent arg0) {}
}
Preparing an MCVE, as required in SO, not only it makes helping much easier.
In many case, while preparing one, you are likely to find the problem, so it is a good debugging tool.
To answer "why is my JFrame blank ?" you could create the minimal code example like the following (copy-paste the entire code into GameBoard.java and run):
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GameBoard extends JPanel {
static final int HEIGHT = 600, WIDTH = 720, BRICK_ROWS = 8;
private final int horizontalCount;
private static final Font scoreFont = new Font(Font.SANS_SERIF, Font.BOLD, 15);
private final Paddle player;
private final Ball ball;
ArrayList<ArrayList<Brick>> bricks;
public GameBoard() {
super();
setPreferredSize( new Dimension(WIDTH, HEIGHT));
player = new Paddle(WIDTH/2-Paddle.PADDLE_WIDTH/2);
ball = new Ball (player.getX() + Paddle.PADDLE_WIDTH / 2 - Ball.DIAMETER / 2,
Paddle.Y_POS - (Ball.DIAMETER + 10 ));
bricks = new ArrayList<>();
horizontalCount = WIDTH / Brick.BRICK_WIDTH;
for(int i = 0; i < BRICK_ROWS; ++i) {
ArrayList<Brick> temp = new ArrayList<>();
for(int j = 0; j < horizontalCount; ++j) {
Brick tempBrick = new Brick(j*Brick.BRICK_WIDTH , Brick.BRICK_YPOS + i*Brick.BRICK_HEIGHT);
temp.add(tempBrick);
}
bricks.add(temp);
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2D = (Graphics2D)g;
g2D.clearRect(0, 0, WIDTH, HEIGHT);
player.drawPaddle(g2D);
ball.drawBall(g2D);
for(ArrayList<Brick> row : bricks) {
for(Brick b : row) {
b.drawBrick(g2D);
}
}
g2D.setFont(scoreFont);
g2D.drawString("Score: " + player.getScore(), 10, 25);
}
}
class Paddle{
public final static int PADDLE_WIDTH = 100, PADDLE_HEIGHT= 30, Y_POS = GameBoard.HEIGHT - 2* PADDLE_HEIGHT;
private int xPos, score;
Paddle(int xPos) {
this.xPos = xPos;
}
void setX(int xPos) {this.xPos = xPos;}
int getX() {return xPos;}
String getScore() {
return String.valueOf(score);
}
void drawPaddle(Graphics2D g2D) {
g2D.setColor(Color.GREEN);
g2D.fillRect(xPos, Y_POS, PADDLE_WIDTH, PADDLE_HEIGHT);
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocation(400,250);
frame.add(new GameBoard());
frame.pack();
frame.setResizable(false);
frame.setVisible(true);
}
}
class Brick{
final static int BRICK_WIDTH = 80, BRICK_HEIGHT = 15, BRICK_YPOS = 50;
int xPos, yPos;
Brick(int xPos, int yPos) {
this.xPos = xPos;
this.yPos = yPos;
}
void drawBrick(Graphics2D g2D) {
g2D.setColor(Color.RED);
g2D.fillRect(xPos, yPos, BRICK_WIDTH, BRICK_HEIGHT);
g2D.setColor(Color.BLACK);
g2D.drawRect(xPos, yPos, BRICK_WIDTH, BRICK_HEIGHT);
}
}
class Ball{
final static int DIAMETER = 40;
int xPos, yPos;
Ball(int xPos, int yPos) {
this.xPos = xPos;
this.yPos = yPos;
}
void drawBall(Graphics2D g2D) {
g2D.setColor(Color.BLUE);
g2D.fillOval(xPos, yPos, DIAMETER, DIAMETER);
}
}
This produces the following result, which I believe can serve as the basis of what you wanted to achieve:
Now start adding the missing functionality and see what breaks it.
Here is the code which creates the bezier curve with total 4 control points:
Blue color is the starting and end control point.
Cyan color is the second and third control point.
I want to add a control point to the existing curve so that now I have 3 cyan coloured control points so that I can resize the curve(like dragging the curve) from any of these 3 control points instead of the 2 control points. What needs to be done for this?
I have attached the output of the below code as an attachment.
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.GeneralPath;
public class Piyush extends Frame implements MouseListener, MouseMotionListener {
// private int[] xs = { 75, 150, 300, 375 };
//
// private int[] ys = { 250, 100, 350, 250 };
private int[] xs = { 75, 200, 300, 375 };
private int[] ys = { 250, 100, 100, 250 };
private int dragIndex = NOT_DRAGGING;
private final static int NEIGHBORHOOD = 15;
private final static int NOT_DRAGGING = -1;
public static void main(String[] args) {
new Piyush();
}
public Piyush() {
setSize(500, 450);
addMouseListener(this);
addMouseMotionListener(this);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
setVisible(true);
}
public void paint(Graphics g) {
for (int i = 0; i < 4; i++) {
if (i == 0 || i == 3){
g.setColor(Color.blue);
g.fillOval(xs[i] - 6, ys[i] - 6, 12, 12);}
else{
g.setColor(Color.cyan);
g.fillOval(xs[i] - 6, ys[i] - 6, 12, 12);
}
}
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.black);
GeneralPath path = new GeneralPath();
path.moveTo(xs[0], ys[0]);
path.curveTo(xs[1], ys[1], xs[2], ys[2], xs[3], ys[3]);
g2d.draw(path);
}
public void mousePressed(MouseEvent e) {
dragIndex = NOT_DRAGGING;
int minDistance = Integer.MAX_VALUE;
int indexOfClosestPoint = -1;
for (int i = 0; i < 4; i++) {
int deltaX = xs[i] - e.getX();
int deltaY = ys[i] - e.getY();
int distance = (int) (Math.sqrt(deltaX * deltaX + deltaY * deltaY));
if (distance < minDistance) {
minDistance = distance;
indexOfClosestPoint = i;
}
}
if (minDistance > NEIGHBORHOOD)
return;
dragIndex = indexOfClosestPoint;
}
public void mouseReleased(MouseEvent e) {
if (dragIndex == NOT_DRAGGING)
return;
xs[dragIndex] = e.getX();
ys[dragIndex] = e.getY();
dragIndex = NOT_DRAGGING;
repaint();
}
public void mouseDragged(MouseEvent e) {
if (dragIndex == NOT_DRAGGING)
return;
xs[dragIndex] = e.getX();
ys[dragIndex] = e.getY();
repaint();
}
public void mouseClicked(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mouseMoved(MouseEvent e) {
}
}
Also asked here
http://www.dreamincode.net/forums/topic/408270-need-help-in-adding-a-control-point-for-bezier-curve/page__pid__2347742__st__0&#entry2347742
code base comes from here
http://www.java2s.com/Tutorials/Java/Graphics/Shape/Drag_the_control_point_for_Bezier_curve_in_Java.htm
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;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.Timer;
public class FinalFlappy implements ActionListener, MouseListener,
KeyListener
{
public static FinalFlappy finalFlappy;
public final int WIDTH = 800, HEIGHT = 800;
public FinalFlappyRend renderer;
public Rectangle bee;
public ArrayList<Rectangle> rect_column;
public int push, yMotion, score;
public boolean gameOver, started;
public Random rand;
public FinalFlappy()
{
JFrame jframe = new JFrame();
Timer timer = new Timer(16, this);
renderer = new FinalFlappyRend();
rand = new Random();
jframe.add(renderer);
jframe.setTitle("Flappy Bee");
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jframe.setSize(WIDTH, HEIGHT);
jframe.addMouseListener(this);
jframe.addKeyListener(this);
jframe.setResizable(false);
jframe.setVisible(true);
bee = new Rectangle(WIDTH / 2 - 10, HEIGHT / 2 - 10, 40, 40);
rect_column = new ArrayList<Rectangle>();
addColumn(true);
addColumn(true);
addColumn(true);
addColumn(true);
timer.start();
}
public void addColumn(boolean start)
{
int space = 300;
int width = 60;
int height = 50 + rand.nextInt(300);
if (start)
{
rect_column.add(new Rectangle(WIDTH + width + rect_column.size() * 300, HEIGHT - height - 120, width, height));
rect_column.add(new Rectangle(WIDTH + width + (rect_column.size() - 1) * 300, 0, width, HEIGHT - height - space));
}
else
{
rect_column.add(new Rectangle(rect_column.get(rect_column.size() - 1).x + 600, HEIGHT - height - 120, width, height));
rect_column.add(new Rectangle(rect_column.get(rect_column.size() - 1).x, 0, width, HEIGHT - height - space));
}
}
public void jump()
{
if (gameOver)
{
bee = new Rectangle(WIDTH / 2 - 10, HEIGHT / 2 - 10, 40, 40);
rect_column.clear();
yMotion = 0;
score = 0;
addColumn(true);
addColumn(true);
addColumn(true);
addColumn(true);
gameOver = false;
}
if (!started)
{
started = true;
}
else if (!gameOver)
{
if (yMotion > 0)
{
yMotion = 0;
}
yMotion -= 10;
}
}
#Override
public void actionPerformed(ActionEvent e)
{
int speed = 10;
push++;
if (started)
{
for (int i = 0; i < rect_column.size(); i++)
{
Rectangle column = rect_column.get(i);
column.x -= speed;
}
if (push % 2 == 0 && yMotion < 15)
{
yMotion += 2;
}
for (int i = 0; i < rect_column.size(); i++)
{
Rectangle column = rect_column.get(i);
if (column.x + column.width < 0)
{
rect_column.remove(column);
if (column.y == 0)
{
addColumn(false);
}
}
}
bee.y += yMotion;
for (Rectangle column : rect_column)
{
if (column.y == 0 && bee.x + bee.width / 2 > column.x + column.width / 2 - 10 && bee.x + bee.width / 2 < column.x + column.width / 2 + 10)
{
score++;
}
if (column.intersects(bee))
{
gameOver = true;
if (bee.x <= column.x)
{
bee.x = column.x - bee.width;
}
else
{
if (column.y != 0)
{
bee.y = column.y - bee.height;
}
else if (bee.y < column.height)
{
bee.y = column.height;
}
}
}
}
if (bee.y > HEIGHT - 120 || bee.y < 0)
{
gameOver = true;
}
if (bee.y + yMotion >= HEIGHT - 120)
{
bee.y = HEIGHT - 120 - bee.height;
gameOver = true;
}
}
renderer.repaint();
}
public void paintColumn(Graphics g, Rectangle column)
{
g.setColor(Color.green.darker());
g.fillRect(column.x, column.y, column.width, column.height);
g.fillRect(column.x-20, column.y+column.height-10, column.width+40, 10);
g.fillRect(column.x-20, column.y-10, column.width+40, 10);
}
public void repaint(Graphics g)
{
g.setColor(new Color(153,204,255));
g.fillRect(0, 0, WIDTH, HEIGHT);
g.setColor(new Color(255,255,255));
g.fillOval(50, 50, 100, 100);
g.setColor(Color.YELLOW);
g.fillOval(600, 50, 100, 100);
g.setColor(new Color(156,93,82));
g.fillRect(0, HEIGHT - 120, WIDTH, 120);
g.setColor(new Color(128,255,0));
g.fillRect(0, HEIGHT - 120, WIDTH, 20);
g.setColor(Color.YELLOW);
g.fillRect(bee.x, bee.y, bee.width, bee.height);
for (Rectangle column : rect_column)
{
paintColumn(g, column);
}
g.setColor(Color.white);
g.setFont(new Font("Times New Roman", 1, 100));
if (!started)
{
g.drawString("Push A to start", 100, HEIGHT / 2 - 50);
}
if (gameOver)
{
g.drawString("Game Over", 100, HEIGHT / 2 - 50);
g.drawString("A to replay", 100, HEIGHT / 2 + 90);
}
}
public static void main(String[] args)
{
finalFlappy = new FinalFlappy();
}
#Override
public void mouseClicked(MouseEvent e)
{
jump();
}
#Override
public void keyReleased(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_A)
{
jump();
}
}
#Override
public void mousePressed(MouseEvent e)
{
}
#Override
public void mouseReleased(MouseEvent e)
{
}
#Override
public void mouseEntered(MouseEvent e)
{
}
#Override
public void mouseExited(MouseEvent e)
{
}
#Override
public void keyTyped(KeyEvent e)
{
}
#Override
public void keyPressed(KeyEvent e)
{
}
}
import java.awt.Graphics;
import javax.swing.JPanel;
public class FinalFlappyRend extends JPanel
{
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
FinalFlappy.finalFlappy.repaint(g);
}
}
I am working on making a Flappy bird game and I am stuck on how to make and display a timer that updates every second onto the screen
How do I make it start as the game starts and end as the game over pops up?
There are a few ways you might achieve what you're asking. The important thing to remember is, any solution is going to have a degree of drift, meaning that it's unlikely to absolutely accurate, the degree of drift will depend on a lot of factors, so just beware.
You could use a Swing Timer
It's among the safest means for updating the UI on a regular basis, it's also useful if your main loop is already based on a Swing Timer
See How to Use Swing Timers for more details
You could...
Maintain some kind of counter within in your main loop. This assumes that you're using a separate thread (although you can do the same thing with a Swing Timer) and are simply looping at some consistent rate
long tick = System.nanoTime();
long lastUpdate = -1;
while (true) {
long diff = System.nanoTime() - tick;
long seconds = TimeUnit.SECONDS.convert(diff, TimeUnit.NANOSECONDS);
if (seconds != lastUpdate) {
lastUpdate = seconds;
updateTimerLabel(seconds);
}
Thread.sleep(100);
}
This basically runs a while-loop, which calculates the difference between a given point in time (tick) and now, if it's a "second" difference, it then updates the UI (rather than constantly updating the UI with the same value)
The updateTimerLabel method basically updates the label with the specified time, but does so in a manner which is thread safe
protected void updateTimerLabel(long seconds) {
if (EventQueue.isDispatchThread()) {
timerLabel.setText(Long.toString(seconds));
} else {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
updateTimerLabel(seconds);
}
});
}
}
To make and display a timer that updates every second, Put this code in your main class:
private Timer timer = new Timer();
private JLabel timeLabel = new JLabel(" ", JLabel.CENTER);
timer.schedule(new UpdateUITask(), 0, 1000);
private class UpdateUITask extends TimerTask {
int nSeconds = 0;
#Override
public void run() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
timeLabel.setText(String.valueOf(nSeconds++));
}
});
}
}
So I'm making a game where you jump on rocks and you must not jump on rock which is covered by water. I'm stuck at the part where rocks (circles) randomly disappear in water and randomly appear and around 1.5 seconds before they disappear make it change color. I think its best to use javax.swing.Timer.
Could you help me achieve that?
Here is my code so far:
Main class:
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Menu;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferStrategy;
import java.util.Random;
import javax.swing.Timer;
public class Game extends Canvas implements Runnable{
private static final long serialVersionUID = -7800496711589684767L;
public static final int WIDTH = 640, HEIGHT = WIDTH / 12 * 9;
private Thread thread;
private boolean running = false;
private Random r;
private Handler handler;
//private HUD hud;
private Menu menu;
public enum STATE {
Menu,
Help,
Game
};
public STATE gameState = STATE.Menu;
public Game() {
handler = new Handler();
menu = new Menu(this, handler);
this.addKeyListener(new KeyInput(handler));
this.addMouseListener(menu);
new Window(WIDTH, HEIGHT, "My game", this);
//hud = new HUD();
r = new Random();
//if(gameState == STATE.Game) {
if(gameState == STATE.Game) { //handler.addObject(new Player(100, 200, ID.Player));
}
//handler.addObject(new Player(100, 200, ID.Player));
//handler.addObject(new BasicEnemy(100, 200, ID.BasicEnemy));
}
public synchronized void start() {
thread = new Thread(this);
thread.start();
running = true;
}
public synchronized void stop() {
try {
thread.join();
running = false;
}catch(Exception ex) { ex.printStackTrace(); }
}
public void run()
{
this.requestFocus();
long lastTime = System.nanoTime();
double amountOfTicks = 60.0;
double ns = 1000000000 / amountOfTicks;
double delta = 0;
long timer = System.currentTimeMillis();
int frames = 0;
while(running)
{
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while(delta >=1)
{
tick();
delta--;
}
if(running)
render();
frames++;
if(System.currentTimeMillis() - timer > 1000)
{
timer += 1000;
//System.out.println("FPS: "+ frames);
frames = 0;
}
}
stop();
}
private void tick() {
handler.tick();
//hud.tick();
if(gameState == STATE.Game) {
Random r = new Random();
long now = System.currentTimeMillis();
int b = 0;
//System.out.println(now);
long extraSeconds = 500;
}else if(gameState == STATE.Menu) {
menu.tick();
}
}
private void render() {
BufferStrategy bs = this.getBufferStrategy();
if(bs == null) {
this.createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
long now = System.currentTimeMillis();
g.setColor(new Color(87, 124, 212));
g.fillRect(0, 0, WIDTH, HEIGHT);
if(gameState == STATE.Game) {
g.setColor(new Color(209, 155, 29));
for(int i = 0; i < 5; i++) {
g.fillOval(80 + (100 * i), 325, 70, 20);
}
if(gameState == STATE.Game) {
}else if(gameState == STATE.Menu || gameState == STATE.Help){
menu.render(g);
}
handler.render(g);
if(gameState == STATE.Game) {
}
//hud.render(g);
g.dispose();
bs.show();
}
public static int clamp(int var, int min, int max) {
if(var >= max)
return var = max;
else if(var <= max)
return var = min;
else
return var;
}
public static void main(String[] args) {
new Game();
}
}
GameObject class:
package com.pitcher654.main;
import java.awt.Graphics;
public abstract class GameObject {
protected static int x, y;
protected ID id;
protected int velX, velY;
public GameObject(int x, int y, ID id) {
this.x = x;
this.y = y;
this.id = id;
}
public abstract void tick();
public abstract void render(Graphics g);
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void setID(ID id) {
this.id = id;
}
public ID getID() {
return id;
}
public void setVelX(int velX) {
this.velX = velX;
}
public void setVelY(int velY) {
this.velY = velY;
}
public int getVelX() {
return velX;
}
public int getVelY() {
return velY;
}
}
Handler class:
package com.pitcher654.main;
import java.awt.Graphics;
import java.util.LinkedList;
public class Handler {
LinkedList<GameObject> object = new LinkedList<GameObject>();
public void tick() {
for(int i = 0; i < object.size(); i++) {
GameObject tempObject = object.get( i );
tempObject.tick();
}
}
public void render(Graphics g) {
for(int i = 0; i < object.size(); i++) {
GameObject tempObject = object.get(i);
tempObject.render(g);
}
}
public void addObject(GameObject object) {
this.object.add(object);
}
public void removeObject(GameObject object) {
this.object.remove(object);
}
}
ID class:
package com.pitcher654.main;
public enum ID {
Player(),
Player2(),
BasicEnemy(),
Misc();
}
KeyInput class:
package com.pitcher654.main;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
public class KeyInput extends KeyAdapter{
private Handler handler;
public KeyInput(Handler handler) {
this.handler = handler;
}
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
for(int i = 0; i < handler.object.size(); i++) {
GameObject tempObject = handler.object.get(i);
if(tempObject.getID() == ID.Player) {
//kez events for Player 1
//GameObject object = new GameObject(0, 0, ID.Misc);
//System.out.println(tempObject.getID());
if(GameObject.x != 500) {
if(key == KeyEvent.VK_RIGHT) {
Player.currentStone++;
tempObject.setX(tempObject.getX() + 100);
}
}
if(GameObject.x != 100){
if(key == KeyEvent.VK_LEFT) {
Player.currentStone--;
tempObject.setX(tempObject.getX() - 100);
}
}
}
}
if(key == KeyEvent.VK_ESCAPE) System.exit(1);
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
}
}
Menu class:
package com.pitcher654.main;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import com.pitcher654.main.Game.STATE;
public class Menu extends MouseAdapter{
private Game game;
private Handler handler;
private GameObject Player;
public Menu(Game game, Handler handler) {
this.game = game;
this.handler = handler;
}
public void mouseClicked(MouseEvent e) {
int mx = e.getX();
int my = e.getY();
if(game.gameState == STATE.Menu) {
//play 1 button
if(mouseOver(mx, my, (Game.WIDTH - 250) / 2, 150, 250, 64)) {
game.gameState = STATE.Game;
handler.addObject(new Player(100, 200, ID.Player));
//handler.addObject(new BasicEnemy(0, 0, ID.BasicEnemy));
}
//Instructions button
if(mouseOver(mx, my, (Game.WIDTH - 250) / 2, 250, 250, 64)) {
game.gameState = STATE.Help;
}
//Quit button
if(mouseOver(mx, my, (Game.WIDTH - 250) / 2, 350, 250, 64)) {
System.exit(1);
}
}
//Bacl to menu in game button
if(game.gameState == STATE.Help) {
if(mouseOver(mx, my, 23, 395, 100, 32)) {
game.gameState = STATE.Menu;
//handler.object.remove(Player);
}
}
}
public void mouseReleased(MouseEvent e) {
}
private boolean mouseOver(int mx, int my, int x, int y, int width, int height) {
if(mx > x && mx < x + width) {
if(my > y && my < y + height) {
return true;
}else return false;
}else return false;
}
public void tick() {
}
public void render(Graphics g) {
if(game.gameState == STATE.Menu) {
Font fnt = new Font("Trebuchet MS", 30, 15);
g.setColor(new Color(87, 124, 212));
g.fillRect(0, 0, game.WIDTH, game.HEIGHT);
g.setColor(Color.white);
g.setFont(new Font("Papyrus", 1, 50));
g.drawString("Price iz davnine", (Game.WIDTH - 250) / 2 - 50, 70);
g.drawRect((Game.WIDTH - 250) / 2, 150, 250, 64);
g.drawRect((Game.WIDTH - 250) / 2, 250, 250, 64);
g.drawRect((Game.WIDTH - 250) / 2, 350, 250, 64);
g.setFont(new Font("Trebuchet MS", 5000, 20));
g.drawString("Play", (Game.WIDTH - 250) / 2 + 110, 190);
g.setFont(fnt);
g.drawString("How to Play", (Game.WIDTH - 250) / 2 + 85, 290);
g.drawString("Quit", (Game.WIDTH - 250) / 2 + 105, 390);
}else if(game.gameState == STATE.Help) {
g.setColor(Color.white);
g.setFont(new Font("Papyrus", 1, 50));
g.drawString("How to play", (Game.WIDTH - 250) / 2 - 50, 70);
g.setFont(new Font("Trebuchetr MS", 30, 10));
g.drawRect(23, 395, 100, 32);
g.setColor(Color.black);
g.drawString("Back to Menu", 33, 415);
}
}
}
Player class:
package com.pitcher654.main;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.Timer;
import com.pitcher654.main.Game.STATE;
public class Player extends GameObject {
Random r = new Random();
public static int currentStone = 1;
public Player(int x, int y, ID id) {
super(x, y, id);
//velX = r.nextInt(5) + 1;
//velY = r.nextInt(5);
}
public void tick() {
x += velX;
y += velY;
//System.out.println(x);
//if(x == 500) x = 500;
}
public void render(Graphics g) {
if(id == ID.Player) g.setColor(Color.white);
g.fillRect(x, y, 32, 32);
g.drawLine(x + 15, y, x + 15, y + 100);
g.drawLine(x + 15, y + 100, x, y + 135);
g.drawLine(x + 15, y + 100, x + 33, y + 135);
g.drawLine(x + 15, y + 70, x - 35, y + 30);
g.drawLine(x + 15, y + 70, x + 65, y + 30);
/*if(game.gameState == STATE.Menu) {
g.setColor(new Color(87, 124, 212));
g.fillRect(0, 0, Game.WIDTH, Game.HEIGHT);
}*/
}
}
And window class:
package com.pitcher654.main;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Window extends Canvas{
private static final long serialVersionUID = 9086330915853125521L;
BufferedImage image = null;
URL url = null;
public Window(int width, int height, String title, Game game) {
JFrame frame = new JFrame(title);
try {
image = ImageIO.read(new URL("https://static.wixstatic.com/media/95c249_b887de2536aa48cb962e2336919d2693.png/v1/fill/w_600,h_480,al_c,usm_0.66_1.00_0.01/95c249_b887de2536aa48cb962e2336919d2693.png"));
} catch (IOException e) {
e.printStackTrace();
}
frame.setPreferredSize(new Dimension(width, height));
frame.setMaximumSize(new Dimension(width, height));
frame.setMinimumSize(new Dimension(width, height));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.add(game);
frame.setIconImage(image);
//DrawingPanel panel = new DrawingPanel();
//frame.getContentPane().add(panel);
frame.setVisible(true);
frame.requestFocus();
game.start();
}
public class DrawingPanel extends JPanel {
private static final long serialVersionUID = -7662876024842980779L;
public void paintComponent(Graphics g) {
g.setColor(new Color(209, 155, 29));
g.fillOval(100, 100, 100, 100);
}
}
}
Based on you code, a Swing Timer isn't what you want. You already have a "game/main" loop which should be updating the current state of the game on each cycle and rendering it, you simply need to devise a means by which you can create a "rock", with a given life span, each time it's rendered, it needs to check if it's life span is nearly over and have it removed when it dies.
The rock is really just another entity in your game, which can be updated and rendered.
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics2D;
import java.awt.event.ComponentAdapter;
import java.awt.image.BufferStrategy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class RockyRoad {
public static void main(String[] args) {
new RockyRoad();
}
public RockyRoad() {
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 Game());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class Game extends Canvas implements Runnable {
private static final long serialVersionUID = -7800496711589684767L;
public static final int WIDTH = 640, HEIGHT = WIDTH / 12 * 9;
private Thread thread;
private boolean running = false;
private Random rnd;
private List<Entity> entities = new ArrayList<>(25);
public enum STATE {
Menu,
Help,
Game
};
public STATE gameState = STATE.Game;
public Game() {
rnd = new Random();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
start();
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(WIDTH, HEIGHT);
}
public synchronized void start() {
thread = new Thread(this);
thread.start();
running = true;
}
public synchronized void stop() {
try {
thread.join();
running = false;
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void run() {
this.requestFocus();
long lastTime = System.nanoTime();
double amountOfTicks = 60.0;
double ns = 1000000000 / amountOfTicks;
double delta = 0;
long timer = System.currentTimeMillis();
int frames = 0;
while (running) {
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while (delta >= 1) {
tick();
delta--;
}
if (running) {
update();
render();
}
frames++;
if (System.currentTimeMillis() - timer > 1000) {
timer += 1000;
//System.out.println("FPS: "+ frames);
frames = 0;
}
}
stop();
}
private void tick() {
//hud.tick();
}
protected void update() {
if (gameState == STATE.Game) {
if (rnd.nextBoolean()) {
System.out.println("New...");
int x = rnd.nextInt(getWidth() - Rock.SIZE);
int y = rnd.nextInt(getHeight() - Rock.SIZE);
int lifeSpan = 4000 + rnd.nextInt(6000);
entities.add(new Rock(lifeSpan, x, y));
}
List<Entity> toRemove = new ArrayList<>(entities.size());
List<Entity> control = Collections.unmodifiableList(entities);
for (Entity entity : entities) {
if (entity.update(control, this) == EntityAction.REMOVE) {
System.out.println("Die...");
toRemove.add(entity);
}
}
entities.removeAll(toRemove);
}
}
private void render() {
BufferStrategy bs = this.getBufferStrategy();
if (bs == null) {
this.createBufferStrategy(3);
return;
}
Graphics2D g = (Graphics2D) bs.getDrawGraphics();
long now = System.currentTimeMillis();
g.setColor(new Color(87, 124, 212));
g.fillRect(0, 0, WIDTH, HEIGHT);
if (gameState == STATE.Game) {
g.setColor(new Color(209, 155, 29));
if (gameState == STATE.Game) {
for (Entity entity : entities) {
entity.render(g, this);
}
}
g.dispose();
bs.show();
}
}
public static int clamp(int var, int min, int max) {
if (var >= max) {
return var = max;
} else if (var <= max) {
return var = min;
} else {
return var;
}
}
}
public interface Renderable {
public void render(Graphics2D g2d, Component parent);
}
public enum EntityAction {
NONE,
REMOVE;
}
public interface Entity extends Renderable {
// In theory, you'd pass the game model which would determine
// all the information the entity really needed
public EntityAction update(List<Entity> entities, Component parent);
}
public static class Rock implements Renderable, Entity {
protected static final int SIZE = 20;
private int lifeSpan;
private long birthTime;
private int x, y;
public Rock(int lifeSpan, int x, int y) {
if (lifeSpan <= 1500) {
throw new IllegalArgumentException("Life span for a rock can not be less then or equal to 1.5 seconds");
}
this.lifeSpan = lifeSpan;
birthTime = System.currentTimeMillis();
this.x = x;
this.y = y;
}
#Override
public void render(Graphics2D g2d, Component parent) {
long age = System.currentTimeMillis() - birthTime;
if (age < lifeSpan) {
if (age < lifeSpan - 1500) {
g2d.setColor(Color.BLUE);
} else {
g2d.setColor(Color.RED);
}
g2d.fillOval(x, y, SIZE, SIZE);
}
}
#Override
public EntityAction update(List<Entity> entities, Component parent) {
EntityAction action = EntityAction.NONE;
long age = System.currentTimeMillis() - birthTime;
System.out.println("Age = " + age + "; lifeSpan = " + lifeSpan);
if (age >= lifeSpan) {
action = EntityAction.REMOVE;
}
return action;
}
}
}