This java method is skipping over a return statement. I was wondering if anybody has encountered this and know of a solution. Whatever the bug is it's very subtle.
public GameState getNextGameState() {
if (player.getLives() > 0) {
if (!player.isAlive()) {
System.out.println("checkpoint 1");
player.setIsAlive(true);
return new PlayField(width, height, hiScores, player.setCoordinates(width / 2, height - 8),
stagePattern, stage);
}
System.out.println("checkpoint 2");
if(++stage > 29)
stage = 0;
return new PlayField(width, height, hiScores, player.setCoordinates(width / 2, height - 8), stage);
}
return new GameOver(Game.key, hiScores, player.getRank());
}
Here is a screenshot with console output to prove it:
Also, this bug only started happening when I put my gamestates in a stack structure. Here is the code I'm now using for the gamestate transition:
public void update() {
gsm.peek().update();
if(gsm.peek().finished)
if(gsm.peek().getNextGameState() == null)
gsm.pop();
else
gsm.push(gsm.pop().getNextGameState());
}
gsm declaration is:
public static Stack<GameState> gsm = new Stack<GameState>();
Hopefully someone has some insight. Thank you!
It is not the result of the same call.
You call twice the method here.
The first time it is not alive, the second is alive. So you have the both message in the output.
In a game, the update phase is called in a continuous way.
Just add a System.out.println at the beginning of the method (that is before the conditions) and you could have the confirmation :
public GameState getNextGameState() {
System.out.println("enter method");
...
}
Can you post more code? You are probably calling it twice and it is not skipping over the return. If you really think it is put a break point to assist you with debugging and watch the code run.
Related
I'm making an escape room through the console.
I'm trying to run an if statement, and I want to have the if statement code run once, and then run the else code forever afterward. My program is looped to go back to the same menu after it's finished with a choice the user chooses.
Here is my current code:
if (checkBedDraw = false) {
clear();
typePrint("You found a \u001b[34mpicklock\u001b[0m! you can only use this on a specific lock, because of its shape. This item has been added to your \u001b[31minventory\u001b[0m.", 50);
invArray[0] = "picklock";
checkBedDraw = true;
} else if (checkBedDraw = true) {
typePrint("You have already checked the drawers, and aqcuired a picklock.", 50);
}
typePrint() and clear() are methods I made.
= and ==
Be careful, in if statements you have to use == as = is used to assign a value to a variable.
Also, you are dealing with Boolean so you can just do something like this:
if (checkBedDraw) {
typePrint("You have already checked the drawers, and aqcuired a picklock.", 50);
} else {
clear();
typePrint("You found a \u001b[34mpicklock\u001b[0m! you can only use this on a specific lock, because of its shape. This item has been added to your \u001b[31minventory\u001b[0m.", 50);
invArray[0] = "picklock";
checkBedDraw = true;
}
I've been writing a method to switch two images. This method is called in a mouse drag-and-drop event and is followed by another method that lets images drop down a few positions (I'm talking about a sort of candy crush mechanism).
In my case, the transition in the second method starts before the switch is done, which is why you can barely see the switch.
What I'm looking for is a way to make the program wait until the first transition is finished before it steps into the next method. Thread.sleep() isn't working for me since it stops the switch animation as well, and I don't know how to use the transition.setOnFinished() properly within my switch method without causing an infinite loop.
This is part of my switch method:
public void animateSwitch(int xFirst, int yFirst, int xLast, int yLast) {
/.../
ParallelTransition allMovements = new ParallelTransition();
TranslateTransition tt = new TranslateTransition(Duration.millis(FALL_TIME_PER_ROW), getNodeFromGridPane(grdPane, xFirst, yFirst));
TranslateTransition tt2 = new TranslateTransition(Duration.millis(FALL_TIME_PER_ROW), getNodeFromGridPane(grdPane, xLast, yLast));
Image old = iv1.getImage();
iv1.setImage(iv2.getImage());
iv1.setTranslateX(iv2.getX());
iv1.setTranslateY(iv2.getY());
iv2.setImage(old);
iv2.setTranslateX(iv1.getX());
iv2.setTranslateY(iv1.getY());
if (xFirst == xLast) {
tt.toYProperty().set(0);
tt.toXProperty().set(tt.getFromX());
if (yFirst < yLast) {
tt.fromYProperty().set(rowHeight);
tt2.fromYProperty().set(-rowHeight);
}
else {
tt.fromYProperty().set(-rowHeight);
tt2.fromYProperty().set(rowHeight);
}
tt2.toYProperty().set(0);
tt2.toXProperty().set(tt2.getFromX());
}
else if (yFirst == yLast) {
tt.toXProperty().set(0);
tt.toYProperty().set(tt.getFromY());
if (xFirst < xLast) {
tt.fromXProperty().set(rowWidth);
tt2.fromXProperty().set(-rowWidth);
}
else {
tt.fromXProperty().set(-rowWidth);
tt2.fromXProperty().set(rowWidth);
}
tt2.toXProperty().set(0);
tt2.toYProperty().set(tt2.getFromY());
}
allMovements.getChildren().add(tt);
allMovements.getChildren().add(tt2);
allMovements.play();
}
Thanks in advance!
You will have to set the onFinished event handler using allMovements.setOnFinished(eventHandler); Here eventHandler is an object that implements the EventHandler interface.
EDIT:
I skipped past the part where you don't know how to prevent an infinite loop using this solution. You can use two different eventHandlers to do the different parts. The first calls the second when it finishes. The second doesn't need to call the first, so you will not get into a loop.
I am trying to perform white box testing on the method below. It's a method for blinking an array list (lightUpSequence) of JButtons in Swing using a timer.
My question is as follows:
since this is a void method, how would one check the expected output? I plan to create different sizes of array lists as the inputs. For white box testing, is one allowed to add any codes such as print/counter statements inside the method being tested? I feel hesitant to add any modifications to the method and think that the method should be tested as is.
Thank you very much.
private void blinkSequence() {
final Timer timer = new Timer(BLINKING_TIMER_DELAY, null);
timer.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (lightUpSequence.size() == 0) {
timer.stop();
}
// Turn button ON
if (!isON && lightUpSequence.size() > 0) {
int elementIndex = lightUpSequence.get(0);
buttonArrayList.get(elementIndex).setBackground(
Color.yellow);
isON = true;
// Turn button OFF if it's ON already. Then remove the
// element.
} else if (isON && lightUpSequence.size() > 0) {
int elementIndex = lightUpSequence.get(0);
buttonArrayList.get(elementIndex).setBackground(null);
lightUpSequence.remove(0);
isON = false;
}
}
});
timer.start();
timer.setRepeats(true);
}
Well, there is nothing stopping you from making it return a boolean, but if you want to keep it the way it is you can use assert statements.
have a look at assert
For testing void method I use the following startegy:
Granulize the variables of the method through globalizing them.
So if you have an array, check the size before and after calling it.
If the size is the same, check the state of the objects in the array and compare them as before and after calling the method, like if they are lit or not.
In this way you can effectively comply to the white box testing rules.
[UPDATE] i changed the order a bit so i call the super.act(delta) at the end of the method and it seems to help a bit! But not that sure about it yet.
I got a square system for my map. So its an 2D array and i i make one move the figure does move from one square to the next. While that it's not possible to "stop" the figure between 2 squares. When my characters made one move i check if the Touchpad is touched and if yes i start the next move. While that it seems to lag sometimes and i dont know why!? I really hope you may find the "lag". Here is how i calculate the next move inside the act()of my Actor Character:
#Override
public void act(float delta) {
super.act(delta); // so the actions work
if (moveDone) {
if (screen.gameHud.pad.isTouched()) {
// check in which direction is the touchcontroller
if (screen.gameHud.pad.getKnobPercentX() < 0
&& Math.abs(screen.gameHud.pad.getKnobPercentY()) < Math
.abs(screen.gameHud.pad.getKnobPercentX())) {
// checkt if the |x|>|y|
if (checkNextMove(Status.LEFT)) {
this.status = Status.LEFT;
move(Status.LEFT);
this.screen.map.mapArray[(int) (this.mapPos.x)][(int) this.mapPos.y] = Config.EMPTYPOSITION;
this.screen.map.mapArray[(int) (this.mapPos.x - 1)][(int) this.mapPos.y] = Config.CHARSTATE;
this.mapPos.x--;
moveDone = false;
}
} else if //.... rest is the same just with other directions
else{ //if touchpad isnt touched!
setIdle();
}
updateSprite(delta); //just change the textureRegion if its time for that
} //methode end
Okay so you need some more informations i am sure. Checkmoves like this:
case LEFT:
if (this.mapPos.x - 1 >= 0)
if (this.screen.map.mapArray[(int) (this.mapPos.x - 1)][(int) this.mapPos.y] == Config.EMPTYPOSITION)
return true;
break; //same for all other just direction changin
And the last you need to know is the move(_) i guess. It does add an moveTo Action to my figures.
public void move(Status direction) {
switch (direction) {
case LEFT:
this.addAction(Actions.sequence(
Actions.moveTo((getX() - Config.BLOCK_SIZE), getY(), speed),
moveDoneAction));
break;
moveDoneAction is a simple RunnableAction that set the boolean moveDone to true if its done moving.
i really hope you can help. If you need some more informations please let me know as comment!
There are better tools than StackOverflow for optimizing Android code. Use a profiler and see what is actually happening. Specifically, the traceview profiler: how to use traceview in eclipse for android development? (If you're not using Eclipse, you can use traceview directly via the ADT.)
I am just trying to figure out the logic of why I have an error. I'm trying to add 2 displays in 1 for the first time and switching the views using the commandListener. I thought logically I did everything right but I'm getting a null pointer exception. I never want to know the answers, I enjoy working hard so maybe if anyone can maybe ask me a question as to what I am trying to achieve that can lead me to think of the answer using your clues or hints. It will be appreciated.
import java.io.*;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class ClassApp extends MIDlet implements CommandListener {
private Display mydisplay;
private TextBox d;
private Alert alert;
private Command c,e,f,mNextCommand,l;
private List mList;
public ClassApp(){
alert = new Alert("Listen", "Do you really want to start this app?", null, null);
alert.setTimeout(Alert.FOREVER);
c = new Command("Exit", Command.EXIT, 2);
e = new Command("Back", Command.BACK, 0);
f = new Command("Alert", Command.SCREEN, 3);
mNextCommand = new Command("Next", Command.SCREEN, 4);
l = new Command("List", Command.SCREEN, 3);
d = new TextBox("ClassApp", "Commander", 20, TextField.ANY | TextField.PASSWORD);
d.addCommand(c);
d.addCommand(e);
d.addCommand(f);
d.addCommand(l);
d.setCommandListener(this);
mList.addCommand(mNextCommand);
mList.setCommandListener(this);
String[] stringElements = { "Airplane", "Car", "Hotel" };
Image[] imageElements = { loadImage("/airplane.png"),
loadImage("/car.png"), loadImage("/hotel.png") };
mList = new List("Reservation type", List.IMPLICIT,
stringElements, imageElements);
}
public void startApp()
{
mydisplay = Display.getDisplay(this);
mydisplay.setCurrent(d);
}
public void commandAction(Command j, Displayable s)
{
if(j == f)
mydisplay.setCurrent(alert);
if(j == l)
mydisplay.setCurrent(mList);
if (j == mNextCommand || j == List.SELECT_COMMAND) {
int index = mList.getSelectedIndex();
Alert alert2 = new Alert("Your selection",
"You chose " + mList.getString(index) + ".",
null, AlertType.INFO);
mydisplay = Display.getDisplay(this);
mydisplay.setCurrent(alert2, mList);
}
else if(j == c)
notifyDestroyed();
}
public void pauseApp() { }
public void destroyApp(boolean unconditional) { }
private Image loadImage(String name) {
Image image = null;
try {
image = Image.createImage(name);
}
catch (IOException ioe) {
System.out.println(ioe);
}
return image;
}
}
And the error I get is :
Starting emulator in execution mode
Installing suite from: http://127.0.0.1:2913/ClassApp.jad
java.lang.NullPointerException: 0
at ClassApp.<init>(ClassApp.java:33)
at java.lang.Class.newInstance(), bci=0
at com.sun.midp.main.CldcMIDletLoader.newInstance(), bci=46
at com.sun.midp.midlet.MIDletStateHandler.createMIDlet(), bci=66
at com.sun.midp.midlet.MIDletStateHandler.createAndRegisterMIDlet(), bci=17
at com.sun.midp.midlet.MIDletStateHandler.startSuite(), bci=27
at com.sun.midp.main.AbstractMIDletSuiteLoader.startSuite(), bci=52
at com.sun.midp.main.CldcMIDletSuiteLoader.startSuite(), bci=8
at com.sun.midp.main.AbstractMIDletSuiteLoader.runMIDletSuite(), bci=161
at com.sun.midp.main.AppIsolateMIDletSuiteLoader.main(), bci=26
maybe if anyone can maybe ask me a question as to what I am trying to achieve that can lead me to think of the answer using your clues or hints...
OK here we go.
ClassApp.java:33 part of error message says you which line of the code in ClassApp.java is problematic. Side note cryptic looking part ClassApp.<init> is telling you that bad things are happening within ClassApp constructor.
If you count to line 33 from top, you'll probably find this:
mList.addCommand(mNextCommand);
Now, if you look for the way how mList is dealt with inside the constructor (there are about 20 lines to check), you'll discover one amusing fact that will guide you in finding what is wrong there.
Another thing worth keeping in mind investigating bugs like that is the name NullPointerException shown at the top of stack trace. It translates to human language as
There is null value somewhere where it should not be.
This often indicates that some variable has not been properly assigned as you probably already noticed.
PS.
I'm going to continue to look for better efficiency (like moving the code into startapp)
Initializing in startApp is rather a matter of reliability than that of efficiency.
There are couple things that are recommended to initialize in the startApp instead of constructor. These are explained for example in tutorial MIDlet Life Cycle -> Execution States: "Typically, you'll use startApp() to allocate record stores, network connections, UI components, and such..."
As far as I understand there is no definitive list of what is guaranteed to be safely initialized in constructor. Because of that I try to do a much initialization as possible in startApp - that way, I don't need to bother with cumbersome checks in specification for whether it is safe or not.