Need to slow rectangle movement - java

I am having a problem with threading. I am trying to recreate pong where there are 2 Action Listeners for 2 players. The 2 paddles move at the speed that I want them to move at. However, the "ball"(Rectangle object with an oval painted over it) is moving way too fast. I've tried slowing it down using a second thread in the Ball class, but that doesn't seem to work. Any help would be appreciated.
Here's my code:
public class BattleBallz extends JFrame implements Runnable {
AL keyListen1 = new AL();
AL2 keyListen2 = new AL2();
Image dbi;
Graphics dbg;
int x1,x2;
int ballX, ballY, direction;
Ball b1;
public BattleBallz(){
setTitle("Battle Ballz");
setSize(350, 400);
setResizable(false);
setVisible(true);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
addKeyListener(keyListen1);
addKeyListener(keyListen2);
x1 = 150;
x2 = 150;
int direction = 0 + (int)(Math.random() * ((2 - 0) + 1));
b1 = new Ball(direction);
Thread b = new Thread(b1);
b.start();
}
public void paint(Graphics g){
dbi = createImage(getWidth(), getHeight());
dbg = dbi.getGraphics();
paintComponent(dbg);
g.drawImage(dbi, 0, 0, this);
}
public void paintComponent(Graphics g){
Rectangle p1 = new Rectangle(x1,375,60,10);
g.setColor(Color.blue);
g.fillRect(x1, 375, 60, 10);
Rectangle p2 = new Rectangle(x2,45,60,10);
g.setColor(Color.red);
g.fillRect(x2,45,60,10);
b1.paintComponent(g, p1, p2);
repaint();
}
#Override
public void run() {
try {
while(true){
move();
Thread.sleep(5);
}
} catch (Exception e) {
// TODO: handle exception
}
}
public void move(){
x1 += keyListen1.getXdirection();
x2 += keyListen2.getXdirection();
if (x1<=0){
x1 =0;
}
if (x1>=305){
x1 = 305;
}
if (x2<=0){
x2=0;
}
if (x2>=305){
x2=305;
}
}
}
public class Ball extends JPanel implements Runnable {
boolean up,down,right,left;
int x = 150, y = 150 ;
public Ball(int direction){
if(direction ==1){
down = true;
}
if (direction ==0){
up = true;
}
}
public void paintComponent(Graphics g, Rectangle p1, Rectangle p2){
super.paintComponents(g);
if(down){
y++;
Rectangle ball = new Rectangle(x,y,49,49);
g.fillOval(x, y, 50, 50);
if (y>=385 || ball.intersects(p1)){
down = false;
up = true;
}
}
if (up){
y--;
Rectangle ball = new Rectangle(x,y,49,49);
g.fillOval(x, y, 50, 50);
if (y<=10 || ball.intersects(p2)){
up = false;
down = true;
}
}
}
#Override
public void run() {
// TODO Auto-generated method stub
try {
while (true){
Thread.sleep(30);
}
} catch (Exception e) {
// TODO: handle exception
}
}
}

use Swing Timer instead of plain Thread, you have an issue with Concurency in Swing, code posted to block Event Dispatch Thread, locked by Thread.sleep, endless block
use paintComponent but put there JPanel, 1st. code line inside should be super.paintComponent, otherwise paint is cumulated, override getPreferredSize for JPanel
use KeyBindings instead of KeyListener

Related

JPanel not showing up in another JPanel

