I'm a bit of a noob at using swing and keybindings, but I wanted to try to make a simple platformer where the player (an oval in this case) could be moved with the WASD-keys. I've seen that KeyBindings is preferred for this.
The problem now is that I can't seem to get the object moving in the right direction at the first keypress.
Here is my code, including the keybindings and the actions:
class Player extends JPanel {
private int x = 100;
private int y = 100;
private int velX = 0;
private int velY = 0;
private boolean left, right, up, down = true;
public Player() {
new Timer(10, taskPerformer).start();
keyBindings();
repaint();
}
public void paint(Graphics g) {
super.paintComponent(g);
setBackground(Color.black);
g.setColor(Color.MAGENTA);
g.fillOval(x, y, 10, 5);
}
ActionListener taskPerformer = evt -> {
x = x + velX;
y = y + velY;
repaint();
};
//KEYBINDINGS
public void keyBindings() {
this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("A"), "startMoving");
this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("released A"), "stopMoving");
this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("D"), "startMoving");
this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("released D"), "stopMoving");
this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("W"), "startMoving");
this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("released W"), "stopMoving");
this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("S"), "startMoving");
this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("released S"), "stopMoving");
this.getActionMap().put("startMoving", Move);
this.getActionMap().put("stopMoving", stopMove);
}
//ACTIONS
Action Move = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand().equals("a")) {
if (left) {
left = false;
velX--;
}
} else if (e.getActionCommand().equals("d")) {
if (right) {
velX++;
right = false;
}
} else if (e.getActionCommand().equals("w")) {
if (up) {
velY--;
up = false;
}
} else if (e.getActionCommand().equals("s")) {
if (down) {
down = false;
velY++;
}
}
}
};
Action stopMove = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("a")) {
System.out.println(left);
left = true;
velX++;
} else if (e.getActionCommand().equals("d")) {
right = true;
velX--;
} else if (e.getActionCommand().equals("w")) {
up = true;
velY++;
} else if (e.getActionCommand().equals("s")) {
down = true;
velY--;
}
}
};
}
The "game" starts with an oval on the screen, but when I press a button (e.g. A), the oval doesn't move at all. Then when I release the button, the oval starts moving the other way. When I press the opposing button (so after the A, the second button press would be D) and release it, the oval stops and I can move it properly in both directions. Then the same happens for W and S, since they're using velY instead of velX is my guess.
Now I would like to know if anyone knows how to fix this, with that I mean, moving in the right direction on first keypress.
Thanks in advance!
Related
I'm working on a snake game, and I'm trying to make the snake move to the right. The issue here is the snake isn't actually moving, it just seems to copy itself to the right and also it's not going to the right automatically you have to keep pressing the key.
I am really not sure what the issue is, I made some code without any images. That should make the code run able for testing as it is.
public class Game{
static Graphics g;
public static void main(String[] args) {
JFrame b = new JFrame("Snake");
b.setBounds(300,60,905,700);
b.setBackground(Color.DARK_GRAY);
b.setResizable(false);
Snake snake = new Snake();
b.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
b.add(snake);
b.setVisible(true);
}
}
public class Snake extends JPanel implements KeyListener,ActionListener {
/**
*
*/
private static final long serialVersionUID = 1L;
private int[] snakeXlength = new int [750];
private int[] snakeYlength = new int [750];
private boolean right = true;
private boolean left = false;
private boolean up = false;
private boolean down = false;
private ImageIcon rightmouth;
private ImageIcon snakeimage;
private ImageIcon leftmouth;
private ImageIcon downmouth;
private ImageIcon upmouth;
private ImageIcon enemy;
private Timer timer;
private int snakeDelay = 100;
private int moves = 1;
private int lengtOfSnake = 3;
public Snake(){
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
timer = new Timer(snakeDelay, this);
timer.start();
}
public void paint(Graphics g) {
g.setColor(Color.WHITE);
g.drawRect (20, 24, 851, 612);
g.setColor(Color.BLACK);
g.fillRect (21, 25, 850, 610);
if (moves == 0) {
snakeXlength[2]= 63;
snakeXlength[1]= 83;
snakeXlength[0]= 100;
snakeYlength[2]= 100;
snakeYlength[1]= 100;
snakeYlength[0]= 98;
rightmouth = new ImageIcon("rightmouth.png");
rightmouth.paintIcon(this, g, snakeXlength[0], snakeYlength[0]);
}
for(int a = 0; a < lengtOfSnake; a++) {
if (a == 0 && right) {
if (a == 0 && right) {
g.setColor(Color.RED);
g.drawRect(5,10,snakeXlength[a],snakeYlength[a]);
g.fillRect (snakeXlength[a],snakeYlength[a],21,21);
g.drawRect(5,10,snakeXlength[a],snakeYlength[a]);
// rightmouth = new ImageIcon("rightmouth.png");
//rightmouth.paintIcon(this, g, snakeXlength[a], snakeYlength[a]);
}
if (a == 0 && left) {
leftmouth = new ImageIcon("leftmouth.png");
leftmouth.paintIcon(this, g, snakeXlength[a], snakeYlength[a]);
}
if (a == 0 && down) {
downmouth = new ImageIcon("downmouth.png");
downmouth.paintIcon(this, g, snakeXlength[a], snakeYlength[a]);
}
if (a == 0 && up) {
upmouth = new ImageIcon("uptmouth.png");
upmouth.paintIcon(this, g, snakeXlength[a], snakeYlength[a]);
}
if (a != 0) {
g.setColor(Color.GREEN);
g.fillOval(snakeXlength[a],snakeYlength[a],17,17);
//snakeimage = new ImageIcon("snakeimage.png");
//snakeimage.paintIcon(this, g, snakeXlength[a], snakeYlength[a]);
}
}
g.dispose();
}
public void keyPressed(KeyEvent e) {
timer.start();
if(right) {
for (int r = lengtOfSnake-1; r >= 0;r--) {
snakeYlength[r+1] = snakeYlength[r];
}
for(int r = lengtOfSnake;r >=0;r--) {
if(r==0) {
snakeXlength[r] = snakeXlength[r] +25;
}
else {
snakeXlength[r] = snakeXlength[r-1];
}
if(snakeXlength[r] > 850){
snakeXlength[r] = 25;
}
}
repaint();
}
if(left) {
}
if(up) {
}
if(down) {
}
}
#Override
public void keyTyped(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_RIGHT) {
moves++;
right = true;
if(left != true) {
right = true;
}
else
{
right = false;
left = true;
}
down = false;
up = false;
}
if(e.getKeyCode() == KeyEvent.VK_LEFT) {
moves++;
left = true;
if(right != true) {
left = true;
}
else
{
left = false;
right = true;
}
down = false;
up = false;
} if(e.getKeyCode() == KeyEvent.VK_UP) {
moves++;
up = true;
if(down != true) {
up = true;
}
else
{
up = false;
down = true;
}
left = false;
right = false;
}
if(e.getKeyCode() == KeyEvent.VK_DOWN) {
moves++;
down = true;
if(up != true) {
down = true;
}
else
{
up = true;
down = false;
}
left = false;
right = false;
}
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}
}
it just seems to copy itself to the right
public void paint(Graphics g)
{
g.setColor(Color.WHITE);
Custom painting should be done by overriding paintComponent(...) and then you need to invoke super.paintComponent(...):
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.WHITE);
This will make sure the background of the panel is cleared before doing the custom painting.
it's not going to the right automatically you have to keep pressing the key.
Well, that is usually the way a game is designed. You only have motion when the key is pressed as this will keep generating events. Then if you don't want motion you just don't press any keys.
If you want animation then you use a Swing Timer. Each time the Timer fires you invoke a move(...) method. This method would need to look at your "direction" variable to determine whether to move the snake left, right, up or down.
Check out:
Motion Using the Keyboard for animation when a key is pressed and held and
get width and height of JPanel outside of the class for continuous animation
I am making a game like Space Impact. In my game the rockets are working correctly, but I can't create monsters randomly. Monsters are on the screen but they aren't moving so they aren't active
How can I do this?
public class Dnm extends JFrame implements Runnable {
Graphics dbg;
Image dbImage;
Image Pik1;
Image Boss;
static ImageIcon active;
int x, y, xDirection, yDirection, BossX, BossY;
public void run() {
try {
while (true) {
move();
boss();
Thread.sleep(10);
}
} catch (Exception e) {
System.out.println("Uh-oh, something went wrong!.");
}
}
private void move() {
x += xDirection;
y += yDirection;
}
private void boss() {
while (BossX == 0) {
BossX = getX() - 1;
}
Random rastgele = new Random(getY());
BossY = rastgele.nextInt();
}
public void setXDirection(int xdir) {
xDirection = xdir;
}
public void setYDirection(int ydir) {
yDirection = ydir;
}
// KEY COMMANDS //
public class AL extends KeyAdapter {
#Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == e.VK_LEFT) {
setXDirection(-1);
}
if (keyCode == e.VK_RIGHT) {
setXDirection(+1);
}
if (keyCode == e.VK_UP) {
setYDirection(-1);
}
if (keyCode == e.VK_DOWN) {
setYDirection(+1);
}
}
#Override
public void keyReleased(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == e.VK_LEFT) {
setXDirection(0);
}
if (keyCode == e.VK_RIGHT) {
setXDirection(0);
}
if (keyCode == e.VK_UP) {
setYDirection(0);
}
if (keyCode == e.VK_DOWN) {
setYDirection(0);
}
}
#Override
public void keyTyped(KeyEvent e) {
}
}
// CONSTRUCTOR //
public Dnm() {
//Image Import
ImageIcon still = new ImageIcon("img/rocket.png");
Pik1 = still.getImage();
addKeyListener(new AL());
setTitle("Dnm");
setSize(500, 500);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(true);
setVisible(true);
x = 15;
y = 15;
}
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) {
ImageIcon background = new ImageIcon("img/space.jpeg");
Image background1 = background.getImage();
ImageIcon still1 = new ImageIcon("img/Alien.png");
Boss = still1.getImage();
g.setColor(Color.red);
g.drawImage(background1, 0, 0, this);
g.drawImage(Boss, BossX, BossY, this);
g.drawImage(Pik1, x, y, this);
g.setColor(Color.blue);
repaint();
}
public static void main(String[] args) {
Dnm game = new Dnm();
Thread t1 = new Thread(game);
t1.start();
}
}
Thank You.
With your code being incomplete, it is hard to say for sure, but this line looks suspicious:
while (BossX == 0) {
BossX = getX() - 1;
}
This code is mostly likely going to be executed once, right? If BossX is initially zero, the code executes where you change its value. On the next update, BossX is not zero (presumably), so the code doesn't execute. Since BossX is the X coordinate where you are drawing the boss, then it will not move. Instead it just gets redrawn over and over in the same spot.
To get the monster to move randomly, increment or decrement both the X and Y coordinate values randomly during each game loop. Add a second random variable to cause them to move at random speeds in the random direction (by adjusting the coordinate value by a value greater than one).
As NPE commented, you should step through the code in a debugger and find out precisely what is going on.
I am fairly a beginner at programming, but here is my best attempt:
I would create a method that is called every x seconds that generates a random number using Math.Random(). I would say
int number = .5;
if(number > Math.Random())
GenerateMonster();
Your GenerateMonster method would then create a new object with the default values for monster. In order for the monster's created to act a certain way, you need to inherit those functions wherever you defined how you want the monster to act. I don't see the code for these functions so I am assuming you just didn't list them. Hope this at least helps. Good Luck!
I am creating a pacman game in Java and I have 1 problem I can't get rid of.. The problem is as follows:
I have 4 buttons in the game screen for each way: up, down, left, right. The problem is that I can not use the buttons in the same time in x position as in the y position because I always get a value of 0 ( you understand this if you see my code below )
Below you can find my class for the pacman that i think is related to the problem ( see setBesturing(int besturing) method )
package h04PacMan;
/*
* PacMan laten bewegen
*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class PacMan extends JPanel implements ActionListener {
private int horizontalePlaats = 250; // x location
private int verticalePlaats = 150; // y location
private int richtingEnSnelheid = +10; // speed
private final int WACHTTIJD = 500; // DELAY
int diameter;
int waarde;
public PacMan() {
// create timer and start timer
javax.swing.Timer autoKlik = new javax.swing.Timer(WACHTTIJD, this);
autoKlik.start();
}
public int getHorPlaats() {
return horizontalePlaats;
}
// current y positie
public int getVerPlaats() {
return verticalePlaats;
}
// speed and way;
public int getRichtingEnSnelheid() {
return richtingEnSnelheid;
}
// new x position
public void setHorPlaats(int nieuweHorPlaats) {
if(nieuweHorPlaats > getWidth()) {
nieuweHorPlaats = 0;
}
else if(nieuweHorPlaats < 0) {
nieuweHorPlaats = getWidth();
}
horizontalePlaats = nieuweHorPlaats;
}
// new y position
public void setVerPlaats(int nieuweVerPlaats) {
if(nieuweVerPlaats > getHeight()) {
nieuweVerPlaats = 0;
}
else if(nieuweVerPlaats < 0) {
nieuweVerPlaats = getHeight();
}
verticalePlaats = nieuweVerPlaats;
}
public void setRichtingEnSnelheid(int nieuweRichtingEnSnelheid) {
richtingEnSnelheid = nieuweRichtingEnSnelheid;
}
//movement
public void setBesturing(int besturing) {
besturing = waarde;
if(waarde == 0) {
setVerPlaats( getVerPlaats() + richtingEnSnelheid);
}
else if(waarde == 1){
setHorPlaats( getHorPlaats() + richtingEnSnelheid);
}
}
#Override
public void actionPerformed(ActionEvent e) {
setBesturing(waarde);
System.out.println(waarde);
repaint();
}
DrawPacMan pacman = new DrawPacMan();
DrawPacMan ghost1 = new DrawPacMan();
DrawPacMan ghost2 = new DrawPacMan();
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);
}
}
and this is the actionListener in my gamecontrol class
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == links) {
pacman.setRichtingEnSnelheid( -10 );
pacman.setBesturing(1);
System.out.println("links");
}
else if(e.getSource() == rechts) {
pacman.setRichtingEnSnelheid( +10 );
pacman.setBesturing(1);
System.out.println("rechts");
}
else if(e.getSource() == boven) {
pacman.setRichtingEnSnelheid( -10);
pacman.setBesturing(0);
System.out.println("boven");
}
else {
pacman.setRichtingEnSnelheid( +10);
pacman.setBesturing(0);
System.out.println("beneden");
}
}
Here is your problem:
//movement
public void setBesturing(int besturing) {
besturing = waarde; <-- THIS LINE
if(waarde == 0) {
setVerPlaats( getVerPlaats() + richtingEnSnelheid);
}
else if(waarde == 1){
setHorPlaats( getHorPlaats() + richtingEnSnelheid);
}
}
You are overwriting the value of besturing with the old value waarde. It should be the other way around.
//movement
public void setBesturing(int besturing) {
waarde = besturing; <-- THIS LINE
if(waarde == 0) {
setVerPlaats( getVerPlaats() + richtingEnSnelheid);
}
else if(waarde == 1){
setHorPlaats( getHorPlaats() + richtingEnSnelheid);
}
}
I think inside the method setBesturing(int besturing) should be:
waarde = besturing;
In your setBesturing method: -
besturing = waarde;
This line never changes the value of your waarde.. It is always zero.
You should do the assignment the other way : -
this.waarde = besturing;
You'll need to keep track of whether the button is pressed or not indepentently. Also, you're model doesn't support a diagonal movement at all (I'm not sure what your nederlands names exactly mean, i can interprete snelheid=Schnelligkeit=speed and some more).
You'll need to put diagonal movement into the model (e.g. give him an x and y velocity indepent from each other)
The problem is that this ball after it is dragged and exited click, it is supposed to repaint according to the new y component given. This is calculated from the gravity final and added to the velocity which is added to the existing y component in a loop.
I have debugged many times and I just cant hit it on the head.
Its supposed to..
move to where you drag it >>> when you let go it is supposed to fall until it hits the ground.
Thank you ahead of time.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DragBallPanel extends JPanel implements MouseListener, MouseMotionListener
{
private static final int BALL_DIAMETER = 40;
private int screen_size_x = 300;
private int screen_size_y = 300;
private int ground_lvl = screen_size_y - 15;
private int _ballX = ground_lvl/2;
private int _ballY = ground_lvl - BALL_DIAMETER;
private final double GRAVITY = -9.8;
private double velocity;
private static final double TERM_VEL = -100;
private int _dragFromX = 0;
private int _dragFromY = 0;
private boolean _canDrag = false;
public DragBallPanel() throws InterruptedException
{
setPreferredSize(new Dimension(screen_size_x, screen_size_y));
setBackground(Color.darkGray);
setForeground(Color.darkGray);
this.addMouseListener(this);
this.addMouseMotionListener(this);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g); // Required for background.
g.setColor (Color.green);
g.fillRect (0, 280, 400, 50 );
g.setColor (Color.black);
g.fillOval(_ballX, _ballY, BALL_DIAMETER, BALL_DIAMETER);
}
public void mousePressed(MouseEvent e)
{
int x = e.getX();
int y = e.getY();
if (x >= _ballX && x <= (_ballX + BALL_DIAMETER)
&& y >= _ballY && y <= (_ballY + BALL_DIAMETER))\
{
_canDrag = true;
_dragFromX = x - _ballX;
_dragFromY = y - _ballY;
} else
{
_canDrag = false;
}
}
//===== mouseDragged ======
/** Set x,y to mouse position and repaint. */
public void mouseDragged(MouseEvent e)
{
if (_canDrag)
{ // True only if button was pressed inside ball.
//--- Ball pos from mouse and original click displacement
_ballX = e.getX() - _dragFromX;
_ballY = e.getY() - _dragFromY;
//--- Don't move the ball off the screen sides
_ballX = Math.max(_ballX, 0);
_ballX = Math.min(_ballX, getWidth() - BALL_DIAMETER);
//--- Don't move the ball off top or bottom
_ballY = Math.max(_ballY, 0);
_ballY = Math.min(_ballY, getHeight() - BALL_DIAMETER);
this.repaint();
}
}
public void mouseExited(MouseEvent e)
{
while(_ballY < ground_lvl)
{
simulateGravity();
}
}
public void simulateGravity()
{
if(_canDrag)
{
try{
velocity = velocity + GRAVITY;
if (velocity < TERM_VEL)
{
velocity = TERM_VEL;
}
if (_ballY >= ground_lvl - BALL_DIAMETER)
{
velocity = velocity/4;
}
_ballY += velocity;
Thread.sleep(400);
this.repaint();//**problem occurs here**
}catch(InterruptedException ie)
{
}
}
}
public void mouseMoved (MouseEvent e){}
public void mouseEntered (MouseEvent e){}
public void mouseClicked (MouseEvent e){}
public void mouseReleased(MouseEvent e){}
}
main() class
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class DragDemo extends JApplet
{
public static void main(String[] args) throws InterruptedException
{
JFrame window = new JFrame();
window.setTitle("Drag Demo");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//window.add(new DragBallPanel());
window.setContentPane(new DragBallPanel());
window.setResizable(false);
window.pack();
window.show();
}
public DragDemo() throws InterruptedException
{
new DragBallPanel();
}
}
This SSCCE begins to show the problems in the code.
Compile the code.
Run it.
Drag the ball upwards.
Release the ball.
Remove the mouse from the drawing area, to see..
The ball fall upwards!
You seem to have gotten the Y values upside down. They start at top of screen, and go downwards. Also, the code was blocking the EDT in an infinite loop. To solve that, run the animation using a Swing Timer.
Please read the document on the SSCCE & ask if there is anything in it you do not understand. I am well placed to explain. :)
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DragBallPanel extends JPanel implements MouseListener, MouseMotionListener
{
private static final int BALL_DIAMETER = 40; // Diameter of ball
private int screen_size_x = 300;
private int screen_size_y = 300;
private int ground_lvl = screen_size_y - 15;
private int _ballX = ground_lvl/2;
private int _ballY = ground_lvl - BALL_DIAMETER;
private final double GRAVITY = -9.8;
private double velocity;
private static final double TERM_VEL = 100;
private int _dragFromX = 0; // pressed this far inside ball's
private int _dragFromY = 0; // bounding box.
/** true means mouse was pressed in ball and still in panel.*/
private boolean _canDrag = false;
public DragBallPanel()
{
setPreferredSize(new Dimension(screen_size_x, screen_size_y));
setBackground(Color.darkGray);
setForeground(Color.darkGray);
this.addMouseListener(this);
this.addMouseMotionListener(this);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g); // Required for background.
g.setColor (Color.green);
g.fillRect (0, 280, 400, 50 );
g.setColor (Color.black);
g.fillOval(_ballX, _ballY, BALL_DIAMETER, BALL_DIAMETER);
}
public void mousePressed(MouseEvent e)
{
int x = e.getX(); // Save the x coord of the click
int y = e.getY(); // Save the y coord of the click
if (x >= _ballX && x <= (_ballX + BALL_DIAMETER)
&& y >= _ballY && y <= (_ballY + BALL_DIAMETER)) {
_canDrag = true;
_dragFromX = x - _ballX; // how far from left
_dragFromY = y - _ballY; // how far from top
} else {
_canDrag = false;
}
}
//========= mouseDragged =================
/** Set x,y to mouse position and repaint. */
public void mouseDragged(MouseEvent e)
{
if (_canDrag) { // True only if button was pressed inside ball.
//--- Ball pos from mouse and original click displacement
_ballX = e.getX() - _dragFromX;
_ballY = e.getY() - _dragFromY;
//--- Don't move the ball off the screen sides
_ballX = Math.max(_ballX, 0);
_ballX = Math.min(_ballX, getWidth() - BALL_DIAMETER);
//--- Don't move the ball off top or bottom
_ballY = Math.max(_ballY, 0);
_ballY = Math.min(_ballY, getHeight() - BALL_DIAMETER);
this.repaint(); // Repaint because position changed.
}
}
//====================================================== method mouseExited
/** Turn off dragging if mouse exits panel. */
public void mouseExited(MouseEvent e)
{
System.out.println("Exited: " + e);
//_canDrag = false;
runGravity();
/* while(_ballY < ground_lvl)
{
simulateGravity();
}*/
}
Timer timer;
ActionListener animate;
public void runGravity() {
if (animate==null) {
animate = new ActionListener() {
public void actionPerformed(ActionEvent ae) {
System.out.println("Ground: " + (_ballY-ground_lvl));
if (_ballY > ground_lvl) {
timer.stop();
} else {
simulateGravity();
}
}
};
timer = new Timer(100,animate);
}
timer.start();
}
public void simulateGravity()
{
System.out.println("_canDrag: " + _canDrag);
if(_canDrag)
{
velocity = velocity + GRAVITY;
if (velocity > TERM_VEL)
{
velocity = TERM_VEL;
}
if (_ballY >= ground_lvl - BALL_DIAMETER)
{
//We have hit the "ground", so bounce back up. Reverse
//the speed and divide by 4 to make it slower on bouncing.
//Just change 4 to 2 or something to make it faster.
velocity = velocity/4;
}
_ballY += velocity;
//this.revalidate();
this.repaint();
}
}
public void mouseMoved (MouseEvent e){}
public void mouseEntered (MouseEvent e){}
public void mouseClicked (MouseEvent e){}
public void mouseReleased(MouseEvent e){}
public static void main(String[] args) {
SwingUtilities.invokeLater( new Runnable() {
public void run() {
DragBallPanel dbp = new DragBallPanel();
JOptionPane.showMessageDialog(null, dbp);
}
});
}
}
Try updateUI() instead of repaint().
If there is no effect remove the component and add it again.
I'm coding a game and I'm using Java's Swing. And right now i'm trying to get the KeyListeners and Action listeners to work.
What I'm trying to do is to make my object to move according to what key i'm pressing. (Left,Right,Up,Down), But for some reason nothing happens when i press either of these keys, but when i press 3 of them at the same time. the object is strangely moving to the left..
So here's my code for the class to create the Runner-object:
import java.awt.*;
public class Runner{
private int xpos, ypos, base, side;
public Runner(int b, int h ) {
base = b;
side = h;
}
public void setPosition(int x, int y){
xpos = x;
ypos = y;
}
public void view(Graphics g) {
int x[] = { xpos, xpos-base/2, xpos + base/2};
int y[] = { ypos, ypos + side, ypos + side };
g.setColor(Color.lightGray);
g.fillPolygon( x, y, 3 );
g.setColor(Color.darkGray);
g.drawLine(xpos, ypos, xpos, ypos + side);
}
public void shoot(Graphics g){
g.setColor(Color.red);
g.drawLine(xpos,ypos, xpos, 0);
}
}
And here's the code thats suppose to run the damn thing:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class RunningGame extends JPanel implements KeyListener, ActionListener{
Runner rs;
int x,y;
Timer t;
boolean shot = false;
boolean left = false, right = false, up = false, down = false;
public RunningGame() {
x = 100;
y = 150;
rs = new Runner(40,60);
rs.setPosition(x,y);
this.addKeyListener(this);
this.setBackground(Color.black);
t = new Timer(40, this);
t.start();
}
public void paintComponent(Graphics g){
super.paintComponent(g);
rs.view(g);
if(shot) rs.shoot(g);
}
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == 37) {left = true;}
if (e.getKeyCode() == 39) {right = true;}
if (e.getKeyCode() == 38) {up = true;}
if (e.getKeyCode() == 40) {down = true;}
if (e.getKeyCode() == 32) {shot = true;}
rs.setPosition(x,y);
this.repaint();
}
public void keyReleased(KeyEvent e){
if (e.getKeyCode() == 37) left = false;
if (e.getKeyCode() == 39) right = false;
if (e.getKeyCode() == 38) up = false;
if (e.getKeyCode() == 40) down = false;
if (e.getKeyCode() == 32) shot = false;
this.repaint();
}
public void keyTyped(KeyEvent e){}
public void actionPerformed(ActionEvent e) {
if (left) {
if(right){
right = false;
x = x - 10; shot = false;
}
}
if (right) {
if(left){
left = false;
x = x + 10; shot = false;
}
}
if (up) {
if(down){
down = false;
y = y - 10; shot = false;
}
}
if (down) {
if(up){
up = false;
y = y + 10; shot = false;
}
}
rs.setPosition(x,y);
this.repaint();
}
public static void main(String[] args) {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(300, 300); f.setLocation(100,100);
f.setTitle("Running");
RunningGame p = new RunningGame();
f.add(p); f.setVisible(true);
p.requestFocus();
}
}
(This is not the final code it's just using an example with a spaceship, later i will use a different object, just wanna test the KeyListener and ActionListener so it works before proceeding.)
Anyways can anyone help me make the space ship move smoothly? and without having to release all keys to activate another? i.e If i hold left i want it to be able to press another button. so that if i press right, the space ship will start to move in that direction instead.
//MrElephants
In the blocks that look like:
if (left) {
if(right){
right = false;
x = x - 10; shot = false;
}
}
I think you should have x = x - 10; outside the second if:
if (left) {
if(right){
right = false;
shot = false;
}
x = x - 10;
}
although I'm not really sure what that inner if is for, maybe you should remove it completely (but keep the x -= 10 etc.). This should be sufficient to make the movement seem natural.