I have this small project that upon running the program it will automatically animate. In this case an oval shape should continuously animate using a thread. However in my program it will stop for the fifth direction - meaning following a certain path. Can anyone suggest me a better solution or help me let the oval shape continuously move until the user closes the program.
package movingball;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MovingBall extends JPanel{
private int ballX = 30;
private int ballY = 30;
private int pattern = 1;
private int limitHeight;
private int limitWidth;
boolean horizontalBoundary = true;
boolean verticalBoundary = true;
public MovingBall(){
setBackground(Color.BLACK);
}
public MovingBall(int x, int y){
x = this.ballX;
y = this.ballY;
repaint();
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500,700);
MovingBall movingBall = new MovingBall();
frame.add(movingBall);
frame.setVisible(true);
BallUsingThread ball = new BallUsingThread(movingBall);
Thread first = new Thread(ball);
first.start();
}
#Override
public void paintComponent(Graphics canvas){
super.paintComponent(canvas);
canvas.setColor(Color.BLUE);
canvas.fillOval(ballX, ballY, 100, 100);
}
public void animateBall(){
if(horizontalBoundary && verticalBoundary){
if(pattern == 1){
diagonalDown(getWidth()-100,365);
}else if(pattern == 2){
diagonalDown(getWidth(),150);
}
}
if(!horizontalBoundary && !verticalBoundary){
diagonalDownLeft(150, getHeight());
pattern = 4;
}
if(horizontalBoundary && !verticalBoundary){
if(pattern == 4){
diagonalUp(0, 490);
}
if(pattern == 5){
System.out.print("helo");
diagonalUp(500,10);
}
System.out.print("last move" + pattern);
}
if(!horizontalBoundary && verticalBoundary){
diagonalUpRight(getWidth(),100);
pattern = 5;
System.out.print(pattern);
}
repaint();
}
public void diagonalDown(int limitWidth, int limitHeight){
this.limitWidth = limitWidth;
this.limitHeight = limitHeight;
if((ballX += 30) >= limitWidth){
horizontalBoundary = false;
}
if((ballY += 30) >= limitHeight){
verticalBoundary = false;
}
}
public void diagonalUp(int limitWidth, int limitHeight){
this.limitWidth = limitWidth;
this.limitHeight = limitHeight;
if((ballX -= 30) <= limitWidth) {
horizontalBoundary = false;
}
if((ballY -= 30) <= limitHeight){
verticalBoundary = true;
}
}
public void diagonalUpRight(int limitWidth, int limitHeight){
this.limitWidth = limitWidth;
this.limitHeight = limitHeight;
if((ballX += 30) >= limitWidth) {
horizontalBoundary = true;
}
if((ballY -= 30) <= limitHeight){
verticalBoundary = false;
}
}
public void diagonalDownLeft(int limitWidth, int limitHeight){
this.limitWidth = limitWidth;
this.limitHeight = limitHeight;
if((ballX -= 30) <= limitWidth){
horizontalBoundary = true;
}
if((ballY += 30) >= limitHeight){
verticalBoundary = false;
}
//System.out.print("downleft");
}
}
class BallUsingThread implements Runnable{
private final MovingBall movingBall;
public BallUsingThread(MovingBall mb){
movingBall = mb;
}
#Override
public void run() {
for(;;){
movingBall.animateBall();
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
System.out.printf("Error",ex);
}
}
}
}
It is not the problem with loop, if you System.out.println("loop running"); you will see that the loop is running, but that there is the problem with your draw ball logic that in this part of your code
if(!horizontalBoundary && verticalBoundary){
diagonalUpRight(getWidth(),100);
pattern = 5;
System.out.print(pattern);
}
You are trying to diagonalUpRight() so after some calling to this method, then the none of the if clause will executed, because the conditions are not satisfied, so the ball remains in the same place at every loop, and seems that the loop stopped working.
A small suggestion: It is better to use while(tru /*some condition*/) loop instead of for(;;) in such cases.
Solution: If you carefully check the logic you will see that there is no an if clause which is used for the condition below:
horizontalBoundary = true
verticalBoundary = true
When pattern = 5 So when these two variables become true andpattern = 5 then nothing will happen to the ball position, so you can write a condition which is used to check these two variables for true value.
Eidt Eidt the below part of you code and you will see the result which loop is not stopping, I just initialized the position of ball the values become true and the pattern = 5.
if(horizontalBoundary && verticalBoundary){
if(pattern == 1){
diagonalDown(getWidth()-100,365);
}else if(pattern == 2){
diagonalDown(getWidth(),150);
} else { // added this else block
ballX = 30;
ballY = 30;
pattern = 1;
}
}
Override paintComponent(Graphics) and implement all painting inside this method (but not animations).
Then use Swing timer to schedule periodic events each 100 ms, implement everything that changes the picture in the handler of this event and call repaint() from there at the end to refresh the picture.
Related
i am trying to create a game similar to jetpack joyride in which the user can hold the spacebar to go up and let go to travel downward. I am using timers to simulate the gravity and using keyPressed and keyReleased to check if the user is holding the spacebar. I am using print statements to know for sure that both keyPressed and keyReleased are working, but i dont know why the physics arent running. I dont know whether the problem is my if statements not updating, if it is the new timers being created inside of the if statement. Either way, the gravity is not changing, and im stuck. Help is appreciated.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Calendar;
public class Game implements KeyListener {
JFrame frame;
JLabel player;
public boolean grounded = false;
public int velocity = 0;
public int finalY = 0;
public boolean spaceHeld = false;
Action spaceAction;
Game() {
frame = new JFrame("Nicholas Seow-Xi Crouse");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1920, 1080);
frame.setLayout(null);
frame.setFocusable(true);
frame.addKeyListener(this);
player = new JLabel();
player.setBackground(Color.red);
player.setBounds(10, 1800, 50, 50);
player.setOpaque(true);
frame.add(player);
frame.setVisible(true);
Timer flightTime = new Timer();
TimerTask flight = new TimerTask() {
public void run() {
if(velocity > -5) {
velocity -= 1;
}
else{
velocity = -5;
}
if (finalY < -61) {
finalY = finalY + velocity;
}
else{
finalY = -61;
}
player.setLocation(player.getX(), player.getY() + finalY);
if (player.getY() <= 0){
cancel();
velocity = 0;
finalY = 0;
player.setLocation(player.getX(), 0);
}
}
};
Timer gravityTime = new Timer();
TimerTask gravity = new TimerTask() {
//creates a timer run method that simulates the falling gravity when not grounded
public void run() {
if(velocity < 5){
velocity += 1;
}
else{
velocity = 5;
}
//creates the variable the tells where the player is located
if (finalY < 61) {
finalY = finalY + velocity;
}
else{
finalY = 61;
}
player.setLocation(player.getX(), player.getY() + finalY);
if (player.getY() >= 1000){
cancel();
velocity = 0;
finalY = 0;
player.setLocation(player.getX(), 990);
}
}
};
if (spaceHeld == false ) {
gravityTime.scheduleAtFixedRate(gravity, 0, 33);
}
if (spaceHeld == true ) {
flightTime.scheduleAtFixedRate(flight, 0 ,33);
}
}
public void keyTyped(KeyEvent e) {
}
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_SPACE){
spaceHeld = true;
//debug
System.out.println(spaceHeld);
}
}
public void keyReleased(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_SPACE){
spaceHeld = false;
//debug
System.out.println(spaceHeld);
}
}
}
Code is event based, and currently nothing triggers your timers to start. To do this you can simply move the timer schedule/start actions inside the key events:
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_SPACE){
//Cancel the other timer here so that they don't overlap
gravity.cancel();
gravityTime.cancel();
//Create a new instance of the timer
flightTime = new Timer();
flight = new TimerTask() {
public void run() {
if(velocity > -5) {
velocity -= 1;
}
else{
velocity = -5;
}
if (finalY < -61) {
finalY = finalY + velocity;
}
else{
finalY = -61;
}
player.setLocation(player.getX(), player.getY() + finalY);
if (player.getY() <= 0){
cancel();
velocity = 0;
finalY = 0;
player.setLocation(player.getX(), 0);
}
}
};
//Now start the timer
flightTime.scheduleAtFixedRate(flight, 0 ,33);
}
}
//Do the same for the gravity method
public void keyReleased(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_SPACE){
......
}
}
}
Note above that you should also cancel the other scheduled task with the opposing key events so that they do not overlap each other and value strange results.
And to make flightTime and gravityTime accessible to the keyPressed method simply declare them as class variables:
public class Game implements KeyListener {
JFrame frame;
JLabel player;
public boolean grounded = false;
public int velocity = 0;
public int finalY = 0;
public boolean spaceHeld = false;
//Move them here but don't assign a value:
public Timer flightTime;
public TimerTask flight;
public Timer gravityTime;
public TimerTask gravity;
You can still create the object later in the Game method:
flightTime = new Timer();
flight = new TimerTask() {
....
};
When I try to control my character with the arrow keys, everything works fine but after a while I get this error:
Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError
and then
at java.awt.AWTEventMulticaster.keyPressed(AWTEventMulticaster.java:249)
multiple times. The class that I have isn't even 249 lines of code long so I don't know where to look for the problem. My code is very messy right now but I'll post it if it helps anyone come up with the answer.
import javax.swing.JButton;
import javax.swing.JComponent;
import java.awt.Graphics;
import javax.swing.JFrame;
import java.awt.image.*;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
public class mainFrame extends JPanel implements Runnable, KeyListener {
static boolean gameIsRunning = false;
static final int TARGET_FPS = 1;
static int x = 100;
static int y = 100;
static long startTime = 0;
static long elapsedTime = 0;
static long waitTime = 0;
JFrame window = new JFrame("Out from Eden");
JPanel panel = new JPanel();
getResources get = new getResources();
BufferedImage player = get.getImg("player");
static int playerVal = 0;
static int i = 0;
static String currentState = "";
static int lastFacing = 0;
public void createFrame() {
gameIsRunning = true;
gameStart();
}
public void setGame(boolean game) {
gameIsRunning = game;
}
public void gameStart() {
(new Thread(new mainFrame())).start();
}
public void run() {
while (gameIsRunning == true) {
startTime = System.nanoTime();
updateGame();
renderGame();
elapsedTime = System.nanoTime() - startTime;
waitTime = (TARGET_FPS * 10) - (elapsedTime / 1000000);
if (waitTime < 0) {
waitTime = 5;
}
try {
Thread.sleep(waitTime);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void updateGame() {
if (x > 800) {
x = 0;
}
if (currentState == "left") {
x--;
}
if (currentState == "right") {
x++;
}
player = royImage();
}
public BufferedImage royImage() {
if (currentState == "right") {
lastFacing = 2;
i++;
if (playerVal == 0) {
playerVal = 1;
i = 0;
player = get.getImg("royWalk1");
}
if (playerVal == 1 && i > 20) {
playerVal = 2;
i = 0;
return get.getImg("royWalk2");
}
if (playerVal == 2 && i > 20) {
playerVal = 3;
i = 0;
player = get.getImg("royWalk3");
}
if (playerVal == 3 && i > 20) {
playerVal = 4;
i = 0;
player = get.getImg("royWalk4");
}
if (playerVal == 4 && i > 20) {
playerVal = 0;
i = 0;
player = get.getImg("royWalk1");
}
}
if (currentState == "left") {
lastFacing = 1;
i++;
if (playerVal == 0) {
playerVal = 1;
i = 0;
player = get.getImg("royWalkL1");
}
if (playerVal == 1 && i > 20) {
playerVal = 2;
i = 0;
player = get.getImg("royWalkL2");
}
if (playerVal == 2 && i > 20) {
playerVal = 3;
i = 0;
player = get.getImg("royWalkL3");
}
if (playerVal == 3 && i > 20) {
playerVal = 4;
i = 0;
player = get.getImg("royWalkL4");
}
if (playerVal == 4 && i > 20) {
playerVal = 0;
i = 0;
player = get.getImg("royWalkL1");
}
}
if (currentState == "null") {
i = 0;
playerVal = 0;
if (lastFacing == 1) {
player = get.getImg("playerL");
}
if (lastFacing == 2) {
player = get.getImg("player");
}
}
return player;
}
public void renderGame() {
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setBounds(30, 30, 700, 500);
panel.setLayout(new BorderLayout());
window.getContentPane().add(panel);
panel.add(this);
window.setFocusable(true);
window.setFocusTraversalKeysEnabled(false);
window.setVisible(true);
window.addKeyListener(this);
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.drawString("Hello", x, y);
g2.drawLine(0, 63, 700, 63);
g2.drawImage(player, x - 100, y - 100, null);
}
public void keyTyped(KeyEvent e) {
}
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if (code == KeyEvent.VK_UP) {
currentState = "up";
}
if (code == KeyEvent.VK_DOWN) {
currentState = "down";
}
if (code == KeyEvent.VK_LEFT) {
currentState = "left";
}
if (code == KeyEvent.VK_RIGHT) {
currentState = "right";
}
}
public void keyReleased(KeyEvent e) {
currentState = "null";
}
}
Could anyone help me figure out why I am getting the stack overflow error and how to avoid it?
Your while true loop is shooting you in the foot as you're adding a KeyListener umpteen thousand times within that loop. Don't do that, in particular your renderGame() method. Why would you even want to call a method that is for setting the GUI that many times? It would make much more sense to call that method once.
Also, instead use a Swing Timer (Google the tutorial) in place of your while loop, avoid KeyListeners in favor of Key Binding (Google the tutorial, and have a look at this example) and do your set-up code only once.
Also, your code is at risk of causing Swing threading errors as you're calling Thread.sleep(...) and while (true) in a non-background thread. For safety's sake, use a Swing Timer instead.
Also, you're comparing Strings wrong. Don't compare Strings using == or !=. Use the equals(...) or the equalsIgnoreCase(...) method instead. Understand that == checks if the two object references are the same which is not what you're interested in. The methods on the other hand check if the two Strings have the same characters in the same order, and that's what matters here. So instead of
if (fu == "bar") {
// do something
}
do,
if ("bar".equals(fu)) {
// do something
}
or,
if ("bar".equalsIgnoreCase(fu)) {
// do something
}
I want players to be able to press "r" after dying and be able to restart. I think I'm supposed to put my entire code into a reset method, but I am only a beginner, and I'm not quite there yet.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JPanel;
public class Screen extends JPanel implements Runnable {
private static final long serialVersionUID = 1L;
public static final int WIDTH = 800, HEIGHT = 800;
private Thread thread;
private boolean running = false;
private BodyPart b;
private ArrayList<BodyPart> snake;
private Apple apple;
private ArrayList<Apple> apples;
private Random r;
private int xCoor = 10, yCoor = 10;
private int size = 20;
private boolean right = true, left = false, up = false, down = false;
private int ticks = 0;
private Key key;
public Screen() {
setFocusable(true);
key = new Key();
addKeyListener(key);
setPreferredSize(new Dimension(WIDTH, HEIGHT));
r = new Random();
snake = new ArrayList<BodyPart>();
apples = new ArrayList<Apple>();
start();
}
public void tick() {
if(snake.size() == 0) {
b = new BodyPart(xCoor, yCoor, 10);
snake.add(b);
}
if(apples.size() == 0) {
int xCoor = r.nextInt(80);
int yCoor = r.nextInt(80);
apple = new Apple(xCoor, yCoor, 10);
apples.add(apple);
}
for(int i = 0; i < apples.size(); i++) {
if(xCoor == apples.get(i).getxCoor() && yCoor == apples.get(i).getyCoor()) {
size++;
apples.remove(i);
i--;
}
}
for(int i = 0; i < snake.size(); i++) {
if(xCoor == snake.get(i).getxCoor() && yCoor == snake.get(i).getyCoor()) {
if(i != snake.size() - 1) {
stop();
}
}
}
if(xCoor < -1) xCoor = 80;
if(xCoor > 80) xCoor = -1;
if(yCoor < -1) yCoor = 80;
if(yCoor > 80) yCoor = -1;
ticks++;
if(ticks > 250000) {
if(right) xCoor++;
if(left) xCoor--;
if(up) yCoor--;
if(down) yCoor++;
ticks = 185000;
b = new BodyPart(xCoor, yCoor, 10);
snake.add(b);
if(snake.size() > size) {
snake.remove(0);
}
}
}
public void paint(Graphics g) {
g.clearRect(0, 0, WIDTH, HEIGHT);
g.setColor(new Color(10, 50, 0));
g.fillRect(0, 0, WIDTH, HEIGHT);
g.setColor(Color.BLACK);
for(int i = 0; i < WIDTH / 10; i++) {
g.drawLine(i * 10, 0, i * 10, HEIGHT);
}
for(int i = 0; i < HEIGHT / 10; i++) {
g.drawLine(0, i * 10, WIDTH, i * 10);
}
for(int i = 0; i < snake.size(); i++) {
snake.get(i).draw(g);
}
for(int i = 0; i < apples.size(); i++) {
apples.get(i).draw(g);
}
}
public void start() {
running = true;
thread = new Thread(this, "Game Loop");
thread.start();
}
public void stop() {
running = false;
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void run() {
while(running) {
tick();
repaint();
}
}
private class Key implements KeyListener {
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_RIGHT && !left) {
up = false;
down = false;
right = true;
}
if(key == KeyEvent.VK_LEFT && !right) {
up = false;
down = false;
left = true;
}
if(key == KeyEvent.VK_UP && !down) {
left = false;
right = false;
up = true;
}
if(key == KeyEvent.VK_DOWN && !up) {
left = false;
right = false;
down = true;
}
}
#Override
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
}
}
Any help is greatly appreciated!
You can modify your code as follows:
I've added comments to explain my modifications
//this resets the position/size of the snake and clears the array
public void reset() {
snake.clear();
apples.clear();
xCoor = 10;
yCoor = 10;
size = 20;
running = true;
}
private class Key implements KeyListener {
//reset when you are dead and the user presses r
if (!running && (e.getKeyChar() == 'r' || e.getKeyChar() == 'R')){
reset();
}
}
public void tick() {
while (running){
//prev code
for(int i = 0; i < snake.size(); i++) {
if(xCoor == snake.get(i).getxCoor() && yCoor == snake.get(i).getyCoor()) {
if(i != snake.size() - 1) {
//don't kill the process, just stop the game and wait for the user to press 'r'
//you may need to do additional stuff here
running = false;
}
}
}
//remaining code
}
}
First of all, yes you are on the right track. The best way is to put the initilization code (setting all variables to their initial values) in a seperate method. Then when you press 'r' you simply call this method and it will 'reset' itself.
To make this happen you should do ALL variable initializations at the start. Currently you initialize b = new BodyPart(xCoor, yCoor, 10); in tick(). Since this only ever happens once (when the game started) this is better to put in your initilization method.
A rough proposal of an initilization method:
public void initialize() {
snake = new ArrayList<BodyPart>();
apples = new ArrayList<Apple>();
b = new BodyPart(xCoor, yCoor, 10);
snake.add(b);
}
This method initializes all variables that are 'resettable'. You can then call this method when the int key = e.getKeyCode(); is KeyCode.R.
I am trying to get a ball to bounce up and down when you press the up arrow key. I can get the ball to move up but it will not stop moving up. I have written the code for the ball movement in my update method. I am trying to get the ball to stop at y coordinate 400, but it just passes it up.
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
public class Game extends Canvas implements Runnable {
int x,y;
public static int width = 300;
public static int height = width / 16 * 9;
public static int scale = 3;
private boolean running = false;
public Thread thread;
public JFrame frame;
public Keyboard key;
private BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
private int[] pixels = ((DataBufferInt)image.getRaster().getDataBuffer()).getData();
public Game() {
Dimension size = new Dimension(width * scale, height * scale);
setPreferredSize(size);
frame = new JFrame();
key = new Keyboard();
addKeyListener(key);
}
public synchronized void start() {
running = true;
thread = new Thread(this, "Display");
thread.start();
}
public synchronized void stop(){
running = false;
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
#Override
public void run() {
long lastTime = System.nanoTime();
final double nanoSeconds = 1000000000.0 / 60.0;
double delta = 0;
int frames = 0;
int gameUpdates = 0;
long timer = System.currentTimeMillis();
requestFocus();
while(running){
long now = System.nanoTime();
delta += (now - lastTime) / nanoSeconds;
lastTime = now;
//this ensures that delta only updates the screen 60 times each second
while (delta >= 1){
update();
gameUpdates++;
delta--;
}
render();
frames++;
//this if statement happens once a second
if (System.currentTimeMillis() - timer > 1000){
timer += 1000;
frame.setTitle("Bouncy Ball! ~ ~ ~ Updates per second: " + gameUpdates + ". Frames per second: " + frames + ".");
gameUpdates = 0;
frames = 0;
}
}
stop();
}
int yy;
public void update() {
key.update();
y = y + yy;
if(key.up){
yy = -5;
if(y == 400){
yy = 0;}
}
}
public void render() {
BufferStrategy bs = getBufferStrategy();
if (bs == null){
createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
g.drawImage(image,0,0,getWidth(),getHeight(),null);
g.setColor(Color.DARK_GRAY);
g.fillRect(0,0,getWidth(),getHeight());
g.setColor(Color.MAGENTA);
g.fillOval(300,y+435,50,50);
g.dispose();
bs.show();
}
public static void main(String[] args) {
Game game = new Game();
game.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
game.frame.setResizable(false);
game.frame.setVisible(true);
game.frame.add(game);
game.frame.pack();
game.frame.setTitle("Bouncy Ball");
game.start();
}
}
This is my keylisener class
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class Keyboard implements KeyListener{
private boolean[] keys = new boolean[120];
public boolean up, down, left, right;
public void update(){
up = keys[KeyEvent.VK_UP];
down = keys[KeyEvent.VK_DOWN];
left = keys[KeyEvent.VK_LEFT];
right = keys[KeyEvent.VK_RIGHT];
}
#Override
public void keyPressed(KeyEvent e) {
keys[e.getKeyCode()] = true;
}
#Override
public void keyReleased(KeyEvent e) {
keys[e.getKeyCode()] = false;
}
#Override
public void keyTyped(KeyEvent e) {
}
}
Your issue is in the key.update() method. key.up will only be true while you're holding the up key, not just if you press the up key once. If, for now, you only care about a single button press, change it to:
public void update() {
if (keys[KeyEvent.VK_UP]) {
up = true;
}
}
Which will only update once, once you press up, and keys.up will stay true.
Also, y is decreasing, not increasing (you're subtracting 5 from it), so you want to change
== 400 to == 400, or even better, <= 400, in case you don't increment with whole numbers (as per the other answer).
As a general debugging idea: At that if statement, I printed out the value of y, and noticed it only printed out 3 or 4 values (corresponding to how long I was holding it down), which meant that the if statement wasn't being checked, or wasn't returning true (which was the case here).
Instead of:
if(key.up){
yy = -5;
if(y == 400){
yy = 0;}
}
try:
if(key.up){
yy = -5;
if(y >= 400){
yy = 0;}
}
If your ball is moving at 5px per update then it may pass 400px without actually
equaling 400px, this is why you check if it is greater than 400px.
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)