I'm trying to make a 2D racing game here by adding a Jpanel on top of a Jpanel. This is done by using 2 classes which I have posted down below.
The problem is the car is never appears on the track... I'm really not sure what I'm missing.. any help is more than welcome!
Thank you in advance!
Car.java
public class Car extends JPanel implements Runnable
{
private static final long serialVersionUID = 007;
private BufferedImage car = null;
private float x = 100F, y = 100F;
private Thread driveThread = new Thread(this);
private double currentAngle = 0; // angel of the car
private static int[] key = new int[256]; // keyboard input
private float MAX_SPEED = 7F;
private float speed = 0F; // speed of our racing car
private float acceleration = 0.15F;
private int player;
private boolean playable = true;
public Car(int player)
{
this.player = player;
this.setSize(super.getHeight(), super.getWidth());
this.setFocusable(true); // enables keyboard
try
{
if (player == 1)
{
//red car
car = ImageIO.read(this.getClass().getResource(
"/imagesCar/first-0.png"));
System.out.println(car.getColorModel());
} else if(player == 2)
{
//blue car
car = ImageIO.read(this.getClass().getResource(
"/imagesCar/second-0.png"));
x = x +30;
}
} catch (IOException e) {
System.out.println("dupi");
}
// starts the drive thread
startGame();
}
private void startGame() {
driveThread.start();
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
this.setOpaque(false);
// rotation
Graphics2D g2d = (Graphics2D) g;
AffineTransform rot = g2d.getTransform();
// Rotation at the center of the car
float xRot = x + 12.5F;
float yRot = y + 20F;
rot.rotate(Math.toRadians(currentAngle), xRot, yRot);
g2d.setTransform(rot);
//Draws the cars new position and angle
g2d.drawImage(car, (int) x, (int) y, 50, 50, this);
}
protected void calculateCarPosition() {
//calculates the new X and Y - coordinates
x += Math.sin(currentAngle * Math.PI / 180) * speed * 0.5;
y += Math.cos(currentAngle * Math.PI / 180) * -speed * 0.5;
}
protected void carMovement() {
// Player One Key's
if (player == 1) {
if (key[KeyEvent.VK_LEFT] != 0) {
currentAngle-=2;
} else if (key[KeyEvent.VK_RIGHT] != 0) {
currentAngle+=2;
}
if (key[KeyEvent.VK_UP] != 0) {
if (speed < MAX_SPEED) {
speed += acceleration;
}
} else if (key[KeyEvent.VK_DOWN] != 0 && speed > -1) {
speed = speed - 0.1F;
}
speed = speed * 0.99F;
} else {
//Player Two Key's
if (key[KeyEvent.VK_A] != 0) {
currentAngle -= 2;
} else if (key[KeyEvent.VK_D] != 0) {
currentAngle += 2;
}
if (key[KeyEvent.VK_W] != 0) {
if (speed < MAX_SPEED) {
speed += acceleration;
}
} else if (key[KeyEvent.VK_S] != 0 && speed > -1) {
speed = speed - 0.1F;
}
//reduce speed when no key is pressed
speed = speed * 0.99F;
}
}
public void getUnderground() {
}
// get key events!
final protected void processKeyEvent(KeyEvent e) {
key[e.getKeyCode()] = e.getID() & 1;
}
#Override
public void run() {
while (true) {
repaint();
carMovement();
calculateCarPosition();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
RaceTrack.java
public class RaceTrack extends JPanel
{
#Override
public void paintComponent(Graphics g)
{
Color c1 = Color.green;
g.setColor(c1);
g.fillRect(150, 200, 550, 300);
Color c2 = Color.black;
g.setColor(c2);
g.drawRect(50, 100, 750, 500); // outer edge
g.drawRect(150, 200, 550, 300); // inner edge
Color c3 = Color.yellow;
g.setColor(c3);
g.drawRect(100, 150, 650, 400); // mid-lane marker
Color c4 = Color.white;
g.setColor(c4);
g.drawLine(425, 500, 425, 600); // start line
}
}
main
public static void main(String[] args) {
JFrame mainFrame = new JFrame();
mainFrame.setSize(850,650);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container content = mainFrame.getContentPane();
RaceTrack track = new RaceTrack();
Car carP1 = new Car(1);
track.add(carP1);
content.add(track);
mainFrame.setVisible(true);
}
Car has no defined sizing hints, so it's default size is 0x0
Adding Car to RaceTrack, which is using a FlowLayout will layout Car to it's preferred size of 0x0
Swing is not thread safe so you're probably have a bunch of thread race conditions/violations as well
Not sure if this is the proper way to solve this
Don't use components for this purpose, this problem just screams custom painting all the way.
There are plenty of blogs and tutorials about basic game development, so I don't want to spend a lot of time going over the same material.
Basically, what you want is to define a series of "attributes" to the objects you want to use in your game (AKA "entities"). Not all entities need to be paintable, some might trigger other actions or simply act as "markers" for other entities to use.
In this example, I'm defining two basic entities, "movable" and "paintable". A "paintable" entity may be static (ie the track) or "movable" (ie the car)
The intention is to provide a isolated concept of functionality which can easily be applied to a verity objects in order to "describe" their functionality and purpose within the game.
For example...
public interface MovableEntity extends Entity {
public void update(Rectangle bounds);
}
public interface PaintableEntity extends Entity {
public void paint(Graphics2D g2d, ImageObserver imageObserver, Rectangle bounds);
}
So, in your case, a Car is both Paintable and Movable.
Your "engine" would then maintain one or more lists of these "entities" and process them accordingly.
This example simply makes use of a Swing Timer to act as the "main loop"
mainLoop = new Timer(5, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Rectangle bounds = new Rectangle(0, 0, getWidth(), getHeight());
// Lots of collision detection and other awesome stuff
for (MovableEntity entity : movableEntitys) {
entity.update(bounds);
}
repaint();
}
});
mainLoop.start();
This provides a level of thread safety, as the Timer is triggered within the context of the Event Dispatching Thread, meaning that while we're updating the entities, they can't be painted.
Then we simply make use of the JPanel's paintComponent method to act as the rendering process...
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Rectangle bounds = new Rectangle(0, 0, getWidth(), getHeight());
for (PaintableEntity paintable : paintableEntities) {
Graphics2D g2d = (Graphics2D) g.create();
paintable.paint(g2d, this, bounds);
g2d.dispose();
}
}
This is a pretty broad example based on demonstrating basic concepts in a simple manner. There are far more complex possible solutions which would follow the same basic principles.
Personally, I'd define some kind of "path" which acts as the track, on which the cars would then calculate there positions based on different factors, but that's somewhat of a more complex solution then is required right now. But if you're really interested, it might look something like this
Runnable Example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.ImageObserver;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
/*
You could have entities which can collide which have collision detection
capabilities
Some entities don't need to be painted and may provide things like
visual or audio affects
*/
public interface Entity {
}
public interface MovableEntity extends Entity {
public void update(Rectangle bounds);
}
public interface PaintableEntity extends Entity {
public void paint(Graphics2D g2d, ImageObserver imageObserver, Rectangle bounds);
}
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 GamePane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class GamePane extends JPanel {
// Could use a single list and filter it, but hay
private List<PaintableEntity> paintableEntities;
private List<MovableEntity> movableEntitys;
private Timer mainLoop;
public GamePane() {
paintableEntities = new ArrayList<>(25);
movableEntitys = new ArrayList<>(25);
paintableEntities.add(new TrackEntity());
CarEntity car = new CarEntity();
paintableEntities.add(car);
movableEntitys.add(car);
mainLoop = new Timer(5, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Rectangle bounds = new Rectangle(0, 0, getWidth(), getHeight());
// Lots of collision detection and other awesome stuff
for (MovableEntity entity : movableEntitys) {
entity.update(bounds);
}
repaint();
}
});
mainLoop.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Rectangle bounds = new Rectangle(0, 0, getWidth(), getHeight());
for (PaintableEntity paintable : paintableEntities) {
Graphics2D g2d = (Graphics2D) g.create();
paintable.paint(g2d, this, bounds);
g2d.dispose();
}
}
}
public class CarEntity implements PaintableEntity, MovableEntity {
private int delta = 1;
private int xDelta = 0;
private int yDelta = delta;
private int xPos = 2;
private int yPos = 2;
private int size = 4;
#Override
public void paint(Graphics2D g2d, ImageObserver imageObserver, Rectangle bounds) {
g2d.translate(bounds.x, bounds.y);
g2d.setColor(Color.RED);
g2d.fillRect(xPos - size / 2, yPos - size / 2, size, size);
}
#Override
public void update(Rectangle bounds) {
xPos += xDelta;
yPos += yDelta;
if (xPos + (size / 2) > bounds.x + bounds.width) {
xPos = bounds.x + bounds.width - (size / 2);
xDelta = 0;
yDelta = -delta;
} else if (xPos - (size / 2) < bounds.x) {
xPos = bounds.x + (size / 2);
xDelta = 0;
yDelta = delta;
}
if (yPos + (size / 2) > bounds.y + bounds.height) {
yPos = bounds.y + bounds.height - (size / 2);
xDelta = delta;
yDelta = 0;
} else if (yPos - (size / 2) < bounds.y) {
yPos = bounds.y + (size / 2);
xDelta = -delta;
yDelta = 0;
}
}
}
public class TrackEntity implements PaintableEntity {
#Override
public void paint(Graphics2D g2d, ImageObserver imageObserver, Rectangle bounds) {
g2d.translate(bounds.x, bounds.y);
g2d.setColor(Color.BLUE);
g2d.drawRect(2, 2, bounds.width - 4, bounds.height - 4);
}
}
}

