So I\'ve pretty much thrown together a basic game in java by following a bunch of different tutorials - the problem is i cant manage to figure out how to get my sprite to mo
This is a basic example of spinning a sprite
What this is maintain's a virtual state which the Player
object inspects in order to determine how it should be changed accordingly. This separates the action from the result, meaning that it would be possible to substitute the action (arrow up key) with some other action, but still obtain the same result.
This example also uses the key bindings API, which doesn't suffer from the same focus related issues that KeyListener
does, but this is a pure Swing API and won't be compatiable with Canvas
, but is a nice demonstration ;)
The real magic occurs in the characters paint
method...
public void paint(Graphics2D g2d) {
Graphics2D g = (Graphics2D) g2d.create();
AffineTransform at = new AffineTransform();
at.translate(x, y);
at.rotate(Math.toRadians(angle), character.getWidth() / 2, character.getHeight() / 2);
g.transform(at);
g.drawImage(character, 0, 0, null);
}
Basically, this creates a AffineTransformation
which is then compounded to produce the result we need. That is, first it's anchor position is translated to the characters x/y position and then rotated about the characters center point. Because it's been translated, we can simply paint the character at 0x0. This much easier then try to calculate the characters rotation anchor somewhere else in virtual space - IMHO
The character is rotated by pressing either the Up or Down arrow keys. While pressed, the character will continue to rotate, this is a feature of the example for demonstration purpose.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class RotateCharater {
public static void main(String[] args) {
new RotateCharater();
}
public RotateCharater() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private DefaultState state;
private Player player;
public TestPane() {
player = new Player();
state = new DefaultState();
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "upKeyPressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), "upKeyReleased");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "downKeyPressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "downKeyReleased");
ActionMap am = getActionMap();
am.put("upKeyPressed", new UpKeyAction(state, true));
am.put("upKeyReleased", new UpKeyAction(state, false));
am.put("downKeyPressed", new DownKeyAction(state, true));
am.put("downKeyReleased", new DownKeyAction(state, false));
Timer timer = new Timer(40, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
player.update(state);
repaint();
}
});
timer.start();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
player.paint(g2d);
g2d.dispose();
}
public class UpKeyAction extends AbstractAction {
private DefaultState state;
private boolean pressed;
public UpKeyAction(DefaultState state, boolean pressed) {
this.state = state;
this.pressed = pressed;
}
@Override
public void actionPerformed(ActionEvent e) {
state.setUpKeyPressed(pressed);
}
}
public class DownKeyAction extends AbstractAction {
private DefaultState state;
private boolean pressed;
public DownKeyAction(DefaultState state, boolean pressed) {
this.state = state;
this.pressed = pressed;
}
@Override
public void actionPerformed(ActionEvent e) {
state.setDownKeyPressed(pressed);
}
}
}
public interface State {
public boolean isUpKeyPressed();
public boolean isDownKeyPressed();
}
public class DefaultState implements State {
private boolean upKeyPressed;
private boolean downKeyPressed;
public boolean isDownKeyPressed() {
return downKeyPressed;
}
public boolean isUpKeyPressed() {
return upKeyPressed;
}
public void setDownKeyPressed(boolean downKeyPressed) {
this.downKeyPressed = downKeyPressed;
upKeyPressed = false;
}
public void setUpKeyPressed(boolean upKeyPressed) {
this.upKeyPressed = upKeyPressed;
downKeyPressed = false;
}
}
public class Player {
private BufferedImage character;
private int x = 100 - 32, y = 100 - 32;
private double angle;
public Player() {
try {
character = ImageIO.read(getClass().getResource("/Character.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
public void paint(Graphics2D g2d) {
Graphics2D g = (Graphics2D) g2d.create();
AffineTransform at = new AffineTransform();
at.translate(x, y);
at.rotate(Math.toRadians(angle), character.getWidth() / 2, character.getHeight() / 2);
g.transform(at);
g.drawImage(character, 0, 0, null);
}
public void update(State state) {
if (state.isUpKeyPressed()) {
angle -= 22.5;
} else if (state.isDownKeyPressed()) {
angle += 22.5;
}
}
}
}
Remember, this is just an example used to present the concept ;)