My Bouncing Ball Does Not Draw - java

I am having a problem getting my application to draw a Ball when i click on the frame.
I thought my code was correct, and I don't get any errors, but it still doesn't work.
I feel the problem is with the MouseListener implementation and that the application is not handling the MouseEvent properly.
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.*;
public class BouncingBallApp extends JFrame
{
public static void main(String[] args)
{
Container container;
BouncingBallApp bouncingBalls = new BouncingBallApp();
bouncingBalls.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
container = new Container();
BouncingBallPanel BBP = new BouncingBallPanel();
container.add(BBP);
bouncingBalls.addMouseListener(BBP);
//addMouseListener;
bouncingBalls.setBackground( Color.WHITE );
bouncingBalls.setSize(400,300);
bouncingBalls.setVisible( true );
}//end of main method
}//end of BouncingBallApp
class BouncingBallPanel extends JPanel implements MouseListener, Runnable
{
private Ball[] ballArray = new Ball[20];
private int ballCount = 0;
public void run()
{
for(int i = 0; i<ballArray.length; i++){
if(ballArray[i] != null){
ballArray[i].move();}}
repaint();
//delay(1);
}
public void mouseClicked(MouseEvent e)
{
ballArray[ballCount] = new Ball();
ballCount++;
if(ballCount == 1)
(new Thread(new BouncingBallPanel())).start();
}
//empty interface methods
public void mouseExited(MouseEvent e){}
public void mouseReleased(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mousePressed(MouseEvent e){}
public void paintComponent(Graphics g)
{
super.paintComponent( g );
Graphics2D g2d = (Graphics2D) g;
for(int i = 0; i<ballArray.length; i++)
{
if(ballArray[i] != null){
g2d.setColor(ballArray[i].getColor());
g2d.fill(new Ellipse2D.Double(ballArray[i].getX(),ballArray[i].getY(),ballArray
[i].getDiameter(),ballArray[i].getDiameter()));}
}//end of for loop
}
}//end of BouncingBallPanel
class Ball
{
private double x;
private double y;
private double deltaX;
private double deltaY;
private double diameter;
private Color color;
Random random = new Random();
public Ball()
{
x = random.nextInt(400);
y = random.nextInt(300);
deltaX = 2;
deltaY = 2;
diameter = 10;
color = new Color(random.nextInt(256),random.nextInt(256),random.nextInt(256));
}//end of constructor
public double getX(){
return x;}
public double getY(){
return y;}
public double getDiameter(){
return diameter;}
public Color getColor(){
return color;}
public void move()
{
x += deltaX;
y += deltaY;
if (x < 0) {
x = 0;
deltaX = -deltaX;}
else if (x > 400) {
x = 400;
deltaX = -deltaX;}
if (y < 0) {
y = 0;
deltaY = -deltaY;}
else if (y > 300) {
y = 300;
deltaY = -deltaY;}
}//end of method move
}//end of ball

3 Things
No size for container
You are not adding container
No loop to update graphics
The code below is working
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.*;
public class BouncingBallApp extends JFrame {
public static void main(String[] args) {
// Container container;
BouncingBallApp bouncingBalls = new BouncingBallApp();
bouncingBalls.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// container = new Container();
BouncingBallPanel BBP = new BouncingBallPanel();
// container.add(BBP);
bouncingBalls.addMouseListener(BBP);
// addMouseListener;
bouncingBalls.setBackground(Color.WHITE);
bouncingBalls.setSize(400, 300);
BBP.setSize(400, 300);
BBP.setLayout(null);
bouncingBalls.setContentPane(BBP);
/*
* JTextField jtf = new JTextField(); BBP.add(jtf); jtf.setSize(100,
* 20);
*/
bouncingBalls.setVisible(true);
}// end of main method
}// end of BouncingBallApp
class BouncingBallPanel extends JPanel implements MouseListener {
private Ball[] ballArray = new Ball[20];
private int ballCount = 0;
public void mouseClicked(MouseEvent e) {
ballArray[ballCount] = new Ball();
ballCount++;
if (ballCount == 1) {
final Runnable updateGraphics = new Runnable() {
public void run() {
for (int i = 0; i < ballArray.length; i++) {
if (ballArray[i] != null) {
ballArray[i].move();
}
}
repaint();
}
};
Runnable animation = new Runnable() {
public void run() {
while (true) {
try {
EventQueue.invokeLater(updateGraphics);
Thread.sleep(100);
} catch (InterruptedException e) {
return;
}
}
}
};
new Thread(animation).start();
}
}
// empty interface methods
public void mouseExited(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
}
public void paintComponent(Graphics g) {
// super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
for (int i = 0; i < ballArray.length; i++) { if (ballArray[i] !=
null) { System.out.println(" ball " + i + " , " +
ballArray[i].getColor() + " , " + ballArray[i].getX() + " , " +
ballArray[i].getY() + " , " + ballArray[i].getDiameter());
g2d.setColor(ballArray[i].getColor());
g2d.fillRect((int)ballArray[i].getX(), (int)ballArray[i].getY(),
(int)ballArray[i].getDiameter(), (int)ballArray[i].getDiameter()); }
}// end of for loop
}
}// end of BouncingBallPanel
class Ball {
private double x;
private double y;
private double deltaX;
private double deltaY;
private double diameter;
private Color color;
Random random = new Random();
public Ball() {
x = random.nextInt(400);
y = random.nextInt(300);
deltaX = 2;
deltaY = 2;
diameter = 10;
color = new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256));
}// end of constructor
public double getX() {
return x;
}
public double getY() {
return y;
}
public double getDiameter() {
return diameter;
}
public Color getColor() {
return color;
}
public void move() {
x += deltaX;
y += deltaY;
if (x < 0) {
x = 0;
deltaX = -deltaX;
}
else if (x > 400) {
x = 400;
deltaX = -deltaX;
}
if (y < 0) {
y = 0;
deltaY = -deltaY;
}
else if (y > 300) {
y = 300;
deltaY = -deltaY;
}
}// end of method move
}// end of ball

