Delay in how sprite rotates - java

I'm trying to make this vehicle movement seem more realistic.
This works perfect except for how instant the rotation is.
It could do 180 instantly. I don't want it to turn around so fast.
public void onControlChange(final BaseOnScreenControl pBaseOnScreenControl, final float pValueX, final float pValueY) {
final Body carBody = CityRacerActivity.this.mCarBody;
final float rotationInRad = (float)Math.atan2(-pValueX, pValueY);
if ((pValueX == 0) && (pValueY == 0)) {
//Don't turn the body/sprite of the car
}else {
carBody.setTransform(carBody.getWorldCenter(), rotationInRad);
//turn the car body in the direction of movement
CityRacerActivity.this.mCar.setRotation(MathUtils.radToDeg(rotationInRad));
}
//set the velocity
final Vector2 velocity = Vector2Pool.obtain(pValueX * 5, pValueY * 5);
carBody.setLinearVelocity(velocity);
Vector2Pool.recycle(velocity);
}
I want it to have more play like driving a car.

The method setRotation changes the body's "facing direction" immediately.
You can use setAngularVelocity instead. It will also make your game much more reallistic because a car can't really rotate on the spot, so with an angular velocity the car will rotate during the physics world update, when it also moves according to your regular velociy. So it rotates as it moves, and that what's happening in our world.
I'd give setAngularVelocity a parameter depending on how sharp the turn is, 90 degrees should be the maximum IMO (But decide it after your own tests).

Related

Move rectangle by touching the screen

