set a delay in libgdx game - java

i have a game(like super jumper, this game is a jumping game) that our character has life. after collision with enemies, his life reduce. and i want to after 1 sec , calculate the collisions. i mean in this 1 sec, if my character contact with enemies , nothing happen and he continue his way.
for this , i define a boolean variable in my GameScreen class, name "collision" and another in Wolrd class, name "collBirds". after one contact with enemy collision and collBirds change to true. but i want after 1 sec collistion change to false. i use several things like System.currentTimeMillis() and "for loop",and nothing happen. i'm not so good in java.
this is my condition:
if(World.collBirds == true && collition == false){
life -= 1;
lifeString = "Life : " + life;
World.collBirds = false;
collition = true;
for (??? "need to stay here for 1 sec" ???) {
collition = false;
}
}

In some cases you could also want to use com.badlogic.gdx.utils.Timer
Example usage:
float delay = 1; // seconds
Timer.schedule(new Task(){
#Override
public void run() {
// Do your work
}
}, delay);

When the first collision occurs, set a float timeSinceCollision = 0;
Then each loop, you will need to add the time since last check to the variable, and check if it's more than a second.
timeSinceCollision += deltaTime;
if(timeSinceCollision > 1.0f) {
// do collision stuff
} else {
// ignore the collision
}

If you want to do this in same thread than you can use Thread.sleep(). But in this case your current thread will freeze and if this is single thread game, than your whole game will freeze. If you don't want your game to freeze for 1 second, than you should spawn the thread and in that thread call the sleep and after sleep, change the flag

Related

how to get onKeyPressed Duration?

I am trying to create a snake game where i use arrow keys or WASD to move the snake.
Initially the snake is slow and moves at 2 fps speed (like the classic snake game), i want the snake to move faster when i am holding down one of the keys and set it to original speed when i release it.
i tried changing the movement rate inside onKeyPressed like so:
scene.setOnKeyPressed(event -> {input = event.getCode().toString();
for (String acceptedKey : acceptedKeys) {
if (event.getCode().toString().contains(acceptedKey)) {
movement.setRate(4);
break;
}
}
});
Then changing it to normal rate when i released it:
scene.setOnKeyReleased(event -> movement.setRate(1));
*movement is a Timeline which starts since the beginning of game till stopped or death of snake.
The code works as i intended But every time i hit a key it speeds up for a cycle and then slows down.
I want the speed to change only when i hold a key for a certain duration (say 400 milliseconds) so is there a way i can put an if statement that checks duration of onKeypressed()?
Instead of handling this complicated logic in the listener, set a boolean flag that is flipped on when a key is pressed.
scene.setOnKeyPressed(event -> {input = event.getCode().toString();
for (String acceptedKey : acceptedKeys) {
if (event.getCode().toString().contains(acceptedKey)) {
acceptedKeyBeingPressed = true;
break;
}
}
});
scene.setOnKeyReleased(event -> acceptedKeyBeingPressed = false);
Then keep track of time with some sort of numTicksHeld variable when the flag acceptedKeyPressed is true.
Check if acceptedKeyPressed is true on each tick. Reset the numTicksHeld variable to 0 when acceptedKeyPressed is false. If it is true, increment by one. If numTicksHeld is above some threshold, movement.setRate(4).
I don't know what the tick/update method looks like in your framework but it would be something like:
public void tick() {
if(acceptedKeyPressed) {
numTicksHeld++;
if(numTicksHeld > KEY_HELD_THRESHOLD)
movement.setRate(4)
} else {
numTicksHeld = 0;
movement.setRate(1)
}
}

How to count the number of collisions with collidesWith() in JavaME?