Related

Breakout Program only shows 1 Brick

To be frank i have not the slightest clue how to fix this whats so ever. It works until you get to the part that only 1 brick shows and its kinda frustrating... If anyone could help me i would appreciate it. I did look up how to fix this but i didn't even find anyone that had this problem. Google searching isn't really that good. Oh and i used Eclipse for this program.
Board Class
package Final;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JPanel;
public class Board extends JPanel implements Commons {
private Timer timer;
private String message = "Your Fired";
private Ball ball;
private Paddle paddle;
private Brick bricks[];
private boolean ingame = true;
public Board() {
initBoard();
}
private void initBoard() {
addKeyListener(new TAdapter());
setFocusable(true);
bricks = new Brick[N_OF_BRICKS];
setDoubleBuffered(true);
timer = new Timer();
timer.scheduleAtFixedRate(new ScheduleTask(), DELAY, PERIOD);
}
#Override
public void addNotify() {
super.addNotify();
gameInit();
}
private void gameInit() {
ball = new Ball();
paddle = new Paddle();
int k = 0;
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 6; j++) {
bricks[k] = new Brick(j * 40 + 30, i * 10 + 50);
k++;
}
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
if (ingame) {
drawObjects(g2d);
} else {
gameFinished(g2d);
}
Toolkit.getDefaultToolkit().sync();
}
private void drawObjects(Graphics2D g2d) {
g2d.drawImage(ball.getImage(), ball.getX(), ball.getY(),
ball.getWidth(), ball.getHeight(), this);
g2d.drawImage(paddle.getImage(), paddle.getX(), paddle.getY(),
paddle.getWidth(), paddle.getHeight(), this);
for (int i = 0; i < N_OF_BRICKS; i++) {
if (!bricks[i].isDestroyed()) {
g2d.drawImage(bricks[i].getImage(), bricks[i].getX(),
bricks[i].getY(), bricks[i].getWidth(),
bricks[i].getHeight(), this);
}
}
}
private void gameFinished(Graphics2D g2d) {
Font font = new Font("Verdana", Font.BOLD, 18);
FontMetrics metr = this.getFontMetrics(font);
g2d.setColor(Color.BLACK);
g2d.setFont(font);
g2d.drawString(message,
(Commons.WIDTH - metr.stringWidth(message)) / 2,
Commons.WIDTH / 2);
}
private class TAdapter extends KeyAdapter {
#Override
public void keyReleased(KeyEvent e) {
paddle.keyReleased(e);
}
#Override
public void keyPressed(KeyEvent e) {
paddle.keyPressed(e);
}
}
private class ScheduleTask extends TimerTask {
#Override
public void run() {
ball.move();
paddle.move();
checkCollision();
repaint();
}
}
private void stopGame() {
ingame = false;
timer.cancel();
}
private void checkCollision() {
if (ball.getRect().getMaxY() > Commons.BOTTOM_EDGE) {
stopGame();
}
for (int i = 0, j = 0; i < N_OF_BRICKS; i++) {
if (bricks[i].isDestroyed()) {
j++;
}
if (j == N_OF_BRICKS) {
message = "Pay Day";
stopGame();
}
}
if ((ball.getRect()).intersects(paddle.getRect())) {
int paddleLPos = (int) paddle.getRect().getMinX();
int ballLPos = (int) ball.getRect().getMinX();
int first = paddleLPos + 8;
int second = paddleLPos + 16;
int third = paddleLPos + 24;
int fourth = paddleLPos + 32;
if (ballLPos < first) {
ball.setXDir(-1);
ball.setYDir(-1);
}
if (ballLPos >= first && ballLPos < second) {
ball.setXDir(-1);
ball.setYDir(-1 * ball.getYDir());
}
if (ballLPos >= second && ballLPos < third) {
ball.setXDir(0);
ball.setYDir(-1);
}
if (ballLPos >= third && ballLPos < fourth) {
ball.setXDir(1);
ball.setYDir(-1 * ball.getYDir());
}
if (ballLPos > fourth) {
ball.setXDir(1);
ball.setYDir(-1);
}
}
for (int i = 0; i < N_OF_BRICKS; i++) {
if ((ball.getRect()).intersects(bricks[i].getRect())) {
int ballLeft = (int) ball.getRect().getMinX();
int ballHeight = (int) ball.getRect().getHeight();
int ballWidth = (int) ball.getRect().getWidth();
int ballTop = (int) ball.getRect().getMinY();
Point pointRight = new Point(ballLeft + ballWidth + 1, ballTop);
Point pointLeft = new Point(ballLeft - 1, ballTop);
Point pointTop = new Point(ballLeft, ballTop - 1);
Point pointBottom = new Point(ballLeft, ballTop + ballHeight + 1);
if (!bricks[i].isDestroyed()) {
if (bricks[i].getRect().contains(pointRight)) {
ball.setXDir(-1);
} else if (bricks[i].getRect().contains(pointLeft)) {
ball.setXDir(1);
}
if (bricks[i].getRect().contains(pointTop)) {
ball.setYDir(1);
} else if (bricks[i].getRect().contains(pointBottom)) {
ball.setYDir(-1);
}
bricks[i].setDestroyed(true);
}
}
}
}
}
Brick Class
package Final;
import javax.swing.ImageIcon;
public class Brick extends Sprite {
private boolean destroyed;
public Brick(int x, int y) {
ImageIcon ii = new ImageIcon("images/bricks.png");
image = ii.getImage();
i_width = image.getWidth(null);
i_heigth = image.getHeight(null);
destroyed = false;
}
public boolean isDestroyed() {
return destroyed;
}
public void setDestroyed(boolean val) {
destroyed = val;
}
}
Commons Class
package Final;
public interface Commons {
public static final int WIDTH = 300;
public static final int HEIGTH = 400;
public static final int BOTTOM_EDGE = 390;
public static final int N_OF_BRICKS = 30;
public static final int INIT_PADDLE_X = 200;
public static final int INIT_PADDLE_Y = 360;
public static final int INIT_BALL_X = 230;
public static final int INIT_BALL_Y = 355;
public static final int DELAY = 1000;
public static final int PERIOD = 10;
}
Sprite Class
package Final;
import java.awt.Image;
import java.awt.Rectangle;
public class Sprite {
protected int x;
protected int y;
protected int i_width;
protected int i_heigth;
protected Image image;
public void setX(int x) {
this.x = x;
}
public int getX() {
return x;
}
public void setY(int y) {
this.y = y;
}
public int getY() {
return y;
}
public int getWidth() {
return i_width;
}
public int getHeight() {
return i_heigth;
}
Image getImage() {
return image;
}
Rectangle getRect() {
return new Rectangle(x, y,
image.getWidth(null), image.getHeight(null));
}
}
Breakout Class
package Final;
import java.awt.EventQueue;
import javax.swing.JFrame;
public class Breakout extends JFrame {
public Breakout() {
initUI();
}
private void initUI() {
add(new Board());
setTitle("Lord Carl's Demolition Job");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(Commons.WIDTH, Commons.HEIGTH);
setLocationRelativeTo(null);
setResizable(false);
setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
Breakout game = new Breakout();
game.setVisible(true);
}
});
}
}
The problem is in checkCollision(). Inside the loop, j will never equal N_OF_BRICKS because of the loop condition. You could change to:
private void checkCollision() {
if (ball.getRect().getMaxY() > Commons.BOTTOM_EDGE) {
stopGame();
}
int j = 0;
for (int i = 0; i < N_OF_BRICKS; i++) {
if (bricks[i].isDestroyed()) {
j++;
}
}
if (j == N_OF_BRICKS) {
message = "Pay Day";
stopGame();
}
}
Also, in the Brick class you neglect to store the x,y coords:
public class Brick extends Sprite {
....
public Brick(int x, int y) {
ImageIcon ii = new ImageIcon("images/bricks.png");
image = ii.getImage();
i_width = image.getWidth(null);
i_heigth = image.getHeight(null);
destroyed = false;
// Save these
this.x = x;
this.y = y
}
....
}
Or, add a constructor to the Sprite class and call that from the Brick constructor:
public class Sprite {
....
public Sprite(int x, int y) {
this.x = x;
this.y = y;
}
....
}
public class Brick extends Sprite {
....
public Brick(int x, int y) {
// Call the sprite constructor
super(x, y);
ImageIcon ii = new ImageIcon("images/bricks.png");
image = ii.getImage();
i_width = image.getWidth(null);
i_heigth = image.getHeight(null);
destroyed = false;
}
....
}

