So, I have been working on this code for way to long for one day. I am sure there has to be a simple way to solve this but I can't think anything right now. First a small section of the code:
if(Settings.totalHits >= 50 && Settings.totalHits <= 99)
{
Settings.medal1 = true;
Settings.save(game.getFileIO());
totalMedals = totalMedals + 1;
}
This is a very basic achievement/medal system. Basically, once the user has done a total of 50 hits, it sets the value of "medal1" to true, which will remove the "lock" image which only displays when medal1 = false.
The issue deals with the totalMedals section. Basically, there is a total of 32 medals a user can earn, and after one is unlocked, it needs to update the totalMedals by 1. So in this case, the output would be "1/32". Except, now after the medal is unlocked (by hitting 50), the lock image is removed correctly, but the totalMedals keeps increasing by 1 extremely fast instead of just increasing to "1" and stopping.
Like I said, there has to be something small that I am overlooking here. I tried tossing into a for loop but that didn't work (or I did it wrong). Any idea what I can change to fix this?
Instead of
if(Settings.totalHits >= 50 && Settings.totalHits <= 99)
Try:
if(Settings.totalHits >= 50 && Settings.totalHits <= 99 && !Settings.medal1)
This way, once the medal has been triggered, it cannot be triggered again. Thus, totalMedals is only incremented once.
You only want to unlock the medal if you've reached the threshold and you haven't already unlocked it (the upper limit is irrelevant here), so you can use:
if (Settings.totalHits >= 50 && !Settings.medal1) {
Settings.medal1 = true;
Settings.save(game.getFileIO());
totalMedals++;
}
if (Settings.totalHits >= 100 && !Settings.medal2) {
Settings.medal2 = true;
Settings.save(game.getFileIO());
totalMedals++;
}
// and so on.
Though of course, this positively calls out for refactoring so as to efficiently use arrays, something like:
for (i = 1; i < 33; i++) {
if (Settings.totalHits >= 50 * i && !Settings.medal[i-1]) {
Settings.medal[i-1] = true;
Settings.save(game.getFileIO());
totalMedals++;
}
}
And, if the thresholds aren't a direct multiple of 50, you can easily place an arbitrarily complex function (or array lookup) into the if statement to match your needs.
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'm new to java and I'm trying to constantly add "zombie" entity to my game after a delay, and then shortening the delay as time goes on.
In my PlayState class I've got the code to spawn the entities in a position when my update(); method is run (which houses getInput(); and such. Not shown for clarity.)
public void update(long elapsed) {
this.entities.add(new Zombie(-535));
}
How would i make a delay that shortens? I'm guessing I would make the delay and then use a multiplier which i have getting smaller every 10 seconds or so, but how would I do this?
Now, I don't know much about the finer workings of your class, but this might give you a general idea of what I mean:
int counter = 50;
for(int i = 100; i >= 0; i--)
{
if(i == counter)
{
counter = counter / 2;
this.entities.add(new Zombie(-535));
}
}
Suppose i is the the total run-time of the game, and counter represents a percent of the game when you want to add a zombie.
If you want to add a zombie after 50% of the run-time (here, 100 seconds), then as the time reduces, you check if the time has come to add a zombie (Here, 50 seconds).
What I've done here is reduce the delay to half, and continue checking if the time has come to add a zombie.
Maybe you could call sleep on your thread of execution:
int sleepInMs = 5000
Thread.sleep(sleepInMs);
sleepInMs+=1000; //Then of course handle the case when sleepInMs == 0
Really need more information about your implementation.
For a simple delay, use "delay ms;"
Edit ms for the number of milliseconds you want. 1000 milliseconds is one second
The Problem I have ArrayList of "pellets". I'm pushing around 25 of them and they all bounce. However, for some reason they seem to go faster while render() is slower / takes more time (wut?) Please help me make it so that the 25 sprites smoothly glide about at a constant speed. It also jerks when only 5 sprites are onScreen.
Tried this stuff:
Reading around SO. They recommended getDeltaTime
Gdx.graphics.getDeltaTime() multiplying by pelletSpeed (no Change)
In the current code the pellets hop, jerk, and inconsistently sputter about almost unpredictably. I am assuming that it's going constant speed underneath the hood but honestly it's hard to tell
For Loop in Render:
String currentDir = pelletList.get(i).getDir();
String currentColor = pelletList.get(i).getColor6();
pelletSpeedElapsedTime = TimeUtils.nanoTime();
if(currentDir.equals("Up")) {
pelletList.get(i).y -= pelletSpeed * TimeUtils.timeSinceNanos(pelletSpeedElapsedTime);
if(pelletList.get(i).y < 0 ) {
pelletList.get(i).setDir("Down");
}
} else if (currentDir.equals("Down")) {
pelletList.get(i).y += pelletSpeed * TimeUtils.timeSinceNanos(pelletSpeedElapsedTime);
if(pelletList.get(i).y > screenHeight) {
pelletList.get(i).setDir("Up");
}
} else if (currentDir.equals("Left")) {
pelletList.get(i).x -= pelletSpeed * TimeUtils.timeSinceNanos(pelletSpeedElapsedTime);
if(pelletList.get(i).x < 0) {
pelletList.get(i).setDir("Right");
}
} else if (currentDir.equals("Right")) {
pelletList.get(i).x += pelletSpeed * TimeUtils.timeSinceNanos(pelletSpeedElapsedTime);
if(pelletList.get(i).x > screenWidth) {
pelletList.get(i).setDir("Left");
}
}
Thanks
The pelletSpeedElapsedTime = TimeUtils.nanoTime(); looks suspicious to me - you're getting this time, and then calculating elapsed time for bullets immediately afterward. Almost no time will have elapsed by then, and you won't be accounting at all for whatever time passes before the next call to whatever method this is.
I think (guessing at what the rest of your code is like) that you want to move that pelletSpeedElapsedTime assignment to the end of this method. The idea here is that you want to capture the time where you finished this update, so that the next time you update you know how much time has passed between updates (e.g. time spent rendering, sleeping, whatever.)
Doing this would mean that you'd have to handle the case where pelletSpeedElapsedTime hasn't been initialized, as well (maybe initialize it in the constructor? again, not sure of the broader context.) Also, I don't think all those TimeUtils.timeSinceNanos calls or necessary - I would call that once at the start of this section of code and use the value (to make sure the moving entities all get a consistent time delta, and to avoid the redundant call/calculation.)
If I want to test the speed at which a method returned, should I include its output? For example
public static void fizzBuzz2(int n)
{
for(int i = 1; i <= n; i++)
{
if(i % 3 == 0 && i % 5 == 0)
System.out.println("FizzBuzz");
else if(i % 3 == 0)
System.out.println("Fizz");
else if(i % 5 == 0)
System.out.println("Buzz");
else
System.out.println(i);
}
}
I'm going to modify so that instead of printing to the console it will write to a file. Should the time writing to the file be included in timing? Fortunately the parameter is passed in but in the situations where userinput is taken, how does benchmarking take place?
I was thinking of commenting out the System.out.println statements but I'm not sure if the optimizer would then get rid of the entire program :/
store the processing time in a variable and then save it to a file, then you won't have to worry about any extra time it takes writing it.
calling on some of the comments here, I'm not sure what level of precision you're looking for, but a simple long start = System.currentTimeMillis() before the process starts and subtracting that from a second timestamp at completion will give you a good idea. You can do file saving and output after you capture the end time
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.