i have this assignment where i have to create multiple ball, 2 obstacle and one paddle, so i've fined a similar question so i've tried to work on it and to improve it the problem i have is when i want to check intersection between ball and obstacle or ball and the paddle, i really need your help for this question. i've google about it but i did not find something that can help me.
here is my main code
import java.awt.Color;
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.util.Random;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class BallWindow extends JFrame implements ActionListener, Runnable{
JButton btnStop = new JButton("SAVE");
JButton btnSave = new JButton("LOAD");
Vector<BallP> ballVector = new Vector<BallP>();
JPanel p1 = createPanel(280, 200, 200, 20, Color.gray);
JPanel p2 = createPanel(280, 300, 200, 20, Color.gray);
JPanel lborder = createPanel(10, 10, 2, 560, Color.black);
JPanel rborder = createPanel(720, 10, 2, 560, Color.black);
JPanel tborder = createPanel(10, 10, 710, 2, Color.black);
//Movement
private static final int Y = 500;
private static final int WIDTH = 60;
private static final int HEIGHT = 10;
int x = 10;
int xa = 0;
Rectangle rect2 = new Rectangle(x, Y, WIDTH, HEIGHT);
JPanel bottomp = createPanel(rect2.x, rect2.y, rect2.width, rect2.height, Color.black);
public BallWindow() {
addKeyListener(new KeyListener()
{
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
if (e.getKeyCode() == KeyEvent.VK_LEFT)
bottomp.setLocation(bottomp.getLocation().x -6, bottomp.getLocation().y);
if (e.getKeyCode() == KeyEvent.VK_RIGHT)
bottomp.setLocation(bottomp.getLocation().x + 6, bottomp.getLocation().y);
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
});
setFocusable(true);
setLayout(null);
btnStop.setBounds(12, 15, 100, 30);
btnStop.addActionListener(this);
add(btnStop);
btnSave.setBounds(12, 50, 100, 30);
//btnSave.addActionListener(this);
add(btnSave);
Random r = new Random();
for(int i=0; i<2; i++){
BallP bp = new BallP(r.nextInt(740), r.nextInt(590));
Rectangle BallP;
Thread t = new Thread(bp);
ballVector.add(bp);
t.start();
add(bp);
}
add(p1);
add(p2);
Rectangle b = bottomp.getBounds();
add(bottomp);
// add(lborder);
// add(rborder);
// add(tborder);
setSize(740, 570);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
repaint();
}
JPanel createPanel(int x, int y, int width, int height, Color pColor){
JPanel temp = new JPanel();
temp.setBackground(pColor);
temp.setBounds(x, y, width, height);
return temp;
}
public static void main(String[] args) {
new BallWindow();
}
#Override
public void actionPerformed(ActionEvent arg0) {
for (BallP ball : ballVector) {
ball.pleaseWait = !ball.pleaseWait;
}
if( btnStop.getText().equalsIgnoreCase("STOP"))
btnStop.setText("START");
else
btnStop.setText("STOP");
// if(arg0.getSource())
}
#Override
public void run() {
// TODO Auto-generated method stub
}
}
find down my code for the ball
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.Random;
import javax.swing.JPanel;
public class BallP extends JPanel implements Runnable {
int RED, GREEN, BLUE;
int Xdirection = 1, Ydirection = 1;
boolean pleaseWait = false;
BallP(int X, int Y){
locateBall(X, Y, 30, 30);
}
public void paintComponent(Graphics g){
int panelWidth = this.getWidth();
int panelHeight = this.getHeight();
Rectangle rect1 = new Rectangle(panelWidth/2, panelHeight/2, panelWidth/2, panelHeight/2);
//Rectangle rect2 = new Rectangle(120, 80, 80, 120);
// g.setColor( new Color(RED, GREEN, BLUE ));
g.setColor(Color.ORANGE);
g.fillOval(rect1.x,rect1.y,rect1.width,rect1.height);
}
public void locateBall(int x, int y, int width, int height){
setBounds(x, y, width, height);
repaint();
}
public void run() {
int width = this.getWidth();
int height = this.getHeight();
Random r = new Random();
while(true){
if(!pleaseWait){
int lastX = this.getX();
int lastY = this.getY();
if (lastX > 675) Xdirection = -1;
if (lastY > 485) Ydirection = -1;
if (lastX < -5) Xdirection = 1;
if (lastY < -5) Ydirection = 1;
locateBall(lastX + Xdirection*r.nextInt(3),
lastY + Ydirection*r.nextInt(3),
width, height );
}
try{
Thread.sleep(5);
}catch(Exception e){};
}
}
}
I'm trying to create a moving sprite in java, which I have managed to do, except every time I move it there is an afterimage that follows the sprite. Are there any ways I could easily fix this problem without radically changing my code?
I'm completely stumped as to any kind of ways I could fix this problem.
To get the full context I have to post all three files.
Here's the first file:
package gameproject;
import java.awt.Image;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
public class CarMovement {
private int dx;
private int dy;
private int x = 635;
private int y = 550;
private int w;
private int h;
private Image moveimage;
public CarMovement() {
loadImage();
}
private void loadImage() {
ImageIcon q = new ImageIcon("racecar.png");
moveimage = q.getImage();
w = moveimage.getWidth(null);
h = moveimage.getHeight(null);
}
public void move() {
x += dx;
y += dy;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getWidth() {
return w;
}
public int getHeight() {
return h;
}
public Image getImage() {
return moveimage;
}
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_A) {
dx = -10;
}
if (key == KeyEvent.VK_D) {
dx = 10;
}
if (key == KeyEvent.VK_W) {
dy = -10;
}
if (key == KeyEvent.VK_S) {
dy = 10;
}
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_A) {
dx = 0;
}
if (key == KeyEvent.VK_D) {
dx = 0;
}
if (key == KeyEvent.VK_W) {
dy = 0;
}
if (key == KeyEvent.VK_S) {
dy = 0;
}
}
}
The second:
package gameproject;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JPanel;
import javax.swing.Timer;
public class CarMovement2 extends JPanel implements ActionListener {
private Timer timer;
private CarMovement racecar;
private final int DELAY = 10;
public CarMovement2() {
initBoard();
}
private void initBoard() {
addKeyListener(new TAdapter());
setBackground(Color.black);
setFocusable(true);
racecar = new CarMovement();
timer = new Timer(DELAY, this);
timer.start();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(new Color(0, 204, 0));
g.fillRect(0, 0, 400, 1100);
g.fillRect(1525, 0, 400, 1100);
g.setColor(new Color(102, 102, 102));
g.fillRect(400, 0, 1125, 1100);
g.setColor(new Color(255, 255, 255));
g.fillRect(940, 25, 25, 100);
g.fillRect(940, 325, 25, 100);
g.fillRect(940, 475, 25, 100);
g.fillRect(940, 625, 25, 100);
g.fillRect(940, 775, 25, 100);
g.fillRect(940, 925, 25, 100);
g.setColor(new Color(255, 255, 255));
g.fillRect(400, 175, 1125, 100);
g.setColor(new Color(0, 0, 0));
g.fillRect(400, 225, 50, 50);
g.fillRect(450, 175, 50, 50);
g.fillRect(500, 225, 50, 50);
g.fillRect(550, 175, 50, 50);
g.fillRect(600, 225, 50, 50);
g.fillRect(650, 175, 50, 50);
g.fillRect(700, 225, 50, 50);
g.fillRect(750, 175, 50, 50);
g.fillRect(800, 225, 50, 50);
g.fillRect(850, 175, 50, 50);
g.fillRect(900, 225, 50, 50);
g.fillRect(950, 175, 50, 50);
g.fillRect(1000, 225, 50, 50);
g.fillRect(1050, 175, 50, 50);
g.fillRect(1100, 225, 50, 50);
g.fillRect(1150, 175, 50, 50);
g.fillRect(1200, 225, 50, 50);
g.fillRect(1250, 175, 50, 50);
g.fillRect(1300, 225, 50, 50);
g.fillRect(1350, 175, 50, 50);
g.fillRect(1400, 225, 50, 50);
g.fillRect(1450, 175, 50, 50);
g.fillRect(1500, 225, 25, 50);
g.setColor(new Color(255, 255, 255));
g.fillRect(380, 0, 20, 1100);
g.fillRect(1525, 0, 20, 1100);
doDrawing(g);
Toolkit.getDefaultToolkit().sync();
}
private void doDrawing(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(racecar.getImage(), racecar.getX(),
racecar.getY(), this);
}
#Override
public void actionPerformed(ActionEvent e) {
step();
}
private void step() {
racecar.move();
repaint(racecar.getX()-1, racecar.getY()-1,
racecar.getWidth()+2, racecar.getHeight()+2);
}
private class TAdapter extends KeyAdapter {
#Override
public void keyReleased(KeyEvent e) {
racecar.keyReleased(e);
}
#Override
public void keyPressed(KeyEvent e) {
racecar.keyPressed(e);
}
}
}
The third:
package gameproject;
import java.awt.EventQueue;
import javax.swing.JFrame;
public final class CarMovement3 extends JFrame {
public CarMovement3() {
InitUI();
}
private void InitUI() {
add(new CarMovement2());
setTitle("Top Speed Triumph");
setSize(1900, 1100);
setResizable(false);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
CarMovement3 ex = new CarMovement3();
ex.setVisible(true);
});
}
}
And the link to the sprite :
http://www.clker.com/clipart-red-sports-car-top-view.html
So, your problem stems from using...
repaint(racecar.getX() - 1, racecar.getY() - 1,
racecar.getWidth() + 2, racecar.getHeight() + 2);
Basically, you're not covering enough of the "existing" area that use to occupy to completely "remove" it.
You can simply use repaint() instead and it will solve your basic problem. I'd avoid worrying about this level of optimisation until it actually becomes a problem.
If you want to use it, then I would take a snap shot of the location of the care before it was moved (ie grab it's current x/y position) and merge that with it's new location so you cover both areas. That, or call repaint(x, y, width, height) twice, once with the old position and once with the new
private void step() {
Rectangle old = new Rectangle(racecar.getX(), racecar.getY(), racecar.getWidth(), racecar.getHeight());
racecar.move();
Rectangle now = new Rectangle(racecar.getX(), racecar.getY(), racecar.getWidth(), racecar.getHeight());
repaint(old);
repaint(now);
}
Also, you'll find that KeyListener is unreliable, I would suggest making use of the key bindings API which will solve the issues which KeyListener suffers from
I would also recommend using ImageIO over ImageIcon as more reliable way of loading your images, see Reading/Loading an Image for more details
I recently made a drawing of a car and tried changing the .fillPolygon to .fillRect but it didnt work to change the car to look like a truck. How would I change my code below to make the drawing of the car into a drawing of a truck?I did this on Eclipse.
Car.java
import java.awt.*;
public class Car {
//Coordinates if car is drawn at position 0,0
private int [] x = {0, 0, 20, 25, 70, 80, 105, 110};
private int[] y = {35, 15, 15, 0, 0, 15, 15, 35};
private int [] xCurrent = new int [x.length];
private int [] yCurrent = new int [y.length];
private int xOffset = 0, yOffset =0;
private Color carColor;
//-----------------------------------------------------------------
// Sets up the graphical car with the specified offsets.
//-----------------------------------------------------------------
public Car(int xOff, int yOff, Color color)
{
xOffset = xOff;
yOffset = yOff;
carColor = color;
for (int i=0; i < x.length; i++)
{
xCurrent[i] = x[i] + xOffset;
yCurrent[i] = y[i] + yOffset;
}
}
//
public int getXOffset() {return xOffset;}
public int getYOffset() {return yOffset;}
//-----------------------------------------------------------------
// Draws the car at a particular x and y offset.
//-----------------------------------------------------------------
public void draw(Graphics page)
{
page.setColor(carColor);
page.fillPolygon(xCurrent, yCurrent, x.length);
page.setColor(Color.black);
page.fillOval(13+xOffset, 28+yOffset, 14, 14); // rear wheel
page.fillOval(83+xOffset, 28+yOffset, 14, 14); // front wheel
page.drawLine(15+xOffset, 18+yOffset, 15+xOffset, 3+yOffset);
}
}
CarPanel.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class CarPanel extends JPanel {
private Car car1, car2, car3;
private final int DELAY =20;
private int x, y;
private final int SPEED =2;
public CarPanel ()
{
car1 =new Car(200, 150, Color.BLUE);
car2 = new Car(50, 50, Color.RED);
car3 = new Car(0, 220, Color.GREEN);
x =0;
y= 220;
setPreferredSize(new Dimension(450,300));
ActionListener taskPerformer = new ActionListener()
{
public void actionPerformed(ActionEvent evt)
{
x = car3.getXOffset() + SPEED;
y = car3.getYOffset();
if (x > getWidth()) x = 0;
car3 = new Car(x, y, Color.GREEN);
x = car2.getXOffset() + SPEED + 5;
if (x > getWidth()) x = 0;
y = car2.getYOffset();
car2 = new Car(x, y, Color.RED);
repaint();
}
};
new Timer(DELAY, taskPerformer).start();
}
//-----------------------------------------------------------------
// Draws the car.
//-----------------------------------------------------------------
public void paint(Graphics page)
{
super.paint(page);
car1.draw(page);
car2.draw(page);
car3.draw(page);
}
}
GUITester.java
import javax.swing.JFrame;
public class GUITester {
//-----------------------------------------------------------------
// Sets up a frame containing a tabbed pane. The panel on each
// tab demonstrates a different layout manager.
//-----------------------------------------------------------------
public static void main(String[] args)
{
JFrame frame = new JFrame("GUI Tester");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// add any panel into here
//ArrayReviews panel = new ArrayReviews();
//ArrayBetter panel = new ArrayBetter();
CarPanel panel = new CarPanel();
//NumericKeypadPanel panel = new NumericKeypadPanel();
//StarPanel panel = new StarPanel();
//SnowPanel panel = new SnowPanel();
//Draw1StarPanel panel = new Draw1StarPanel();
//Rain panel = new Rain();
//Cards panel = new Cards();
//SelectionSortPanel panel = new SelectionSortPanel();
//PersonPanel panel = new PersonPanel();
//SinPanel panel = new SinPanel();
//KochSnowFlake panel = new KochSnowFlake();
//CalculatorPanelSimple panel = new CalculatorPanelSimple();
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
}
}
Yuk! You are declaring x[] y[] arrays, and then constructing xOffset[] yOffset[] arrays to translate you car/truck to different positions. You can let the GPU do the work for you:
void draw(Graphics g) {
Graphics2D g2d = (Graphics2D) g; // Every Graphics is actually a Graphics2D.
translate(xOffset, yOffset); // Move the graphic origin
g2d.fillPolygon(x, y, x.length); // Draw with original coordinates
translate(-xOffset, yOffset); // Restore graphic origin, for other drawing
}
It doesn't turn your car into a truck, but your code doesn't show your attempt, so it is hard to say where you went wrong.
But, if this simplifies your code, perhaps that will help.
As #MadProgrammer points out, the Shape API might also be useful.
static Shape CAR_SHAPE;
static {
// Initialize CAR_SHAPE
}
void draw(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
translate(xOffset, yOffset);
g2d.draw(CAR_SHAPE);
translate(-xOffset, yOffset);
}
See Trail: 2D Graphics
I am working on a 2D game as a learning project and I have hit a bump. I cannot figure out how to move a Polygon object using the KeyListener within a JPanel (which is added to a JFrame). I've tried the frog.translate(int x, int y) method, which does not update the location. I've also tried changing the array coordinates manually. A sample of my code is below:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class Board extends JPanel implements KeyListener {
private Frog frog;
public Board() {
setBackground(Color.GREEN);
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
frog = new Frog();
// Frog graphics
g2.setColor(Color.BLACK);
g2.drawPolygon(frog);
g2.setColor(new Color(0,150,15));
g2.fillPolygon(frog);
}
#Override
public void keyTyped(KeyEvent ke) {
}
#Override
public void keyPressed(KeyEvent ke) {
int c = ke.getKeyCode();
if(c == KeyEvent.VK_LEFT){
frog.moveFrogLeft(25);
//frog.translate(-25,0);
}
if(c == KeyEvent.VK_RIGHT){
frog.moveFrogRight(25);
//frog.translate(25,0);
}
if(c == KeyEvent.VK_UP){
frog.moveFrogUp(25);
//frog.translate(0,-25);
}
if(c == KeyEvent.VK_DOWN){
frog.moveFrogDown(25);
//frog.translate(0,25);
}
repaint();
}
#Override
public void keyReleased(KeyEvent ke) {
}
}
///////////////////////
import java.awt.Polygon;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class Frog extends Polygon {
private Integer[] xcoord;
private Integer[] ycoord;
public Frog(){
xcoord = new Integer[] {5,10,10,15,15,20,
20,30,30,35,35,40,40,
45,45,40,40,30,30,40,
40,45,45,40,40,35,35,
30,30,20,20,15,15,10,
10,5,5,10,10,20,20,
10,10,5,5};
ycoord = new Integer[] {10,10,5,5,20,20,
10,10,20,20,5,5,10,10,
15,15,25,25,30,30,35,35,
40,40,45,45,35,35,40,40,
35,35,45,45,40,40,35,35,
30,30,25,25,15,15,10};
for(int i = 0; i < xcoord.length; i++){
this.addPoint(xcoord[i],ycoord[i]);
}
}
public void moveFrogLeft(int x) {
if(xcoord[0] - x < 0){
//do nothing
} else {
for(int i = 0; i < xcoord.length; i++){
xcoord[i] = xcoord[i] - x;
}
}
}
public void moveFrogRight(int x){
if(xcoord[0] + x > 600){
//do nothing
} else {
for(int i = 0; i < xcoord.length; i++){
xcoord[i] = xcoord[i] + x;
}
}
}
public void moveFrogUp(int y){
if(ycoord[0] - y < 0){
//do nothing
} else {
for(int i = 0; i < ycoord.length; i++){
ycoord[i] = ycoord[i] - y;
}
}
}
public void moveFrogDown(int y){
if(ycoord[0] + y > 600){
//do nothing
} else {
for(int i = 0; i < ycoord.length; i++){
ycoord[i] = ycoord[i] + y;
}
}
}
}
This code has a simple issue:
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
frog = new Frog();// <-- !!!!!
// Frog graphics
g2.setColor(Color.BLACK);
g2.drawPolygon(frog);
g2.setColor(new Color(0,150,15));
g2.fillPolygon(frog);
}
The marked line overwrites the frog with a new instance, every time the frog is painted, thus reseting it to the original point. Apart from the obvious issue that this is the reason for the unexpected behaviour, never do any unnecessary calculations in the paintComponent(...)-method. Any precomputation, Object-generation, etc. should be done outside of paintComponent!!!
First of all, I would strongly discourage you from using KeyListener, it's troublesome at the best, a better choice would be to make use of the Key Bindings API which was desgiend to fix the short commings of the KeyListener API.
Second, you shouldn't be modifying the points of the polygon, the 2D Graphics API is actually capable of some really neat tricks which makes it much easier and faster to change the location (and rotation and scale) of what you are drawing.
Take a look closer look at 2D Graphics for more details.
Instead of changing the points of the polygon, which isn't taking into consideration the viewable bounds, you could simply use an AffineTransform...
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
Point location = frog.getLocation();
AffineTransform at = AffineTransform.getTranslateInstance(location.x, location.y);
g2d.transform(at);
g2d.setColor(new Color(0, 150, 15));
g2d.fill(frog);
g2d.setColor(Color.BLACK);
g2d.draw(frog);
g2d.dispose();
}
This just simply changes the origin point of the Graphics context to the location where you want to paint the polygon (yes, there's another reason why I'm using AffineTransform
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.geom.AffineTransform;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
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 Board());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
protected enum VerticalDirection {
NONE, UP, DOWN;
}
protected enum HorizontalDirection {
NONE, LEFT, RIGHT;
}
public static class Board extends JPanel {
protected static final int Y_DELTA = 4;
protected static final int X_DELTA = 4;
private Frog frog;
private VerticalDirection verticalDirection = VerticalDirection.NONE;
private HorizontalDirection horizontalDirection = HorizontalDirection.NONE;
public Board() {
setBackground(Color.GREEN);
frog = new Frog();
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Point location = frog.getLocation();
switch (verticalDirection) {
case UP:
location.y -= Y_DELTA;
break;
case DOWN:
location.y += Y_DELTA;
break;
}
switch (horizontalDirection) {
case LEFT:
location.x -= X_DELTA;
break;
case RIGHT:
location.x += X_DELTA;
break;
}
Rectangle bounds = frog.getBounds();
int width = bounds.x + bounds.width;
int height = bounds.y + bounds.height;
if (location.y < 0) {
location.y = 0;
} else if (location.y + height > getHeight()) {
location.y = getHeight() - height;
}
if (location.x < 0) {
location.x = 0;
} else if (location.x + width > getWidth()) {
location.x = getWidth() - width;
}
frog.setLocation(location);
repaint();
}
});
timer.start();
addPressedKeyBinding("up", KeyEvent.VK_UP, new VerticalMovementAction(VerticalDirection.UP));
addPressedKeyBinding("down", KeyEvent.VK_DOWN, new VerticalMovementAction(VerticalDirection.DOWN));
addPressedKeyBinding("left", KeyEvent.VK_LEFT, new HorizontalMovementAction(HorizontalDirection.LEFT));
addPressedKeyBinding("right", KeyEvent.VK_RIGHT, new HorizontalMovementAction(HorizontalDirection.RIGHT));
addReleasedKeyBinding("up", KeyEvent.VK_UP, new VerticalMovementAction(VerticalDirection.NONE));
addReleasedKeyBinding("down", KeyEvent.VK_DOWN, new VerticalMovementAction(VerticalDirection.NONE));
addReleasedKeyBinding("left", KeyEvent.VK_LEFT, new HorizontalMovementAction(HorizontalDirection.NONE));
addReleasedKeyBinding("right", KeyEvent.VK_RIGHT, new HorizontalMovementAction(HorizontalDirection.NONE));
}
protected void addPressedKeyBinding(String name, int virtuaKey, Action action) {
addKeyBinding(name + ".pressed", KeyStroke.getKeyStroke(virtuaKey, 0, false), action);
}
protected void addReleasedKeyBinding(String name, int virtuaKey, Action action) {
addKeyBinding(name + ".released", KeyStroke.getKeyStroke(virtuaKey, 0, true), action);
}
protected void addKeyBinding(String name, KeyStroke ks, Action action) {
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(ks, name);
am.put(name, action);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
Point location = frog.getLocation();
AffineTransform at = AffineTransform.getTranslateInstance(location.x, location.y);
g2d.transform(at);
g2d.setColor(new Color(0, 150, 15));
g2d.fill(frog);
g2d.setColor(Color.BLACK);
g2d.draw(frog);
g2d.dispose();
}
protected class VerticalMovementAction extends AbstractAction {
private VerticalDirection direction;
public VerticalMovementAction(VerticalDirection direction) {
this.direction = direction;
}
#Override
public void actionPerformed(ActionEvent e) {
verticalDirection = direction;
}
}
protected class HorizontalMovementAction extends AbstractAction {
private HorizontalDirection direction;
public HorizontalMovementAction(HorizontalDirection direction) {
this.direction = direction;
}
#Override
public void actionPerformed(ActionEvent e) {
horizontalDirection = direction;
}
}
}
public static class Frog extends Polygon {
private Integer[] xcoord;
private Integer[] ycoord;
private Point location;
public Frog() {
location = new Point(0, 0);
xcoord = new Integer[]{5, 10, 10, 15, 15, 20,
20, 30, 30, 35, 35, 40, 40,
45, 45, 40, 40, 30, 30, 40,
40, 45, 45, 40, 40, 35, 35,
30, 30, 20, 20, 15, 15, 10,
10, 5, 5, 10, 10, 20, 20,
10, 10, 5, 5};
ycoord = new Integer[]{10, 10, 5, 5, 20, 20,
10, 10, 20, 20, 5, 5, 10, 10,
15, 15, 25, 25, 30, 30, 35, 35,
40, 40, 45, 45, 35, 35, 40, 40,
35, 35, 45, 45, 40, 40, 35, 35,
30, 30, 25, 25, 15, 15, 10};
for (int i = 0; i < xcoord.length; i++) {
this.addPoint(xcoord[i], ycoord[i]);
}
}
public Point getLocation() {
return location;
}
public void setLocation(Point location) {
this.location = location;
}
}
}
Now, you're probably wondering why I would use AffineTransform instead of Graphcis2D#translate, the main reason is, it's easy to apply other transformations, like rotation...
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
Point location = frog.getLocation();
Rectangle bounds = frog.getBounds();
int width = bounds.x + bounds.width;
int height = bounds.y + bounds.height;
AffineTransform at = AffineTransform.getTranslateInstance(location.x, location.y);
at.rotate(Math.toRadians(angle), width / 2, height / 2);
g2d.transform(at);
g2d.setColor(new Color(0, 150, 15));
g2d.fill(frog);
g2d.setColor(Color.BLACK);
g2d.draw(frog);
g2d.dispose();
}
All this does is apply a compound transformation, moving the Graphics context's origin and rotation matrix
And for a complete example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.geom.AffineTransform;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
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 Board());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
protected enum VerticalDirection {
NONE, UP, DOWN;
}
protected enum HorizontalDirection {
NONE, LEFT, RIGHT;
}
public static class Board extends JPanel {
protected static final int Y_DELTA = 4;
protected static final int X_DELTA = 4;
private Frog frog;
private VerticalDirection verticalDirection = VerticalDirection.NONE;
private HorizontalDirection horizontalDirection = HorizontalDirection.NONE;
private double angle = 0; // Up...
public Board() {
setBackground(Color.GREEN);
frog = new Frog();
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Point location = frog.getLocation();
switch (verticalDirection) {
case UP:
angle = 0;
location.y -= Y_DELTA;
break;
case DOWN:
angle = 180;
location.y += Y_DELTA;
break;
}
switch (horizontalDirection) {
case LEFT:
location.x -= X_DELTA;
angle = 270;
break;
case RIGHT:
location.x += X_DELTA;
angle = 90;
break;
}
Rectangle bounds = frog.getBounds();
int width = bounds.x + bounds.width;
int height = bounds.y + bounds.height;
if (location.y < 0) {
location.y = 0;
} else if (location.y + height > getHeight()) {
location.y = getHeight() - height;
}
if (location.x < 0) {
location.x = 0;
} else if (location.x + width > getWidth()) {
location.x = getWidth() - width;
}
frog.setLocation(location);
repaint();
}
});
timer.start();
addPressedKeyBinding("up", KeyEvent.VK_UP, new VerticalMovementAction(VerticalDirection.UP));
addPressedKeyBinding("down", KeyEvent.VK_DOWN, new VerticalMovementAction(VerticalDirection.DOWN));
addPressedKeyBinding("left", KeyEvent.VK_LEFT, new HorizontalMovementAction(HorizontalDirection.LEFT));
addPressedKeyBinding("right", KeyEvent.VK_RIGHT, new HorizontalMovementAction(HorizontalDirection.RIGHT));
addReleasedKeyBinding("up", KeyEvent.VK_UP, new VerticalMovementAction(VerticalDirection.NONE));
addReleasedKeyBinding("down", KeyEvent.VK_DOWN, new VerticalMovementAction(VerticalDirection.NONE));
addReleasedKeyBinding("left", KeyEvent.VK_LEFT, new HorizontalMovementAction(HorizontalDirection.NONE));
addReleasedKeyBinding("right", KeyEvent.VK_RIGHT, new HorizontalMovementAction(HorizontalDirection.NONE));
}
protected void addPressedKeyBinding(String name, int virtuaKey, Action action) {
addKeyBinding(name + ".pressed", KeyStroke.getKeyStroke(virtuaKey, 0, false), action);
}
protected void addReleasedKeyBinding(String name, int virtuaKey, Action action) {
addKeyBinding(name + ".released", KeyStroke.getKeyStroke(virtuaKey, 0, true), action);
}
protected void addKeyBinding(String name, KeyStroke ks, Action action) {
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(ks, name);
am.put(name, action);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
Point location = frog.getLocation();
Rectangle bounds = frog.getBounds();
int width = bounds.x + bounds.width;
int height = bounds.y + bounds.height;
AffineTransform at = AffineTransform.getTranslateInstance(location.x, location.y);
at.rotate(Math.toRadians(angle), width / 2, height / 2);
g2d.transform(at);
g2d.setColor(new Color(0, 150, 15));
g2d.fill(frog);
g2d.setColor(Color.BLACK);
g2d.draw(frog);
g2d.dispose();
}
protected class VerticalMovementAction extends AbstractAction {
private VerticalDirection direction;
public VerticalMovementAction(VerticalDirection direction) {
this.direction = direction;
}
#Override
public void actionPerformed(ActionEvent e) {
verticalDirection = direction;
}
}
protected class HorizontalMovementAction extends AbstractAction {
private HorizontalDirection direction;
public HorizontalMovementAction(HorizontalDirection direction) {
this.direction = direction;
}
#Override
public void actionPerformed(ActionEvent e) {
horizontalDirection = direction;
}
}
}
public static class Frog extends Polygon {
private Integer[] xcoord;
private Integer[] ycoord;
private Point location;
public Frog() {
location = new Point(0, 0);
xcoord = new Integer[]{5, 10, 10, 15, 15, 20,
20, 30, 30, 35, 35, 40, 40,
45, 45, 40, 40, 30, 30, 40,
40, 45, 45, 40, 40, 35, 35,
30, 30, 20, 20, 15, 15, 10,
10, 5, 5, 10, 10, 20, 20,
10, 10, 5, 5};
ycoord = new Integer[]{10, 10, 5, 5, 20, 20,
10, 10, 20, 20, 5, 5, 10, 10,
15, 15, 25, 25, 30, 30, 35, 35,
40, 40, 45, 45, 35, 35, 40, 40,
35, 35, 45, 45, 40, 40, 35, 35,
30, 30, 25, 25, 15, 15, 10};
// I rest the coordinates back to 0x0 because it's easier to
// deal with when applying a rotation...
for (int index = 0; index < xcoord.length; index++) {
xcoord[index] -= 5;
}
for (int index = 0; index < ycoord.length; index++) {
ycoord[index] -= 5;
}
for (int i = 0; i < xcoord.length; i++) {
this.addPoint(xcoord[i], ycoord[i]);
}
}
public Point getLocation() {
return location;
}
public void setLocation(Point location) {
this.location = location;
}
}
}
Look ma, no maths!
Don't create a Frog in your paintComponent() method! That is throwing away the existing frog and creating a new one with default position.
You should create all of your Frog instances when you initialize your panel, or possibly in response to a b button click to "create a new frog".
I am working on a project that simulates a traffic intersection. So far I did the map, traffic lights. Now I want to add some movement, some cars in my project. The problem that I am facing is that i can't add graphics on the same Panel from different classes. And can someone give me a good tutorial where I can learn how to move multiple graphics (cars in my case) .
Main class:
import java.awt.Color;
import javax.swing.JFrame;
public class Main {
public static void main(String[] args) {
MyMap map = new MyMap();
MyCar car = new MyCar();
Thread x = new Thread(map);
x.start();
JFrame f = new JFrame("Broadway Intersection");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
map.setBackground(Color.white);
f.add(map);
f.add(car);
f.setSize(1366, 738);
f.setVisible(true);
}
}
Map class:
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class MyMap extends JPanel implements Runnable {
Color color = Color.RED;
Color color2 = Color.RED;
Color color3 = Color.RED;
Color color4 = Color.RED;
int[] faza = new int[4];
int k;
int faza_curenta = 0;
public MyMap() {
faza[0] = 20;
faza[1] = 20;
faza[2] = 20;
faza[3] = 20;
}
public void run() {
color = Color.GREEN;
while (true) {
System.out.println("Faza = " + faza_curenta + " k= " + k);
k++;
if (k == faza[0]) {
faza_curenta = 1;
color = Color.RED;
color2 = Color.GREEN;
} else if (k == (faza[0] + faza[1])) {
faza_curenta = 2;
color = Color.RED;
color2 = Color.RED;
color3 = Color.GREEN;
} else if (k == (faza[0] + faza[1] + faza[2])) {
faza_curenta = 3;
color = Color.RED;
color3 = Color.RED;
color4 = Color.GREEN;
} else if (k == (faza[0] + faza[1] + faza[2] + faza[3])) {
faza_curenta = 0;
color = Color.GREEN;
color4 = Color.RED;
k = 0;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void paintComponent(final Graphics g) {
super.paintComponent(g);
g.setColor(Color.GREEN);
g.fillRect(0, 0, 500, 250); // stanga sus
g.fillRect(900, 0, 500, 250); // dreapta sus
g.fillRect(0, 500, 500, 250);// stanga jos
g.fillRect(900, 500, 500, 250); // dreapta jos
g.setColor(Color.GRAY);
g.fillRect(500, 0, 400, 900);
g.fillRect(0, 250, 500, 250);
g.fillRect(900, 250, 500, 250);
g.setColor(Color.WHITE);
g.fillRect(695, 0, 5, 100);// linii verticale
g.fillRect(695, 150, 5, 100);
g.fillRect(695, 500, 5, 100);
g.fillRect(695, 650, 5, 50);
g.fillRect(0, 370, 50, 5);
g.fillRect(100, 370, 100, 5); // linii orizontale
g.fillRect(250, 370, 100, 5);
g.fillRect(400, 370, 100, 5);
g.fillRect(900, 370, 100, 5);
g.fillRect(1050, 370, 100, 5);
g.fillRect(1200, 370, 100, 5);
g.setColor(Color.BLACK);
g.fillRect(470, 220, 30, 30); // semafor Nord
g.setColor(color);
g.fillOval(475, 225, 20, 20); // semafor Nord
g.setColor(Color.BLACK);
g.fillRect(900, 220, 30, 30); // semafor Est
g.setColor(color2);
g.fillOval(905, 225, 20, 20); // semafor Nord
g.setColor(Color.BLACK);
g.fillRect(470, 500, 30, 30); // semafor Vest
g.setColor(color4);
g.fillOval(475, 505, 20, 20); // semafor Nord
g.setColor(Color.BLACK);
g.fillRect(900, 500, 30, 30); // semafor Sud
g.setColor(color3);
g.fillOval(905, 505, 20, 20); // semafor Nord
repaint();
}
}
And finally MyCar class:
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class MyCar extends JPanel {
int x; // X position
int y; // Y position
int xSpeed; // Speed in the X direction
int ySpeed; // Speed in the Y direction
public void paintComponent(final Graphics g) {
super.paintComponent(g);
g.setColor(Color.GREEN);
g.fillRect(420, 200, 30, 30);
repaint();
}
}
You can set Panel.setLayout(null); and add JButton by setting image icon on it now you can control Button (CAR) location by button.setLocation(x,y);