I am just looking to confirm that this code would be correct for what I am looking for. Basically, I would like when called, this function to roll a number out of a certain rarity. The rarities right now are 15% chance, 20% chance, and a 65% common chance. However, after rereading my code, it seems to be that the 20% chance actually is a lower chance than the 15% chance which would not be ideal. Could someone check this for me? Thanks!
public void roll() {
float rarity = random.nextFloat();
if(rarity <= 0.15f) {
// Roll Legendary Item
} else if(rarity <= 0.35) {
// Roll Rare Item
} else {
// Roll Common Item
}
}
It should be
else if(rarity <= 0.35f)
The way your code is written, it is currently 15%-5%-80%
Related
I recently embarked on a project to simulate a collection of stellar bodies with the use of LWJGL. The solution required many loop iterations per frame to accomplish. The program calculates the forces exerted on each body by every other body. I did not wish to implement any form of limitations, such as tree algorithms. The program itself is able to simulate 800 bodies of random mass (between 1 and 50) at around 15 fps. Here is the original code for calculating, then updating the position of each body.
public void updateAllBodies() {
for (Body b : bodies) {
for (Body c : bodies) {
if (b != c) {
double[] force = b.getForceFromBody(c, G);
b.velocity[0] += force[0];
b.velocity[1] += force[1];
b.velocity[2] += force[2];
b.updatePosition();
}
}
}
}
Recently I came across the subject of parallels and streams. Seeing that my original code used only one thread, I thought I might be able to improve the performance by converting the array to a stream, and executing it with the use of
.parallelStream()
I don't know much about multi-threading and parallelism, but here is the resulting code that I came up with.
public void updateAllBodies() {
Arrays.asList(bodies).parallelStream().forEach(i -> {
for(Body b: bodies){
if (i != b){
double[] force = i.getForceFromBody(b, G);
i.velocity[0] += force[0];
i.velocity[1] += force[1];
i.velocity[2] += force[2];
i.updatePosition();
}
}
});
}
Unfortunately, when executed, this new code resulted in the same 15 fps as the old one. I was able to confirm that there were 3 concurrent threads running with
Thread.currentThread().getName();
At this point, I have no idea as to what the cause could be. lowering the number of bodies does show a drastic increase in frame rate. Any help will be greatly appreciated.
I cant seem to find a way to mark a comment as the answer to a post, so I will state that the best answer was given by softwarenwebie7331.
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.)
:D
I'm currently making an RPG, made the combat system, if a player attack makes contact with the enemy it deals damage, now what I want to do is add critical strike into the mix and blocking.
How it should work? well first it will roll the chances of the monster blocking based on his blocking chance, if it blocks the incoming damage gets reduced to zero, if it doesnt it rolls the chance of critical strike based on the players critical strike chance, if its critical it will deal x bonus amount of damage based on the players critical strike multiplier.
Now what I want to know is how to calculate the percentage chance, I've seen several posts but they usually turn the percentage into a whole number, and probably my players will start with low rolls as 1.7% or 3.9%, but not 1-2-3-5, flat percentages. Anyone got suggestions on how to make it?
so far the code goes like this:
public class Player{
private double criticalStrikeChance = 0.009; <--- thats 0.9% chance.
private double criticalStrikeMultiplier = 1.2; <--- thats 120% moar damage
public double getCritStrk(){
return criticalStrikeChance;
}
}
public class Monster(){
private double blockingChance = 0.3; <--- thats 30%
private double blockingReduction = 0.75; <--- thats 75% reduced damage when blocking
}
public class Game(){
public void checkIfDamaged(){
if(intersects){
// blockroll should be done here based on the monster chance
if(blockRoll >= minimum he had to roll){
//means its successfull
monster.getHit(0); //PEANUT DAMAGE ACHIEVED GREAT SUCCESS
}else{
//Critical strike chance should be rolled here based on player
//chance
if(critstrike successful){
incdamage + (incdamage * player.criticalStrikeMultiplier;
monster.getHit(incdamage);
}
}else{//Crit didnt roll with cinnamon
monster.getHit(player.getDamage);
}
}
}
}
Ok so that's pretty much it as pseudo-code because my code looks way different but thats simple and should give you guys an idea on how it should work, so please help me senpais! I SHALL GIVE YOU CHOCO COOKIES + a nice shield with 100% block rate :D to whoever halps me!
If you are just looking to roll a random percentage, you can use the Random class in java.
Random rand = new Random();
Double pickedNumber = rand.nextDouble();
Running that, will result in pickedNumber being some double between 0 and 1. For example:
0.3650998187710377
Then check if that percentage is less than whatever your block/crit chance is. For example:
if(pickedNumber < blockChange)
//doBlock();
A full example, for a test case could be something like:
private static Random rand = new Random();
public static void main(String[] args) {
double blockChance = .5; // 50% chance to block the attack
Double pickedNumber = rand.nextDouble(); // Roll to see if we block the attack
System.out.println(pickedNumber); // output roll for debug purposes
if(pickedNumber < blockChance){ // if the attack was blocked
System.out.println("Blocked"); // do block logic
}else{ // if the attack wasn't blocked
System.out.println("Damaged"); // do damage logic
}
}
Which gave me the output:
0.2768592334674802
Blocked
And:
0.8762124334674802
Damaged
Another approach:
To get 0.75:
if (Math.random() < 0.75) {
//do this with probability 0.75
}
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.
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.