Hey so I'm fairly new to java, but based on doing a lot of research and analyzing various code, I came up with some code to move a basic circle on a screen by using arrow keys.
However, for some reason, the code does not run the whole key event. If I press any key on the keyboard, even different arrow keys, it will cause the circle to only move one direction.
Based on my code, I feel like everything should work, but it just won't run the KeyEvent function properly. Any ways to fix it?
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
public class second extends JPanel implements ActionListener, KeyListener
{
Timer t = new Timer(5, this);
int x = 0, y = 0, velx = 0, vely = 0;
public second()
{
t.start();
addKeyListener(this);
setFocusable(true);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.fill(new Ellipse2D.Double(x, y, 40, 40));
}
public void actionPerformed(ActionEvent e)
{
x += velx;
y += vely;
repaint();
}
public void up()
{
velx = 0;
vely = 2;
}
public void down()
{
velx = 0;
vely = -2;
}
public void left()
{
velx = -2;
vely = 0;
}
public void right()
{
velx = 2;
vely = 0;
}
public void keyPressed(KeyEvent e)
{
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_UP);
{
up();
}
if (keyCode == KeyEvent.VK_DOWN);
{
down();
}
if (keyCode == KeyEvent.VK_LEFT);
{
left();
}
if (keyCode == KeyEvent.VK_RIGHT);
{
right();
}
}
public void keyTyped(KeyEvent e)
{
}
public void keyReleased(KeyEvent e)
{
velx = 0;
vely = 0;
}
public static void main(String args[])
{
second s = new second();
f.add(s);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(800, 600);
}
}
First of all, ActionListener is not required in this case. KeyListener is sufficient. Also there is a semicolon beside if statements, this is causing all the functions up, down, left and right to be invoked negating the effect.
Also for up, y should be reduced and for down, y should be increased.
Please find the below code which works fine. You can limit the right and down movement with MAX_LIMIT based on the window size. I limited it for 0,0 for left and up movement.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
public class Second extends JPanel implements KeyListener
{
int x = 0, y = 0;
public Second()
{
addKeyListener(this);
setFocusable(true);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.fill(new Ellipse2D.Double(x, y, 40, 40));
}
public void up()
{
if(y >= 5) {
y -= 5;
repaint();
}
}
public void down()
{
y += 5;
repaint();
}
public void left()
{
if(x >= 5) {
x -= 5;
repaint();
}
}
public void right()
{
x += 5;
repaint();
}
public void keyPressed(KeyEvent e)
{
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_UP)
{
up();
}
if (keyCode == KeyEvent.VK_DOWN)
{
down();
}
if (keyCode == KeyEvent.VK_LEFT)
{
left();
}
if (keyCode == KeyEvent.VK_RIGHT)
{
right();
}
}
public void keyTyped(KeyEvent e)
{
}
public void keyReleased(KeyEvent e)
{
}
public static void main(String args[])
{
Second s = new Second();
JFrame f = new JFrame();
f.add(s);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(800, 600);
}
}
First, you have a semi-colon following your first if statement in keyPressed(), which impeaches considering following instructions. cf :
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_UP)
up();
if (keyCode == KeyEvent.VK_DOWN)
down();
if (keyCode == KeyEvent.VK_LEFT)
left();
if (keyCode == KeyEvent.VK_RIGHT)
right();
}
You also have a negative value for vely in down() where it should be positive (and vice-versa). And since you already reset velx and vely to 0 on keyReleased(), it is unnecessary to do it in your directions functions.
public void up() {
vely = -2;
}
public void down() {
vely = 2;
}
Class names should be CamelCase (not lowercase as presented).
Have fun.
Related
This is my code, I have a key listener however it does do what it is supposed to do when the key is pressed. The shape moves as it should in the ActionListener however when I press one of the keys it does nothing.
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.Ellipse2D;
import javax.swing.*;
public class Snake extends JPanel implements ActionListener {
Timer t = new Timer(5, this);
double x = 0 , y = 0, xVel = 2, yVel = 2;
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
Ellipse2D circle = new Ellipse2D.Double(x, y, 40, 40);
g2.fill(circle);
t.start();
}
public void actionPerformed(ActionEvent e){
if(x < 0 || x >460)
{
xVel = -xVel;
}
if(y < 0 || y > 459)
{
yVel = -yVel;
}
x += xVel;
y += yVel;
repaint();
}
public void keyPressed(KeyEvent e) //This part of the Code Doesnt seem to be running
{
int key = e.getKeyCode();
if( key == KeyEvent.VK_DOWN)
{
yVel = yVel; //There may be something wrong with the way i wrote this
xVel = 0;
}
if(key == KeyEvent.VK_UP)
{
yVel = -yVel;
xVel = 0;
}
if(key == KeyEvent.VK_RIGHT)
{
xVel = xVel;
yVel = 0;
}
if(key == KeyEvent.VK_LEFT)
{
xVel = -xVel;
yVel =0;
}
x+= xVel;
y+= yVel;
repaint();
}
}
It appears as though you haven't implemented the KeyListener interface. You're going to want to add that to your implements ActionListener, KeyListener and then register the the class for the KeyListener as well as implement the methods provided by the KeyListener interface.
For more information on KeyListener look at this link
I'm currently working on a similar project, how I do it:
1) Implement KeyListener (can't recall if that is the exact name*)
2) addKeylistener(this)
3) Write the method which you have already done.
*Might be KeyboardListener
You need to .addKeyListener to your frame. So where ever you created your frame you need to add this:
JFrame frame = new JFrame();
frame.addKeyListener(new KeyListener() {
#Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if( key == KeyEvent.VK_DOWN)
{
yVel = 2;
xVel = 0;
}
if(key == KeyEvent.VK_UP)
{
yVel = -2;
xVel = 0;
}
if(key == KeyEvent.VK_RIGHT)
{
xVel = 2;
yVel = 0;
}
if(key == KeyEvent.VK_LEFT)
{
xVel = -2;
yVel =0;
}
x+= xVel;
y+= yVel;
}
#Override
public void keyReleased(KeyEvent arg0) {
}
#Override
public void keyTyped(KeyEvent arg0) {
}
});
Snake snake = new Snake();
frame.add(snake);
frame.setSize(500, 500);
frame.setVisible(true);
I am making a class (called Play), that extends JFrame, and implements ActionListener and KeyListener. This class does not hold the main() method, because there is a different class for that.
I am getting an error which states, "Class Play must either be declared abstract, or implement abstract method keyReleased(KeyEvent) in KeyListener".
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.Ellipse2D;
public class Play extends JFrame implements ActionListener, KeyListener {
Timer timer = new Timer(5, this);
double x = 0, y = 0, velx = 0, vely = 0;
public Play() {
timer.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
g2.fill(new Ellipse2D.Double(x, y, 40, 40));
}
public void actionPreformed(ActionEvent e) {
repaint();
x += velx;
y += vely;
}
public void up() {
vely = -1.5;
velx = 0;
}
public void down() {
vely = 1.5;
velx = 0;
}
public void left() {
vely = 0;
velx = -1.5;
}
public void right() {
vely = 0;
velx = 1.5;
}
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if (code == KeyEvent.VK_UP) {
up();
}
if (code == KeyEvent.VK_DOWN) {
down();
}
if (code == KeyEvent.VK_LEFT) {
left();
}
if (code == KeyEvent.VK_RIGHT) {
right();
}
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}
}
Well, do what it says. Since you're inheriting the KeyListener interface, you have to implement all of the interface's methods, including 'keyReleased'
The KeyListener must have all of it's methods implemented.
Simply add this method to the class and it should work
#Override
public void keyReleased(KeyEvent e) {
}
You must also Override all of the KeyListener implemented methods
I tried this code in BlueJ which should create a rectangle and move it around but it does not function. Then I put the same exact code into Eclipse and it functions as I thought it would. Any ideas to why this works in Eclipse but not in BlueJ?
import javax.swing.*;
import java.awt.*;
public class Shapes
{
public static void main(String[] args)
{
JFrame frame = new JFrame("Test");
Draw object = new Draw();
frame.add(object);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400,400);
frame.setVisible(true);
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Draw extends JPanel implements ActionListener, KeyListener
{
Timer tm = new Timer(5,this);
int x = 0, y = 0, velX = 0, velY = 0;
public Draw()
{
tm.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.BLUE);
g.fillRect(x,y,100,20);
}
public void actionPerformed(ActionEvent e)
{
x += velX;
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;
}
}
I can see what you mean I believe it attaches it to that corner of the screen because when I resize the screen it moves with that corner. I think its not that BlueJ can't Run it properly i believe it can but it does it differently than what eclipse does.
I believe this question asks the same thing and it gets pretty good answers you should look at it first.
package testapplication;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
public class TestApplication extends JFrame implements Runnable {
int sizex = 800;
int sizey = 650;
int x, y, xDirection, yDirection;
private Image dbImage;
private Graphics dbg;
Image character;
#Override
public void run(){
try{
while(true){
move();
Thread.sleep(5);
}
}
catch(Exception e){
System.out.println("ERROR!!!");
}
}
public void move(){
x += xDirection;
y += yDirection;
if(x <= 0)
x = 0;
if(x >= 778)
x = 778;
if(y <= 22)
y = 22;
if(y >= 628)
y = 628;
}
public void setXDirection(int xdir){
xDirection = xdir;
}
public void setYDirection(int ydir){
yDirection = ydir;
}
Font font = new Font("Arial", Font.BOLD, 30);
public class AL extends KeyAdapter {
#Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
//Key press inputs "WASD"
if(keyCode == KeyEvent.VK_W) {
setYDirection(-1);
}
if(keyCode == KeyEvent.VK_A) {
setXDirection(-1);
}
if(keyCode == KeyEvent.VK_S) {
setYDirection(+1);
}
if(keyCode == KeyEvent.VK_D) {
setXDirection(+1);
}
//end Key press inputs "WASD"
}
#Override
public void keyReleased(KeyEvent e) {
int keyCode = e.getKeyCode();
//Key release inputs "WASD"
if(keyCode == KeyEvent.VK_W) {
setYDirection(0);
}
if(keyCode == KeyEvent.VK_A) {
setXDirection(0);
}
if(keyCode == KeyEvent.VK_S) {
setYDirection(0);
}
if(keyCode == KeyEvent.VK_D) {
setXDirection(0);
}
//end Key release inputs "WASD"
}
}
public TestApplication() {
//Load images
ImageIcon i = new ImageIcon("C:/Users/Min/Documents/NetBeansProjects/TestApplication/src/testapplication/Untitled-1.png") {};
character = i.getImage();
//Game properties
addKeyListener(new AL());
setTitle("TestApplication");
setSize(sizex, sizey);
setResizable(false);
setVisible(true);
setBackground(Color.LIGHT_GRAY);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
x = 30;
y = 628;
}
#Override
public void paint(Graphics g) {
dbImage = createImage(getWidth(), getHeight());
dbg = dbImage.getGraphics();
paintComponent(dbg);
g.drawImage(dbImage, 0, 0, this);
}
public void paintComponent(Graphics g) {
g.setFont(font);
g.setColor(Color.RED);
g.drawString("Welcome to TESTTEST", 300,125);
g.setColor(Color.RED);
g.drawImage(character, x, y, this);
repaint();
}
public static void main(String[] args) {
TestApplication ta = new TestApplication();
//Threads
Thread t1 = new Thread();
t1.start();
}
}
In my Java code, there is supposed to be an image that moves using the WASD keys. The image shows, yet it will not move. What's wrong?
This is a simple Java code that is supposed to make an image roam around the window with WASD keys. I am not sure what I did wrong in the code, I've double checked and everything looked fine...
First of all, if you need to change the image location while the user presses one of the wsda keys then you need to add 1 and -1 to the current value of x and y ( image location). You just set 1 and -1 which will move the image just one pixel even if, for example, you press the d button multiple times over and over.
You need to change method setXDirection to this (I have added a plus before the equal sign to add xDir value to whatever xDirection is.)
public void setXDirection(int xDir)
{
xDirection += xDir
}
Make the same correction with yDirection (yDirection += yDir)
Second, you don't call your paint method. You have to call it each time your user presses a key (one of wasd ofcourse), so do it at the final line of your keyReleased method.
I hope these two correct your code but I think you need to recheck the code again with much care.
Good luck,
Iman
You forgot to add the Runnable instance to the Thread constructor.
Your main method should be:
public static void main(String[] args) {
TestApplication ta = new TestApplication();
//Threads
Thread t1 = new Thread(ta);
t1.start();
}
So I was making a game for my Computer Science class, pretty much making a modified version of the game Frogger, and I first started off by just moving a circle across the JPanel to mimic the frogs movement and I realized a very annoying lag between the interactions with the buttons. Does anyone know how to completely get rid of the lag or perhaps reduce it? Any tips or help would be much appreciated! Here is the code so far for just the circle movement and if you see any improvements that could be done, please feel free to leave your comments.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
public class second extends JPanel implements ActionListener, KeyListener
{
Timer t = new Timer (5, this);
double x = 0, y = 0, velx = 0, vely = 0;
public second()
{
t.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public void paintComponent (Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.fill(new Ellipse2D.Double(x, y, 10, 10));
}
public void actionPerformed (ActionEvent e)
{
repaint();
x += velx;
y += vely;
}
public void up()
{
vely = -5;
velx = 0;
}
public void down()
{
vely = 5;
velx = 0;
}
public void left()
{
velx = -5;
vely = 0;
}
public void right()
{
velx = 5;
vely = 0;
}
public void upEnd()
{
velx = 0;
vely = 0;
}
public void downEnd()
{
velx = 0;
vely = 0;
}
public void leftEnd()
{
velx = 0;
vely = 0;
}
public void rightEnd()
{
velx = 0;
vely = 0;
}
public void keyPressed (KeyEvent e)
{
int code = e.getKeyCode();
if (code == KeyEvent.VK_UP)
{
up();
}
if (code == KeyEvent.VK_DOWN)
{
down();
}
if (code == KeyEvent.VK_RIGHT)
{
right();
}
if (code == KeyEvent.VK_LEFT)
{
left();
}
}
public void keyTyped (KeyEvent e) {}
public void keyReleased (KeyEvent e)
{
int code = e.getKeyCode();
if (code == KeyEvent.VK_UP)
{
upEnd();
}
if (code == KeyEvent.VK_DOWN)
{
downEnd();
}
if (code == KeyEvent.VK_RIGHT)
{
rightEnd();
}
if (code == KeyEvent.VK_LEFT)
{
leftEnd();
}
}
}
And here is the Main file:
import javax.swing.JFrame;
public class Macheads
{
public static void main (String[] args)
{
JFrame f = new JFrame();
second s = new second();
f.add(s);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(800,600);
}
}
Don't use a KeyListener. Instead you should be using Key Bindings.
The keyboard has a delay for repeating events. Use a Swing Timer to schedule the animation instead of relying on key events to be generated. See Motion Using the Keyboard for more information and examples.
Try using only the keyListener without the timer and actionlistener.
public void keyPressed (KeyEvent e)
{
int code = e.getKeyCode();
if (code == KeyEvent.VK_UP)
{
up();
}
if (code == KeyEvent.VK_DOWN)
{
down();
}
if (code == KeyEvent.VK_RIGHT)
{
right();
}
if (code == KeyEvent.VK_LEFT)
{
left();
}
x += velx;
y += vely;
repaint(); //added and will repaint everytime key is pressed
}
//no need to place arguments in keyTyped and keyReleased because JPanel is repainted on keypressed...