I'm developing a game with JavaME and I need to count the number of collisions in my game.
I'm using the collidesWith() method, and I'm doing something like this:
private void checkCollision()
{
if (spBoy.collidesWith(spBall, true)) {
this.collides++;
if (this.collides == 3) {
//here I will show a Game Over image.
}
}
}
As you can see, if the number of collisions is 3, the game is over, but I can't count the number of collisions, because when I increment this.collides, automatically I have 3 collisions in one time.
I'm assuming you're calling checkCollision() inside your main loop. This means it gets called 30-60 times per second.
If the two sprites doesn't move at all during that second, there will be 30-60 collisions - because it's true in each cycle.
What you wanna do is add a timer where your spBoy sprite can't be hurt.
int safeTimer = 0;
int timeSinceLastLoop; // Add this calculation to your loop
private void checkCollision() {
safeTimer-= timeSinceLastLoop;
if (spBoy.collidesWith(spBall, true) && safeTimer<=0) {
this.collides++;
safeTimer=3000; // Wait 3 seconds till vulnerability
if (this.collides == 3) {
//here I will show a Game Over image.
}
}
}

How to limit player activity?

I have a simple game where a player shoots some bullets. However, I want to make it so that the player can only shoot a bullet every x seconds. How would I do this?
I have tried to do it by taking the average time between bullets and saying that if average time is less than one second don't let the space bar (the control for shooting) work. However, I don't know how to make the space bar not work, AND that would mean a player could just not shoot for a wile and then shoot a lot of bullets at once.
The method for shooting looks something like this:
public void keyPressed(KeyEvent e) {
if (!keysDown.contains(e.getKeyCode()))
keysDown.add(new Integer(e.getKeyCode()));
This adds the integer of the key value to an array, which is then read here:
if (keysDown.contains(KeyEvent.VK_SPACE)) {
b = new Bullets(x);
bullCount.add(b);
System.out.println(bullCount.get(0).getY());
System.out.println ("There are " + bullCount.size() + "bullets alive.");
//elapsed = System.nanoTime() - start;
//if ((elapsed / bulletCount) < 1000000000) {
//this is where I would say 'no more bullets shot until
//average time in nanoseconds is more than 1 second!' but I don't know how
//}
Make a global variable ie: long lastShot.
When user shot, check if (System.currentTimeMilis()-lastShot>5000) before you allow him to shoot.
If it is ok to shoot, store the lastShot = System.currentTimeMilis(); and do the real shot. If not, don't allow him to shoot.
Here is an example in pseudo-code:
class SomeClass {
private long lastShot;
public void userPressedShot() {
if (System.currentTimeMillis()-lastShot>5000) {
lastShot = System.currentTimeMillis();
doTheRealShot();
}
// Ignored till 5000 miliseconds from last shot
}
}
One overkill option is to use the Guava's RateLimiter
final RateLimiter rateLimiter = RateLimiter.create(2.0); // rate is "2 permits per second"
while(true) {
rateLimiter.acquire();
shootSomething();
}
For this solution I assume that you use a Player Object.
It's very simple:
1.: add the field lastShot of the type long with the value 0 to your class.
2.: Whenever the player shoots, set lastShot to System.currentTimeMillis()
3.: Now, before you let him shoot, check if System.currentTimeMillis()-lastShot is smaller than your bullet delay in seconds.
This would be a MWE which has to be inserted in your player class:
Just call the Method player.shoot() to let him shoot - or not, if it's not possible.
private long lastShot = 0;
//return value is for you to check if the shot happened
public boolean shoot(){
//Did the last shot happen less than 1 second (1000 milliseconds) ago
if(System.currentTimeMillis()-lastShot <= 1000){
//If yes: return false, the shot can not happen
return false;
}else{
lastShot = System.currentTimeMillis();
//If no: insert your shooting code here to be executed
//return true, the shot happened
return true;
}
}
Try using a timer that resets every second the bullets count :
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
bullCount.clear();
}
}, 0, 1000); // 0 is the delay in milliseconds before it starts and 1000 is the time in milliseconds between successive task executions
Then when a player wants to shoot you just have to look at bullCount's size

How to check if a body has almost stopped moving in libgdx + box2d

