State Management - [Switching States, Replaying the Game] - java

How to effectively switch states?Whenever I press the replay button, the two states shows alternatively (win & play). I believe that was an infinite loop but Eclipse does not print any errors.
When I tried this, it results to null.Thus, ending the game.
Could this be the answer? But I don't understand his Update(). What to put exactly there?will that overwrite the update of the state class?
Here is my code:
stateID(2) is the Wins.java
PlayGround.java
public static boolean bouncy = true;
public void update(GameContainer gc, StateBasedGame sbg, int delta) throws SlickException{
//if the user is successful, show winner state
if(!bouncy){
sbg.enterState(2);
}
//moves the image randomly in the screen
new Timer(10,new ActionListener(){
public void actionPerformed(ActionEvent e)
{
posX = (r.nextInt(TestProject4.appGC.getWidth()-75));
posY = (r.nextInt(TestProject4.appGC.getHeight()-75));
}
}).start();
}
public void mousePressed(int button,int x,int y){
//if the user pressed the mouse button And
//if the user's coordinates is inside the hit area(rect)
if((button == 0) && (rect.contains(x, y))){
Toolkit.getDefaultToolkit().beep();
bouncy = false;
}
}
Wins.java
#Override
public void update(GameContainer gc, StateBasedGame sbg, int delta)throws SlickException {
//replay game
if(backToGame == true){
sbg.enterState(state);
}
}
public void mousePressed(int button,int x,int y){
//if the user clicks the replay button
if(button == 0){
if((x>160 && x<260)&&(y>280 && y<320)){
if(Mouse.isButtonDown(0)){
backToGame = true;
state = 1;
}
}
//exit button
if((x>=360 && x<460)&&(y>280 && y<320)){
if(Mouse.isButtonDown(0)){
System.exit(0);
}
}
}
}

