I'm trying to get a rectangle to move using KeyListener. I have seen others use the same code but for some reason I can't get it to move. Right now the rectangle does show up. I'm not sure if I'm forgetting something if there is something I'm missing.
Here's my code:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.Graphics;
public class roomwars extends JPanel implements ActionListener, KeyListener {
//public JPanel pane;
public JFrame frame;
public JButton start, help;
public JTextField box;
int x=0, y=0, velx =0, vely =0;
Timer t = new Timer(5, this);
public void run(){
frame = new JFrame("ROOM WARS!");
frame.setSize(700, 700);
frame.setVisible(true);
frame.add(this);
}
public void second (){
t.start();
addKeyListener(this);
//setFocusalbe(true);
//SETFocusTraversalKeyEnabled(false);
}
public void paintComponent(Graphics g) {
Color mypurple = new Color(34, 0, 56);
g.setColor(mypurple);
g.fillRect(x, y, 30, 30);
//g.setColor(Color.PINK);
//g.fillRect(655,632,30,30);
}
public void actionPerformed(ActionEvent e){
repaint();
x+= velx;
y+= vely;
}
public void keyPressed(KeyEvent e){
int code = e.getKeyCode();
if (code == KeyEvent.VK_UP){
vely = -1;
velx = 0;
}
else if (code == KeyEvent.VK_DOWN) {
vely = 1;
velx = 0;
}
else if (code == KeyEvent.VK_RIGHT) {
velx = -1;
vely = 0;
}
else if (code == KeyEvent.VK_LEFT) {
velx = 1;
vely = 0;
}
}
public void keyTyped(KeyEvent e){}
public void keyReleased(KeyEvent e) {}
public static void main(String[] args) {
new roomwars().run();
}
}
Apart from not honouring the paint chain (and calling super.paintComponent), you're primary issue is the use of KeyListener.
A short amount of searching will tell you quickly that KeyListener is notorious for not responding as is generally unreliable.
The most common solution is to use the key bindings API
The following is very simply example of implementing key bindings into your current code base
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.IOException;
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 Test {
public static void main(String[] args) throws IOException, InterruptedException {
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 RoomWars());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class RoomWars extends JPanel implements ActionListener {
//public JPanel pane;
int x = 0, y = 0, velx = 0, vely = 0;
Timer t = new Timer(5, this);
public RoomWars() {
t.start();
InputMap im = getInputMap(JPanel.WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "up.pressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), "up.released");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "down.pressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "down.released");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "left.pressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, true), "left.released");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "right.pressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, true), "right.released");
am.put("up.pressed", new MoveAction(-1, 0));
am.put("up.released", new MoveAction(0, 0));
am.put("down.pressed", new MoveAction(1, 0));
am.put("down.released", new MoveAction(0, 0));
am.put("left.pressed", new MoveAction(0, -1));
am.put("left.released", new MoveAction(0, 0));
am.put("right.pressed", new MoveAction(0, 1));
am.put("right.released", new MoveAction(0, 0));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Color mypurple = new Color(34, 0, 56);
g.setColor(mypurple);
g.fillRect(x, y, 30, 30);
//g.setColor(Color.PINK);
//g.fillRect(655,632,30,30);
}
public class MoveAction extends AbstractAction {
private int yDelta;
private int xDelta;
public MoveAction(int yDelta, int xDelta) {
this.yDelta = yDelta;
this.xDelta = xDelta;
}
#Override
public void actionPerformed(ActionEvent e) {
vely = yDelta;
velx = xDelta;
}
}
public void actionPerformed(ActionEvent e) {
repaint();
x += velx;
y += vely;
}
}
}
Note that in your code snippet, second() isn't called so the key listener isn't registered. Your panel also needs to be focusable in order to receive key press events. You may also want to call super.paintComponent() first in your method.
See here for details:
https://docs.oracle.com/javase/tutorial/uiswing/events/keylistener.html
Related
I am trying to get a circle to move through the input of a keyboard. I am not able to move the object at all. Can someone help me figure out what is wrong? Here is my code:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JPanel;
public class AlienInvader extends JPanel implements KeyListener{
Constants constant = new Constants();
public void update() {
constant.x += constant.xvel;
addKeyListener(this);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.MAGENTA);
g.fillOval(constant.x, constant.y, 30, 30);
repaint();
}
#Override
public void keyPressed(KeyEvent e) {
System.out.println(constant.x);
switch(e.getKeyCode()) {
case KeyEvent.VK_LEFT:
constant.xvel = -1;
break;
case KeyEvent.VK_RIGHT:
constant.xvel = 1;
break;
}
}
#Override
public void keyReleased(KeyEvent e) {
switch(e.getKeyCode()) {
case KeyEvent.VK_LEFT:
constant.xvel = -1;
break;
case KeyEvent.VK_RIGHT:
constant.xvel = 1;
break;
}
}
#Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
}
I am not sure what I am doing wrong. I thought it was because I wasn't calling the update method, but when I added a if statement in paintComponent (so it only calls itself once) and tried it, I had no luck.
To start with, don't call repaint within any paintXxx method. Paint methods are typically called in response to a call to repaint, therefore you are creating a nasty, never ending, ever consuming loop of resource hell.
Secondly, KeyListeners only respond to key events when 1- The component the are registered to are focusable 2- When the component they are registered to have focus.
They are a poor choice in this case. Use Key bindings instead
Thirdly, you are not providing a preferredSize hint for layout managers to use. This may or may not be a bad thing in your case, but it's possible that you component will be laid out with a size of 0x0
Example
Something like....
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 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 MoveCircle {
public static void main(String[] args) {
new MoveCircle();
}
public MoveCircle() {
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 int xDelta = 0;
private int keyPressCount = 0;
private Timer repaintTimer;
private int xPos = 0;
private int radius = 10;
public TestPane() {
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "pressed.left");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "pressed.right");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, true), "released.left");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, true), "released.right");
am.put("pressed.left", new MoveAction(-2, true));
am.put("pressed.right", new MoveAction(2, true));
am.put("released.left", new MoveAction(0, false));
am.put("released.right", new MoveAction(0, false));
repaintTimer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
xPos += xDelta;
if (xPos < 0) {
xPos = 0;
} else if (xPos + radius > getWidth()) {
xPos = getWidth() - radius;
}
repaint();
}
});
repaintTimer.setInitialDelay(0);
repaintTimer.setRepeats(true);
repaintTimer.setCoalesce(true);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.RED);
g2d.drawOval(xPos, 0, radius, radius);
g2d.dispose();
}
public class MoveAction extends AbstractAction {
private int direction;
private boolean keyDown;
public MoveAction(int direction, boolean down) {
this.direction = direction;
keyDown = down;
}
#Override
public void actionPerformed(ActionEvent e) {
xDelta = direction;
if (keyDown) {
if (!repaintTimer.isRunning()) {
repaintTimer.start();
}
} else {
repaintTimer.stop();
}
}
}
}
}
For example...
I have the following code to show you:
public class Test extends JPanel implements ActionListener, KeyListener
{
Timer tm = new Timer(5, this);
int x = 0, y = 0, velX = 0, velY = 0;
public Test()
{
tm.start(); //starts the timer
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public void paint(Graphics g)
{
super.paint(g);
ImageIcon s = new ImageIcon("C:\\Users\\Owner\\Pictures\\Stick.jpg");
s.paintIcon(this,g,x,y);
}
public void actionPerformed(ActionEvent e)
{
if (x < 0)
{
velX = 0;
x = 0;
}
if (x > 630)
{
velX = 0;
x = 630;
}
if(y < 0)
{
velY = 0;
y = 0;
}
if(y > 430)
{
velY = 0;
y = 430;
}
x = x + velX;
y = y + velY;
repaint();
}
public void keyPressed(KeyEvent e)
{
int c = e.getKeyCode();
if (c == KeyEvent.VK_LEFT)
{
velX = -1;
velY = 0;
}
if(c == KeyEvent.VK_UP)
{
velX = 0;
velY = -1;
}
if(c == KeyEvent.VK_RIGHT)
{
velX = 1;
velY = 0;
}
if(c == KeyEvent.VK_DOWN)
{
velX = 0;
velY = 1;
}
}
public void keyTyped(KeyEvent e){}
public void keyReleased(KeyEvent e)
{
velX = 0;
velY = 0;
}
public static void main(String[] args)
{
Test t = new Test();
JFrame jf = new JFrame();
jf.setTitle("Tutorial");
jf.setSize(700, 600);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.add(t);
jf.setVisible(true);
}
My problem is I whenever the user holds the right arrow on the keyboard it changes an image, when the user lets go it goes back the the default image. Please tell me how to do that. I think it is a series of if statements in the Graphics class then calling them to the key input but I'm not quite sure. I am also using Eclipse. Thank You.
Override paintComponent instead of paint. See Performing Custom Painting and Painting in AWT and Swing for more details
Use the key bindings API instead of KeyListener, it will cause you less issues. See How to Use Key Bindings for more details
Essentially, you could just have a Image as a class instance field, which was painted by the paintComponent method. When the key was pressed, you would change the image to the "move image" and when it was released, change it back to the "default image"
Updated with example
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.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.Action;
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;
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 interface Mover {
public enum Direction {
LEFT, RIGHT, NONE;
}
public void setDirection(Direction direction);
public Direction getDirection();
}
public class TestPane extends JPanel implements Mover {
private BufferedImage left;
private BufferedImage right;
private BufferedImage stand;
private BufferedImage current;
private Direction direction = Direction.NONE;
private int xPos;
private int yPos;
public TestPane() {
try {
left = ImageIO.read(getClass().getResource("/Left.png"));
right = ImageIO.read(getClass().getResource("/Right.png"));
stand = ImageIO.read(getClass().getResource("/Stand.png"));
current = stand;
xPos = 100 - (current.getWidth() / 2);
yPos = 100 - (current.getHeight() / 2);
} catch (IOException exp) {
exp.printStackTrace();
}
bindKeyStrokeTo(WHEN_IN_FOCUSED_WINDOW, "move.left", KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), new MoveAction(this, Direction.LEFT));
bindKeyStrokeTo(WHEN_IN_FOCUSED_WINDOW, "stop.left", KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, true), new MoveAction(this, Direction.NONE));
bindKeyStrokeTo(WHEN_IN_FOCUSED_WINDOW, "move.right", KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), new MoveAction(this, Direction.RIGHT));
bindKeyStrokeTo(WHEN_IN_FOCUSED_WINDOW, "stop.right", KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, true), new MoveAction(this, Direction.NONE));
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
updatePosition();
repaint();
}
});
timer.start();
}
protected void bindKeyStrokeTo(int condition, String name, KeyStroke keyStroke, Action action) {
InputMap im = getInputMap(condition);
ActionMap am = getActionMap();
im.put(keyStroke, name);
am.put(name, action);
}
#Override
public Direction getDirection() {
return direction;
}
#Override
public void setDirection(Direction direction) {
this.direction = direction;
}
protected void updatePosition() {
switch (getDirection()) {
case LEFT:
current = left;
xPos -= 1;
break;
case RIGHT:
current = right;
xPos += 1;
break;
case NONE:
current = stand;
break;
}
if (xPos < 0) {
xPos = 0;
current = stand;
} else if (xPos + current.getWidth() > getWidth()) {
current = stand;
xPos = getWidth() - current.getWidth();
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(current, xPos, yPos, this);
g2d.dispose();
}
}
public class MoveAction extends AbstractAction {
private Mover mover;
private Mover.Direction direction;
public MoveAction(Mover mover, Mover.Direction direction) {
this.mover = mover;
this.direction = direction;
}
#Override
public void actionPerformed(ActionEvent e) {
mover.setDirection(direction);
}
}
}
So I have seen a few threads about this already and I need some help about how to fix it specifically. When you hold down a key, Java will read the first key press, then there will be a small delay, and then it will continuously read the key press until you release the key.
public void keyPressed(KeyEvent key) {
int code = key.getKeyCode();
if (code == KeyEvent.VK_DOWN) {
//Do stuff
}
if (code == KeyEvent.VK_LEFT) {
//Do stuff
}
if (code == KeyEvent.VK_RIGHT) {
//Do stuff
}
if (code == KeyEvent.VK_UP) {
//Do stuff
}
}
That is my current code. I heard that to fix this you can create a timer which rapidly checks for key presses, but I'm not really sure how to do that. Would appreciate some help here or if there is a better solution.
The basic answer to your question is, you can't, the delay is OS specific.
The longer answer is, you should be ignoring the individual events themselves and monitor a change in state (between press and release) through the use of appropriate flags.
This means, that when a key is pressed, you set some flag which you program can use to change the state of the program and when released, you reset it.
This disassociates the event from state change and provides you with much more flexibility, as your program doesn't care what caused the state change, only that the state has changed and it should react to it.
This will require you to have some kind of "loop" whose responsibility it is, is to monitor this change and react to it accordingly. In gaming, this is commonly known as a "game-loop", but can also been known as "main-loop".
It's this "loops" responsibility to update the state of the program and get it painted.
Below is a very simple example which uses the key bindings API and a javax.swing.Timer to demonstrate the basic concepts
import com.sun.glass.events.KeyEvent;
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.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
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 MoveMe {
public static void main(String[] args) {
new MoveMe();
}
public MoveMe() {
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 MovementState {
public int xDirection;
public int yDirection;
}
public class TestPane extends JPanel {
private MovementState movementState;
private Rectangle box;
public TestPane() {
movementState = new MovementState();
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "down-pressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "down-released");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "up-pressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), "up-released");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "left-pressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, true), "left-released");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "right-pressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, true), "right-released");
am.put("down-pressed", new YDirectionAction(movementState, 2));
am.put("down-released", new YDirectionAction(movementState, 0));
am.put("up-pressed", new YDirectionAction(movementState, -2));
am.put("up-released", new YDirectionAction(movementState, 0));
am.put("left-pressed", new XDirectionAction(movementState, -2));
am.put("left-released", new XDirectionAction(movementState, 0));
am.put("right-pressed", new XDirectionAction(movementState, 2));
am.put("right-released", new XDirectionAction(movementState, 0));
box = new Rectangle(90, 90, 20, 20);
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
box.x += movementState.xDirection;
box.y += movementState.yDirection;
if (box.x < 0) {
box.x = 0;
} else if (box.x + box.width > getWidth()) {
box.x = getWidth() - box.width;
}
if (box.y < 0) {
box.y = 0;
} else if (box.y + box.height > getHeight()) {
box.y = getHeight() - box.height;
}
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();
g2d.setColor(Color.RED);
g2d.fill(box);
g2d.dispose();
}
}
public abstract class AbstractDirectionAction extends AbstractAction {
private final MovementState movementState;
private final int value;
public AbstractDirectionAction(MovementState movementState, int value) {
this.movementState = movementState;
this.value = value;
}
public MovementState getMovementState() {
return movementState;
}
public int getValue() {
return value;
}
}
public class YDirectionAction extends AbstractDirectionAction {
public YDirectionAction(MovementState movementState, int value) {
super(movementState, value);
}
#Override
public void actionPerformed(ActionEvent e) {
getMovementState().yDirection = getValue();
}
}
public class XDirectionAction extends AbstractDirectionAction {
public XDirectionAction(MovementState movementState, int value) {
super(movementState, value);
}
#Override
public void actionPerformed(ActionEvent e) {
getMovementState().xDirection = getValue();
}
}
}
I am building a small program where I want rectangles called checkpoints to disappear when the main square hots them.
The code i have used so far is:
if (antalCheckpoints == 5) {
lblGameOver.setText("Du vann!");
btnUpp.setEnabled(false); // Upp = up
btnNer.setEnabled(false); //Ner = down
btnHöger.setEnabled(false); // Höger = right
btnVänster.setEnabled(false); //Vänster = left
}
if (spelare.intersects(checkpoint1)) {
checkpoint1.resize(0, 0);
antalCheckpoints++;
repaint();
}
if (spelare.intersects(checkpoint2)) {
checkpoint1.setSize(0, 0);
antalCheckpoints++;
repaint();
}
if (spelare.intersects(checkpoint3)) {
checkpoint1.setSize(0, 0);
antalCheckpoints++;
repaint();
}
if (spelare.intersects(checkpoint4)) {
checkpoint1.resize(0,0);
antalCheckpoints++;
repaint();
}
if (spelare.intersects(checkpoint5)) {
checkpoint1.setSize(0, 0);
antalCheckpoints++;
repaint();
}
spelare is the main player square and the checkpoints are the checkpoint squares. antalCheckpoints in the amount of checkpoints found. I want the checkpoints to disappear when touched and I want the antalCheckpoints to go off when all checkpoints have been reached.
As it is now, when I touch the first checkpoint, the if(antalCheckpoints==5){ goes off and the game says it has been complete while the checkpoint is still there.
I have tried to .resize and to .setSize the squares but they still won't disappear.
Any idea what might be wrong?
Create a List of Rectangles which represent the checkpoints.
On each update, run through this List and check which ones collide, removing those from the List
When painting, simply iterate the List and paint what's still contained within
When there are no more Rectangles in the List, you win :)
Updated with an example
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
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.KeyEvent;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class CheckPointCharlie {
public static void main(String[] args) {
new CheckPointCharlie();
}
public CheckPointCharlie() {
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 CheckPointsPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class CheckPointsPane extends JPanel {
private List<Rectangle> checkpoints;
private Rectangle player;
public CheckPointsPane() {
checkpoints = new ArrayList<>(20);
int count = (int)(Math.random() * 20);
while (checkpoints.size() < count) {
int x = (int)(Math.random() * 195);
int y = (int)(Math.random() * 195);
Rectangle rect = new Rectangle(x, y, 5, 5);
boolean keep = true;
for (Rectangle check : checkpoints) {
if (check.intersects(rect)) {
keep = false;
break;
}
}
if (keep) {
checkpoints.add(rect);
}
}
player = new Rectangle(95, 95, 10, 10);
checkCollisions();
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "Up");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "Down");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "Left");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "Right");
ActionMap am = getActionMap();
am.put("Up", new MovementAction(this, player, 0, -4));
am.put("Down", new MovementAction(this, player, 0, 4));
am.put("Left", new MovementAction(this, player, -4, 0));
am.put("Right", new MovementAction(this, player, 4, 0));
}
protected void checkCollisions() {
Iterator<Rectangle> it = checkpoints.iterator();
while (it.hasNext()) {
Rectangle check = it.next();
if (player.intersects(check)) {
it.remove();
}
}
repaint();
if (checkpoints.isEmpty()) {
JOptionPane.showMessageDialog(this, "You rock!");
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.RED);
for (Rectangle rect : checkpoints) {
g2d.fill(rect);
}
g2d.setColor(Color.BLUE);
g2d.fill(player);
g2d.dispose();
}
}
public class MovementAction extends AbstractAction {
private CheckPointsPane parent;
private Rectangle player;
private int xDelta;
private int yDelta;
private MovementAction(CheckPointsPane parent, Rectangle player, int xDelta, int yDelta) {
this.parent = parent;
this.player = player;
this.xDelta = xDelta;
this.yDelta = yDelta;
}
#Override
public void actionPerformed(ActionEvent e) {
player.x += xDelta;
player.y += yDelta;
if (player.x < 0) {
player.x = 0;
} else if (player.x + player.width > parent.getWidth()) {
player.x = parent.getWidth() - player.width;
}
if (player.y < 0) {
player.y = 0;
} else if (player.y + player.height > parent.getHeight()) {
player.y = parent.getHeight() - player.height;
}
parent.checkCollisions();
}
}
}
Im newish to keylistener, but recently I made a little program which will be below, which uses keylistener to make the A,W,S,D keys move a square. Well I used dropbox to get the program on this laptop, and now it doesn't work. It seems weird to me that it works on a keyboard, but not on a laptop keyboard. Any ideas why? Here is the code, well a portion:
public class Game extends JApplet implements KeyListener
{
public boolean isMoving = false;
int test = 0;
Rect r = new Rect();
public void keyPressed(KeyEvent e){}
public void keyReleased(KeyEvent e){} // ignore
public void keyTyped(KeyEvent e)
{
char keyChar = e.getKeyChar();
if (keyChar == KeyEvent.VK_S)
{
r.yVelocity -= 1;
}
if (keyChar == KeyEvent.VK_W)
{
r.yVelocity+=1;
}
if (keyChar == KeyEvent.VK_A)
{
r.xVelocity -=1;
}
if (keyChar == KeyEvent.VK_D)
{
r.xVelocity +=1;
}
}
KeyListener has focus issues. That is, it will only respond to key events when is focusable AND has focus.
The simply solution would be to make the component which the KeyListener is registered to focusable and use requestFocusInWindow, but this makes no gurentees that the component will recieve key board focus.
A better solution would be to use the Key Bindings API which allows you to configure the focus level required for key events to be raised...
Updated with a key bindings example/test
import java.awt.BorderLayout;
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.KeyEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
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.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestKeyBindings {
public static void main(String[] args) {
new TestKeyBindings();
}
public TestKeyBindings() {
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 KeyPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class KeyPane extends JPanel {
private Triangle up;
private Triangle down;
private Triangle left;
private Triangle right;
private Set<String> activeKeys;
public KeyPane() {
activeKeys = new HashSet<>(4);
up = new Triangle(20);
down = new Triangle(20);
left = new Triangle(20);
right = new Triangle(20);
AffineTransform at = AffineTransform.getRotateInstance(Math.toRadians(-90), 10, 10);
left.transform(at);
at = AffineTransform.getRotateInstance(Math.toRadians(180), 10, 10);
down.transform(at);
at = AffineTransform.getRotateInstance(Math.toRadians(-270), 10, 10);
right.transform(at);
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "upPressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "downPressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "leftPressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "rightPressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), "upReleased");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "downReleased");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, true), "leftReleased");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, true), "rightReleased");
ActionMap am = getActionMap();
am.put("upPressed", new DirectionAction("up", true));
am.put("downPressed", new DirectionAction("down", true));
am.put("leftPressed", new DirectionAction("left", true));
am.put("rightPressed", new DirectionAction("right", true));
am.put("upReleased", new DirectionAction("up", false));
am.put("downReleased", new DirectionAction("down", false));
am.put("leftReleased", new DirectionAction("left", false));
am.put("rightReleased", new DirectionAction("right", false));
}
public void addKey(String name) {
activeKeys.add(name);
repaint();
}
public void removeKey(String name) {
activeKeys.remove(name);
repaint();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - (up.getBounds().width * 3)) / 2;
int y = (getHeight() - 10) / 2;
AffineTransform at = AffineTransform.getTranslateInstance(x, y);
if (activeKeys.contains("left")) {
g2d.fill(left.createTransformedShape(at));
} else {
g2d.draw(left.createTransformedShape(at));
}
at = AffineTransform.getTranslateInstance(x + 40, y);
if (activeKeys.contains("right")) {
g2d.fill(right.createTransformedShape(at));
} else {
g2d.draw(right.createTransformedShape(at));
}
at = AffineTransform.getTranslateInstance(x + 20, y - 20);
if (activeKeys.contains("up")) {
g2d.fill(up.createTransformedShape(at));
} else {
g2d.draw(up.createTransformedShape(at));
}
at = AffineTransform.getTranslateInstance(x + 20, y + 20);
if (activeKeys.contains("down")) {
g2d.fill(down.createTransformedShape(at));
} else {
g2d.draw(down.createTransformedShape(at));
}
g2d.dispose();
}
public class DirectionAction extends AbstractAction {
private String name;
private boolean pressed;
public DirectionAction(String name, boolean pressed) {
this.name = name;
this.pressed = pressed;
}
#Override
public void actionPerformed(ActionEvent e) {
if (pressed) {
addKey(name);
} else {
removeKey(name);
}
}
}
}
public class Triangle extends Path2D.Double {
public Triangle(int size) {
moveTo(size / 2, 0);
lineTo(size, size);
lineTo(0, size);
closePath();
}
}
}