Character can not move any more

So here is the code after taking the tips into account.
The map is kept being repainted, the keylistener has changed but there still seems to be a problem.
The problem again is, the little square in the upper left corner will not move, which is the desired outcome.
package schoolgamev2;
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Spel {
public static void main(String[] args) {
Speelveld map = new Speelveld();
map.Speelveld();
map.GenerateMap();
}
}
class Speelveld extends JPanel {
final int rijen = 16;
final int kolommen = 16;
Speler speler = new Speler();
Loopgebied loopgebied = new Loopgebied();
Blokken blok = new Blokken();
int[][] coordinaten = new int[rijen][kolommen];
public void Speelveld() {
JFrame frame = new JFrame();
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(this);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
setFocusable(true);
addKeyListener(new KeyListener(this));
}
//genereer map
public void GenerateMap() {
Random random = new Random();
int x;
int y;
for (y = 0; y < rijen; y++) { //scan langs y
for (x = 0; x < kolommen; x++) { //scan langs x
//selecteert type blok voor coordinaten x y
coordinaten[x][y] = random.nextInt(4);
//debugprint
}
//debugprint
}
coordinaten[0][0] = 4; //speler begint altijd links boven
coordinaten[15][15] = 5; //finish is altijd rechts onder
}
public int[][] getCoordinaten() {
return coordinaten;
}
public Speler getSpeler2() {
return speler;
}
public int getSpelerX() {
return speler.getX();
}
public int getSpelerY() {
return speler.getY();
}
public void setSpelerX(int x) {
speler.setX(x);
}
public void setSpelerY(int y) {
speler.setY(y);
}
//#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
int x;
int y;
for (y = 0; y < rijen; y++) { //scan langs y
System.out.println("");
for (x = 0; x < kolommen; x++) { //scan langs x
blok.setX(x);
blok.setY(y);
blok.setType(coordinaten[x][y]);
System.out.print(coordinaten[x][y] + " ");
switch (blok.getType()) {
case 0:
loopgebied.teken(g);
break;
case 4:
speler.teken(g);
/*case 5:
eindveld.teken(g);
break;*/
default:
break;
}
}
}
}
}
class Speler extends Blokken {
Blokken blok = new Blokken();
public void teken(Graphics g) {
g.drawRect(blok.getX(), blok.getY(), 10, 10);
}
}
class Loopgebied extends Blokken {
Blokken blok = new Blokken();
public void teken(Graphics g) {
g.drawRect(blok.getX() * size, blok.getY() * size, size, size);
}
}
class Blokken {
private static int x;
private static int y;
private static int type;
public int size = 16;
//setters voor x y en type
public void setX(int xIn) {
x = xIn;
}
public void setY(int yIn) {
y = yIn;
}
public void setType(int typeIn) {
type = typeIn;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getType() {
return type;
}
}
class KeyListener extends KeyAdapter {
private static final int SCALE = 3;
private Speelveld speelveld;
public KeyListener(Speelveld speelveld) {
this.speelveld = speelveld;
}
#Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
int deltaX = 0;
int deltaY = 0;
if (key == KeyEvent.VK_LEFT) {
deltaX = -1 * SCALE;
deltaY = 0;
} else if (key == KeyEvent.VK_UP) {
deltaX = 0;
deltaY = -1 * SCALE;
} else if (key == KeyEvent.VK_RIGHT) {
deltaX = 1 * SCALE;
deltaY = 0;
} else if (key == KeyEvent.VK_DOWN) {
deltaX = 0;
deltaY = 1 * SCALE;
} else {
return;
}
int x = speelveld.getSpelerX() + deltaX;
int y = speelveld.getSpelerY() + deltaY;
speelveld.setSpelerX(x);
speelveld.setSpelerY(y);
speelveld.repaint();
}
}
As mentioned in comments, you got your player, the Speler class, that extends JPanel and is wired to use a KeyListener, but note that it is not being used as a JPanel, and so the KeyListener is non-functioning, because they only work when they have been added to a visible component that has focus.
Suggestions:
Again as per comments, make Speler a non-GUI logical class. Meaning don't have it extend JPanel or any other Swing component, and certainly don't add a KeyListener to it.
Instead give it code for the player's behavior and for having the player draw itself, and that's it. What I'm suggesting is that you try to separate part of your "Model" here the player from the "View" here the Swing GUI.
Have one JPanel and only one that does drawing. Have it override paintComponent (don't forget to call the super's paintComponent within it), and have it draw each logical component by calling the logical component's draw method (public void verf(Graphics2D g2)? or public void teken(Graphics2D g2)?) within its paintComponent method.
As a general rule, you also don't want your GUI component classes, the JPanel here, directly implementing listener interfaces, such as the KeyListener, but will want to keep them separate.
Either make this drawing JPanel focusable, give it focus and add the KeyListener, a separate class, to it.
Or better, use Key Bindings as per the tutorial: Key Bindings
For example the simple [MCVE] below doesn't use a Swing Timer or change velocities, but rather it uses a KeyListener to change position of the Speler2 object using only one drawing JPanel and a KeyListener. If I were making this more robust and larger, I would use the Swing Timer, would use Key Bindings, and would change the velocities using the key bindings.
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class Spel2 {
private static final int VELD_WIDTH = 500;
private static void createAndShowGui() {
Speelveld2 speelveld2 = new Speelveld2(VELD_WIDTH, VELD_WIDTH);
JFrame frame = new JFrame("Spel2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(speelveld2);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
speelveld2.requestFocusInWindow();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
class MyKeyListener extends KeyAdapter {
private static final int SCALE = 3;
private Speelveld2 speelveld2;
public MyKeyListener(Speelveld2 speelveld2) {
this.speelveld2 = speelveld2;
}
#Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
int deltaX = 0;
int deltaY = 0;
if (key == KeyEvent.VK_LEFT) {
deltaX = -1 * SCALE;
deltaY = 0;
} else if (key == KeyEvent.VK_UP) {
deltaX = 0;
deltaY = -1 * SCALE;
} else if (key == KeyEvent.VK_RIGHT) {
deltaX = 1 * SCALE;
deltaY = 0;
} else if (key == KeyEvent.VK_DOWN) {
deltaX = 0;
deltaY = 1 * SCALE;
} else {
return;
}
int x = speelveld2.getSpelerX() + deltaX;
int y = speelveld2.getSpelerY() + deltaY;
speelveld2.setSpelerX(x);
speelveld2.setSpelerY(y);
speelveld2.repaint();
}
}
#SuppressWarnings("serial")
class Speelveld2 extends JPanel {
private int prefW;
private int prefH;
private Speler2 speler2 = new Speler2();
public Speelveld2(int prefW, int prefH) {
this.prefW = prefW;
this.prefH = prefH;
setFocusable(true);
addKeyListener(new MyKeyListener(this));
}
public Speler2 getSpeler2() {
return speler2;
}
public int getSpelerX() {
return speler2.getX();
}
public int getSpelerY() {
return speler2.getY();
}
public void setSpelerX(int x) {
speler2.setX(x);
}
public void setSpelerY(int y) {
speler2.setY(y);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
speler2.teken(g2);
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(prefW, prefH);
}
}
class Speler2 extends Blokken2 {
private static final int RECT_W = 10;
public Speler2() {
super(BlokkenType.SPELER);
}
#Override
public void teken(Graphics2D g2) {
int x = getX();
int y = getY();
g2.drawRect(x, y, RECT_W, RECT_W);
}
}
class Blokken2 {
private int x;
private int y;
private int velx = 0;
private int vely = 0;
private BlokkenType type;
private BufferedImage img;
public Blokken2(BlokkenType type) {
this.type = type;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getVelx() {
return velx;
}
public void setVelx(int velx) {
this.velx = velx;
}
public int getVely() {
return vely;
}
public void setVely(int vely) {
this.vely = vely;
}
public BlokkenType getType() {
return type;
}
public void setType(BlokkenType type) {
this.type = type;
}
public void setImg(BufferedImage img) {
this.img = img;
}
public BufferedImage getImg() {
return img;
}
public void teken(Graphics2D g2) {
if (img != null) {
g2.drawImage(img, x, y, null);
}
}
}
enum BlokkenType {
LOOPGEBIED, BARRICADE, MUUR, SLEUTEN, SPELER, EINDVELD
}
Edit: your latest code has an error here:
class Speler extends Blokken {
Blokken blok = new Blokken();
public void teken(Graphics g) {
g.drawRect(blok.getX(), blok.getY(), 10, 10);
}
}
Regarding your edit:
Now when you create a Speler instance, you create TWO Blokken instances, one which is the Speler instance since it extends Blokken and the other which is contained by the Speler instance since it also has a Blokken field.
You update the x/y state of the first one, but you draw with the second one, and that's why no motion is being displayed. The solution is obvious: use one or the other but not both. Either have Speler extend Blokken or have it contain a Blokken instance but don't do both.

Move object from point A to the nearest object

Basically, I'm developing a Java game where I have to make the troops move to the nearest hall inside the panel (like in Clash of Clans).
I have a BasePanel class that initializes 5 objects (Halls) that are randomly placed anywhere in the panel. The BasePanel has a mouselistener that when clicked, drops another object (Troop) to the x and y coordinates. The Troop object has an attribute that moves in a linear pattern. My problem is that the troop object just moves in a downward direction.
The question is how do I get the Troop object move to the closest Hall object in the BasePanel?
Here is my code:
import javax.swing.*;
import java.util.*;
import java.util.List;
import java.awt.*;
import java.awt.event.*;
import javax.imageio.*;
import java.io.*;
import java.awt.image.*;
public class Test extends JFrame{
public static BasePanel panel1;
public static JButton baseClick, buttonClick, barbarian, archer, goblin;
public static int clicks=0, count1=10, count2=5, count3=7, hallCount=5, basePanelW=600, basePanelH=420;
public List<Troop> troops = new ArrayList<Troop>(20);
public List<Hall> halls = new ArrayList<Hall>(5);
public Thread gameThread;
Random rand = new Random();
float mouseX, mouseY;
float x = mouseX; // troop's center (x, y)
float y = mouseY;
double troopSpeedX = 1;
double troopSpeedY = 1;
float troopRadius = 5;
public static void main(String[] args){
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
Test Test = new Test();
}
});
}
public void update() {
for (Troop troop : troops) {
troop.move(panel1);
}
}
class Hall{
int xVal = rand.nextInt(basePanelW);
int yVal = rand.nextInt(basePanelH);
public Hall(){}
public void paint(Graphics g){
g.setColor(Color.BLACK);
g.fillOval(xVal, yVal, 50, 50);
}
public int getX(){
System.out.println("xVal: "+xVal);
return xVal;
}
public int getY(){
System.out.println("yVal: "+yVal);
return yVal;
}
}
class Troop{
float x = mouseX;
float y = mouseY;
double troopSpeedX = 1;
double troopSpeedY = 1;
float troopRadius = 5;
Hall h = new Hall();
public Troop(){}
public void paint(Graphics g){
g.setColor(Color.BLUE);
g.fillOval((int) (x - troopRadius), (int) (y - troopRadius), (int)(2 * troopRadius), (int)(2 * troopRadius));
}
public void move(JPanel panel){
x += troopSpeedX;
y += troopSpeedY;
if (x - troopRadius < 0) {
troopSpeedX = -troopSpeedX;
x = troopRadius;
}else if (x + troopRadius > basePanelW) {
troopSpeedX = -troopSpeedX;
x = basePanelW - troopRadius;
}else if (y - troopRadius < 0) {
troopSpeedY = -troopSpeedY;
y = troopRadius;
}else if (y + troopRadius > basePanelH) {
troopSpeedY = -troopSpeedY;
y = basePanelH - troopRadius;
}repaint();
}
}
public void start(){
gameThread = new Thread() {
public void run() {
while (true) {
update();
repaint();
try {Thread.sleep(100/3);}catch(InterruptedException ex){}
}
}
}; gameThread.start();
}
class BasePanel extends JPanel{
private BufferedImage image;
BasePanel(){
setPreferredSize(new Dimension(basePanelW,basePanelH));
setBackground(Color.green);
while(hallCount>0){
halls.add(new Hall());
hallCount--;
}
addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent e){
mouseX = e.getX();
mouseY = e.getY();
clicks++;
}
public void mouseReleased(MouseEvent e){
troops.add(new Troop());
}
});
}
private void msgbox(String s){
JOptionPane.showMessageDialog(null, s);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (Troop troop : troops){
troop.paint(g);
}
}
public void paint(Graphics g){
super.paint(g);
for (Hall hall : halls){
hall.paint(g);
}
}
}
public Test(){
panel1 = new BasePanel();
add(panel1, BorderLayout.CENTER);
setVisible(true);
setSize(700,420);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
start();
}
}