I think you switch between both states again and again because both GameState objects are still in the same "state" (variables have still the same values) when you switch back.
Try:
if(!bouncy){
bouncy = true; // next time we are in this game state it will not trigger immediately
sbg.enterState(2);
}
if(backToGame == true){
backToGame = false; // same here
sbg.enterState(state);
}
Previous answer:
Please check your if statement:
if((x>160 && x<180)||(y>280 && y<320)){
You are checking whether the mouse is between some x coordinates OR some y coordinates.
I think you want to check whether the mouse is between some x AND some y coordinates:
if((x>160 && x<180)&&(y>280 && y<320)){

Your code has two methods mousePressed() one in PlayGround.java and the other in Wins.java.
The application is clearly using the Playground.java Code.
Adding the button detection code into the PlayGround.java may solve the problem.
Other wise explicitly calling the mousePressed() method in Wins from PlayGround.java
may work as well.
Adding comments help.
It can show your train of thought for a project, Helps others to try and see what you are doing.
In fleshing out a complex method I comment excessively at first, weeding out obvious comments through iterations of debugging and code review.
I also helps when others are viewing your code.
Remember There are no stupid comments, only stupid people.

Related

main menu with switch statement

So for a school project, I have to create a game with a program called 'Processing'.
I am creating a main menu with the switch statement. For that I want to use the buttons 'Start', 'Help', and 'exit'.i would like to use those buttons to change the variables of the switch statement. Therefore I'm using "mousePressed". The problem is that which button I'm pressing, is giving me the same result as the 'exit' button. Could somebody give me tips on how I can structure my menu better or even make my button work? I am using a library on Processing called 'ControlP5' to make my buttons.
here is my code so far:
int mode; // 1: intro screen, 2: game , 3: game over
final int INTRO = 1;
final int PLAY = 2;
final int GAMEOVER = 3;
//==============================================================
void setup(){
size(1920,1080);
mode = 1;
}
//========================================================
void draw(){
if(mode == 1){
introScreen();
}
else if (mode == 2){
gameItself();
}
else if (mode == 3){
gameOver();
}
else println("mode error");{
}
}
void introScreen(){
mode = 1;
static int Page = 0;
import controlP5.*;
ControlP5 cp5;
cp5= new ControlP5(this);
switch(Page){
case 0: // main menu
cp5.addButton("Start").setValue(0).setPosition(1420,250).setSize(400,100);
cp5.addButton("Exit").setValue(0).setPosition(1420,650).setSize(400,100);
cp5.addButton("Help").setValue(0).setPosition(1420,450).setSize(400,100);
break;
case 1: //help menu
cp5.addButton("Back").setValue(0).setPosition(1420,450).setSize(400,100);
break;
}
public void Start(){
if(mousePressed){
mode = 2; // switching to the game itself
}
println("Start");
}
public void Exit(){
if(mousePressed){
exit(); }
println("Exit");
}
public void Help(){
Page = 1;
println("Help");
}
public void Back(){
if(mousePressed){
Page = 0;
}
println("Back");
}
void gameItself(){
// game and stuff
}
void gameOver(){
//gameover
}
Take a look at how the mousePressed event works. You may use this information useful.
To achieve your goal as to change the Page variable by clicking buttons, there are multiple options. First, I'll go with the easier one, the one which doesn't need an import but just check for coordinates. Then I'll do the same thing, but with controlP5.
1. Just checking where the clicks lands
I'll go with the most basic one: detecting the "click" and checking if it's coordinates are inside a button.
First, we'll add the mouseClicked() method. This method is called every time a mouse button is pressed.
// I'm typing this out of IDE si there may be some quirks to fix in the code
void mouseClicked() {
switch(Page) {
case 0:
if (mouseX > 1420 && mouseX < 1420+400 && mouseY > 250 && mouseY < 250+100) {
// You're in the main menu and Start was clicked
}
if (mouseX > 1420 && mouseX < 1420+400 && mouseY > 650 && mouseY < 650+100) {
// You're in the main menu and Exit was clicked
}
if (mouseX > 1420 && mouseX < 1420+400 && mouseY > 450 && mouseY < 450+100) {
// You're in the main menu and Help was clicked
}
// You should use 'else if' instead of 3 different if, but I coded it like that so it would be easier to see the small differences between the coordinates
case 1:
if (mouseX > 1420 && mouseX < 1420+400 && mouseY > 450 && mouseY < 450+100) {
// You're un the help menu and Back was clicked
}
}
}
As you can see, I just used the coordinates and size of your buttons to check if the click was located inside one. That's kind of ninja-ing my way out of this issue. I don't know how far into programming you are, or else I would recommand to build a class to handle user inputs, but this way is easy to manage for small exercises like homework.
2. Designing controlP5 buttons
I'm not a ControlP5 expert, so we'll keep close to the basics.
I'll be blunt, the code you provided is ripe with problems, and it's not so many lines, so instead of pointing where it goes wrong I'll give you some skeleton code which will work and on which you can build some understanding. I'll give you the tools and then you can make your project work.
When you design your buttons, if you design them all in the same object, they'll share some properties. For an example, all your buttons will be visible or invisible at the same time. You don't need to redraw them all the time, because they already handle this, so you need to manage them with another method.
You should design your buttons as global objects (as you did), and add them to the ControlP5 object which makes the most sense. You can have one button per object if you want, or many if they are linked together, for an example all the "menu" buttons which appears at the same time could be owned by the same object. Design your buttons in the setup() method if you design them only one time for the whole program. Of course, if this was more than an homework, you may want to avoid the buttons being globals, but it'll be much easier to keep them in memory for a short project.
The "name" of the button is also the name of the method that it'll try to call if you click on it. Two buttons cannot share the same "name". Buttons can have a set value which will be sent to the method that they call.
You don't need to use Processing's mouse events for the buttons to work. They are self-contained: they have their own events, like being clicked on or detecting when the mouse is over them. Here's the documentation for the full list of the methods included in the ControlP5 buttons.
You don't need to manage the buttons in the draw() loop. They manage themselves.
Here's some skeleton code to demonstrate what I just said. You can copy and paste it in a new Processing project and run it to see what's going on.
ControlP5 cp5;
ControlP5 flipVisibilityButton;
int Page = 0;
void setup() {
size(1920, 800);
textAlign(CENTER, CENTER);
textSize(60);
fill(255);
cp5 = new ControlP5(this); // this is ONE object, which will own buttons.
cp5.addButton("MenuButton0") // this is the name of the button, but also the name of the method it will call
.setValue(0) // this value will be sent to the method it calls
.setPosition(1420, 250)
.setSize(400, 100);
cp5.addButton("MenuButton1")
.setValue(1)
.setPosition(1420, 450)
.setSize(400, 100);
cp5.addButton("MenuButton2")
.setValue(2)
.setPosition(1420, 650)
.setSize(400, 100);
flipVisibilityButton = new ControlP5(this); // this is a different object which own it's own controls (a button in this case)
flipVisibilityButton.addButton("flipVisibility")
.setValue(2)
.setPosition(200, height/2)
.setSize(200, 100);
}
void draw() {
// No button management to see here
background(0);
// showing which button has been pressed while also keeping watch to see if the mouse is over one of the cp5 buttons
text(Page + "\n" + cp5.isMouseOver(), width/2, height/2);
}
void MenuButton0(int value) {
ChangePage(value);
}
void MenuButton1(int value) {
ChangePage(value);
}
void MenuButton2(int value) {
ChangePage(value);
}
void ChangePage(int value) {
Page = value;
}
void flipVisibility(int value) {
// When the buttons are invisible, they are also unclickable
cp5.setVisible(!cp5.isVisible());
}
You should be able to expand on this example to do your project, but if you have difficulties don't hesitate to comment here and ask further questions. Have fun!

How to record a longer touch for a higher jump on libgdx

So in my game I want to have it so the longer someone holds down on the screen the higher my character jumps. However I don't know how to check if someone is holding down on the screen.
My current attempt is to do this:
And run it every frame in the update method
public void handleInput(float dt) {
if (Gdx.input.isTouched()) {
if (sheep.getPosition().y != sheep.maxHeight && sheep.getPosition().y == sheep.minHeight) {
sheep.jump(1);
}
if (sheep.getPosition().y == sheep.maxHeight && sheep.getPosition().y != sheep.minHeight) {
sheep.jump(-1);
}
}
}
I am suggesting two way to detect long touch, choose one according to your requirement.
You can use longPress method of GestureListener interface to detect there is a long press or not. By default longPress duration is 1.1 seconds that mean user have to touch the screen equal to this duration, to fire a longPress event.
#Override
public boolean longPress(float x, float y) {
Gdx.app.log("MyGestureListener","LONG PRESSED");
return false;
}
Set your implementation as InputProcessor.
Gdx.input.setInputProcessor(new GestureDetector(new MyGestureListener()));
longPress only gets called one time after holding the screen for X time. so it's better to create own logic and check how long user touched the screen.
if (Gdx.input.isTouched()) {
//Finger touching the screen
counter++;
}
And on touchUp of InputListener interface make jump according to value of counter and reset value of counter to zero.
#Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
//make jump according to value of counter
counter=0; //reset counter value
return false;
}
Set your implementation as InputProcessor.
Gdx.input.setInputProcessor(new MyInputListener());

Adjust Key Pressed So You Cant "Hold" it

Wasn't sure how to word the title.
I have some code for my "space invaders" type game. I made the entire thing just making adjustments. To shoot, i use spacebar. The problem is im able to hold spacebar and it continually shoots. I would rather have to press it multiple times (if i hold it down.. for it not to continually fire) How would i change it?
*here is the code i believe is the source of the problem. If the source is located elsewhere please say so.
private class KeyInputHandler extends KeyAdapter {
private int pressCount = 1;
/**
* key pressed
*/
public void keyPressed(KeyEvent e) {
if (waitingForKeyPress) {
return;
}
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
leftPressed = true;
}
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
rightPressed = true;
}
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
firePressed = true;
}
}
/**
* Key Released
*/
public void keyReleased(KeyEvent e) {
if (waitingForKeyPress) {
return;
}
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
leftPressed = false;
}
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
rightPressed = false;
}
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
firePressed = false;
}
}
added code
public class ShotEntity extends Entity {
//vertical speed
private double moveSpeed = -300;
private Game game;
private boolean used = false;
/**
* Create a new shot from the player
*/
public ShotEntity(Game game,String sprite,int x,int y) {
super(sprite,x,y);
this.game = game;
dy = moveSpeed;
}
/**
* Request that this shot moved based on time
*/
public void move(long delta) {
super.move(delta);
if (y < -100) {
game.removeEntity(this);
}
}
//collision
public void collidedWith(Entity other) {
// prevents double kills.
if (used) {
return;
}
// alien killed
if (other instanceof AlienEntity) {
game.removeEntity(this);
game.removeEntity(other);
game.notifyAlienKilled();
used = true;
}
}
}
Listen for two seperate key events. One when the key is pressed, and one when it is released. Now, you make a boolean.
public boolean myBoolean;
When the key is pressed, set the boolean to true (myBoolean==true)and if it is released, set it to false (myBoolean==false).
Now, create a simple if statement:
if(myBoolean==true){ //Key is being held down
//execute this code
//Have nothing be done
}
Thats it!
P.S. If you want, you can have one separate method to clean up the code. This method could just change the value of the boolean:
public void changeValueOfBoolean(Boolean b){
if(b = true){
return false;
}
if(b==false){
return true;
}
}
It's very simple. Let me know if you need any help, and if this was helpful, please mark it as best answer. Feel free to ask me any questions, I am always happy to help!
Clarifications:
Okay, so we have this boolean, right? Now, this boolean essencialy decides whether the key is pressed or not.
Say we press the button:
Because the key is being held down, we make the boolean myBoolean as true. Now, because the user is holding the key down, we want to do nothing, right? That's why we created that if statement:
if(myBoolean==true){ //Key is being held down
//execute this code
//Have nothing be done
}
It says, if the boolean is true, then we won't do anything. Recall, the boolean is true when the key is being held down, remember? So, when the key is held down, the boolean is true, and nothing will be done.
Now, when the user releases the key:
Now, say the user has pressed the key. This will call two listeners. One listener for when the key is pressed and another for when it is released. If the user just presses the key, myBoolean will end as false, since they have let go of the key. Therefore, we can execute some code when myBoolean is false (shooting).
**In summary:
myBoolean is true when when the key is being held down. So, when it is true, we do nothing. myBoolean is false when the user lets go of the key, and there, we shoot the space invaders.**
Simple, just have a Boolean variable which causes the ship to shoot only when it is true. Then set it to true in the space bar is pressed and set it to false when the ship shoots. I can't show you how to implement it in your program as I don't know how your shoot method works. However, if you were to post the method which causes the ship to shoot then, I could show you how to implement it or, you could try your self.

