Sorry, I couldn't word my title properly but I will explain my problem with more clarity here.
I am using libgdx.
When I want to move a Texture so that it covers the same distance with all FPS I will do this:
//...define Player class with x property up here.
Player player = new Player();
int SPEED = 100
public void render() {
player.x += SPEED * Gdx.graphics.getDeltaTime();
}
Now I want to know how to do this to have the same affect on a body in box2d. Here is an example(the render method of a class that extends ApplicationAdapter):
public void render() {
//clear screen, ... do other stuff up here.
playerBody.applyForce(new Vector2(0.5f / PIXEL_PER_METER, 0.0f), playerBody.getWorldCenter(), true);
//PIXEL_PER_METER -> applied to scale everything down
//update all bodies
world.step(1/60f, 6, 2);
}
This applies a force on the playerBody so that it's acceleration increases. How do I make shore, just like with my first example, that how fast the body is travelling stays constant across at 30fps, 10fps, 60fps, etc. I know the timeStep parameter of the world.step is the amount of time to simulate but this value shouldn't vary.
Thankyou in advance.
You can update all bodies with delta (not 1/60 fixed delta)
world.step(Gdx.graphics.getDeltaTime(), 6, 2);
EDIT:
As #Tenfour04 mentioned, in order to prevent high delta values (causes huge jumps), we mostly set a cap for delta.
world.step(Math.min(Gdx.graphics.getDeltaTime(), 0.15f), 6, 2);
I wouldn't use a variable timestep - this is the approach I've used:
private float time = 0;
private final float timestep = 1 / 60f;
public void updateMethod(float delta) {
for(time += delta; time >= timestep; time -= timestep)
world.step(timestep, 6, 2);
}
Basically a variable-ish timestep, but uniformly updating.
If you run your game at very low FPS, or if you force it to with the application configuration (e.g. for testing) this will keep updating at roughly the same speed as a normal 60 FPS instance.
Take a look at Fix your timestep!
Related
I am a new coder on processing, because of this reason please be gentle.
Normally my code is more longer and complex but I wrote a simple code for you, which I can adapt on my code:
int speed = 1;
int x, z = 50;
void setup() {
size(400, 400, P3D);
}
void draw() {
background(0);
noStroke();
lights();
translate(x, height/2, z);
fill(255,0,0);
sphere(25);
if (x > width -50)
noLoop();
x += speed;
}
So, like you see, sphere starts with color of red and it reaches end of the window. I want to change it's color from red to white and it should take 30 sec. to reach end of the window. However I don't know how. If you help me I will be happy.
Note: I tried lerpColor function but didn't help me.
Math is the secret. Is often is.
There are a couple things you'll need to keep track of to accomplish this: the time it takes to cross the screen (you said 30 seconds), the speed of the sphere, the speed at which the color changes.
Before we start, I suggest that you use float for your variables which are positions and speeds. Integers will do the job, but at some point when you want precision you may regret not using floats or a similar type.
There are 2 ways to deal with changes over time: you can calculate time and draw what needs to be drawn where it's supposed to be, or calculate how many frames will be drawn in a certain amount of time and move things accordingly. The first technique has the advantage of being able to draw things where they are supposed to be even if the system is laggy (Processing will lower the framerate if it's not able to respect it), while the second is often easier to work with. We'll go with the framerate technique, as this is not supposed to be complicated and because most programs won't need so much resource that it'll lower the framerate.
The framerate, in Processing, is also the rate at which the main loop (the draw() loop) run. So we'll choose a framerate which will let us calculate the speed of the sphere and the speed at which the color change. The rest is just watching it move.
Here's your example, but modified so it works approximately as you told:
float speed;
float x, z = 50;
float greenBlueStrength = 0;
float colorFadeRate = 1;
int fadeTimeInFrames;
void setup() {
size(400, 400, P3D);
frameRate(60); // 60 is the default framerate per second
// so 30 seconds == (30*60) == 1800 frames
// so you must have the speed to match
fadeTimeInFrames = 60 * 30;
speed = (width - 50) / (float)fadeTimeInFrames;
colorFadeRate = 255 / (float)fadeTimeInFrames;
println(colorFadeRate);
}
void draw() {
background(0);
textSize(30);
text((millis()/1000) + " s. // color: " + (int)greenBlueStrength, 20, 50);
// this is just to keep track of changes while they happen
noStroke();
lights();
translate(x, height/2, z);
fill(255, greenBlueStrength, greenBlueStrength);
sphere(25);
if (x > width -50) {
noLoop();
} // no actual change, but use brackets anyway, it's easier to read
// updating what needs to be updated
x += speed;
greenBlueStrength += colorFadeRate;
}
I'll hang around so don't hesitate if you have questions.
Have fun!
I think something like that would work:
int r=255,b=255,g=255;
...
void draw(){
...
int percent=x/width*100;
fill(r,b*percent,g*percent)
sphere(25)
...
}
so the sphere would be red only on the left of the screen and white on the right
I’m trying to achieve constant speed on a path using the LibGDX CatmullRomSpline and I’m having problems getting it to work. I’ve tried researching on this topic a lot including reading the LibGDX wiki, but their explanation for achieving constant speed doesn’t really make sense and I wasn’t able to get their method to work. https://github.com/libgdx/libgdx/wiki/Path-interface-&-Splines
In my case, the derivative values are very large (in the hundreds) so when dividing a number between 0-1 by the derivative the result is very small and the movement is very slow and still not constant. So I’m not sure exactly how their example works.
In my example I have a couple visual aids coinciding with the speed of the ball, the bar at the bottom of the screen increases in length as the speed increases and the color also changes from white to red as the speed increases.
In the act() method of MyPath.java I have two sections commented out starting with [1] and [2]. The first one is normal with the variable speed through the path and the second one is my failed attempt at getting the LibGDX wiki constant speed to work. So just un-comment these lines to switch between the two versions.
My idea for constant speed involves figuring out the speed based on the total length of the path (using the approxLength(1000) method on the spline), then using the derivative function to determine the actual speed at a given instant, and adjusting the percentage value sent into the spline to compensate for the speed changes in order to make the speed constant. However, I don’t quite understand what the derivative function actually represents. I posted a question about the derivative function earlier, but based a comment I received I figured it might be easier to ask about achieving constant speed instead. Here is my previous question on the derivative function:
LibGDX CatmullRomSpline Derivative Meaning?
Any ideas on how to achieve constant speed in my example (or explaining what the derivative function for the CatmullRomSpline actually represents so I could better understand how to use it) would be greatly appreciated.
For anyone who'd like to run the program, here are the two image files I created for my example (add these to the root of the assets folder):
http://dropshots.com/Tekker/date/2015-09-19
Here is my example code:
DesktopLauncher.java: (changed desktop window width and height to 1000)
public class DesktopLauncher {
public static void main (String[] arg) {
LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
config.width = 1000;
config.height = 1000;
new LwjglApplication(new TEST(), config);
}
}
TEST.java:
public class TEST extends Game {
Stage stage;
MyPath path;
#Override
public void create () {
stage = new Stage();
stage.setViewport(new ScreenViewport(stage.getViewport().getCamera()));
Gdx.input.setInputProcessor(stage);
path = new MyPath(1000, 1000);
stage.addActor(path);
}
#Override
public void render () {
Gdx.gl.glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
}
#Override
public void dispose(){
stage.dispose();
super.dispose();
}
}
MyPath.java:
public class MyPath extends WidgetGroup {
Image start, end, path, bar1, horizontal;
float time, percent, dVal, pathLength, dMax=1000, cycle=6, maxPercent, deltaCycle;
CatmullRomSpline<Vector2> catmull;
Vector2 result = new Vector2();
Vector2 previousResult = new Vector2(50,150);
Vector2 derivative = new Vector2();
Vector2 previousDerivative = new Vector2();
Vector2[] points = {
new Vector2(50,150), new Vector2(50,150),
new Vector2(400,800), new Vector2(600,150), new Vector2(700,400),
new Vector2(860,150), new Vector2(860,150)
};
boolean print = true;
public MyPath(int width, int height){
this.setSize(width, height);
catmull = new CatmullRomSpline<Vector2>(points, false);
createPath();
createBar();
pathLength = catmull.approxLength(1000);
}
#Override
public void act(float delta){
// [1] VARIABLE SPEED
//time += delta;
//percent = (time / cycle) % 1;
// [2] CONSTANT SPEED FAIL!
//catmull.derivativeAt(previousDerivative, percent);
//time += delta;
//percent = ((time / cycle) / previousDerivative.len() ) % 1;
catmull.valueAt(result, percent);
path.setPosition(result.x, this.getHeight() - result.y);
updateSpeedVisuals();
debugPrint();
previousResult.set(result);
}
private void createPath(){
start = new Image(new Texture("dot.png"));
start.setColor(Color.GRAY);
start.setPosition(50, this.getHeight() - 150);
this.addActor(start);
end = new Image(new Texture("dot.png"));
end.setColor(Color.GRAY);
end.setPosition(860, this.getHeight() - 150);
this.addActor(end);
path = new Image(new Texture("dot.png"));
path.setColor(Color.WHITE);
this.addActor(path);
}
private void createBar(){
Texture texture = new Texture("ninepatch.png");
int crop = (int)(texture.getWidth()/2)-1;
NinePatch patch9 = new NinePatch(texture, crop, crop, crop, crop);
bar1 = new Image(patch9);
bar1.setColor(Color.GRAY);
bar1.setPosition(5, this.getHeight()-900);
this.addActor(bar1);
}
private void updateSpeedVisuals(){
catmull.derivativeAt(derivative, percent);
dVal = derivative.len() / dMax;
path.setColor(1f, 1f-dVal, 1f-dVal, 1f);
bar1.setWidth(derivative.len());
bar1.setColor(1f, 1f-dVal, 1f-dVal, 1f);
}
private void debugPrint(){
maxPercent = (percent > maxPercent) ? percent : maxPercent;
if (maxPercent > percent){
print = false;
}
if (print){
String debugPrint = "";
debugPrint = debugPrint + "pathLength=" + pathLength + "\t";
debugPrint = debugPrint + "derivative=" + derivative.len() + "\t";
System.out.println(debugPrint);
}
}
}
Since the derivative is the rate of change of the spline position it is indeed the 'speed', and when the spline is bending away from the underlying data points it has to 'speed up' to make the calculated spline reach the next data point in time, you must divide out this speed to perceive a visual constant speed.
You aren't getting a constant speed because you are still incrementing your time variable by delta instead of delta divided by the rate of change (derivative). You should be adding a variable amount to the percent variable each frame, instead you were modifying everything by the derivative of a single point along the Catmull-Rom spline.
Instead of:
catmull.derivativeAt(previousDerivative, percent);
time += delta;
percent = ((time / cycle) / previousDerivative.len() ) % 1;
You should:
catmull.derivativeAt(previousDerivative, percent);
percent += derivativeAverage / cycle * delta / previousDerivative.len();
percent %= 1;
you should use the average derivative divided by cycle now since you can't use cycle alone as a percent per second variable anymore.
Iterating over the spline to find the average value of the derivativeAverage:
int samples = 100; //the higher the more accurate, however slower
float derivativeAverage = 0;
Vector2 out = new Vector2();
for (float i=0;i<1;i+=1f/samples) {
catmull.derivativeAt(out, i);
derivativeAverage += out.len();
}
derivativeAverage /= samples;
In the ApplicationAdapter class, I override the render() method and draws my game from there.
I also have an own method: update() inside the render method which is where I want to update everything.
The render() method is as I know called ~60 times a second.
I dont want my update method to be dependent on how many times the render method is called.
I want the render method to render as much as the device can handle below 60 FPS.
I also want the update method to get called at a fixed rate: 60 times a second.
I´ve tried to call my update method 60 times a second in my render method like this:
double beforeMillis;
double FPS=4; //test
double millisPassed=0;
int x=0;
#Override
public void render () {
beforeMillis=System.currentTimeMillis();
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(tex, x, 10);
batch.end();
millisPassed+=(System.currentTimeMillis()-beforeMillis);
if(millisPassed>=1000/FPS){
update();
millisPassed=0;
}
}
...but it updates like once every four seconds.
Any good way of doing this? Thanks in advance!
The code you posted won't compare accurate time, because it ignores all the time spent doing things between batch.end() and the next call to render(), some of which occurs in the libgdx backend. And if you update after drawing in the render method, you will always have at least one visual frame of lag.
A basic implementation of a fixed timestep update in libgdx would be like this:
static final double DT = 1/60.0;
static final int MAX_UPDATES_PER_FRAME = 3; //for preventing spiral of death
private long currentTimeMillis;
public void create() {
currentTimeMillis = System.currentTimeMillis();
}
public void render() {
long newTimeMillis = System.currentTimeMillis();
float frameTimeSeconds = (newTimeMillis - currentTimeMillis) / 1000f;
currentTimeMillis = newTimeMillis;
int updateCount = 0;
while (frameTimeSeconds > 0f && updateCount <= MAX_UPDATES_PER_FRAME) {
float deltaTimeSeconds = Math.min(frameTimeSeconds, DT);
update(deltaTimeSeconds);
frameTimeSeconds -= deltaTimeSeconds;
++updateCount;
}
draw();
}
This does result in update occurring more than 60 times a second, because it gets updated with the "leftovers" to keep the visuals current (no stuttering). The update(float delta) method must be designed to use a variable delta time.
You can do a truly fixed update as described here in the last two sections, but that has the disadvantage of visual stuttering or needing to implement a one-frame delay and interpolating ahead.
Im trying to make a Vortex effect on a Circle Body that is a Sensor.
I've been looking for this and all examples i look for are in C++ or Objective C and i dont seem to translate them well.
when my objects collition, it calls beginContact(..) and it sets a flag so that i can call bodyToUpdate.applyForce(...);
public void beginContact(Contact contact) {
setColliding(true);
}
//updating collition every frame
public void act(){
if (colliding) {
ball.getBody().applyForce(....);
}
how to calculate the amount of force to apply every frame to make it a vortex?
Edit:
so i now have the object going straight to the center of the vortex, but no "spin"
public void act() {
if (colliding) {
ball.getBody().setLinearVelocity(0, 0);
ball.getBody().applyForce((portal.getBody().getPosition().x - ball.getBody().getPosition().x) * i,
(portal.getBody().getPosition().y - ball.getBody().getPosition().y) * i,
ball.getBody().getPosition().x, ball.getBody().getPosition().y, true);
i++;
} else
i = 10;
}
If by "spin" you mean that the falling object would move along a curve or a spiral, rather then changing the direction of movement immediately towards the black hole, there is an easy fix for that.
ball.getBody().setLinearVelocity(0, 0);
This completely stops the current movement of the body. I would start by removing that line. Also, for better realistic behaviour, you can follow the proper formula to compute attractive force, which goes something like this:
force = mass1 * mass2 * [some constant] / (distance ^ 2)
When you have the vector from your body towards the black hole (computed as black hole position - body position), the length of the vector is the distance, and after normalizing and multiplying by the force, you have the desired forceX and forceY force vector that needs to be applied to the body each update, as long as it stays in range of the hole.
However this formula will cause the force to grow to infinity as body moves closer to the hole, so you could try changing to linear conversion (closest = 1, farest = 0) if that causes any trouble.
force = mass1 * mass2 * [some constant] * ( (maxDistance - distance) / maxDistance )
You want to implement a tangential force with a magnitude that increases towards the center of the vortex.
Here's some pseudocode.
radialVector = objectPosition - vortexPosition;
tangentialVector = radialVector.perpendicularVector();
if (radialVector.length() < vortexRadius) {
// Swirl faster when near the center of the vortex.
// Max tangential force when distance from center is 0.
// Min tangential force when distance from center is vortexRadius.
forceMagnitude = map(radialVector.length(), vortexRadius, 0, minTangentialForce, maxTangentialForce);
force = forceMagnitude * tangentialVector.normalize();
object.applyForce(force);
}
Here's an image that shows the vector components:
To create a whirlpool effect there should be increasing radial (Fr) and tangential (Ft) forces as the object moves closer to the center.
I would like to use AndEngine's particle system to create a splash(as in splashing water).
I have checked out the particle system example, but not really sure on what needs to be done to create a splash affect of water using the particle system.
Any idea's?
I don't know of any water splash simulation algorithms, so I'll do what I think, but you will have to modify to make it look real.
Water splash animation in 2D will create many small water drops from a single location, then send each one in a different direction with an initial velocity, then each water drop slows down and fades out.
Try this out:
public ParticleSystem createParticleSystem(final TextureRegion waterDropTextureRegion) {
//X & Y for the particles to spawn at.
final float particlesXSpawn = 400;
final float particlesYSpawn = 300;
//Max & min rate are the maximum particles per second and the minimum particles per second.
final float maxRate = 10;
final float minRate = 5;
//This variable determines the maximum particles in the particle system.
final int maxParticles = 100;
//Particle emitter which will set all of the particles at a ertain point when they are initialized.
final PointParticleEmitter pointParticleEmtitter = new PointParticleEmitter(particlesXSpawn, particlesYSpawn);
//Creating the particle system.
final ParticleSystem particleSystem = new ParticleSystem(pointParticleEmtitter, maxRate, minRate, maxParticles, waterDropTextureRegion);
//And now, lets create the initiallizers and modifiers.
//Velocity initiallizer - will pick a random velocity from -20 to 20 on the x & y axes. Play around with this value.
particleSystem.addParticleInitializer(new VelocityInitializer(-20, 20, -20, 20));
//Acceleration initializer - gives all the particles the earth gravity (so they accelerate down).
particleSystem.addParticleInitializer(new GravityInitializer());
//And now, adding an alpha modifier, so particles slowly fade out. This makes a particle go from alpha = 1 to alpha = 0 in 3 seconds, starting exactly when the particle is spawned.
particleSystem.addParticleModifier(new AlphaModifier(1, 0, 0, 3));
//Lastly, expire modifier. Make particles die after 3 seconds - their alpha reached 0.
particleSystem.addParticleModifier(new ExpireModifier(3));
return particleSystem;
}
I haven't tested it, but I think it'd work. Try playing with the values to find an animation which looks reallistic.
The method receives an argument which is a ready texture region for each particle, in your case I guess that'd be a water drop.
After you call this method and get a ParticleSystem, just attach it to your scene:
final ParticleSystem particleSystem = createParticleSystem(...);
scene.attachChild(particleSystem);