So, I have a player body + fixture etc, it is essentially a ball that bounces around.
I want to detect when it is 'pretty much' finished moving.
At the moment I do this:
public Boolean isStopped() {
return body.getLinearVelocity().x <= 0.3f && body.getLinearVelocity().y <= 0.3f;
}
This mostly works, the problem being when the player hits something, there's a split second where its velocity is 0, so this returns true. What I really wanted is to just return true when it is basically finished. Preferably within a range that I can set to whatever I like as I tweak the physics of my game world.
I can't use a check on whether it is sleeping or not as that comes too late, it doesn't sleep until after it has stopped having forces act upon it, I need just before.
I could just store how long it has been stopped/a count of stopped steps, but I was hoping there would be a nice pre existing method that I missed.
Any ideas?
You can keep track of recent movement and update it by mixing in a little of the current speed each time step:
float speedNow = body.getLinearVelocity().len();
recentSpeed = 0.1 * speedNow + 0.9 * recentSpeed;
if ( recentSpeed < someThreshold )
... do something ...
You would need to set recentSpeed to a suitably high value to begin with, otherwise it might be below the threshold in the first time step.
Seeing how you've determined that your false positives are caused by the body making contact with another, why not add a couple of lines in your ContactListener's beginContact method, storing the body's current speed in its user data? Then you can check that speed in your isStopped method. If there is a stored speed and the current speed isn't greater, this means the body is in the process of bouncing off whatever it hit: ignore. If there is a stored speed and the current speed is greater, the ball has bounced and is proceeding in some new direction: clear the stored speed. If there is no stored speed and the current speed is below your threshold, you've detected the sought situation.
In your ContactListener:
public void beginContact(Contact contact) {
Body a = contact.getFixtureA().getBody();
Body b = contact.getFixtureB().getBody();
if (a == mBall) {
a.setUserData(a.getLinearVelocity().len());
} else if (b == mBall) {
b.setUserData(b.getLinearVelocity().len());
}
}
And in your isStopped check:
public Boolean isStopped() {
float storedSpd = (Float) body.getUserData();
float currentSpd = body.getLinearVelocity().len();
if ((storedSpd > Float.MIN_VALUE) && (currentSpd > storedSpd)) {
body.setUserData(Float.MIN_VALUE);
return false;
} else {
return (currentSpd < THRESHOLD);
}
}
This is untested, but you get the idea. Also, remember to initially set the user data to Float.MIN_VALUE.
In the end I have simply passed the delta from each render call to the isStopped() method.
public Boolean isStopped(float delta) {
boolean isMoving = (
Math.abs(body.getLinearVelocity().x) >= 0.25f || Math.abs(body.getLinearVelocity().y) >= 0.25f);
if(isMoving) {
timeStopped = 0f;
return false;
} else {
timeStopped += delta;
return timeStopped >= 0.3f;
}
}
timeStopped is just a class property that starts off as zero. This does return true for the beginning of the game (before the user has made a move) but in my application that is absolutely fine. Besides which, it is true to say it has stopped in that circumstance.
I'd still love to see a way to do this without storing extra crap, since I'm guessing box2d must have this information somewhere in order to figure out if a body with zero velocity has no force acting upon or if it is just changing direction after an impact.

Making just one part of the class wait for execution, with or without threads?