LIBGDX collision with bottom part of box only

Im trying to get my collision using box2D in jumping game work correct but i have some problems. The player have Box Shape and Platform is just a line made with chainShape.
First problem is that i would like to enable collision only when Player touch Platform with bottom line of it's box. I tried to do that by checking the y coordinates of body but it doesnt worked becouse the diffrence beetween platform and bottom part of box while collision was about 0.5 units.
Second problem is that at the moment the collision is turning on two or three times for same platform in single touch. Here i don't have idea how i can fix it.
Actual code for collision in my code is:
#Override
public boolean shouldCollide(Fixture fixtureA, Fixture fixtureB) {
if(fixtureA == fixture || fixtureB == fixture){
return body.getLinearVelocity().y< 0; //&& (fixtureA.getBody().getPosition().y <= fixtureB.getBody().getPosition().y);
}
return false;
}
#Override
public void preSolve(Contact contact, Manifold oldManifold) {
if(contact.getFixtureA() == fixture || contact.getFixtureB() == fixture){
//System.out.println("Contact A: "+ contact.getFixtureA().getBody().getPosition().y);
//System.out.println("Contact B: "+ contact.getFixtureB().getBody().getPosition().y);
if(contact.getFixtureA().getBody().getPosition().y == contact.getFixtureB().getBody().getPosition().y)
contact.setEnabled(true);
else
contact.setEnabled(false);
}
}
//COLLISION CALCULATION
#Override
public void postSolve(Contact contact, ContactImpulse impulse) {
body.applyLinearImpulse(0, jumpPower, body.getWorldCenter().x, body.getWorldCenter().y, true);
}
Thanks in advance.

