I'm making a clock right now and currently my second hand, minute hand, and hour hand are all drawn graphically using a Line object with an (x0, y0) beginning coordinate and (x1, y1) end coordinate.
What's confusing me right now is how to make the second hand "tick" every time a second passes. That is, how can I update the (x1, y1) coordinate (since the beginning coordinate is always in the center of the clock, we don't need to update it) so that it will move clockwise 6 degrees? This is confusing to me because the direction of the unit circle (and thus the direction of radians) goes counter-clockwise.
There are a few methods. Since you probably know the radius of the clock, you can do
theta = (theta - 6)%360;
x1 = radius*cos(theta * PI/180);
y1 = radius*sin(theta * PI/180);
That example works surprisingly well...
public class TestClock {
public static void main(String[] args) {
new TestClock();
}
public TestClock() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new ClockPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
protected class ClockPane extends JPanel {
public ClockPane() {
Timer timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(false);
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected Point getPointTo(float angle) {
int x = Math.round(getWidth() / 2);
int y = Math.round(getHeight() / 2);
double rads = Math.toRadians(angle);
// This is an arbitrary amount, you will need to correct for this
// I'm working of a width of 200 pixels, so that makes the radius
// 100...
int radius = 100;
// Calculate the outter point of the line
int xPosy = Math.round((float) (x + Math.cos(rads) * radius));
int yPosy = Math.round((float) (y - Math.sin(rads) * radius));
return new Point(xPosy, yPosy);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.RED);
Calendar cal = Calendar.getInstance();
int seconds = cal.get(Calendar.SECOND);
float angle = -(360f * (seconds / 60f));
angle += 90; // Correct for 0 being out to the right instead of up
Point p = getPointTo(angle);
int x = getWidth() / 2;
int y = getHeight() / 2;
g2d.drawLine(x, y, p.x, p.y);
FontMetrics fm = g2d.getFontMetrics();
String text = Integer.toString(seconds);
g2d.drawString(text, getWidth() - fm.stringWidth(text), getHeight() - fm.getHeight() + fm.getAscent());
g2d.dispose();
}
}
}
Related
Hi I'm trying to create heart shape for my application and
I could do the hollow one and it's working good, now I need to draw it with filled method but it's created by two Arc2D.Double and two Line2D.Double so because of this just the Arc's filling and two lines not.I've tried to add these two lines in two different 'Area' and add these two areas in one but also not worked.
There is a any way to do this (filling between two lines)?Thanks advance.
My codes : Class Heart
`public class HeartShape {
private ArrayList<Shape> shapes;
public HeartShape() {
}
public ArrayList<Shape> Heart(double x, double y, double HEART_RADIUS) {
shapes = new ArrayList<>();
double r = HEART_RADIUS;
double root2 = Math.sqrt(2);
double cx = x;
double cy = y;
double dx = r / root2;
double heights = 3 * dx + r;
double top = cy - heights / 2;
double bottom = cy + heights / 2;
Shape s = new Arc2D.Double(cx - dx - r, top, 2 * r, 2 * r, 45, 180, Arc2D.OPEN);
shapes.add(s);
s = new Arc2D.Double(cx + dx - r, top, 2 * r, 2 * r, -45, 180, Arc2D.OPEN);
shapes.add(s);
s = new Line2D.Double(cx, bottom, cx - 2 * dx, bottom - 2 * dx);
shapes.add(s);
s = new Line2D.Double(cx, bottom, cx + 2 * dx, bottom - 2 * dx);
shapes.add(s);
if (shapes != null) {
return shapes;
} else {
return null;
}
}
public void drawHeart(Graphics2D g2d, boolean isFilled) {
if (isFilled == true) {
shapes.forEach((ss) -> {
g2d.fill(ss);
});
} else {
shapes.forEach((ss) -> {
g2d.draw(ss);
});
}
}`
And DrawinTest :
public class DrawinTest extends JPanel{
private int HEART_RADIUS;
private Point startpoint;
private int x, y, width, height;
private HeartShape heartShape = new HeartShape();
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
new DrawinTest();
}
public DrawinTest() {
JFrame f = new JFrame("Test Area");
f.setPreferredSize(new Dimension(600, 500));
f.setLocationRelativeTo(null);
f.setLayout(new BorderLayout(0, 1));
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.addMouseListener(new MyMouseListener());
this.addMouseMotionListener(new MyMouseListener());
this.setBackground(Color.WHITE);
f.setContentPane(this);
f.setVisible(true);
f.pack();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setStroke(new BasicStroke(3));
g2d.setColor(Color.RED);
if(heartShape != null) {
heartShape.Heart(x, y, HEART_RADIUS);
heartShape.drawHeart(g2d, false);
}
g2d.dispose();
}
class MyMouseListener implements MouseListener,MouseMotionListener {
#Override
public void mouseClicked(MouseEvent e) {}
#Override
public void mousePressed(MouseEvent e) {
startpoint = new Point(e.getPoint());
}
#Override
public void mouseReleased(MouseEvent e) {}
#Override
public void mouseEntered(MouseEvent e) {}
#Override
public void mouseExited(MouseEvent e) {}
#Override
public void mouseDragged(MouseEvent e) {
x = Math.min(startpoint.x, e.getX());
y = Math.min(startpoint.y, e.getY());
width = Math.abs(startpoint.x - e.getX());
height = Math.abs(startpoint.y - e.getY());
HEART_RADIUS = Math.min(width, height);
repaint();
}
#Override
public void mouseMoved(MouseEvent e) {}
}
}
So far its looking like this :
The Shapes API has a number of really interesting APIs, one of my favorites is Path2D
Basically, what it allows you to do is append other Shapes, making it very useful in this situation.
public class HeartShape {
private Shape shape;
public HeartShape() {
}
public Shape Heart(double x, double y, double HEART_RADIUS) {
double r = HEART_RADIUS;
double root2 = Math.sqrt(2);
double cx = x;
double cy = y;
double dx = r / root2;
double heights = 3 * dx + r;
double top = cy - heights / 2;
double bottom = cy + heights / 2;
Path2D base = new Path2D.Double();
Shape s = new Arc2D.Double(cx - dx - r, top, 2 * r, 2 * r, 45, 180, Arc2D.OPEN);
base.append(s, false);
s = new Line2D.Double(cx, bottom, cx - 2 * dx, bottom - 2 * dx);
base.append(s, true);
s = new Line2D.Double(cx, bottom, cx + 2 * dx, bottom - 2 * dx);
base.append(s, true);
s = new Arc2D.Double(cx + dx - r, top, 2 * r, 2 * r, -45, 180, Arc2D.OPEN);
base.append(s, true);
base.closePath();
shape = base;
return base;
}
public void drawHeart(Graphics2D g2d, boolean isFilled) {
System.out.println("...");
if (isFilled) {
g2d.fill(shape);
} else {
g2d.draw(shape);
}
}
}
As shown in this example, you don't need to re-create the shape when you want to change it's size, you can simply create an instance of it at a "default" size and use a AffineTransform to resize it, much easier ;)
I think that instead of using an arrayList of shapes you should use a GenericPath and append each individual shape to it with GenericPath.append(). One you're done add the pieces of the heart use GenericPath.closePath() to make it a close it up so that it can be filled. Then you should be able to use the new GenericPath object as the path to be drawn with g2d.draw
This question has probably been answered but from the ones i have found they don't seem to work, others actually not making any changes.
I'm creating a game, the game has a screen (Canvas) that is inside of the window (JFrame). In this game i would like to use a mouse, as well as allowing the user to maximize the window. The game screen stays the same size no matter what, but if the window is re-sized, so i scale the game image to the size of the window.
My problem is that i cannot find a suitable way to project the coordinates of the the mouse, as when the window is maximized, its coordinates are still being read as if the window were still normal sized, creating an offset.
I've tried:
#Override public void mouseMoved(MouseEvent e){
MOUSE_X = Math.round((float) e.getX() / (float) RenderableCanvas.oldSizeX * (float) f.getWidth());
MOUSE_Y = Math.round((float) e.getY() / (float) RenderableCanvas.oldSizeY * (float) f.getHeight());
}
Where MOUSE_X/MOUSE_Y are static variables that can be referenced anywhere in the program to get the mouse location.
and RenderableCanvas is the game window, containing an embedded canvas object, this class also keeps track of the original size of the window stated as oldSizeX and oldSizeY
and finally f.getHeight() and f.getWidth() are the current size of the frame, as f is a reference to the JFrame inside of the RenderableCanvas class.
but all that does the same as:
#Override public void mouseMoved(MouseEvent e){
MOUSE_X = e.getX();
MOUSE_Y = e.getY();
}
Thank you for any help in advance.
The basic idea is you need to be able to convert between the two coordinate systems, in this case, the "world" which is the space getting scaled and the "view" which is what the user sees (or something like that)
The basic maths is to use the default value and the current value to generate a percentage value, by which you can then multiple the target value by, for example convert from the view to the world might look like...
pointInView * (staticSize / currentSize)
So, given a point in "world" coordinates, you need to scale back to "view" coordinates...
protected Point toView(int x, int y) {
return toView(new Point(x, y));
}
protected Point toView(Point p) {
Point scaled = new Point(p);
scaled.x = Math.round(p.x * ((float) getWidth() / (float) DEFAULT_WIDTH));
scaled.y = Math.round(p.y * ((float) getHeight() / (float) DEFAULT_HEIGHT));
return scaled;
}
And given "view" coordinates, you need to scale up to the "world" coordinates...
protected Point toWorld(int x, int y) {
return toWorld(new Point(x, y));
}
protected Point toWorld(Point p) {
Point scaled = new Point(p);
scaled.x = Math.round(p.x * ((float) DEFAULT_WIDTH) / (float) getWidth());
scaled.y = Math.round(p.y * ((float) DEFAULT_HEIGHT) / (float) getHeight());
return scaled;
}
So, for example, when the mouse is moved or clicked on your "view", you could use
Point world = toWorld(e.getPoint());
to convert the mouse point into world coordinates
... please feel free to rename those to suit your own needs, but basically, view is the physical view that the user sees and is your virtual concept of that view...
The basic concept will work for Dimension and by extension, Rectangle as well...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
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 TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
protected static final int DEFAULT_WIDTH = 200;
protected static final int DEFAULT_HEIGHT = 200;
private Dimension preferredSize = new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT);
private JLabel properties;
private boolean highlighted = false;
private Rectangle hoverRect = new Rectangle(10, 10, 50, 50);
public TestPane() {
setLayout(new GridBagLayout());
properties = new JLabel("...");
add(properties);
addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
int x = e.getX();
int y = e.getY();
Point world = toWorld(e.getPoint());
highlighted = hoverRect.contains(world);
repaint();
properties.setText("<html>#" + format(e.getPoint())
+ "<br>world = " + format(world)
+ "<br>view = " + format(toView(world)));
}
});
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
preferredSize = new Dimension(DEFAULT_WIDTH * 2, DEFAULT_HEIGHT * 2);
SwingUtilities.windowForComponent(TestPane.this).pack();
}
});
}
protected String format(Point p) {
return p.x + "x" + p.y;
}
protected Point toView(int x, int y) {
return toView(new Point(x, y));
}
protected Point toView(Point p) {
Point scaled = new Point(p);
scaled.x = Math.round(p.x * ((float) getWidth() / (float) DEFAULT_WIDTH));
scaled.y = Math.round(p.y * ((float) getHeight() / (float) DEFAULT_HEIGHT));
return scaled;
}
protected Point toWorld(int x, int y) {
return toWorld(new Point(x, y));
}
protected Point toWorld(Point p) {
Point scaled = new Point(p);
scaled.x = Math.round(p.x * ((float) DEFAULT_WIDTH) / (float) getWidth());
scaled.y = Math.round(p.y * ((float) DEFAULT_HEIGHT) / (float) getHeight());
return scaled;
}
protected Rectangle toWorld(Rectangle bounds) {
return toWorld(bounds.x, bounds.y, bounds.width, bounds.height);
}
protected Rectangle toWorld(int x, int y, int width, int height) {
Rectangle scaled = new Rectangle();
scaled.setLocation(toWorld(x, y));
scaled.width = Math.round(width * ((float) DEFAULT_WIDTH / (float) getWidth()));
scaled.height = Math.round(height * ((float) DEFAULT_HEIGHT / (float) getHeight()));
return scaled;
}
protected Rectangle toView(Rectangle bounds) {
return toView(bounds.x, bounds.y, bounds.width, bounds.height);
}
protected Rectangle toView(int x, int y, int width, int height) {
Rectangle scaled = new Rectangle();
scaled.setLocation(toView(x, y));
scaled.width = Math.round(width * ((float) getWidth() / (float) DEFAULT_WIDTH));
scaled.height = Math.round(height * ((float) getHeight() / (float) DEFAULT_HEIGHT));
return scaled;
}
#Override
public Dimension getPreferredSize() {
return preferredSize;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
Rectangle bounds = toView(hoverRect);
if (highlighted) {
g2d.setColor(Color.BLUE);
g2d.fill(bounds);
}
g2d.setColor(Color.BLACK);
g2d.draw(bounds);
}
}
}
So i think I've got it, i did some old Pen and Paper math and realized that i had part of my equation flipped from what i thought i should have.
This seems to work:
#Override public void mouseMoved(MouseEvent e){
MOUSE_X = (int) ((float) e.getX() / (float) f.getWidth() * (float) RenderableCanvas.oldSizeX);
MOUSE_Y = (int) ((float) e.getY() / (float) f.getHeight() * (float) RenderableCanvas.oldSizeY);
}
This is a grade 12 object oriented programming project.
I have a class called Ball to construct my ball object.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
public class Ball{
private double xPos;
private double yPos;
private int direction;
public Ball(int ixPos, int iyPos, int idirection){
xPos = ixPos;
yPos = iyPos;
direction = idirection;
}
public int returnX(){
return (int)xPos;
}
public int returnY(){
return (int)yPos;
}
public int returnDirection(){
return direction;
}
public void move(){
xPos += 1*Math.cos(Math.toRadians(direction));
yPos -= 1*Math.sin(Math.toRadians(direction));
}
public void collide(int collideWith){
if(collideWith==1){//collide with left wall
if(90<direction && direction<180){
direction = 180-direction;
}
if(180<direction && direction<270){
direction = 540-direction;
}
}
if(collideWith==2){//collide with right wall
if(0<direction && direction<90){
direction = 180-direction;
}
if(270<direction && direction<360){
direction = 540-direction;
}
}
if(collideWith==3){//collide with up wall
if(0<direction && direction<90){
direction = 360-direction;
}
if(90<direction && direction<180){
direction = 360-direction;
}
}
if(collideWith==4){//collide with down wall
direction = 360-direction;
}
}
public void collidePaddle(int collidePos){
if(collidePos!=50 && collidePos!=0){
direction = (50-collidePos)*180/50;
}
}
}
As you can see in the "move" function, right now the ball is going at a very low speed. But i need the ball to go faster. If I change the 1 into something like, 5, there would be a problem. In my main class where it checks if the ball is hitting the wall or blocks to change direction, the ball would go into the wall or the blocks if the amount of pixels the ball can move each time is greater than 1.
To me it seems like there's no way to solve this problem, no idea where I would start thinking, is there a better way of checking collide or something?
Thank you.
Instead of using absolute checks in your collidePaddle check, you should allow for ranges.
For example...
public void collidePaddle(int collidePos){
if (collidePos >= 50) {
direction = (50-collidePos)*180/50;
// Correct the position of the ball to meet the minimum requirements
// of the collision...
} else if (collidePos <= 0) {
direction = (50-collidePos)*180/50;
// Correct the position of the ball to meet the minimum requirements
// of the collision...
}
}
(Sorry, I'm having fun working out your code ;))
This will allow the ball the "pass" beyond the these points within a virtual context, but if you correct the position to componsate, it should make no difference...when it's rendered...
Updated
Here's a REALLY SIMPLE example of what I'm talking about...
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);
}
}
}
My move method doesn't care if you've past the boundaries as it will reposition the ball back to sit within side those boundaries
public int move(int speed, Rectangle bounds) {
// Apply the delta
p.x += speed;
// Have we passed beyond the right side??
if (p.x + radius >= (bounds.x + bounds.width)) {
speed *= -1;
p.x = ((bounds.x + bounds.width) - radius) + speed;
// Have we past beyond the left side??
} else if (p.x <= bounds.x) {
speed *= -1;
p.x = bounds.x + speed;
}
p.y = bounds.y + (bounds.height - radius) / 2;
return speed;
}
Play around with the speed and see what you get ;)
I want to rotate a rectangle in a method but do not understand how to do it and tried as follows:
private void setBoundaryRotate(Rectangle b, int radio) {
AffineTransform transform = new AffineTransform();
transform.rotate(Math.toRadians(45), b.getX() + b.width/2, b.getY() + b.height/2);}
Thanks for all.
You need to call the transform() method on your transform object, passing in the co-ordinates of your rectangle in an array.
This is a little subjective, it all depends on what it is you want to achieve.
The following code uses an AffineTransform to rotate the rectangle, but in order to do so, I need to get a PathIterator and add it back to Path2D
public class SpinBox {
public static void main(String[] args) {
new SpinBox();
}
public SpinBox() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new SpinPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class SpinPane extends JPanel {
private Rectangle box = new Rectangle(0, 0, 100, 100);
private float angle = 0;
public SpinPane() {
Timer timer = new Timer(1000/60, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
angle += 1;
repaint();
}
});
timer.setRepeats(true);
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int width = getWidth() - 1;
int height = getHeight() - 1;
int x = (width - box.width) / 2;
int y = (height - box.height) / 2;
Graphics2D g2d = (Graphics2D) g.create();
AffineTransform at = new AffineTransform();
at.rotate(Math.toRadians(angle), box.x + (box.width / 2), box.y + (box.height / 2));
PathIterator pi = box.getPathIterator(at);
Path2D path = new Path2D.Float();
path.append(pi, true);
g2d.translate(x, y);
g2d.draw(path);
g2d.dispose();
}
}
}
Hello I am very curious how to solve this problem: I created a pacman with the fillArc, drawArc method in Java and I have a pacman guy on my screen now that is always looking to the right no matter what direction it goes.. my question is.. is there a way to change the object by degrees or flip it horizontally in Java?
i tried to use AffineTransform but i don't get where i want with the documentation... How should I be able to achieve this using a switch statement? I tried to do the following but I get stuck at this part because I don't know how to continue.
DrawPacMan pacman = new DrawPacMan();
DrawPacMan ghost1 = new DrawPacMan();
DrawPacMan ghost2 = new DrawPacMan();
AffineTransform pac = new AffineTransform();
public void setPacManView(int waarde) {
// set the view of pacman
switch (waarde) {
case 0 :
// here one view of pacman
break;
case 1 :
// here one view of pacman
break;
case 2 :
// here one view of pacman
break;
case 3 :
// here one view of pacman
break;
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
// pacman movement
diameter = 75;
pacman.drawPacMan(g, getHorPlaats(), getVerPlaats(), diameter, Color.yellow);
// ghosts movement
int g1x;
for(g1x = 0; g1x < 10; g1x++) {
pacman.drawGhost(g, g1x, 40, diameter, Color.red);
}
pacman.drawGhost(g, 170, 70, diameter, Color.blue);
}
Try something like...
The demo is designed to allow images to be rotated through virtual angels (angles < 0 & > 360), but the basic concept is the same...
public class TestFlipImage {
protected static final String IMAGE_PATH = "/path/to/your/image";
public static void main(String[] args) {
new TestFlipImage();
}
public TestFlipImage() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
BufferedImage image = null;
try {
image = ImageIO.read(new File(IMAGE_PATH));
} catch (IOException ex) {
}
JPanel mainPane = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
mainPane.add(new ImagePane(image, 0));
mainPane.add(new ImagePane(image, 90));
mainPane.add(new ImagePane(image, 180));
frame.add(mainPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class ImagePane extends JPanel {
private BufferedImage masterImage;
private BufferedImage renderedImage;
public ImagePane(BufferedImage image, int angle) {
masterImage = image;
applyRotation(angle);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(renderedImage.getWidth(), renderedImage.getHeight());
}
#Override
public Dimension getMinimumSize() {
return getPreferredSize();
}
protected int getVirtualAngle(int angle) {
float fRotations = (float) angle / 360f;
int rotations = (int) (fRotations - (fRotations / 1000));
int virtual = angle - (rotations * 360);
if (virtual < 0) {
virtual = 360 + virtual;
}
return virtual;
}
// The code is designed to rotate an image through 90 degree
// angles, but it can handle angle's less then 0 and greater then
// 360 degrees
public void applyRotation(int angle) {
// This will only work for angles of 90 degrees...
// Normalize the angle to make sure it's only between 0-360 degrees
int virtualAngle = getVirtualAngle(angle);
Dimension size = new Dimension(masterImage.getWidth(), masterImage.getHeight());
int masterWidth = masterImage.getWidth();
int masterHeight = masterImage.getHeight();
double x = 0; //masterWidth / 2.0;
double y = 0; //masterHeight / 2.0;
switch (virtualAngle) {
case 0:
break;
case 180:
break;
case 90:
case 270:
size = new Dimension(masterImage.getHeight(), masterImage.getWidth());
x = (masterHeight - masterWidth) / 2.0;
y = (masterWidth - masterHeight) / 2.0;
break;
}
renderedImage = new BufferedImage(size.width, size.height, masterImage.getTransparency());
Graphics2D g2d = renderedImage.createGraphics();
AffineTransform at = AffineTransform.getTranslateInstance(x, y);
at.rotate(Math.toRadians(virtualAngle), masterWidth / 2.0, masterHeight / 2.0);
g2d.drawImage(masterImage, at, null);
g2d.dispose();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
int width = getWidth() - 1;
int height = getHeight() - 1;
int x = (width - renderedImage.getWidth()) / 2;
int y = (height - renderedImage.getHeight()) / 2;
g2d.drawImage(renderedImage, x, y, this);
}
}
}
Additional
You may also want to take a look at AffineTransform.rotate() - how do I xlate, rotate, and scale at the same time? wch discusses a means for flipping a image on its horizontal and vertical axis
Is it Swing/AWT? If yes, AffineTransform might be what you're looking for.
Given you only have 4 images. I would suggest creating 4 jpgs in paint/gimp/photoshop, and loading them into your program with;
BufferedImage pacUp = ImageIO.read(new File("./images/pac_up.jpg"));
BufferedImage pacDown = ImageIO.read(new File("./images/pac_down.jpg"));
//etc
And then your drawing switch would look something like (assuming a Graphics object g);
switch(direction) {
case 0: g.drawImage(pacUp, x, y, null);
case 1: g.drawImage(pacDown, x, y, null);
case 2: g.drawImage(pacLeft, x, y, null);
case 3: g.drawImage(pacRight, x, y, null);
}