Getting Java Application to Run as an Applet or Standalone

I have written code to drive a Differential Drive Robot through a fixed path, chosen by me. I am trying to get the code to run either from the command line:
java StartRobot
or being able to run the application an an Applet within a browser. My code is below:
import java.awt.*;
import javax.swing.*;
import java.util.ArrayList;
import java.util.List;
class DifferentialDriveRobot {
public static void main(String[] args) {
new DifferentialDriveRobot();
}
public DifferentialDriveRobot() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowGUI();
}
});
}
public void createAndShowGUI() {
JFrame frame = new JFrame("Differential Drive Robot");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
Robots robots = new Robots();
frame.add(robots);
frame.setSize(400,400);
frame.setVisible(true);
new Thread(new Drive(robots)).start();
}
public static int random(int maxRange) {
return (int) Math.round((Math.random() * maxRange));
}
public class Robots extends JPanel {
private List<Bot> robots;
public Robots() {
robots = new ArrayList<Bot>(1);
robots.add(new Bot(Color.red));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
for(Bot robot : robots) {
robot.paint(g2d);
}
g2d.dispose();
}
public List<Bot> getRobots() {
return robots;
}
}
public class Drive implements Runnable {
private Robots parent;
public Drive(Robots parent) {
this.parent = parent;
}
#Override
public void run() {
int width = getParent().getWidth();
int height = getParent().getHeight();
for(Bot robot : getParent().getRobots()) {
int x = 5;
int y = 5;
int diameter = robot.getDiameter();
if(x + diameter > width) {
x = width - diameter;
}
if(y + diameter > height) {
y = height - diameter;
}
robot.setX(x);
robot.setY(y);
}
while(getParent().isVisible()) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
getParent().repaint();
}
});
for(Bot robot : getParent().getRobots()) {
move(robot);
}
try {
Thread.sleep(100);
} catch(InterruptedException ex) {}
}
}
public Robots getParent() {
return parent;
}
public void move(Bot robot) {
int diameter = robot.getDiameter();
double v1 = robot.getV1();
double v2 = robot.getV2();
double x = robot.getX();
double y = robot.getY();
double theta = robot.getTheta();
double dx, dy, dtheta;
int time = robot.getTime();
dx = 0.5*(Math.cos(Math.toRadians(theta)))*(v1+v2);
dy = 0.5*(Math.sin(Math.toRadians(theta)))*(v1+v2);
dtheta = (-1)*(0.5*(v2-v1));
if((x + dx < 0 || x + diameter + dx > getParent().getWidth()) || (y + dy < 0 || y + diameter + dy > getParent().getHeight())) {
v1 = 0;
v2 = 0;
} else {
if(time == 50) {
v2 = 0;
} else if(time > 50 && time < 300 && theta == 89.5) {
v1 = v2 = 1;
} else if(time > 300 && time < 450) {
v1 = 1;
v2 = 3;
}
if(time > 400 && theta == -89.0 && time < 500) {
v1 = 5;
v2 = 5;
}
if(time > 500 && time < 550) {
v1 = v2 = 0;
} else if(time > 550 && time < 600) {
v1 = v2 = -2;
} else if(time > 600) {
v1 = v2 = 0;
}
}
x = x + dx;
y = y + dy;
theta = theta + dtheta;
time = time + 1;
robot.setTheta(theta);
robot.setV1(v1);
robot.setV2(v2);
robot.setX(x);
robot.setY(y);
robot.setTime(time);
}
}
public class Bot {
private Color color;
private double x, y;
private int diameter;
private double v1, v2;
private double theta;
private int time;
public Bot(Color color) {
setColor(color);
v1 = 1;
v2 = 1;
diameter = 30;
theta = 0;
time = 0;
}
public int getTime() {
return time;
}
public void setTime(int time) {
this.time = time;
}
public int getDiameter() {
return diameter;
}
public void setColor(Color color) {
this.color = color;
}
public void setX(double x) {
this.x = x;
}
public void setY(double y) {
this.y = y;
}
public void setTheta(double theta) {
this.theta = theta;
}
public Color getColor() {
return color;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public double getV1() {
return v1;
}
public double getV2() {
return v2;
}
public double getTheta() {
return theta;
}
public void setV1(double v1) {
this.v1 = v1;
}
public void setV2(double v2) {
this.v2 = v2;
}
protected void paint(Graphics2D g2d) {
double x = getX();
double y = getY();
double v1 = getV1();
double v2 = getV2();
g2d.rotate(Math.toRadians(theta),x,y);
g2d.setColor(getColor());
g2d.fillRect((int)x, (int)y, getDiameter(), getDiameter());
g2d.setColor(Color.black);
g2d.fillOval((int)x+9,(int)y-5,15,15);
g2d.fillOval((int)x+9,(int)y+20,15,15);
}
}
}
In the past I have been able to accomplish this by adding the following into my .java file:
public class StartRobot extends JApplet {
public void init() {
EventQueue.invokeLater(new Runnable() {
public void run() {
DifferentialDriveRobot panel = new DifferentialDriveRobot();
getContentPane.add(panel);
}
});
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
DifferentialDriveRobot panel = new DifferentialDriveRobot();
panel.createAndShowGUI();
}
});
}
}
However, this throws an error while compiling. I think this is due to the fact that my main class DifferentialDriveRobot does not extend JPanel, instead it is a subclass where I accomplish this. Is there a quick fix to this?
The class DifferentialDriveRobot is a non-component class that cannot be added to an applet. It is a class that causes a JFrame to be created and adds your Robot panel class. This will cause a JFrame to appear if you run the applet in a browser, which is usually not desirable.
You could define the class Robot as your applet:
public class Robot extends JApplet {
public void init() {
...
}
then add the applet to your main method:
public static void main(String[] args) {
JFrame frame = new JFrame("Applet Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 400);
JApplet applet = new Robot();
applet.init();
applet.start();
frame.add(applet);
frame.setVisible(true);
}
If you want the applet to run as an application, a good alternative is to convert it completely an JFrame-based application and deploy it using Java Web Start.

how to notify multithread event on swing game

I am supposed to make a little game simulation. in this game there are three button . when user click start tank and car will close each other in 90 degrees when user click shut button tank will throw bullet to car.
i made and a simulation for this. tank throw bullet to car but when bullet crash car i couldn't this. i just need increase score of how many times tank hit car.
here is the source code
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JPanel;
public class Vehicle extends Thread {
private JPanel box;
private int XSIZE;
private int YSIZE;
private int time;
private int x;
private int y;
private int dx = 5;
private int dy = 5;
private int dim;
public Vehicle(JPanel b, int i) {
box = b;
this.dim = i;
if (i == 0) {
x = 0;
y = 100;
time = 1000;
XSIZE = 9;
YSIZE = 20;
} else {
time = 200;
y = box.getSize().height;
x = box.getSize().width / 2;
XSIZE = 6;
YSIZE = 10;
}
}
public void draw() {
Graphics g = box.getGraphics();
g.fillOval(x, y, XSIZE, YSIZE);
g.dispose();
}
public void moveHorizontal() {
if (!box.isVisible())
return;
Graphics g = box.getGraphics();
g.setColor(Color.BLUE);
g.setXORMode(box.getBackground());
g.fillOval(x, y, XSIZE, YSIZE);
x += dx;
Dimension d = box.getSize();
if (x < 0) {
x = 0;
dx = -dx;
}
if (x + XSIZE >= d.width) {
x = d.width - XSIZE;
dx = -dx;
}
g.fillOval(x, y, XSIZE, YSIZE);
g.dispose();
}
public JPanel getBox() {
return box;
}
public void setBox(JPanel box) {
this.box = box;
}
public void moveVertical() {
if (!box.isVisible())
return;
Graphics g = box.getGraphics();
g.setXORMode(box.getBackground());
g.fillOval(x, y, XSIZE, YSIZE);
y += dy;
Dimension d = box.getSize();
if (y < 0) {
y = 0;
dy = -dy;
}
if (y + YSIZE >= d.height) {
y = d.height - YSIZE;
dy = -dy;
}
g.fillOval(x, y, XSIZE, YSIZE);
g.dispose();
}
public void move(int i) {
if (i == 0) {
moveHorizontal();
} else {
moveVertical();
}
}
public int getYSIZE() {
return YSIZE;
}
public void setYSIZE(int ySIZE) {
YSIZE = ySIZE;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public int getXSIZE() {
return XSIZE;
}
public void setXSIZE(int xSIZE) {
XSIZE = xSIZE;
}
public void setY(int y) {
this.y = y;
}
public void run() {
try {
draw();
for (;;) {
move(dim);
sleep(time);
}
} catch (InterruptedException e) {
}
}
}
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JPanel;
public class Bullet extends Thread {
private JPanel box;
private int XSIZE = 3;
public int getXSIZE() {
return XSIZE;
}
public void setXSIZE(int xSIZE) {
XSIZE = xSIZE;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
private int YSIZE = 1;
private int x;
private int y;
private int dx = 3;
public Bullet(JPanel b, Vehicle tank, Vehicle car) {
box = b;
x = tank.getX() + tank.getXSIZE();
if (x >= tank.getBox().getSize().width / 2)
dx = -dx;
y = tank.getY() + tank.getYSIZE() / 2;
;
}
public void draw() {
Graphics g = box.getGraphics();
g.fillOval(x, y, XSIZE, YSIZE);
g.dispose();
}
public void move() {
if (!box.isVisible())
return;
Graphics g = box.getGraphics();
g.setColor(Color.RED);
g.setXORMode(box.getBackground());
g.fillOval(x, y, XSIZE, YSIZE);
x += dx;
Dimension d = box.getSize();
if (x < 0) {
x = 0;
}
if (x + XSIZE >= d.width) {
x = d.width - XSIZE;
}
g.fillOval(x, y, XSIZE, YSIZE);
g.dispose();
}
public void run() {
try {
draw();
for (;;) {
move();
sleep(20);
}
} catch (InterruptedException e) {
}
}
}
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
#SuppressWarnings("serial")
public class Tank_Shut_Car_ThreadFrame extends JFrame {
private JPanel canvas;
private boolean isOn = false;
private Vehicle tank;
private Vehicle car;
private JLabel score;
public static int sc = 0;
public Tank_Shut_Car_ThreadFrame() {
setResizable(false);
setSize(600, 400);
setTitle("Tank Shut Car");
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
Container contentPane = getContentPane();
canvas = new JPanel();
contentPane.add(canvas, "Center");
canvas.setLayout(null);
score = new JLabel("0");
score.setBounds(527, 11, 36, 14);
canvas.add(score);
JLabel lblScore = new JLabel("score");
lblScore.setBounds(481, 11, 36, 14);
canvas.add(lblScore);
JPanel p = new JPanel();
addButton(p, "Start", new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (!isOn) {
tank = new Vehicle(canvas, 0);
tank.start();
car = new Vehicle(canvas, 1);
car.start();
isOn = true;
}
}
});
addButton(p, "Shut", new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (isOn) {
Bullet bullet = new Bullet(canvas, tank, car);
bullet.start();
score.setText("" + sc);
}
}
});
addButton(p, "Close", new ActionListener() {
public void actionPerformed(ActionEvent evt) {
canvas.setVisible(false);
System.exit(0);
}
});
contentPane.add(p, "South");
}
public void addButton(Container c, String title, ActionListener a) {
JButton button = new JButton(title);
c.add(button);
button.addActionListener(a);
}
}
import javax.swing.JFrame;
public class Test {
public static void main(String[] args) {
JFrame frame = new Tank_Shut_Car_ThreadFrame();
frame.setVisible(true);
}
}
Okay, so I had a play around with this (just for fun)
Now, this is far from a "proper" or "complete" game engine, but it provides a basic idea of how it might be possible to mix a core thread engine with UI components.
Rather then pasting the entire code, I've uploaded the source it to Tank.zip
But the basic engine looks like this...
public class GameEngine extends Thread {
public static final Object ASSET_LOCK = new Object();
private List<GameAsset> lstAssets;
private GameScreen screen;
public GameEngine(GameScreen screen) {
// Let the thread die when the JVM closes
setDaemon(true);
// Want to be below the UI thread (personal preference)
setPriority(NORM_PRIORITY - 1);
// A list of game assests
lstAssets = new ArrayList<GameAsset>(25);
// A reference to the screen
this.screen = screen;
// Add global key listener, this is simpler to the trying to attach a key listener
// to the screen.
Toolkit.getDefaultToolkit().addAWTEventListener(new EventHandler(), AWTEvent.KEY_EVENT_MASK);
}
public GameAsset[] getAssets() {
synchronized (ASSET_LOCK) {
return lstAssets.toArray(new GameAsset[lstAssets.size()]);
}
}
/*
* Allows for assets to be added
*/
public void addAsset(GameAsset asset) {
synchronized (ASSET_LOCK) {
lstAssets.add(asset);
}
}
#Override
public void run() {
while (true) {
try {
sleep(40);
} catch (InterruptedException ex) {
}
synchronized (ASSET_LOCK) {
GameAsset[] assets = lstAssets.toArray(new GameAsset[lstAssets.size()]);
for (GameAsset asset : assets) {
if (lstAssets.contains(asset)) {
asset.update(this, screen);
}
}
screen.repaint(new ArrayList<GameAsset>(lstAssets));
}
}
}
/**
* Allows the removal of an asset...
*/
public void removeAsset(GameAsset asset) {
synchronized (ASSET_LOCK) {
lstAssets.remove(asset);
}
}
/**
* Key event handling...
*/
protected class EventHandler implements AWTEventListener {
#Override
public void eventDispatched(AWTEvent event) {
KeyEvent keyEvent = (KeyEvent) event;
if (keyEvent.getID() == KeyEvent.KEY_PRESSED) {
synchronized (ASSET_LOCK) {
GameAsset[] assets = lstAssets.toArray(new GameAsset[lstAssets.size()]);
for (GameAsset asset : assets) {
if (lstAssets.contains(asset)) {
asset.processKeyPressed(GameEngine.this, screen, keyEvent);
}
}
}
} else if (keyEvent.getID() == KeyEvent.KEY_RELEASED) {
synchronized (ASSET_LOCK) {
GameAsset[] assets = lstAssets.toArray(new GameAsset[lstAssets.size()]);
for (GameAsset asset : lstAssets) {
if (lstAssets.contains(asset)) {
asset.processKeyReleased(GameEngine.this, screen, keyEvent);
}
}
}
}
}
}
}
Swing is not thread safe. Events should be fired on the event-dispatching thread.
http://www.javamex.com/tutorials/threads/invokelater.shtml

Categories