Java2D games: How to handle keyboard correctly?

I found a very good tutorial about how to create games with Java2D. In this tutorial there is a section called 'Moving sprites' that shows how to move a little spacecraft image on the screen. I was playing with the craft and realized that it was "blocking" on screen sometimes. After some tests and thinking about the problem I found out that the blocking problem was happening because when you use the arrows of the keyboard sometimes you press Left and Right at same time for example, and this blocks the movement.
So my question is: how do I handle this kind of keyboard event - when you are pressing LEFT button keep pressing it and then press RIGHT button - so the character movement is not blocked?
I think this is very common to happen because when you are playing you switch from left to right but for an instant you are pressing left and right at the same time.
You can do this in multiple ways. One way is to use booleans in your program.
You can set booleans to true when you press a certain key and to false when you release them. ie:
int x,xSpeed;
boolean movingLeft = false;
boolean movingRight = false;
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_LEFT){
movingLeft = true;
}
if(key == KeyEvent.VK_RIGHT){
movingRight = true;
}
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_LEFT){
movingLeft = false;
}
if(key == KeyEvent.VK_RIGHT){
movingRight = false;
}
}
public void moving(){
if(movingLeft){
x -= xSpeed;
}
if(movingRight){
x += xSpeed;
}
}
Ok let's look at this code. Because we're using the 'else if' you either move right, or you move left. I haven't test this code so not quite sure if this will work :)
Let me know what you think and good luck!

Categories

Resources