I'm learning Java and would really appreciate some help.
I'm trying to get this effect http://tinypic.com/r/339p0ud/8
I using stack overflow 'MOVE CUBE' example:
How Do I Use KeyEventDispatcher
and
stack overflow 'Click coordinate' example:
Using the coordinate plane in the JFrame
I wish to join them together, so that I have a cube I can move around with my keys and
as I do the coordinates show up next to the cube (so the coordinates move with the cube) and change as the position changes.
I would be fascinated to see how this is done as I have tried my best the past week with no success.
thanks in advance for any help or tips you provide here,
Joe
MOVE.java (move the block around with keys)
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
public class Move extends JPanel {
public static final long serialVersionUID = 1L;
public static final String IMAGE_PATH = "http://mathforum.org/alejandre/magic.square/4x4grid.gif";
public static final String IMAGE_PATH_PLAYER = "http://upload.wikimedia.org/wikipedia/commons/thumb/c/c1/Square-symbol.svg/50px-Square-symbol.svg.png";
public static final int STEP = 3;
public static final int TIMER_DELAY = STEP * 8;
public BufferedImage bkgrndImage = null;
public BufferedImage playerImage = null;
public Map<Direction, Boolean> directionMap = new HashMap<Direction, Boolean>();
public int playerX = 0;
public int playerY = 0;
enum Direction {
UP(KeyEvent.VK_UP, 0, -1), DOWN(KeyEvent.VK_DOWN, 0, 1),
LEFT(KeyEvent.VK_LEFT, -1, 0), RIGHT(KeyEvent.VK_RIGHT, 1, 0);
public int keyCode;
public int xDirection;
public int yDirection;
private Direction(int keyCode, int xDirection, int yDirection) {
this.keyCode = keyCode;
this.xDirection = xDirection;
this.yDirection = yDirection;
}
public int getKeyCode() {
return keyCode;
}
public int getXDirection() {
return xDirection;
}
public int getYDirection() {
return yDirection;
}
}
public Move() {
try {
URL bkgrdImageURL = new URL(IMAGE_PATH);
URL playerImageURL = new URL(IMAGE_PATH_PLAYER);
bkgrndImage = ImageIO.read(bkgrdImageURL);
playerImage = ImageIO.read(playerImageURL);
setPreferredSize(new Dimension(bkgrndImage.getWidth(), bkgrndImage.getHeight()));
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
for (Direction direction : Direction.values()) {
directionMap.put(direction, false);
}
setKeyBindings();
Timer timer = new Timer(TIMER_DELAY, new TimerListener());
timer.start();
}
public void setKeyBindings() {
InputMap inMap = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
ActionMap actMap = getActionMap();
for (final Direction direction : Direction.values()) {
KeyStroke pressed = KeyStroke.getKeyStroke(direction.getKeyCode(), 0, false);
KeyStroke released = KeyStroke.getKeyStroke(direction.getKeyCode(), 0, true);
inMap.put(pressed, direction.toString() + "pressed");
inMap.put(released, direction.toString() + "released");
actMap.put(direction.toString() + "pressed", new AbstractAction() {
public static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
directionMap.put(direction, true);
}
});
actMap.put(direction.toString() + "released", new AbstractAction() {
public static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
directionMap.put(direction, false);
}
});
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (bkgrndImage != null) {
g.drawImage(bkgrndImage, 0, 0, null);
}
if (playerImage != null) {
g.drawImage(playerImage, playerX, playerY, null);
}
}
public class TimerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
boolean moved = false;
for (Direction direction : Direction.values()) {
if (directionMap.get(direction)) {
playerX += STEP * direction.getXDirection();
playerY += STEP * direction.getYDirection();
moved = true;
}
}
if (moved) {
int x = playerX - 2 * STEP;
int y = playerY - 2 * STEP;
int w = playerImage.getWidth() + 4 * STEP;
int h = playerImage.getHeight() + 4 * STEP;
Move.this.repaint(x, y, w, h); // !! repaint just the player
}
}
}
public static void createAndShowUI() {
JFrame frame = new JFrame("MoveIcon");
frame.getContentPane().add(new Move());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowUI();
}
});
}
COORDINATE.java (get x and y position in JFrame)
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Coordinate
{
private int x;
private int y;
private String text;
private DrawingBase canvas;
private void displayGUI()
{
JFrame frame = new JFrame("Drawing Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
canvas = new DrawingBase();
canvas.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent me)
{
text = "X : " + me.getX() + " Y : " + me.getY();
x = me.getX();
y = me.getY();
canvas.setValues(text, x, y);
}
});
frame.setContentPane(canvas);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new Coordinate().displayGUI();
}
});
}
}
class DrawingBase extends JPanel
{
private String clickedAt = "";
private int x = 0;
private int y = 0;
public void setValues(String text, int x, int y)
{
clickedAt = text;
this.x = x;
this.y = y;
repaint();
}
public Dimension getPreferredSize()
{
return (new Dimension(500, 400));
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawString(clickedAt, x, y);
}
}
No sure if this is what you want, I removed Coordinate and did everything in one class
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.awt.image.TileObserver;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import org.w3c.dom.events.EventTarget;
import org.w3c.dom.events.MouseEvent;
import org.w3c.dom.views.AbstractView;
public class Move extends JPanel{
public static final long serialVersionUID = 1L;
public static final String IMAGE_PATH = "http://mathforum.org/alejandre/magic.square/4x4grid.gif";
public static final String IMAGE_PATH_PLAYER = "http://upload.wikimedia.org/wikipedia/commons/thumb/c/c1/Square-symbol.svg/50px-Square-symbol.svg.png";
public static final int STEP = 3;
public static final int TIMER_DELAY = STEP * 8;
public BufferedImage bkgrndImage = null;
public BufferedImage playerImage = null;
public Map<Direction, Boolean> directionMap = new HashMap<Direction, Boolean>();
public int playerX = 0;
public int playerY = 0;
private static int xPosition = 0;
private static int yPosition = 0;
private String s = "";
private JLabel jlbl1 = new JLabel("");
enum Direction {
UP(KeyEvent.VK_UP, 0, -1), DOWN(KeyEvent.VK_DOWN, 0, 1),
LEFT(KeyEvent.VK_LEFT, -1, 0), RIGHT(KeyEvent.VK_RIGHT, 1, 0);
public int keyCode;
public int xDirection;
public int yDirection;
private Direction(int keyCode, int xDirection, int yDirection) {
this.keyCode = keyCode;
this.xDirection = xDirection;
this.yDirection = yDirection;
}
public int getKeyCode() {
return keyCode;
}
public int getXDirection() {
return xDirection;
}
public int getYDirection() {
return yDirection;
}
}
public Move() {
this.add(jlbl1,new Dimension(100,100));
try {
URL bkgrdImageURL = new URL(IMAGE_PATH);
URL playerImageURL = new URL(IMAGE_PATH_PLAYER);
bkgrndImage = ImageIO.read(bkgrdImageURL);
playerImage = ImageIO.read(playerImageURL);
setPreferredSize(new Dimension(bkgrndImage.getWidth(), bkgrndImage.getHeight()));
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
for (Direction direction : Direction.values()) {
directionMap.put(direction, false);
}
setKeyBindings();
Timer timer = new Timer(TIMER_DELAY, new TimerListener());
timer.start();
}
public void setKeyBindings() {
InputMap inMap = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
ActionMap actMap = getActionMap();
for (final Direction direction : Direction.values()) {
KeyStroke pressed = KeyStroke.getKeyStroke(direction.getKeyCode(), 0, false);
KeyStroke released = KeyStroke.getKeyStroke(direction.getKeyCode(), 0, true);
inMap.put(pressed, direction.toString() + "pressed");
inMap.put(released, direction.toString() + "released");
actMap.put(direction.toString() + "pressed", new AbstractAction() {
public static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
directionMap.put(direction, true);
}
});
actMap.put(direction.toString() + "released", new AbstractAction() {
public static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
directionMap.put(direction, false);
}
});
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (bkgrndImage != null) {
g.drawImage(bkgrndImage, 0, 0, null);
}
if (playerImage != null) {
g.drawImage(playerImage, playerX, playerY, null);
}
}
public class TimerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
boolean moved = false;
for (Direction direction : Direction.values()) {
if (directionMap.get(direction)) {
playerX += STEP * direction.getXDirection();
playerY += STEP * direction.getYDirection();
moved = true;
}
}
if (moved) {
int x = playerX - 2 * STEP;
int y = playerY - 2 * STEP;
int w = playerImage.getWidth() + 4 * STEP;
int h = playerImage.getHeight() + 4 * STEP;
Move.this.repaint(x, y, w, h); // !! repaint just the player
}
s = playerX+", "+playerY;
jlbl1.setText(s);
}
}
public static void createAndShowUI() {
JFrame frame = new JFrame("MoveIcon");
frame.getContentPane().add(new Move());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowUI();
}
});
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (bkgrndImage != null) {
g.drawImage(bkgrndImage, 0, 0, null);
}
if (playerImage != null) {
g.drawImage(playerImage, playerX, playerY, null);
//offsetX and offsetY are the location relative to the cube to draw the string
//also note that the y coordinate is the location where the BOTTOM of the string begins
g.drawString("Clicked at: " + playerX + "," + playerY + ".", playerX + offsetX, playerY + offsetY)
}
}
This will draw to the location of the player. I can't imagine that it requires much effort to adjust it to draw to the clicked position.
Related
Just a small program I quickly made to see if I could perform collisions with a rectangle object and a rotating rectangle object.
Problem arises when rotating rectangle object, the collision box doesn't rotate, only the image rotates.
In this code I tried to use shape object but and performed transformations to it, but was unsuccessful.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
import java.util.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.imageio.*;
import java.awt.Toolkit;
import java.awt.geom.AffineTransform;
public class test extends JFrame implements Runnable,KeyListener
{
MyDrawPanel playPanel = new MyDrawPanel();
Thread th= new Thread(this);
int w=500, h=539;
Rectangle s1;
Rectangle r1;
int x=50,y=50;
int spx=0;
int spy=0;
int b=0;
int spin=0,spin2=0;
Shape p1;
AffineTransform tx,ax;
public static void main (String [] args)
{
new test();
}
public test()
{
s1= new Rectangle(200,200,106,16);
p1= new Rectangle(200,200,106,16);
r1= new Rectangle(x,y,50,50);
this.setSize(w,h);
this.setVisible(true);
this.setResizable(true);
this.addKeyListener(this);
this.add(playPanel);
playPanel.setDoubleBuffered(true);
th.start();
}
public void keyPressed(KeyEvent e)
{
int key =e.getKeyCode();
if (key == KeyEvent.VK_DOWN)
{
spy=2;
}
if (key == KeyEvent.VK_UP)
{
spy=-2;
}
if (key == KeyEvent.VK_RIGHT)
{
spx=2;
}
if (key == KeyEvent.VK_LEFT)
{
spx=-2;
}
}
public void keyReleased(KeyEvent e)
{
spx=0;
spy=0;
}
public void keyTyped(KeyEvent e)
{}
public void coll()
{
if (r1.getBounds().intersects(p1.getBounds()))
{
b=1;
}
else{b=0;}
}
public void rot()
{
AffineTransform px= new AffineTransform();
px.rotate(Math.toRadians(spin),w/2,h/2);
p1=px.createTransformedShape(s1);
}
///DO TOP HEAD INTERSECT CHECKINGGGGGGGGGGGGGGGGG!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
public void run ()
{
while (true)
{
rot();
r1.x+=spx;
r1.y+=spy;
spin+=2;
coll();
repaint();
try
{
Thread.sleep (30);
}
catch (InterruptedException ex)
{
}
}
}
class MyDrawPanel extends JPanel {
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
if (b==1)
{
g2.setColor(Color.RED);
}
AffineTransform old= g2.getTransform();
//g2.rotate(Math.toRadians(spin),
//p1.getBounds().x+8,p1.getBounds().y+8);
g2.fillRect(p1.getBounds().x,p1.getBounds().y,106,16);
g2.setTransform(old);
g2.fillRect(r1.x,r1.y,r1.width,r1.height);
}
}
}
//15.31
/* ADD YOUR CODE HERE */
Used Bresenham's algorithm to find all pixels on a Line2D to detect collision between Rectangle and Line through class LineIterator.
Try like below said source, by increased value of spx and spy with difference value of 4 for moving the square faster:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.util.Iterator;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
public class RotateRectangleRound extends JFrame implements KeyListener {
private static final long serialVersionUID = 9085168127541601308L;
private Rectangle stableRect;
private int cw = 400, ch = 400;
private boolean collision;
private int spx = 0, spy = 0;
private double radius = 120;
private double angleX = 0, angleY = 0;
private int rotatingVal = 0;
private Line2D line;
private LineIterator iterator;
private Point currentPoint;
private Point2D tp;
private static BasicStroke spinningStroke = new BasicStroke(8);
private static BasicStroke basicStroke = new BasicStroke(1);
private MyPanel panel;
private static boolean startWorker;
private SwingWorker<Void, Void> swingWorker;
public RotateRectangleRound() {
init();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new RotateRectangleRound();
}
});
}
private void init() {
this.setTitle("Rotate Rectangle - Paused");
this.getContentPane().setLayout(new GridLayout(1, 1));
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setBounds(400, 200, 400, 400);
this.setLayout(new GridLayout(1, 1));
this.addKeyListener(this);
this.setVisible(true);
// getting the window width & height insets explicitly
cw = this.getContentPane().getWidth();
ch = this.getContentPane().getHeight();
// setting the stableRect and movableRect to between of screen except insets
stableRect = new Rectangle(20, 20, 40, 40);
angleX = 192;
angleY = 300;
this.panel = new MyPanel();
this.add(panel);
}
#Override
public void keyTyped(KeyEvent evt) {}
public void keyPressed(KeyEvent evt) {
int key = evt.getKeyCode();
if (key == KeyEvent.VK_DOWN) {
spy = 4;
moveStableRectangle();
} else if (key == KeyEvent.VK_UP) {
spy = -4;
moveStableRectangle();
} else if (key == KeyEvent.VK_RIGHT) {
spx = 4;
moveStableRectangle();
} else if (key == KeyEvent.VK_LEFT) {
spx = -4;
moveStableRectangle();
}
if (key == KeyEvent.VK_SPACE) {
startWorker = (!startWorker);
if (startWorker) {
this.setTitle("Rotate Rectangle");
collision = false;
startRotatingFromPoint();
}else {
this.setTitle("Rotate Rectangle - Paused");
}
}
}
private void moveStableRectangle() {
stableRect.x += spx;
stableRect.y += spy;
repaint();
}
public void keyReleased(KeyEvent evt) {
spx = 0;
spy = 0;
}
private void startRotatingFromPoint() {
swingWorker = new SwingWorker<Void, Void>() {
#Override
protected Void doInBackground() throws Exception {
while (startWorker) {
try {
if (rotatingVal == 360)
rotatingVal = 0;
// first getting the angle x, y value for radius 100,
// second adding the half of width & height to rotate
// between screen accordingly with that w & h value
angleX = (Math.sin(Math.toRadians((double) rotatingVal)) * radius) + (cw / 2);
angleY = (Math.cos(Math.toRadians((double) rotatingVal++)) * radius) + (ch / 2);
// calculating collision
collision();
// requesting frame repainting
repaint();
Thread.sleep(10);
} catch (InterruptedException iex) {
iex.printStackTrace();
}
}
return null;
}
};
swingWorker.execute();
}
public void collision() {
if (detectCollision()) {
collision = true;
startWorker = false;
this.setTitle("Rotate Rectangle - Hitted");
} else {
collision = false;
}
}
private boolean detectCollision() {
boolean flag = false;
if(angleX < (cw/2))
line = new Line2D.Double(angleX, angleY, cw / 2, ch / 2);
else
line = new Line2D.Double(cw / 2, ch / 2, angleX, angleY);
//creating a iterator by use of Bresenham's algorithm
iterator = new LineIterator(line);
looperFor:
for (Iterator<Point2D> it = iterator; it.hasNext();) {
//getting Point2D Object of Point Iterator
tp = it.next();
currentPoint = new Point((int) tp.getX(), (int) tp.getY());
if (stableRect.contains(currentPoint)) {
flag = true;
break looperFor;
}
}
//returning the detected collision flag true or false
return flag;
}
class MyPanel extends JPanel {
private static final long serialVersionUID = 1L;
#Override
public void paintComponent(Graphics gr) {
Graphics2D g = (Graphics2D) gr;
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g.setStroke(basicStroke);
if (collision)
g.setColor(Color.RED);
g.fillRect(stableRect.x, stableRect.y, stableRect.width, stableRect.height);
g.setStroke(spinningStroke);
g.drawLine(cw / 2, ch / 2, (int) angleX, (int) angleY);
}
}
}
Hope this would help you.
This question already has an answer here:
Implementing gravity in simple 2d game
(1 answer)
Closed 7 years ago.
I need to use a physics engine or something similar to achieve a downward parabolic jump in the game that I have. Right now, the up arrow will just cause the character to float, but I need him to jump.
Here is my code:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.EnumMap;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.*;
#SuppressWarnings("serial")
public class Level extends JPanel {
public static String chicken = "chicken.gif";
public static String chicken2 = "chicken2.gif";
private static final int PREF_W = 1440;
private static final int PREF_H = 500;
private static final int TIMER_DELAY = 20;
private static final String KEY_DOWN = "key down";
private static final String KEY_RELEASE = "key release";
public static final int TRANSLATE_SCALE = 3;
public static final String back = "back.gif";
public static final String corn = "corn.gif";
private EnumMap<Direction, Boolean> dirMap = new EnumMap<Level.Direction, Boolean>(
Direction.class);
private BufferedImage image = null;
private BufferedImage image2 = null;
private BufferedImage image3 = null;
private static int imgX = 20;
private static int imgY = 320;
private static Random rand = new Random();
private static int cImgX = rand.nextInt(1420) + 10;
private static int cImgY = 335;
private static int cornCounter = 0;
private static String Counter = Integer.toString(cornCounter);
private static final Font BG_STRING_FONT = new Font(Font.SANS_SERIF,
Font.BOLD, 32);
private int bgStringX;
public Level() {
for (Direction dir : Direction.values()) {
dirMap.put(dir, Boolean.FALSE);
}
try {
File bback = new File(back);
image2 = ImageIO.read(bback);
File ccorn = new File(corn);
image3 = ImageIO.read(ccorn);
File img = new File(chicken);
image = ImageIO.read(img);
} catch (IOException e) {
e.printStackTrace();
}
new Timer(TIMER_DELAY, new TimerListener()).start();
// here we set up our key bindings
int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
InputMap inputMap = getInputMap(condition);
ActionMap actionMap = getActionMap();
for (final Direction dir : Direction.values()) {
// for the key down key stroke
KeyStroke keyStroke = KeyStroke.getKeyStroke(dir.getKeyCode(), 0,
false);
inputMap.put(keyStroke, dir.name() + KEY_DOWN);
actionMap.put(dir.name() + KEY_DOWN, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent arg0) {
dirMap.put(dir, true);
}
});
// for the key release key stroke
keyStroke = KeyStroke.getKeyStroke(dir.getKeyCode(), 0, true);
inputMap.put(keyStroke, dir.name() + KEY_RELEASE);
actionMap.put(dir.name() + KEY_RELEASE, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent arg0) {
dirMap.put(dir, false);
}
});
}
FontMetrics fontMetrics = getFontMetrics(BG_STRING_FONT);
int w = fontMetrics.stringWidth(Counter);
bgStringX = (PREF_W - w) / 2;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
if (image != null) {
g.drawImage(image2, 0, 0, this);
validate();
g.drawImage(image3, cImgX, cImgY, this);
validate();
g.drawImage(image, imgX, imgY, this);
validate();
}
g.setFont(BG_STRING_FONT);
g.setColor(Color.BLACK);
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g.drawString(Counter, bgStringX, 190);
}
private class TimerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
for (Direction dir : Direction.values()) {
if (dirMap.get(dir)) {
imgX += dir.getX() * TRANSLATE_SCALE;
imgY += dir.getY() * TRANSLATE_SCALE;
//System.out.println(imgY);
if(imgX >= 188 && imgX <= 380) {
if(imgY <= 190 && imgY >= 199) {
imgY = 194;
}
}
if (imgX >= (cImgX - 10) && imgX <= (cImgX + 10)) {
cImgX = rand.nextInt(1420) + 10;
repaint();
validate();
cornCounter += 1;
Counter = Integer.toString(cornCounter);
//System.out.println(cornCounter);
repaint();
validate();
}
if(imgX <= -60) {
imgX = 1373;
repaint();
validate();
}
else if(imgX >= 1442) {
imgX = 1;
repaint();
validate();
}
if(imgY >= 320) {
imgY = 320;
}
else if(imgY <= 1) {
imgY = 1;
}
}
}
repaint();
};
}
enum Direction {
Up(KeyEvent.VK_UP, 0, -1),
Left(KeyEvent.VK_A, -1, 0), Right(KeyEvent.VK_D, 1, 0),
LeftA(KeyEvent.VK_LEFT, -1, 0), RightA(KeyEvent.VK_RIGHT, 1, 0),
Down(KeyEvent.VK_DOWN, 0, 1);
private int keyCode;
private int x;
private int y;
private Direction(int keyCode, int x, int y) {
this.keyCode = keyCode;
this.x = x;
this.y = y;
}
public int getKeyCode() {
return keyCode;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
private static void createAndShowGui() {
Level mainPanel = new Level();
JFrame frame = new JFrame("Cockadoodle Duty: Awakening");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowGui();
}
});
}
}
That would be an overkill if you just want to achieve a simple jumping motion.
int vy = 0; //velocity of y
//.... heres your update code:
y += vy; //y is the yposition of your image or character
vy += GRAVITY; //GRAVITY is some arbitrary positive value
//...here's your onJump method:
vy = jumpSpeed; //jumpSpeed is some arbitrary negative value
I have a specific "problem" with a game I'm creating for class.
The game is an implementation of "Break it". To move the platform at the bottom I just used a key listener. The problem is that after the first key press there is a short "lag" or "stutter" before the platform starts moving. How could I prevent this to get a smooth response? Is there another way than KeyListener? KeyBindings?
Here is the key listener implementation
private class KeyControl implements KeyListener {
private int dx = 20;
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_RIGHT) {
if(dx < 0 )
dx = -dx;
gamePanel.movePlatform(dx);
}
if(e.getKeyCode() == KeyEvent.VK_LEFT) {
if(dx > 0 )
dx = -dx;
gamePanel.movePlatform(dx);
}
if(e.getKeyCode() == KeyEvent.VK_SPACE) {
System.out.println("space");
gamePanel.play();
}
if(e.getKeyCode() == KeyEvent.VK_ESCAPE) {
gamePanel.pause();
}
}
}
and here is the method that moves the platform around
public void movePlatform(int dx) {
int nextDX = dx;
if(paused || init) {
dx = 0;
}
// make sure platform doesnt exceed right border
if(platform.getX() + platform.getWidth() + dx> size.getWidth()) {
if(nextDX < 0)
dx = nextDX;
else
dx = 0;
}
// make sure platform doesnt exceed left border
if(platform.getX() + dx <= 0) {
if(nextDX > 0)
dx = nextDX;
else
dx = 0;
}
platform.setFrame(platform.getX() + dx, platform.getY(), platform.getWidth(), platform.getHeight());
platformIntervalX = new Interval((int)platform.getX(), (int)(platform.getX() + platform.getWidth()));
platformIntervalY = new Interval((int)(platform.getY() - platform.getHeight()), (int)platform.getY());
repaint();
}
The solution is not to use the KeyListener's key press for moving your sprite. The key is not to rely on the hardware-specific key press frequency, to use a Swing Timer to create your own frequency. Instead use Key Bindings and a Swing Timer. Start the time on key press and stop it on key release.
For example, run this code and press and release the up-arrow key:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class KeyBindingEg extends JPanel {
private static final String UP_KEY_PRESSED = "up key pressed";
private static final String UP_KEY_RELEASED = "up key released";
private static final int UP_TIMER_DELAY = 50;
private static final Color FLASH_COLOR = Color.red;
private Timer upTimer;
private JLabel label = new JLabel();
public KeyBindingEg() {
label.setFont(label.getFont().deriveFont(Font.BOLD, 32));
label.setOpaque(true);
add(label);
setPreferredSize(new Dimension(400, 300));
int condition = WHEN_IN_FOCUSED_WINDOW;
InputMap inputMap = getInputMap(condition);
ActionMap actionMap = getActionMap();
KeyStroke upKeyPressed = KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false);
KeyStroke upKeyReleased = KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true);
inputMap.put(upKeyPressed, UP_KEY_PRESSED);
inputMap.put(upKeyReleased, UP_KEY_RELEASED);
actionMap.put(UP_KEY_PRESSED, new UpAction(false));
actionMap.put(UP_KEY_RELEASED, new UpAction(true));
}
private class UpAction extends AbstractAction {
private boolean onKeyRelease;
public UpAction(boolean onKeyRelease) {
this.onKeyRelease = onKeyRelease;
}
#Override
public void actionPerformed(ActionEvent evt) {
if (!onKeyRelease) {
if (upTimer != null && upTimer.isRunning()) {
return;
}
System.out.println("key pressed");
label.setText(UP_KEY_PRESSED);
upTimer = new Timer(UP_TIMER_DELAY, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Color c = label.getBackground();
if (FLASH_COLOR.equals(c)) {
label.setBackground(null);
label.setForeground(Color.black);
} else {
label.setBackground(FLASH_COLOR);
label.setForeground(Color.white);
}
}
});
upTimer.start();
} else {
System.out.println("Key released");
if (upTimer != null && upTimer.isRunning()) {
upTimer.stop();
upTimer = null;
}
label.setText("");
}
}
}
private static void createAndShowGui() {
KeyBindingEg mainPanel = new KeyBindingEg();
JFrame frame = new JFrame("KeyBindingEg");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Edit
Or a better example, one that moves a sprite in any direction based on a key press of one of the arrow keys. No delay encountered:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.util.EnumMap;
import java.util.Map;
import javax.swing.*;
#SuppressWarnings("serial")
public class KeyBindingEg2 extends JPanel {
enum Dir {
LEFT("Left", KeyEvent.VK_LEFT, -1, 0),
RIGHT("Right", KeyEvent.VK_RIGHT, 1, 0),
UP("Up", KeyEvent.VK_UP, 0, -1),
DOWN("Down", KeyEvent.VK_DOWN, 0, 1);
private String name;
private int keyCode;
private int deltaX;
private int deltaY;
private Dir(String name, int keyCode, int deltaX, int deltaY) {
this.name = name;
this.keyCode = keyCode;
this.deltaX = deltaX;
this.deltaY = deltaY;
}
public String getName() {
return name;
}
public int getKeyCode() {
return keyCode;
}
public int getDeltaX() {
return deltaX;
}
public int getDeltaY() {
return deltaY;
}
}
public static final int TIMER_DELAY = 10;
public static final int DELTA_X = 2;
public static final int DELTA_Y = DELTA_X;
public static final int SPRITE_WIDTH = 10;
public static final int SPRITE_HEIGHT = SPRITE_WIDTH;
private static final String PRESSED = "pressed";
private static final String RELEASED = "released";
private static final int PREF_W = 800;
private static final int PREF_H = 650;
private Map<Dir, Boolean> dirMap = new EnumMap<>(Dir.class);
private int spriteX = 0;
private int spriteY = 0;
private BufferedImage sprite;
private Timer animationTimer = new Timer(TIMER_DELAY, new AnimationListener());
public KeyBindingEg2() {
for (Dir dir : Dir.values()) {
dirMap.put(dir, Boolean.FALSE);
}
sprite = createSprite();
setKeyBindings();
animationTimer.start();
}
private BufferedImage createSprite() {
BufferedImage sprt = new BufferedImage(SPRITE_WIDTH, SPRITE_HEIGHT, BufferedImage.TYPE_INT_ARGB);
Graphics g = sprt.getGraphics();
g.setColor(Color.RED);
g.fillRect(0, 0, SPRITE_WIDTH, SPRITE_HEIGHT);
g.dispose();
return sprt;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (sprite != null) {
g.drawImage(sprite, spriteX, spriteY, this);
}
}
private void setKeyBindings() {
int condition = WHEN_IN_FOCUSED_WINDOW;
InputMap inputMap = getInputMap(condition);
ActionMap actionMap = getActionMap();
for (Dir dir : Dir.values()) {
KeyStroke keyPressed = KeyStroke.getKeyStroke(dir.getKeyCode(), 0, false);
KeyStroke keyReleased = KeyStroke.getKeyStroke(dir.getKeyCode(), 0, true);
inputMap.put(keyPressed, dir.toString() + PRESSED);
inputMap.put(keyReleased, dir.toString() + RELEASED);
actionMap.put(dir.toString() + PRESSED, new DirAction(dir, PRESSED));
actionMap.put(dir.toString() + RELEASED, new DirAction(dir, RELEASED));
}
}
private class AnimationListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
int newX = spriteX;
int newY = spriteY;
for (Dir dir : Dir.values()) {
if (dirMap.get(dir)) {
newX += dir.getDeltaX() * DELTA_X;
newY += dir.getDeltaY() * DELTA_Y;
}
}
if (newX < 0 || newY < 0) {
return;
}
if (newX + SPRITE_WIDTH > getWidth() || newY + SPRITE_HEIGHT > getHeight()) {
return;
}
spriteX = newX;
spriteY = newY;
repaint();
}
}
private class DirAction extends AbstractAction {
private String pressedOrReleased;
private Dir dir;
public DirAction(Dir dir, String pressedOrReleased) {
this.dir = dir;
this.pressedOrReleased = pressedOrReleased;
}
#Override
public void actionPerformed(ActionEvent evt) {
if (pressedOrReleased.equals(PRESSED)) {
dirMap.put(dir, Boolean.TRUE);
} else if (pressedOrReleased.equals(RELEASED)) {
dirMap.put(dir, Boolean.FALSE);
}
}
}
private static void createAndShowGui() {
KeyBindingEg2 mainPanel = new KeyBindingEg2();
JFrame frame = new JFrame("KeyBindingEg");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
In the following code i'm using a doubleBuffer to avoid flickering of the image as was suggested in this question of mine
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class TestProgram extends JFrame implements KeyListener {
private Image doubleBuffer;
private Graphics myGraphics;
private BufferedImage TestImage;
private int cordX = 100;
private int cordY = 100;
public TestProgram() {
setTitle("Testing....");
setSize(500,500);
imageLoader();
setVisible(true);
}
public static void main(String[] args) {
new TestProgram();
}
public void imageLoader() {
try {
String testPath = "test.png";
TestImage = ImageIO.read(getClass().getResourceAsStream(testPath));
} catch (IOException ex) {
ex.printStackTrace();
}
addKeyListener(this);
doubleBuffer = createImage(getWidth(), getHeight());
myGraphics = doubleBuffer.getGraphics();
drawImages();
}
#Override
public void update(Graphics g) {
drawImages();
g.drawImage(doubleBuffer, 0, 0, this);
}
public void drawImages() {
myGraphics.drawImage(TestImage, cordX, cordY, this);
}
public void keyPressed(KeyEvent ke) {
switch (ke.getKeyCode()) {
case KeyEvent.VK_RIGHT: {
cordX+=5;
}
break;
case KeyEvent.VK_LEFT: {
cordX-=5;
}
break;
case KeyEvent.VK_DOWN: {
cordY+=5;
}
break;
case KeyEvent.VK_UP: {
cordY-=3;
}
break;
}
repaint();
}
public void keyTyped(KeyEvent ke) {}
public void keyReleased(KeyEvent ke) {}
}
The problem is that im getting a nullPointerException at this line
myGraphics = doubleBuffer.getGraphics();
is my approach correct in doing this?
Please help.
thanks
don't paint to JFrame directly, put there JPanel or JComponent
Swing GUI should be starting from Initial Thread
whats TestImage and path to the Image???,
KeyListener isn't designated for Swing JComponents, use KeyBindings instead
after coordinates changed you have to call repaint()
put that altogether
.
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.*;
import java.util.HashMap;
import java.util.Map;
import javax.imageio.ImageIO;
import javax.swing.*;
public class MoveIcon extends JPanel {
private static final long serialVersionUID = 1L;
private static final String IMAGE_PATH = "http://duke.kenai.com/misc/Bullfight.jpg";
private static final String IMAGE_PATH_PLAYER = "http://duke.kenai.com/iconSized/duke4.gif";
public static final int STEP = 3;
private static final int TIMER_DELAY = STEP * 8;
private BufferedImage bkgrndImage = null;
private BufferedImage playerImage = null;
private Map<Direction, Boolean> directionMap = new HashMap<Direction, Boolean>();
private int playerX = 0;
private int playerY = 0;
enum Direction {
UP(KeyEvent.VK_UP, 0, -1), DOWN(KeyEvent.VK_DOWN, 0, 1),
LEFT(KeyEvent.VK_LEFT, -1, 0), RIGHT(KeyEvent.VK_RIGHT, 1, 0);
private int keyCode;
private int xDirection;
private int yDirection;
private Direction(int keyCode, int xDirection, int yDirection) {
this.keyCode = keyCode;
this.xDirection = xDirection;
this.yDirection = yDirection;
}
public int getKeyCode() {
return keyCode;
}
public int getXDirection() {
return xDirection;
}
public int getYDirection() {
return yDirection;
}
}
public MoveIcon() {
try {
URL bkgrdImageURL = new URL(IMAGE_PATH);
URL playerImageURL = new URL(IMAGE_PATH_PLAYER);
bkgrndImage = ImageIO.read(bkgrdImageURL);
playerImage = ImageIO.read(playerImageURL);
setPreferredSize(new Dimension(bkgrndImage.getWidth(), bkgrndImage.getHeight()));
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
for (Direction direction : Direction.values()) {
directionMap.put(direction, false);
}
setKeyBindings();
Timer timer = new Timer(TIMER_DELAY, new TimerListener());
timer.start();
}
private void setKeyBindings() {
InputMap inMap = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
ActionMap actMap = getActionMap();
for (final Direction direction : Direction.values()) {
KeyStroke pressed = KeyStroke.getKeyStroke(direction.getKeyCode(), 0, false);
KeyStroke released = KeyStroke.getKeyStroke(direction.getKeyCode(), 0, true);
inMap.put(pressed, direction.toString() + "pressed");
inMap.put(released, direction.toString() + "released");
actMap.put(direction.toString() + "pressed", new AbstractAction() {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
directionMap.put(direction, true);
}
});
actMap.put(direction.toString() + "released", new AbstractAction() {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
directionMap.put(direction, false);
}
});
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (bkgrndImage != null) {
g.drawImage(bkgrndImage, 0, 0, null);
}
if (playerImage != null) {
g.drawImage(playerImage, playerX, playerY, null);
}
}
private class TimerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
boolean moved = false;
for (Direction direction : Direction.values()) {
if (directionMap.get(direction)) {
playerX += STEP * direction.getXDirection();
playerY += STEP * direction.getYDirection();
moved = true;
}
}
if (moved) {
int x = playerX - 2 * STEP;
int y = playerY - 2 * STEP;
int w = playerImage.getWidth() + 4 * STEP;
int h = playerImage.getHeight() + 4 * STEP;
MoveIcon.this.repaint(x, y, w, h); // !! repaint just the player
}
}
}
private static void createAndShowUI() {
JFrame frame = new JFrame("MoveIcon");
frame.getContentPane().add(new MoveIcon());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowUI();
}
});
}
}
I have animation that is an image moving from right to left, which is one cycle. I would like to know how to do if i have to start several cycle, if i want to have several images moving right to left one after the other. At the moment i compute one cycle and update a x value my component and the image is drawn at 0 + this x value. If i have to handle several cycles how can i keep track of each of this x values for each of the image i have to draw ?
Thank you.
for Example (by Darryl)
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class AnimationBackground {
public AnimationBackground() {
Random random = new Random();
JFrame frame = new JFrame("Animation Background");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
final MyJPanel panel = new MyJPanel();
panel.setBackground(Color.BLACK);
for (int i = 0; i < 50; i++) {
Star star = new Star(new Point(random.nextInt(490), random.nextInt(490)));
star.setColor(new Color(100 + random.nextInt(155), 100 + random.nextInt(155), 100 + random.nextInt(155)));
star.setxIncr(-3 + random.nextInt(7));
star.setyIncr(-3 + random.nextInt(7));
panel.add(star);
}
panel.setLayout(new GridLayout(10, 1));
JLabel label = new JLabel("This is a Starry background.", JLabel.CENTER);
label.setForeground(Color.WHITE);
panel.add(label);
JPanel stopPanel = new JPanel();
stopPanel.setOpaque(false);
stopPanel.add(new JButton(new AbstractAction("Stop this madness!!") {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
panel.stopAnimation();
}
}));
panel.add(stopPanel);
JPanel startPanel = new JPanel();
startPanel.setOpaque(false);
startPanel.add(new JButton(new AbstractAction("Start moving...") {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
panel.startAnimation();
}
}));
panel.add(startPanel);
frame.add(panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
AnimationBackground animationBackground = new AnimationBackground();
}
});
}
class Star extends Polygon {
private static final long serialVersionUID = 1L;
private Point location = null;
private Color color = Color.YELLOW;
private int xIncr, yIncr;
static final int WIDTH = 500, HEIGHT = 500;
Star(Point location) {
int x = location.x;
int y = location.y;
this.location = location;
this.addPoint(x, y + 8);
this.addPoint(x + 8, y + 8);
this.addPoint(x + 11, y);
this.addPoint(x + 14, y + 8);
this.addPoint(x + 22, y + 8);
this.addPoint(x + 17, y + 12);
this.addPoint(x + 21, y + 20);
this.addPoint(x + 11, y + 14);
this.addPoint(x + 3, y + 20);
this.addPoint(x + 6, y + 12);
}
public void setColor(Color color) {
this.color = color;
}
public void move() {
if (location.x < 0 || location.x > WIDTH) {
xIncr = -xIncr;
}
if (location.y < 0 || location.y > WIDTH) {
yIncr = -yIncr;
}
translate(xIncr, yIncr);
location.setLocation(location.x + xIncr, location.y + yIncr);
}
public void setxIncr(int xIncr) {
this.xIncr = xIncr;
}
public void setyIncr(int yIncr) {
this.yIncr = yIncr;
}
public Color getColor() {
return color;
}
}
class MyJPanel extends JPanel {
private static final long serialVersionUID = 1L;
private ArrayList<Star> stars = new ArrayList<Star>();
private Timer timer = new Timer(20, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (Star star : stars) {
star.move();
}
repaint();
}
});
public void stopAnimation() {
if (timer.isRunning()) {
timer.stop();
}
}
public void startAnimation() {
if (!timer.isRunning()) {
timer.start();
}
}
#Override
public void addNotify() {
super.addNotify();
timer.start();
}
#Override
public void removeNotify() {
super.removeNotify();
timer.stop();
}
MyJPanel() {
this.setPreferredSize(new Dimension(512, 512));
}
public void add(Star star) {
stars.add(star);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
for (Star star : stars) {
g.setColor(star.getColor());
g.fillPolygon(star);
}
}
}}