I am coding a space invaders clone, I need the invaders to do their usual movement but pause for one second before moving again.
EG. Move 5 pixels, then wait, then move another 5 pixels.
The method called moveInvaders() is the method I want to make wait for 1000ms. Below is that such method.
private void moveInvaders() {
if(direction == "right") {
if(invaderGreenEight.getX() == 455 || invaderRedEight.getX() == 455 || invaderBlueEight.getX() == 455) {
direction = "left"; // Change direction to left
}
} else {
if(invaderGreenOne.getX() == 15 || invaderRedOne.getX() == 15 || invaderBlueOne.getX() == 15) {
direction = "right"; // Change direction to right
}
}
if(direction == "right") {
// Move Green Invaders Right
invaderGreenOne.moveX(1);
invaderGreenTwo.moveX(1);
invaderGreenThree.moveX(1);
invaderGreenFour.moveX(1);
invaderGreenFive.moveX(1);
invaderGreenSix.moveX(1);
invaderGreenSeven.moveX(1);
invaderGreenEight.moveX(1);
// Move Red Invaders Right
invaderRedOne.moveX(1);
invaderRedTwo.moveX(1);
invaderRedThree.moveX(1);
invaderRedFour.moveX(1);
invaderRedFive.moveX(1);
invaderRedSix.moveX(1);
invaderRedSeven.moveX(1);
invaderRedEight.moveX(1);
// Move Blue Invaders Right
invaderBlueOne.moveX(1);
invaderBlueTwo.moveX(1);
invaderBlueThree.moveX(1);
invaderBlueFour.moveX(1);
invaderBlueFive.moveX(1);
invaderBlueSix.moveX(1);
invaderBlueSeven.moveX(1);
invaderBlueEight.moveX(1);
}
if(direction == "left") {
// Move Green Invaders Left
invaderGreenOne.moveX(-1);
invaderGreenTwo.moveX(-1);
invaderGreenThree.moveX(-1);
invaderGreenFour.moveX(-1);
invaderGreenFive.moveX(-1);
invaderGreenSix.moveX(-1);
invaderGreenSeven.moveX(-1);
invaderGreenEight.moveX(-1);
// Move Red Invaders Right
invaderRedOne.moveX(-1);
invaderRedTwo.moveX(-1);
invaderRedThree.moveX(-1);
invaderRedFour.moveX(-1);
invaderRedFive.moveX(-1);
invaderRedSix.moveX(-1);
invaderRedSeven.moveX(-1);
invaderRedEight.moveX(-1);
// Move Blue Invaders Right
invaderBlueOne.moveX(-1);
invaderBlueTwo.moveX(-1);
invaderBlueThree.moveX(-1);
invaderBlueFour.moveX(-1);
invaderBlueFive.moveX(-1);
invaderBlueSix.moveX(-1);
invaderBlueSeven.moveX(-1);
invaderBlueEight.moveX(-1);
}
}
The game is already a thread and the method in question is in the same class so issuing Thread.sleep(1000); just pauses the entire game for 1 second, but I just want the execution of one method to pause.
If you want more information I am more than happy to provide it.
GeissT
The moveInvaders() method should keep track of a member variable which stores the time the invaders were last moved (e.g. as a long number of milliseconds), this way, any time it is called it can check the value of that variable - if enough time has elapsed then the invaders can move, if not, then the method will simply return without doing anything. For example:
protected long invadersLastMovedMillis;
protected void moveInvaders() {
long currentTime = System.currentTimeMillis();
if ((invadersLastMovedMillis != 0)
&& ((currentTime - invadersLastMovedMillis) < 1000L)) {
return; // No need to move them yet.
}
// March on, space invaders!
invadersLastMovedMillis = currentTime;
}
You don't want to actually cause the thread to sleep because the game will then become unresponsive!
I'm guessing that you would use a Timer of some sort, but what sort will depend on many issues not yet known to us. What GUI library are you using?
For example, if this were a Swing GUI, I'd suggest using a Swing Timer for this delay -- but again, we've no idea what libraries your using.
Bottom line: Please provide more information and code.
Edit:
First suggestion: Get rid of all if (myString == "Foo"). You shouldn't compare Strings that way since this checks if one String object is one and the same as another, and you don't care about this. You want to know if they have the same content. Instead use the String#equals(...) or String#equalsIgnoreCase(...) methods.
Next: use arrays to reduce the severe code redundancy present.
Finally for a Swing app, consider using a Swing Timer to drive your game loop, and in the timer notify items listening to it of time ticks. Then have the items only respond after a certain amount of time has elapsed since their last action.
Create another thread (say T1) at the same level where you create game thread.
Start it after game thread is fully created OR when moveInvaders() method can be called without any crash.
ASA game thread ends, stop T1 also.
The game is already a thread and the method in question is in the same class so issuing Thread.sleep(1000);just pauses the entire game for 1 second, but I just want the execution of one method to pause.
The problem is there is one class, one object and only one thread to execute. It should be one class, one object and two thread. (Game Thread and T1)

Categories