I want to move blocks with different x-positions without changing their shape by reducing the x-position.
I have tried to run the following code, but it seems like the blocks move to a tow position way to fast (correct potion and other i can't see where).
downBlocks=new Arraylist<Rectangle>;
for (DownBlocks downBlocks:getBlocks()){
if(Gdx.input.isTouched()) {
Vector3 touchPos = new Vector3();
touchPos.set(Gdx.input.getX(), Gdx.input.getY(), 0);
camera.unproject(touchPos);
downBlocks.x = (int) touchPos.x - downBlocks.x;
}
}
To do a drag, you need to remember the point where the finger last touched the screen so you can get a finger delta. And as a side note, avoid putting code inside your loop iteration if it only needs to be called once. It's wasteful to unproject the screen's touch point over and over for every one of your DownBlocks.
static final Vector3 VEC = new Vector3(); // reusuable static member to avoid GC churn
private float lastX; //member variable for tracking finger movement
//In your game logic:
if (Gdx.input.isTouching()){
VEC.set(Gdx.input.getX(), Gdx.input.getY(), 0);
camera.unproject(VEC);
}
if (Gdx.input.justTouched())
lastX = VEC.x; //starting point of drag
else if (Gdx.input.isTouching()){ // dragging
float deltaX = VEC.x - lastX; // how much finger has moved this frame
lastX = VEC.x; // for next frame
// Since you're working with integer units, you can round position
int blockDelta = (int)Math.round(deltaX);
for (DownBlocks downBlock : getBlocks()){
downBlock.x += blockDelta;
}
}
I don't recommend using integer units for your coordinates, though. If you are doing pixel art, then I recommend using floats for storing coordinates, and rounding off the coordinates only when drawing. That will reduce jerky-looking movement. If you are not using pixel art, I would just use float coordinates all the way. Here's a good article to help understand units.

Optimal Path-finding technique in a non-standard maze

So, my problem is that I'm currently working on a path-finding technique in an open world with tiles of various sizes. The object needs to find an optimal path to a destination inside an infinite world (it generates on the fly), which is filled with tiles of various sizes (which are not located on a set grid - they can have any location and size - and neither have to be integers). (The object has access to the data of all the tiles via and ArrayList). Now some factors that make this problem more difficult:
The objects itself has a size and cannot move through tiles. Therefore, it is possible for a path to exist that is too narrow for the object to move through.
The target destination may itself be a moving object.
It is possible for there to be dozens of such objects at the same time - so it is necessary for the algorithm to either be light on the system or for the path to be calculated in a few separate ticks of the program.
I tried implementing solutions for maze-solving techniques, but the main problem is the in most mazes, the tiles can only have very specific coordinates (such as whole numbers) and are always the same size.
I also tried rendering the scene as a giant conventional maze where tiles are actually pixels of tiles (so if i have a 20x40 tile it becomes a 20x40 block of 1x1 tiles), but ran into performance issues and the still didn't solve the issue with a path potentially being to narrow for the object to fit through.
EDIT:
Terribly sorry for my poor wording before, that happens when I'm trying to rush to a solution without fully understanding the question. So what I'm using the algorithm for at the moment is for NPC enemies to find their way to the player around obstacles. Here is an example of a scene:
The black circle with an arrow is the player, the black bush-like blobs are the NPC enemies. So this my my current algorithm I'm using for the enemy AI:
void move() { //part of the Enemy class, this function is called once each tick for every enemy
PVector velocity = new PVector(speed*game.dt, 0); //speed is a pre-set float denoting the enemy's speed, game.dt is deltatim
velocity.rotate(atan2(game.player.location.y-location.y, game.player.location.x-location.x)); //game.player.location is a PVector of the player's position, location is a PVector of this enemy's position
boolean init_collision = getTileCollision(); //getTileCollision is a boolean of whether this enemy is colliding with any tile
location.add(velocity);
boolean collision = getTileCollision();
if (!init_collision && collision) { //if the enemy happens to spawn inside a tile, let is move out of it before checking for collision
location.sub(velocity);
if (desired_heading != -1) { //desired heading is the angle, in radians, of which 90-degree angle the enemy wants to move in, by default set to -1 (see my descrition of this algorithm below)
velocity = new PVector(speed*game.dt, 0);
velocity.rotate(desired_heading);
location.add(velocity);
if (getTileCollision()) {
location.sub(velocity);
velocity = new PVector(speed*game.dt, 0);
velocity.rotate(current_heading); //current heading the an angle, in radians, of which 90-degree angle the enemy is currently moving in. set to -1 by default but can not equal -1 if desired_heading is not -1
location.add(velocity);
if (getTileCollision()) {
location.sub(velocity);
desired_heading = -1;
current_heading = -1;
}
} else {
desired_heading = -1;
current_heading = -1;
}
} else {
float original_heading = velocity.heading();
desired_heading = radians(round(degrees(velocity.heading())/90.0)*90.0); //round to the nearest 90 degrees
velocity = new PVector(speed*game.dt, 0);
velocity.rotate(desired_heading);
location.add(velocity);
if (getTileCollision()) {
location.sub(velocity);
}
float turn = radians(90);
while (true) { //if it cant move, try rotating 90 degrees and moving
velocity.rotate(turn);
location.add(velocity);
if (!getTileCollision() && abs(round(degrees(current_heading)) - round(degrees(velocity.heading()))) != 180) {
current_heading = velocity.heading();
break;
} else {
location.sub(velocity);
}
}
}
} else {
desired_heading = -1;
current_heading = -1;
}
}
So what my terrible code hopes to accomplish is the the enemy first tries to move directly at the player. If it encounters an obstacle, it will round its angle to the nearest 90 degrees, set desired_heading to this and try to move through. If it cant, it will rotate another 90 degrees and so forth, always keeping the original rounded angle in mind.
This doesn't work remotely well as first of all, rotating 90 degrees has a 50% chance to go in the exact wrong diretion, so I tried adding
if (abs(original_heading - velocity.heading()+turn) < abs(original_heading - velocity.heading()-turn)) {
turn = radians(-90);
}
right before the while (true) but that broke the algorithm completely (sometimes the enemy will freeze in deep thought and not move ever again).
What am I doing terribly wrong? Should I try a different algorithm or does this one have potential?
I hope this is a better question now...

Is it possible to create a simple animation just with translation and rotation in libGDX?

I'm trying to develop a very simple game using libGDX with boxes (so 3D game) moving and rotating.
I have almost everything ready, but I'm not able to animate my boxes. I mean, when I touch the screen, I'd like my cube to move to the right by rotating 90 degrees and translating 1 (unit) to the right. As result, the right side of the box will be the new base, the old base will be in the left side, and the box is moved to the right.
So, the question is: now that I have the move set correctly (I or at least I hope so), but change is applied immediately; so how can I see the animation between first position and second position ?
Only reference to animation for 3D objects in documentation is about using obj files from blender (and similar), and for movement I need I do not consider it necessary.
Can anybody provide me some help? Thanks in advance!!
You can do that something like this:
public static class YourAnimation {
public ModelInstance instance;
public final Vector3 fromPosition = new Vector3();
public float fromAngle;
public final Vector3 toPosition = new Vector3();
public float toAngle;
public float speed;
public float alpha;
private final static Vector3 tmpV = new Vector3();
public void update(float delta) {
alpha += delta * speed;
if (alpha >= 1f) {
alpha = 1f;
// TODO: do whatever you want when the animation if complete
}
angle = fromAngle + alpha * (toAngle - fromAngle);
instance.transform.setToRotation(Vector3.Y, angle);
tmpV.set(fromPosition).lerp(toPosition, alpha);
instance.transform.setTranslation(tmpV);
}
}
YourAnimation animation = null;
void animate(ModelInstance instance) {
animation = new YourAnimation();
animation.instance = instance;
animation.instance.transform.getTranslation(animation.fromPosition);
animation.toPosition.set(animation.fromPosition).add(10f, 10f, 10f);
animation.fromAngle = 0;
animation.toAngle = 90f;
animation.speed = 1f; // 1 second per second
animation.alpha = 0;
}
public void render() {
final float delta = Math.min(Gdx.graphics.getDeltaTime(), 1/30f);
if (animation != null)
animation.update(delta);
// render model as usual etc.
}
Ofcourse this is just a quick example. The actual implementation will vary depending on the use case. For example you could also extend ModelInstance and keep track of the animation in there. Because it is very specific to the use-case, but very simple to implement, it is usually not worth using tools (like the Universal Tween Engine)
Here is another example I recently wrote for my latest tutorial, perhaps it helps as well. It rotates and moves the cards in this video.

Gravity in a Java ball bouncing program that refreshes every game tick

Hey I am trying to figure out the best way to implement gravity in my program that is simply a ball bouncing. The program uses a method that is called 50 times a second (the rate at which the gametimer ticks) and in this method I call the gravity method. In the gravity method I currently have
public void Gravity(){
this.currentPositionY = this.currentPositionY + 9;
if (this.currentPositionY >= 581){
this.currentPositionY=581;
}
}
Problems with my code: In gravity velocity is not constant it varies with the time, but I am unsure of how to implement time with the gravity method being called so often. Also currently I have it so that the ball stops at 581, so that it does not fall through the screen. How would I implement a bounce that is higher when the ball falls for longer and shorter when the ball falls less? Thanks for your time!
Have a variable outside of the method for its y-velocity. Every tick, increase its velocity accounting for gravity.
If the ball is past a boundary, set it to the boundary and set the velocity to -1*velocity to make it "bounce" in the other direction.
Maybe something like this:
private int currentVelocityY = 0;
private int gravity = 3;
public void Gravity(){
this.currentPositionY = this.currentPositionY + this.currentVelocityY;
if (this.currentPositionY >= 581){
this.currentPositionY=581;
this.currentVelocityY = -1 * this.currentVelocityY;
}
currentVelocityY = currentVelocityY + gravity;
}

Binding sprite movement to the camera or scene (AndEngine)

I am using DigitalOnScreenControl to Move Player Sprite.But the Problem is that My Player Sprite goes out of Emulator Screen.I want player sprite be restricted to move in particular bounds and also camera to focus on player sprite as and when my sprite moves on.
i am trying this code:
public Scene onLoadScene() {
// Auto-generated method stub
this.mEngine.registerUpdateHandler(new FPSLogger());
final Scene mScene=new Scene();
mScene.setBackground(new ColorBackground(0.09804f, 0.6274f, 0.8784f));
final int centerX=(CAMERA_WIDTH-this.mPlayerTextureRegion.getWidth())/2;
final int centerY=(CAMERA_HEIGHT-this.mPlayerTextureRegion.getHeight())/2;
final Sprite player=new Sprite(centerX, centerY, this.mPlayerTextureRegion);
this.mCamera.setChaseEntity(player);
final PhysicsHandler physicsHandler=new PhysicsHandler(player);
player.registerUpdateHandler(physicsHandler);
mScene.attachChild(player);
this.mDigitalOnScreenControl=new DigitalOnScreenControl(0,CAMERA_HEIGHT-mOnScreenControlBaseTextureRegion.getHeight(),this.mCamera,this.mOnScreenControlBaseTextureRegion,this.mOnScreenControlKnobTextureRegion,0.1f,new IOnScreenControlListener() {
#Override
public void onControlChange(BaseOnScreenControl pBaseOnScreenControl,
float pValueX, float pValueY) {
// TODO Auto-generated method stub
physicsHandler.setVelocity(pValueX*100, pValueY*100);
}
});
this.mDigitalOnScreenControl.getControlBase().setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
this.mDigitalOnScreenControl.getControlBase().setAlpha(0.5f);
this.mDigitalOnScreenControl.getControlBase().setScaleCenter(0, 128);
this.mDigitalOnScreenControl.getControlBase().setScale(1.25f);
this.mDigitalOnScreenControl.getControlKnob().setScale(1.25f);
this.mDigitalOnScreenControl.refreshControlKnobPosition();
mScene.setChildScene(this.mDigitalOnScreenControl);
return mScene;
}
Honestly I am Very new in andEngine Development
please Help me With Heart
Thank in advance.
Binding the Player to the Camera
What you're asking for is a form of collision handling. Essentially, when you've moved the player outside of the scene, you want to move the player back into the scene, and you want to do that in the same update as you've moved the player, immediately after moving the player, so the out-of-scene location never gets rendered.
Lets take apart what I just said. You move the player here:
physicsHandler.setVelocity(pValueX*100, pValueY*100);
Moving the player with a physicsHandler is perfectly reasonable and takes into account variable frame-rate so, so far, good job. Now you want to move them back into the scene if they're outside it. So we're going to need a new method. Lets throw in a method call right after moving the player (we'll call it "adjustToSceneBinding()" so you have this:
physicsHandler.setVelocity(pValueX*100, pValueY*100);
adjustToSceneBinding(player);
Sidenote, I'd rather have this method be on the player (i.e., player.adjustToSceneBinding()), but your player object is just a sprite. I'd suggest you change that to a custom object that extends sprite so you can throw in your own code there. In any event, lets make the adjustToSceneBinding() method.
public boolean adjustToSceneBinding(Sprite player) {
// Correct the X Boundaries.
if (player.getX() < 0) {
player.setX(0);
} else if (player.getX() + player.getWidth() > CAMERA_WIDTH) {
player.setX(CAMERA_WIDTH - player.getWidth());
}
}
See what I did? If the player's X coordinate is less than zero, move them back to zero. If the player's X PLUS the player's width is more than the camera width, move them back to the camera width minus the player width. Don't forget the player X coordinate represents the left side of the sprite. That's why I'm taking into account the width in addition to the position for calculating the right side.
The above code only addresses left/right movement, but I'm going to let you extrapolate how to do the same for up down.
Binding the Player to the Map Size Instead
Now, what we did so far was really intended for the situation where the map "size" is no larger than the screen. But often what you'll want is a larger map than the screen size and a camera that chases the player around. To do that, just replace the code above, where I referred to the CAMERA_WIDTH with a number that represents the width of your "map". In other words, the map can be much larger than the camera. If you use larger numbers there (than, say, the width of the camera), and you set the camera to chase the player entity (as you have), then you'll have a map where the player can move around until they hit the bounds of the map.
Hope this helps! :)

Categories

Resources