This is my first question so I'll just get straight to it.
I've been developing a little 2D platformer game in Java using the Eclipse Neon IDE. I've been able to overcome any issues I've encountered so far except for the one I'm about to tell you.
As game controls usually go, I've set up the WASD keys for movement and the SPACEBAR for jumping. The character I control does respond to the key inputs so I know that this code works, but for some reason after the program has been running for about 3 minutes or so, the character stops receiving key inputs and I get this error:
java.awt.AWTEventMulticaster.keyPressed(Unknown Source)
I've tried fiddling with the code to see if I could fix it myself, but I can't figure out what's causing the problem.
Here's the relevant section of code from my Player class. You probably don't need to pay attention to any of the variables in the keyPressed() and keyReleased() methods, but just the methods themselves:
public void keyPressed(KeyEvent keyID) { //This method checks to see which keys the user has pressed
int key = keyID.getKeyCode();
if (debug == false && key == KeyEvent.VK_F1) {
debug = true;
}
else if (debug == true && key == KeyEvent.VK_F2) {
debug = false;
}
if (death == false) {
if (key == KeyEvent.VK_SPACE && jumping == false) {
//Player.key = 2;
velY = ySpeed;
jumping = true;
Sound.playSound("audio/playerJump.wav");
}
else if (key == KeyEvent.VK_D && rightIntersect == true) {
velX = 0;
lastKeyPressed = 'D';
Player.key = 1;
}
else if (key == KeyEvent.VK_D && rightIntersect == false) {
velX = xSpeed;
lastKeyPressed = 'D';
Player.key = 1;
}
if (key == KeyEvent.VK_A) {
velX = -xSpeed;
lastKeyPressed = 'A';
Player.key = -1;
}
}
else if (key == KeyEvent.VK_R && death == true) {
for (int i = 0; i < GameFrame.getPlayerList().size(); i++) {
Player p = GameFrame.getPlayerList().get(i);
GameFrame.removePlayer(p);
GameFrame.addPlayer(new Player(GameFrame.xPosStart, GameFrame.yPosStart));
death = false;
GameFrame.level = 1;
GameFrame.mainTimer.setInitialDelay(0);
GameFrame.mainTimer.start();
}
}
}
public void keyReleased(KeyEvent keyID) { //This method checks to see which keys the user has released
int key = keyID.getKeyCode();
if (key == KeyEvent.VK_A || key == KeyEvent.VK_D) {
Player.key = 0;
velX = 0;
}
}
And here's the code for my KeyAdapt class that the Player class references:
public class KeyAdapt extends KeyAdapter {
Player p;
public KeyAdapt (Player player) {
p = player;
}
public void keyPressed (KeyEvent keyID) {
p.keyPressed(keyID);
}
public void keyReleased (KeyEvent keyID) {
p.keyReleased(keyID);
}
Again, this code does work. It just suddenly stops working after the program has been running for a certain amount of time.
Does anyone know what might be causing this issue?
(If more information is needed, I can provide the entire code for the Player class).
Does anyone know what might be causing this issue?
It is not possible to say given the code you have shown us.
I suggest that you add some debugging code. For example, add something to keyPressed that logs the event received, and the state of variables such as death, jumping etcetera.
You say:
I get this error:
java.awt.AWTEventMulticaster.keyPressed(Unknown Source)
That looks like part of a line from a stacktrace, not an error message. If this is a stacktrace, you need to show us the entire trace including the exception at the beginning.
Finally, you should not do this:
if (death == false) {
The correct way to write that is:
if (!death) {
It is more concise, but more importantly it is less fragile. Imagine if you had mistyped your version as:
if (death = false) {
One character difference. Easy to overlook. And it completely changes the meaning of the statement. It is a bad idea to use == and != to test boolean variables.
None of code that you showed us breaks because of this, but this bad habit could be used elsewhere in your code, and that might be the source of your problem.
Related
I wrote code that is supposed to remove 25 HP (health points) each time a rectangle (created by pressing the m key) intersects another rectangle, the enemy. Currently, the enemy looses 25HP continuously after I've pressed the m key only once until I press the m key again outside of the enemy body.
This is my damage code for the enemy. It turns white when killed, that's why I have df1 etc. there.
void damage() {
//if (callMethod) {
HP -=25;
//callMethod = false;
System.out.println(" " + HP);
//}
if (HP == 0) {
df1 = 200;
df2 = 200;
df3 = 200;
}
}
This is the code for the m input.
void Fight() {
if (keyPressed) {
if (key == 'm'|| key == 'M') {
//villkor, flytta höger, X-led.
fill(255, 0, 0, 63);
noStroke();
rect(xF, yF, wF, hF);
xFF = xF;
yFF = yF;
wFF = wF;
hFF = hF;
}
}
}
Here I have my intersect code:
if (g.intersect(f)) {
f.damage();
}
I would appreciate any help I can get. Apologies for my bad English grammar :)
You can use another boolean variable that tracks whether the action was already taken.
Here's a small example:
boolean alreadyPressed = false;
void draw() {}
void mousePressed() {
if(!alreadyPressed){
background(random(255));
}
alreadyPressed = true;
}
You can then reset the boolean variable whenever you want to be eligible to detect the event again.
I'm trying to program a bug to move around an array attached to a custom Room object, whilst keeping count of how many times each tile has been stepped on.
The Room object is working properly, as are the movement and the counting. However, the bug's coordinates, bugX and bugY, are somehow reverting to 0 after exiting the nextMove method. Their values only revert when exiting the method; even the last line of code in the nextMove method itself uses their new values.
Relevant portion of the method is attached, but other sections can be added upon request.
if (dirNum == 0 && bugY < length-1) //Move up
bugY++;
else if (dirNum == 1 && bugX < width-1) //Move right
bugX++;
else if (dirNum == 2 && bugY > 0) //Move down
bugY--;
else if (dirNum == 3 && bugX > 0) //Move left
bugX--;
else {
System.out.println("Error: Cannot move " + direction + ".");
canMove = false;
dirNum = generator.nextInt(4);
continue;
}
This is the context for the command itself.
while (endSim == false) {
nextMove(bugX, bugY);
System.out.print(room.printRoom() + "\n\nNext move? (y/n) ");
simSentinel = in.next();
if (simSentinel.charAt(0) == 'n')
endSim = true;
}
The declarations where the starting coordinates are assigned aren't inside any loops, let alone where the variable itself is called.
The problem is the one described by #T.J.Crowder in his answer though applied to java.
Variables passed as parameters in java are passed by value. If the value is changed by the method receiving the parameter, the change only affects the value inside that method. The "outside" value doesn't change.
What you can do is to encapsulate the coords in an object and pass the encapsulating object as a parameter.
Then the method will receive the object by value, and change it's state (instead of the value of the object).
For a deeper understanding see this question
EDIT I:
I cleand up the code a bit. Though it is is missing the declaration of room and simSentinel, if you add that you should have a running example.
public class Bug{
public int x=0;
public int y=0;
}
public class SimpleSim {
private int dirNum = 0;
private int length = 20;
private int width = 20;
private boolean canMove = true;
private Random generator = new Random();
private boolean endSim = false;
public static void main(String [] args) {
SimpleSim simpleSim = new SimpleSim();
simpleSim.start();
}
private void start() {
Bug myBug = new Bug();
// Give the bug some initial x, y values.
myBug.x = 0;
myBug.y = 0;
while (endSim == false) {
nextMove(myBug);
System.out.print(room.printRoom() + "\n\nNext move? (y/n) ");
simSentinel = in.next();
if (simSentinel.charAt(0) == 'n')
endSim = true;
}
}
}
public void nextMove(Bug bug){
if (dirNum == 0 && bug.y < length-1) //Move up
bug.y++;
else if (dirNum == 1 && bug.x < width-1) //Move right
bug.x++;
else if (dirNum == 2 && bug.y > 0) //Move down
bug.y--;
else if (dirNum == 3 && bug.x > 0) //Move left
bug.x--;
else {
System.out.println("Error: Cannot move " + "?" + ".");
canMove = false;
dirNum = generator.nextInt(4);
}
}
}
It seems that you are passing your bugX and bugY parameters by value. In this case, changing their value inside the method won't affect their values outside the method.
You may want to make your nextMove method return the new values for bugX and bugY after they are computed so that you can gather them back into your actual bugX and bugY variables
I have a list of colors with numbers associated with them. I'd like to make it so that, if the user types in "2", it selects "2: Green"; if they type in "21", it selects "21: Yellow"; etc. I'm trying to use KeyPressed, and I think I need some way for the program to listen for the first number pressed and then wait a second to see if another is pressed. For example, something like this:
// The integer pressed will always be zero or positive.
private void jComboBox1KeyPressed(KeyEvent evt) {
int code = -1;
for(int i = 0; i < 10; i++) {
if (evt.getKeyCode() == i) {
if (code == -1) {
code = i;
} else {
code += i;
}
break;
}
}
// PSEUDO-CODE: if (KeyEvent newEvt is pressed within 1 sec) {
jComboBox1KeyPressed(newEvt);
}
}
Then, I suppose I'd have a key-value map with an index and the color numbers, and I'd set the selected item for jComboBox1 based on code (the selected color number).
I've got it working for a single keyPressed:
private void jComboBox1KeyPressed(java.awt.event.KeyEvent evt) {
if (evt.getKeyCode() == KeyEvent.VK_0) {
jComboBox1.setSelectedItem("2: Green");
}
else if (evt.getKeyCode() == KeyEvent.VK_1) {
jComboBox1.setSelectedItem("21: Yellow");
}
else if (evt.getKeyCode() == KeyEvent.VK_2) {
jComboBox1.setSelectedItem("13: Blue");
}
else if (evt.getKeyCode() == KeyEvent.VK_3) {
jComboBox1.setSelectedItem("2041: Red");
}
}
Here's the interface:
PLEASE NOTE: This is an example I quickly made and not the actual app I'm creating. My app involves many more number options, but as with this example, the numbers will always be positive.
I am working on a landscape java game.
I have a sprite array like this;
Sprite stickArray[] = new Sprite[10];
and initializing it like this with visibility as false.
for (int j = 0; j < stickArray.length; j++) {
if (stickArray[j] != null) {
stickArray[j].setPosition(stickX, stickY);
stickArray[j].setVisible(false);
}
}
Later I want to position it like one after another vertically on repeating a key.pressBool is false initially.
public void keyRepeatInGame(int keyCode) {
int gameKey = getGameAction(keyCode);
Graphics g = getGraphics();
if (gameKey == FIRE || keyCode == KEY_NUM5) {
pressBool = true;
}
}
Later I have written code like this;
Initially one Sticksprite is there.above this sprite, I want to place each sticks on clalling keyrepeat()in space key.
for (int i = 0; i < stickArray.length; i++) {
if (pressBool) {
if (i == 0) {
stickArray[i].setPosition(stickSprite.getX(),
stickSprite.getY() - stickSprite.getHeight());
stickArray[i].setVisible(true);
} else {
stickArray[i].setPosition(stickArray[i-1].getX(),
stickArray[i-1].getY() - stickArray[i].getHeight());
stickArray[i].setVisible(true);
}
}
}
This code is working partially.Stick is getting added on the sprite,all at once.
How can I change the code to make the sticks repeatedly getting added on calling keyrepeat() only, and make it visible one by one properly?
I changed the code with an additional condition and break statement like this;
if (pressBool) {
if (stickSprite != null && !stickArray[i].isVisible()
&& stickArray[i] != null) {
if (i == 0) {
stickArray[i].setPosition(
stickSprite.getX(),
stickSprite.getY());
stickArray[i].setVisible(true);
break;
} else if (i > 0) {
stickArray[i].setPosition(
stickArray[i].getX(),
stickArray[i - 1].getY()
- stickArray[i].getHeight());
stickArray[i].setVisible(true);
break;
}
}
}
It worked.
I'm making a snake game and I've encountered an error.
I have tried two different loops: thread.sleep and Timer.schedule.
I have gotten the same problem.
It will be working fine, but at random intervals, it will start to skip every other frame for 6-10 frames.
In case I wasn't clear, 1 frame is
#Override public void paintComponent(Graphics G){...}
being called. (I have also tried paint)
This has occurred in some other games I've created, but not all. What can I do to fix it?
Here's a full copy of the code:
https://github.com/jnmcd/Snake/blob/master/Code.java
EDIT: I've done some debugging. It appears that the it's not a problem with the paint. The JPanel doesn't always update. What can I do to fix it?
I found what I needed to do. I had to add a revaidate() after the repaint().
Also In the checkKillCollisions you have to break the loop right after you found the losing condition.
Also if the game ends it keeps on showing the error message[Dialog] for which there i no end.So I have created a flag gameOver to check is game is over or not in Snake Class
static Boolean gameOver = false;//Defined in Snake Class
public void checkKillCollisions() {
boolean lose = false;
for (int i = 1; i < Snake.segments.size(); i++) {
if (Snake.segments.get(i).x == x && Snake.segments.get(i).y == y) {
lose = true;
break;//Have to do this
}
}
if (x >= 60 || x < 0 || y >= 60 || y < 0) {
lose = true;
}
if (lose) {
Snake.window.popUp("You Lose");
}
Snake.gameOver = lose;//Will set the gameOVer flag in Snake class
}
And I've modified the Loop class to stop running right after the gameOver flag is set to true
class Loop extends TimerTask {
#Override
public void run() {
if (!Snake.gameOver) {
Snake.updates();
Snake.window.render();
} else {
System.out.println("Game Over");
cancel();
Snake.window.dispose();
}
}
}