Sign in to follow this  
jythonKid

Having problems with arrow key movement.

Recommended Posts

Hi Guys,


I am relatively new to the java programming language, and am still getting used to the whole "object-oriented" deal. After doing a couple basic graphic setups and very basic programs, I decided I would try to make a program based around movement with the arrow keys (original, I know). I got it working without using booleans or anything, but the movement was extremely jumpy and rough (the sprite would move slightly, then pause, then continue moving faster). So, I started experimenting with booleans and while loops and got it to a point where I figured it should work. The only difficulty I had was determining where to call the moveChar method (which redraws the character with the changed x y values). I fiddled with it for a while, trying different spots and modifying loops and if blocks to fit accordingly. No matter what I tried, I always got the same result. The program would run without error, but the sprite would not move when whichever key was pressed. I have a feeling that the program is getting stuck in one of the while loops, but I'm not sure. Here's the code, I was just wondering if someone could give me a few tips on what I'm doing wrong? Thanks a bundle.

P.S. ignore the comments, I have a phobia of deleting code..


[code]
package Enemies;

import java.awt.*;
import java.awt.event.*;
import java.io.File;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import java.io.IOException;
import java.awt.Rectangle;

public class Character extends Canvas {

// Read about JFrames and Canvas objects
// http://en.wikibooks.org/wiki/Java_Programming/Canvas

// Global variable
boolean upmove = false; boolean downmove = false; boolean rightmove = false; boolean leftmove = false;
int myX; int myY;

public Character(int x, int y,JFrame window) {
setSize(new Dimension(window.getWidth(), window.getHeight())); // set size of Canvas
myX = x; myY = y; // set globals from calling program
// IMPORTANT - this is an object that listens for user key input


addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent evt) {

moveTrue(evt); // custom method to evaluate user input
moveChar();
}
public void keyReleased(KeyEvent evt) {
moveFalse(evt);
moveChar();


}



});
}

// This method is a built in method of a canvas that can be overridden to draw what you want
public void paint(Graphics g) {
try {
Image link = new DrawImage().LoadImage("link.png");
g.drawImage(link,myX,myY,null);
g.setColor(Color.red);
Rectangle playerBox = new Rectangle(myX+1,myY+1,1,1 );
//Rectangle boxDet = new Rectangle(0,0,50,50);
//if (boxDet.intersects(playerBox)) {
// g.setColor(Color.red);
// g.drawString("You made it!",0,10);
//}
// g.fillOval(myX, myY, 30, 30);
}
catch (IOException e) {
System.out.println("ARE YOU DUMB?????");
}
}

public void moveTrue(KeyEvent evt) {

switch (evt.getKeyCode()) {
case KeyEvent.VK_DOWN:

downmove = true;


//myY += 5;
//break;

case KeyEvent.VK_UP:
upmove = true;
// myY -= 5;
// break;

case KeyEvent.VK_LEFT:
leftmove = true;
// myX -= 5;
// break;
case KeyEvent.VK_RIGHT:
rightmove = true;
// myX += 5;
// break;


}


// repaint(); // This built in method calls the canvas paint method
}
public void moveFalse(KeyEvent evt) {

switch (evt.getKeyCode()) {
case KeyEvent.VK_DOWN:

downmove = false;


//myY += 5;
//break;

case KeyEvent.VK_UP:
upmove = false;
// myY -= 5;
// break;

case KeyEvent.VK_LEFT:
leftmove = false;
// myX -= 5;
// break;
case KeyEvent.VK_RIGHT:
rightmove = false;
// myX += 5;
// break;


}


// repaint(); // This built in method calls the canvas paint method
}
public void moveChar() {

while (downmove == true) {
myY += 5;
}
while (upmove == true) {
myY -= 5;
}
while (leftmove == true){
myX -= 5;
}
while (rightmove == true){
myX += 5;
}

repaint();
}
}[/code]

Share this post


Link to post
Share on other sites
You should look into an explicitly event-driven solution to this problem. You don't need to be setting booleans on events in order to move a character, or even have a separate function for it like you're doing. (At least not if it's this simple.)

However, keep in mind that when you're coding something of this nature, it's often helpful to have an event processing function, an update function, and a draw (or paint) function, CALLED IN THAT ORDER.

Event processing:
This function (or class) should handle all events called from your game. This includes key strokes and mouse events. This is also where other functions can be called in which change the state of the game, or updates certain things in the game, i.e; a character's position on a map.

Update:
This function should update things in the game that are not updated via events. Mostly things like time driven tasks, such as animations, map resets, timed character skills, etc.

Draw:
Draws the updated game.


From these functions, you would call object specific functions such as:

terrain_map.update() -- (called from the main update function)

or,

terrain_map.character.move() -- called from the event processing function, because you're moving the character on a keypress.

I'm not very c++ or java savvy, but the architecture of the game would be the same in any other language. I would read up more on object oriented programming and the nature of classes and so forth. Get to know them in all their awesomeness, because they are quite useful.

here's an example of the 'main game loop' and what it should, at minimum, be composed of:

[code]
screen = # insert language specific screen initializer here
running = True:
while running:
process_events()
update()
draw(screen)[/code]

We do not pass the screen to process_events() or update(), because it's not needed. Only to the draw function, because the screen is where everything will end up being drawn to.


EDIT:

Also, a good way to check for bugs in your programs is to add lots of print statements if you're unsure of the way its behaving.

If you think the game is stuck in one of your while loops, add a print statement to that loop like "print 'stuck in while loop!' " , then if you see the console flood with that print statement, you know you're stuck in a while loop. Dig down to the level below that and investigate the cause to your loop not breaking.

Share this post


Link to post
Share on other sites
Your moveTrue and moveFalse switch statements need those "break" statements on them, otherwise the code for multiple cases will execute. It doesn't stop when it sees the next "case." Where it's actually getting stuck though is in the moveChar method. You do a while loop while something is true, but nowhere in that loop do you make it so it could ever be false. Logically, it's going to be an infinite loop.

I won't comment on improving the design of the system; hopefully that will come in time. But one thing you should really figure out is how to use a debugger. It's very important. If you used it, you'd be able to see where the execution is getting stuck.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this