I'm a bit new to Java and LibGDX, and I'm working on a point based game. A problem I'm facing is that the update method constantly runs something that I want to run on a timely manner. In my update method, I have the code to increment the score if a point is earned, and to make a lose state come up when the player lost. Without going into much detail, here's the pseudo code I have:
protected void update(float dt){
for(Thing x : a list) {
x.update(dt);
//continue
if (you complete the objective of the game) {
score++;
//do other stuff
}
//lost
if (you fail to complete the objective){
make lose state come up
}
}
//I want something like this to run:
if(score >=0 && score <=10){
do something ONCE(ie. print to console once)
}
if(score >= 11 && score <=15){
do something once
}
if(ect...){
do something else once
}
.
.
.
The problem here is that, if the IF condition is met, I notice the IF block gets executed multiple times very quickly(ie. printing to the console a lot). I have enclosed the details of the code that relies on the score in a separate class, I just want to be able to call the method from this update method and have it run once depending on the score conditions (ie. run it again if the score satisfies another IF statement)
I had the same problem, but I solved it by using following method. In Libgdx the update method runs in 1/60 second. That is the reason the method is rendering continously and the if condition will be executing various times.
To solve this problem, just declare an integer variable, say count, in your create method.
public static int count;
public static void create()
{
count =0;
// do other stuffs
}
protected void update(float dt){
// just increment this count value in your update method
for(Thing x : a list) {
count++
x.update(dt);
//continue
if (you complete the objective of the game) {
score++;
//do other stuff
}
//lost
if (you fail to complete the objective){
make lose state come up
}
}
// and make a small condition to run the if condition only once by using the declared variable "count".
if(count%60==0){
// here the condition only executes when the count%60==0.that is only once in 1/60 frames.
if(score >=0 && score <=10){
}
if(score >= 11 && score <=15){
}
if(ect...){
}
}
.
.
. This is how I solved the same issue.
The update() method is called every frame, multiple times very quickly(usually 60 times per second) in an infinite loop. This is not only specific in libGDX, but in any game engine. And when some condition of your if block evaluates to true, that if block is executed every frame until that condition becomes false again. But you want to execute the block only once after the condition changed.
Just declare a variable named isLastScoreUnder10 or whatever, and update it after the if block. Like this:
private boolean isLastScoreUnder10 = false;
protected void update(float dt){
if(!isLastScoreUnder10 && score >=0 && score <=10){
isLastScoreUnder10 = true;
// ..do something
} else {
isLastScoreUnder10 = false;
}
}
Related
I am making a game where the player can throw up to three projectiles at a time. I'm having trouble with the reloading. Here is the code:
public class AmmoManager {
public void tick(){
if(Player.ammo <= 0){
for(int t = 0; t < 10; t ++){
}
Player.ammo = 3;
}
}
}
It's supposed to wait a bit and then set the ammo to 3, but as soon as the ammo becomes 0, it is set to 3 instantly. What am I doing wrong?
I've tried using sleep, but the entire application would stop.
The problem is that your main program waits for tick() to return something.
Think about it like this; if you have this method
public boolean isOne(int num){
Thread.sleep(1000);
if(num==1){return true;}
return false;
}
and
boolean result = isOne(1);
if(result){ //can't be ran until isOne(1) returns the boolean
//do something
}
You can't continue with you main class when you call isOne() because you dont have the value of the boolean it returns. you have to wait for it to return the value, and then you can continue with the main method
The solution is threading. I'm not an expert on it, so you will need to consult someone else or an online resource, but I think it would look something like this:
public void tick(){
new Thread({ new Runnable(){
#Override
public void run(){
if(Player.ammo <= 0){
Thread.sleep(*seconds* times 1000);
Player.ammo = 3;
}
}).start();
}
There are two problems here.
as soon as the ammo becomes 0, it is set to 3 instantly. What am I doing wrong?
That's because the for loop does nothing. When you enter tick() and Player.ammo is 0, you instantly set it to 3.
I've tried using sleep, but the entire application would stop.
If you only have one thread, that is what Thread.sleep does.
I suspect that what you are attempting is more difficult than you think...
You need a main loop that controls the pace of the game. I might sleep() to ensure that the game does not run too fast.
Each pass, it must instruct every player, or whatever constructs you use, to update themselves. As one of the comments noted, that might involve incrementing a counter to replenish ammo.
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.
}
}
}
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.
I am using AndEngine to develop my game, though I'm thinking this problem is unrelated to AndEngine.
I have two possible dialogs that fire if:
User touches down in an incorrect area or
Users lifts up from an incorrect area.
Unfortunately, if a user touches down in an incorrect area, when they lift up they are also satisfying error 2--lifting up from an incorrect area.
Here's my code in a nutshell:
public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) {
float y = pSceneTouchEvent.getY();
int dialog_count = 0;
if (pSceneTouchEvent.isActionDown() && y < 1000) {
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
AlertDialog Code
..............
}
}
dialog_count ++;
Log.d("Dialog Count", "Count is " + dialog_count);
} else if (dialog_count < 1 && pSceneTouchEvent.isActionUp() && y > 105) {
Log.d("Dialog Count", "Count is still " + dialog_count);
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
Second AlertDialog Code
.................
}
}
}
return false;
}
Now, my first log for dialog_count shows a value of 1. However when I lift up the second log shows a value of 0. Somehow this value is either getting reset or my Else statement just can't see the updated value of dialog_count because I get the second dialog popping on top of my first.
Any ideas?
Your code initializes
int dialog_count = 0;
each time it runs.
To keep the value you saw the last time, make dialog_count an instance variable in the class.
Notice that you will be seeing two events, one for "down" and one for "up".
If you want to show only one then you need to use a flag to check if the user has touched down and then if you want not to show the touch up dialog just check from the flag. But the Touch down will always follow the Touch Up. You can use the Touch Move method if you want to show the dialog when the user has moved a bit.
If I understand correctly, what you are trying to do
dialogCount is function local (garbage collected, after you exit the method). So it will be 0 on each new run of the method. (Make it private class variable).
If you are referring to your dialogCount in multiple threads, dialogCount must be thread safe, so use concurrent primitives - AtomicInteger
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