Java how to move a paint componenet [duplicate]

I'm trying to move the boat on the x-axis (without the keyboard yet). How can I relate the movement/ animation to the boat.png and not to any other image?
public class Mama extends Applet implements Runnable {
int width, height;
int x = 200;
int y = 200;
int dx = 1;
Image img1, img2, img3, img4;
#Override
public void init(){
setSize(627, 373);
Thread t = new Thread(this);
img1 = getImage(getCodeBase(),"Background.png");
img2 = getImage(getCodeBase(), "boat.png");
img3 = getImage(getCodeBase(), "LeftPalm.png");
img4 = getImage(getCodeBase(), "RightPalm.png");
}
#Override
public void paint(Graphics g){
g.drawImage(img1, 0, 0, this);
g.drawImage(img2, 200, 200, this);
g.drawImage(img3, 40, 100, this);
g.drawImage(img4, 450, 130, this);
}
#Override
public void run() {
while(true){
x += dx;
repaint();
try {
Thread.sleep(17);
} catch (InterruptedException e) {
System.out.println("Thread generates an error.");
}
}
}
}
There are a few things that stand out...
The "Problem"
As has already been stated, you need to supply variable arguments to the image drawing process. g.drawImage(img2, x, y, this);, this will allow you define where the image should be painted.
While you've implemented Runnable, you've actually not started any threads to call it. This means, nothing is actually changing the variables.
In you start method, you should be calling something like new Thread(this).start().
Recommendations
Although you've tagged the question as Swing, you're using AWT components. This isn't recommended (in fact applets are generally discouraged as they are troublesome - IMHO). The other problem, as you are bound to find out shortly, is they are not double buffered, this generally leads to flickering when performing animation, which isn't desirable.
As a side note, it is also discouraged to override the paint method of top level containers like Applet. Top level containers tend to contain a number additional components, by overriding the paint method like this, you destroy this setup. Also, top level containers don't tend to be double buffered either.
The example below uses a JFrame, but it wouldn't take much to convert it to use a JApplet (just drop the AnimationPanel on to it. This is another reason why extending from top level containers is generally discouraged ;)
public class AnimatedBoat {
public static void main(String[] args) {
new AnimatedBoat();
}
public AnimatedBoat() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new AnimationPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class AnimationPane extends JPanel {
private BufferedImage boat;
private int xPos = 0;
private int direction = 1;
public AnimationPane() {
try {
boat = ImageIO.read(new File("boat.png"));
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
xPos += direction;
if (xPos + boat.getWidth() > getWidth()) {
xPos = getWidth() - boat.getWidth();
direction *= -1;
} else if (xPos < 0) {
xPos = 0;
direction *= -1;
}
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return boat == null ? super.getPreferredSize() : new Dimension(boat.getWidth() * 4, boat.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int y = getHeight() - boat.getHeight();
g.drawImage(boat, xPos, y, this);
}
}
}
You need to replace g.drawImage(img2, 200, 200, this); with g.drawImage(img2, x, y, this);

How to make an image move from left to right in Java

so far i have created the class below, however, now i would like to insert a code to make the image slide from left to right and right to left. I would normally use the Sliding platform however it doesn't work when i try to implement it. I am still a beginner in java so i am grateful for your help.
This is the code of my Java Class:
package game;
import city.soi.platform.*;
public class Enemy extends Body implements CollisionListener{
private Game game ;
public Enemy(Game g){
super(g.getWorld(), new PolygonShape(-27.0f,25.0f, -27.0f,-24.0f, 25.0f,-24.0f, 26.0f,25.0f, -27.0f,25.0f));
setImage(new BodyImage("images/enemy.png"));
g.getWorld().addCollisionListener(this);
game = g;
}
public void collide(CollisionEvent e) {
if (e.getOtherBody() == game.getPlayer()){
game.getPlayer().subtractFromScore(75);
System.out.println("You have just lossed 75 Points! Current Score = " + game.getPlayer().getScore());
this.destroy();
}
}
}
Just to be clear i would like everyone i include this class onto a platform it moves from left to right.
Many Thanks,
Moe
This will depend a lot on what you individual requirements, but the basic concepts will remain the same.
Any type of animation in Swing must be executed in such away that it does not block the Event Dispatching Thread. Any blocking action on the EDT will prevent any repaint request (amongst other things) from been processed.
This simple example uses a javax.swing.Timer that ticks every 40 milliseconds or so (about 25 fps) and updates the position of a small "ball"
More complex iterations would require a dedicated Thread. This makes the whole process far more complex as
You should never update/create/modify/change any UI component (or property that the UI may require to perform painting) from any thread other then the EDT
You don't control the paint process. This means a repaint may occur at anytime and if you are modifying any property/object that the paint process requires to render the state of the game, it could cause inconsistencies.
.
public class SimpleBouncyBall {
public static void main(String[] args) {
new SimpleBouncyBall();
}
public SimpleBouncyBall() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new CourtPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class CourtPane extends JPanel {
private Ball ball;
private int speed = 5;
public CourtPane() {
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Rectangle bounds = new Rectangle(new Point(0, 0), getSize());
if (ball == null) {
ball = new Ball(bounds);
}
speed = ball.move(speed, bounds);
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(100, 100);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (ball != null) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Point p = ball.getPoint();
g2d.translate(p.x, p.y);
ball.paint(g2d);
g2d.dispose();
}
}
}
public class Ball {
private Point p;
private int radius = 12;
public Ball(Rectangle bounds) {
p = new Point();
p.x = 0;
p.y = bounds.y + (bounds.height - radius) / 2;
}
public Point getPoint() {
return p;
}
public int move(int speed, Rectangle bounds) {
p.x += speed;
if (p.x + radius >= (bounds.x + bounds.width)) {
speed *= -1;
p.x = ((bounds.x + bounds.width) - radius) + speed;
} else if (p.x <= bounds.x) {
speed *= -1;
p.x = bounds.x + speed;
}
p.y = bounds.y + (bounds.height - radius) / 2;
return speed;
}
public void paint(Graphics2D g) {
g.setColor(Color.RED);
g.fillOval(0, 0, radius, radius);
}
}
}

How to move an image (animation)?

I'm trying to move the boat on the x-axis (without the keyboard yet). How can I relate the movement/ animation to the boat.png and not to any other image?
public class Mama extends Applet implements Runnable {
int width, height;
int x = 200;
int y = 200;
int dx = 1;
Image img1, img2, img3, img4;
#Override
public void init(){
setSize(627, 373);
Thread t = new Thread(this);
img1 = getImage(getCodeBase(),"Background.png");
img2 = getImage(getCodeBase(), "boat.png");
img3 = getImage(getCodeBase(), "LeftPalm.png");
img4 = getImage(getCodeBase(), "RightPalm.png");
}
#Override
public void paint(Graphics g){
g.drawImage(img1, 0, 0, this);
g.drawImage(img2, 200, 200, this);
g.drawImage(img3, 40, 100, this);
g.drawImage(img4, 450, 130, this);
}
#Override
public void run() {
while(true){
x += dx;
repaint();
try {
Thread.sleep(17);
} catch (InterruptedException e) {
System.out.println("Thread generates an error.");
}
}
}
}
There are a few things that stand out...
The "Problem"
As has already been stated, you need to supply variable arguments to the image drawing process. g.drawImage(img2, x, y, this);, this will allow you define where the image should be painted.
While you've implemented Runnable, you've actually not started any threads to call it. This means, nothing is actually changing the variables.
In you start method, you should be calling something like new Thread(this).start().
Recommendations
Although you've tagged the question as Swing, you're using AWT components. This isn't recommended (in fact applets are generally discouraged as they are troublesome - IMHO). The other problem, as you are bound to find out shortly, is they are not double buffered, this generally leads to flickering when performing animation, which isn't desirable.
As a side note, it is also discouraged to override the paint method of top level containers like Applet. Top level containers tend to contain a number additional components, by overriding the paint method like this, you destroy this setup. Also, top level containers don't tend to be double buffered either.
The example below uses a JFrame, but it wouldn't take much to convert it to use a JApplet (just drop the AnimationPanel on to it. This is another reason why extending from top level containers is generally discouraged ;)
public class AnimatedBoat {
public static void main(String[] args) {
new AnimatedBoat();
}
public AnimatedBoat() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new AnimationPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class AnimationPane extends JPanel {
private BufferedImage boat;
private int xPos = 0;
private int direction = 1;
public AnimationPane() {
try {
boat = ImageIO.read(new File("boat.png"));
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
xPos += direction;
if (xPos + boat.getWidth() > getWidth()) {
xPos = getWidth() - boat.getWidth();
direction *= -1;
} else if (xPos < 0) {
xPos = 0;
direction *= -1;
}
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return boat == null ? super.getPreferredSize() : new Dimension(boat.getWidth() * 4, boat.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int y = getHeight() - boat.getHeight();
g.drawImage(boat, xPos, y, this);
}
}
}
You need to replace g.drawImage(img2, 200, 200, this); with g.drawImage(img2, x, y, this);

Swing Timer with Graphics component

I want to creat a circle in on a panel which appears and dissapears every 2 seconds.
Here is that i have:
public class Board extends JPanel implements ActionListener {
private final int DELAY = 2000;
private Timer timer;
/*
* constructor
*/
public Board() {
setFocusable(true);
initGame();
}
/*
* initialize board
*/
public void initGame() {
timer = new Timer(DELAY, this);
timer.start();
}
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.gray);
// draw an oval starting at 20,20 with a width and height of 100 and
// fill it
g.drawOval(20, 20, 100, 100);
g.fillOval(20, 20, 100, 100);
g.dispose();
}
#Override
public void actionPerformed(ActionEvent e) {
repaint();
}
}
thank you guys. Now I wanna control my circle. But again something is wrong and it is not moving as I want.
here are new methods:
private boolean left = false;
private boolean right = true;
private boolean up = false;
private boolean down = false;
private Timer timer;
public int x = 20;
public int y = 20;
public int x2 = 100;
public int y2 = 100;
...
public void paint(Graphics g) {
super.paint(g);
if (drawCircle) {
g.setColor(Color.gray);
// draw an oval starting at 20,20 with a width and height of 100 and
// fill it
g.drawOval(x, y, x2, y2);
g.fillOval(x, y, x2, y2);
}
// removes native non-Java recourses
g.dispose();
}
public void move() {
if (left) {
x -= 5;
}
if (right) {
x += 5;
}
if (up) {
y -= 5;
}
if (down) {
y += 5;
}
}
#Override
public void actionPerformed(ActionEvent e) {
move();
repaint();
}
private class TAdapter extends KeyAdapter {
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if ((key == KeyEvent.VK_LEFT) && (!right)) {
left = true;
up = false;
down = false;
}
if ((key == KeyEvent.VK_RIGHT) && (!left)) {
right = true;
up = false;
down = false;
}
if ((key == KeyEvent.VK_UP) && (!down)) {
up = true;
right = false;
left = false;
}
if ((key == KeyEvent.VK_DOWN) && (!up)) {
down = true;
right = false;
left = false;
}
}
}
/****/
Solved , i just added
addKeyListener(new TAdapter());
to my Board constructor!
You just need to have your Timer modify some state. Try something like this:
private boolean drawCircle = false;
public void actionPerformed(ActionEvent e) {
drawCircle = !drawCircle;
repaint();
}
public void paintComponent(Graphics g) {
//...
if ( drawCircle ) {
g.setColor(Color.gray);
//...
}
}
Aren't you supposed to formulate the question... as a question?
Anyway, add a boolean to your class, toggle it on each action event, and paint the oval only if it is true.
Edit/Notes:
- Override paintComponent instead of paint
- Don't dispose of a Graphics you haven't created. Either drop the line, or use g.create() to make a copy. See http://java.sun.com/products/jfc/tsc/articles/swing2d/ for details.

Categories