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.
}
}
}
Related
I have had a persistent issue of my snake game running slowly as the snake gets larger. I have narrowed it down to this block of code that is causing the problems:
for(int i = 0 ; i < snake.size(); i++) {
if(xCoor == snake.get(i).getxCoor() && yCoor == snake.get(i).getyCoor()) {
if(i != snake.size() - 1) {
stop();
tries = 1;
}
}
}
This is the collision detection of the snake's head hitting the snake's body. I haven't been able to think of another way to optimize this besides removing it, which removes the core of the game. I think the issue that this runs each tick. I could change off from using ticks, but I have no idea how to start doing that.
EDIT: Here is how I have my game timing set up:
public void tick() {
if(snake.size() == 0) {
b = new BodyPart(xCoor, yCoor, 10);
snake.add(b);
}
ticks++;
if(ticks > 750000) {
}
}
EDIT2: Thread.sleep(60) worked wonders! My stop() method just doesn't work anymore, but all it really did was set running to false, so I just did that manually on anything that ended the game.
You could try the following approaches:
1.You could create a Map or Set of (x,y) co-ordinates which are already occupied and check against it. This would be updated much less frequently than access.
2.You could create a two-dimensional array of boolean for each board position. Checking would be very fast. Updating would take some time. It depends on the relative frequencies on which the two occur.
I have 2 clients connected to a server, they send new coordinates or spawn new circles and the server updates the position of the circles or creates new ones and draw them. I use a timertask with a delay of 5 seconds and a 5 seconds interval to spawn new circles.
I keep getting IndexOutOfBoundsException at random indexes every time i run the application when i setTranslateX.
private void updateSimulation(ArrayList<String> cl) {
if(cl == translatedCoorsMessage) {
Platform.runLater(() -> {
int x= 1;
for(Circle circle : circlesOnCorridorOfClient) {
circle.setTranslateX(((Double.parseDouble(cl.get(x))) - 20.0)/1000);
x=x+2;
}
circlesOnCorridorOfClient.addAll(newCirclesToAddOnCorridor);
newCirclesToAddOnCorridor.clear();
});
}
else {
Platform.runLater(() -> {
int x= 1;
for(Circle circle : circlesOnCorridorOfClient1) {
circle.setTranslateX(((Double.parseDouble(cl.get(x))) - 967.0)/1000);
x=x+2;
}
circlesOnCorridorOfClient1.addAll(newCirclesToAddOnCorridor1);
newCirclesToAddOnCorridor1.clear();
});
}
}
This error can happen after the second circle spawns or third or the 5th, etc. I set my x = 1 because the first element in the ArrayList i pass to this method is just a small String to know what i will do with the ArrayList. In this case, update. the second is X coordinate and third is Y.
It feels like the foreach loop runs one extra time some times after i add a new circle. I only add new circles after the loop and i do it through another arraylist.
Any tips will be apreciated. thanks for your time.
Im not sure but i think that the problem is that everything i did in Platform.runLater happens in another thread (Application Thread). So my server was updating and adding new circles(this circles are added in a separate ArrayList to avoid ConcurrentModificationException) then i add my new circles to the main ArrayList after i update every circle position. So that was the problem, for a moment i had 1 extra circles.
I "fixed" this problems by adding 2 volatile integers in my Server. i used those integers to check if im done doing everything in Platform.runLater. the server stays in a while loop that does nothing, just waiting until the Platform.runLater part is done and changes the value of this integers so that Server Thread can exit this while loop and continue.
I dont get the IndexOutOfBoundsException any more but the "animation" is really slow.
private void updateSimulation(ArrayList<String> cl) {
if(cl == translatedCoorsMessage) {
Platform.runLater(() -> {
int x= 1;
for(Circle circle : circlesOnCorridorOfClient) {
circle.setTranslateX(((Double.parseDouble(cl.get(x))) - 20.0)/1000);
x=x+2;
}
circlesOnCorridorOfClient.addAll(newCirclesToAddOnCorridor);
newCirclesToAddOnCorridor.clear();
testtest = 1;
});
while(testtest == 0){
//waiting
}
testtest = 0;
}
else {
Platform.runLater(() -> {
int x= 1;
for(Circle circle : circlesOnCorridorOfClient1) {
circle.setTranslateX(((Double.parseDouble(cl.get(x))) - 967.0)/1000);
x=x+2;
}
circlesOnCorridorOfClient1.addAll(newCirclesToAddOnCorridor1);
newCirclesToAddOnCorridor1.clear();
testtest1 = 1;
});
while(testtest1 == 0){
//waiting
}
testtest1=0;
}
}
is an ugly solution.
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;
}
}
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
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