Sprite rotates in the destination point - c++11

I am trying to implement point-and-click control over my sprite. Everything is essentially fine, but strange artifacts occur when sprite arrives to the destination point. Looks like it constantly rotates 180 degrees over and over again.
And normal state for comparison.
I've tried to avoid it using this function:
sf::Vector2f GetDirection(const sf::Vector2f& start, const sf::Vector2f& destination) {
sf::Vector2f dir = destination - start;
if (GetLength(dir) <= 0.1) {
return sf::Vector2f(0.0f, 0.0f);
}
return Normalize(dir);
}
But the condition is rarely true. Full code is here.
What am I doing wrong?

Your problem is that you have no way to "break".
You are going to 300/300. You overshoot your target. You turn. You go back. You overshoot your target. Rinse and repeat.
You are missing a check that if your current speed is more than needed to reach your target, you should just use the speed necessary. Not more.
You check is nice. But it checks if you are less than a tenth of a pixel away from your target. Maybe you should check less detailed. One pixel would be plenty. Replace
if (GetLength(dir) <= 0.1) {
with
if (GetLength(dir) <= 1.0) {
and it will work.

Related

Collision detection on enemy with wall when there is none

I am trying to develop basic enemy AI on a simple platformer game after following Shaun Spalding's gamemaker 2 platformer tutorials on youtube. My code is the exact same as his on the tutorial but for some reason, when my enemy detects collision with the wall he turns around as he is suppose to and then detects another collision where there is none, causing him to turn around again.
This is my code:
// Horizontal collision
if (place_meeting(x+hsp, y, oWall)) {
show_debug_message(hsp)
while (!place_meeting(x+sign(hsp), y, oWall)) {
x += sign(hsp); // slows down I think
}
hsp = -hsp;
}
x += hsp;
The -hsp part is where he turns around. Somehow, he is detecting another collision as soon as he does so, even though the value of hsp is inverted. Can anyone possibly point me in the direction of why this may be occuring?
(Value of hsp initialized at 3 and never changed only for inversion).
Is it turning back to the wall after a short while, or is it stuck and is flickering to left and right rapidly? Both could involve that the collision point isn't updating well.
When I face with collision problems, I'll use a crosshair sprite, and draw it at the same position as where it should be colliding. that way I've a visible view of the 'collision point'.
Another cause could be the sprite's origin point, that determines at which position the x and y appears, and that the sprite by turning collides with the wall itself. Keep in mind that the origin point is at the center of it's collision mask, to avoid been stuck in a wall.
EDIT: Another possibility: the collision point still checks inside the sprite.
For that, you could also try using an offset that keeps the collision point away from the sprite collision, but to let that work, you'll need to keep the inverse direction away from your horizontal speed. Something like this:
// Horizontal collision
_offset = 15; //moves the collision point away to check in front of the sprite. value depends on the size of the sprite.
_dir = 1; //the direction, should only be 1 or -1
//hsp should no longer be used to inverse, use a new variable (like _dir) instead
collisionPoint = (hsp + offset) * _dir;
if (place_meeting(x + collisionPoint , y, oWall)) {
show_debug_message(collisionPoint)
while (!place_meeting(x+sign(collisionPoint), y, oWall)) {
x += sign(collisionPoint); // slows down I think
}
_dir = -_dir
}
x += hsp * _dir;

My mesh flips for a rotation smaller than math.pi

I am coming back since I am having this geometric problem that I am not familiar with on Unity.
For a f-zero style game, I have a collider box (white on the screen captures) which is the origin of my raycast, and is bound to the movement of the vehicle.
In the shown code, this is this.collider. I control its rotation via a traditional applymatrix and there is no problem.
Then, on top of that, I have the rendered body of the vehicle in this.meshes. It inherits the rotation of the collider box, but gets some extra rotation on its vertical axis to give a visual sliding dynamic during the hard turns.
It is separate from the collider to keep the vector.forward of the movement (and the raycast) not affected by the extra-rotation. This is purely visual.
My question is: what is the best way to implement it?
I tried different things, but, basically, if I copy the position and rotation of the collider, no problem. As soon as I try to add some extra rotation = this.driftRotation, my body flips when rotation.y value is less than -math.pi. I can adjust the value of the rotation by incrementing Math.PI (like in Unity), but it doesn't work here.
No clean solution found with applyMatrix neither, and not a lot of google answers on "vertical rotation flip mesh"... though I'm pretty sure this pissue is common.
Some code:
this.meshes.position.set(
this.collider.position.x,
this.collider.position.y,
this.collider.position.z);
this.meshes.rotation.x = this.collider.rotation.x;
this.meshes.rotation.y = this.collider.rotation.y + this.driftRotation;
this.meshes.rotation.z = this.collider.rotation.z;
Enclosed more explicit pictures:
Thank you
Marquizzo, that's precisely the point: the 3rd px follows the 2nd one, so I'm still turning right but rotation suddenly flips (again, when rotation.y reaches -PI).
Anyway, I fixed it by not trying to directly change rotation.y value, but playing with matrix. Just takes time to understand what does what.
For those who may face a similar pb, here is my temp solution, until I find sthing more performant:
this.meshes.matrix.identity();
if (Math.abs(driftAmount) > 0)
{
this.driftAxis.copy(this.driftDirection);
this.driftValue = js.Utils.lerp(this.driftValue, Math.sign(driftAmount) * 0.4, 0.05);
this.meshes.matrix.makeRotationAxis(this.driftAxis, this.driftValue);
}
else if (Math.abs(this.driftValue) > 0)
{
this.driftAxis.copy(this.driftDirection);
this.driftValue = js.Utils.lerp(this.driftValue, 0, 0.1);
if (Math.abs(this.driftValue) < 0.001)
{
this.driftValue = 0;
}
this.meshes.matrix.makeRotationAxis(this.driftAxis, this.driftValue);
}
this.meshes.applyMatrix(this.collider.matrix);
I had to add a driftAxis along a driftDrection, which is my axis for my vertical rotation.
For ref. I think this subject is +/- bound to the issue I had:
https://github.com/mrdoob/three.js/issues/1460
Now I have another issue, how to add another rotation to this.meshes on another axis, the forward one, for a rolling effect, because if I just add another makeRotationAxis in this code it just skips the first one. But that sounds less difficult to figure out, there must exist the equivalent of combineMatrix something...

Few objects moving straight one by one in Unity

I'am trying to create some snake-like movement, but i cant implement algorithm to move one body part straight by another and so on.
I wanna to have some auto-moved snake which consists of separate blocks ( spheres ). This snake should move along some path. I generate path with bezier spline and have already implemented one future snake's part along it. Point for head is obtained from spline by next api:
class BezierSpline
{
Vector3 GetPoint(float progress) // 0 to 1
}
And than I have SnakeMovement script
public class SnakeMovement : MonoBehaviour
{
public BezierSpline Path;
public List<Transform> Parts;
public float minDistance = 0.25f;
public float speed = 1;
//.....
void Update()
{
Vector3 position = Path.GetPoint(progress);
Parts.First().localPosition = position;
Parts.First().LookAt(position + Path.GetDirection(progress));
for (int i = 1; i < Parts.Count; i++)
{
Transform curBody = Parts[i];
Transform prevBody = Parts[i - 1];
float dist = Vector3.Distance(prevBody.position, curBody.position);
Vector3 newP = prevBody.position;
newP.y = Parts[0].position.y;
float t = Time.deltaTime * dist / minDistance * curspeed;
curBody.position = Vector3.Slerp(curBody.position, newP, t);
curBody.rotation = Quaternion.Slerp(curBody.rotation, prevBody.rotation, t);
}
//....
}
For now, if I stopped head movement all parts dont preserve distance and keep moving to the head position. Another problem with above algorithm is that parts don't exectly follow the head path. They can "cut" corners while turning.
The main idea is to have user/ai control for only head(first body part) and each followed part should exectly repeat head path and preserve distance between its neighbours.
For a snake like motion you are likely to get lots of strange behaviours if you treat spheres as seperate objects. While i can imagine its possible to get it to work, I think this is not the best approach.
First solution that comes to mind is to create a List, onto which you would add to index 0, on every frame, the position of the head of the snake.
The list would grow, and all the other segments would wait their turn, so lag x frames, and on each update segment y would have position of list[x*y]
If Count() of the list is greater than number_of_segments*lag, you RemoveAt(Count()-1)
This can be optimized as changing the list is somewhat costly (a ring buffer would be better suited, but a Queue could also work. For starters i find Lists much easier to follow and you can always optimize later). This may behave a bit awkward if your framerate varies a lot but should be very stable in general (as in - no unpredictable motion, we only re-use the same values over and over)
Second method:
You mentioned using a bezier spline to generate a path. beziers are parametrized by a float t so you have something like
SplineAt(t).
if you take your bezier_path_length and distance_between_segments, than segment n should have position of
SplineAt(t-n*distance_between_segments/bezier_path_length)

how can I implement a slow smooth background scrolling in sdl

I am trying to implement background scrolling using SDL 2.
As far as I understand one can only move source rectangle by an integer value.
My scrolling works fine when I move it by one every iteration of the game loop.
But I want to move it slower. I tried to move it using this code
moved += speed;
if (moved >= 1.0) {
++src_rect.x;
moved -= 1;
}
Here moved and speed are doubles . I want my background to move something like ten times slower, therefore I set speed to 0.1. It does move ten times slower, but the animation is no longer smooth. It kind of jumps from one pixel to another, which looks and feels ugly when the speed is low.
I am thinking of making my background larger and scrolling it using an integer. Maybe when background is large enough the speed of 1 will seem slower.
Is there a way to scroll not a very large background slowly and smoothly and the same time?
Thanks.
What I would do is have a set of floats that would track the virtual screen position, then you just cast the floats to integers when you actually render, that way you don't ever lose the precision of the floats.
To give you an example, I have an SDL_Rect, I want to move it every frame. I have two floating point variables that track the x and y position of the rect, every frame I would update those x and y positions, cast them to an integer, and then render the rect, EX:
// Rect position
float XPos = 0.0f;
float YPos = 0.0f;
SDL_Rect rect = {0, 0, 64, 64};
// Update virtual positions
XPos += 20.0f * DeltaTime;
YPos += 20.0f * DeltaTime;
// Move rect down and to the right
rect.x = (int)XPos;
rect.y = (int)YPos;
While this doesn't give you the exact result you are wanting, it is the only way that I know of to do this, it will let you delay your movement more precisely without giving you that ugly chunkiness in the movement, it also will let you add stuff like more precise acceleration too. Hope this helps.

Particle (cloth) to sphere collision

What is the proper way to add a sphere constraint to a cloth sim?
I am trying to add a sphere (or capsule) constraing to Skeel Lee's cloth simulation source code, but I am not sure how to do it properly.
I created a rather simple constraint which "kicks" the particle back out of the sphere in the opposite direction (opposite from the vector towards the center):
void SatisfySphereConstraints()
{
foreach (var simObj in this.simObjects)
simObj.CurrPosition += SphereConstraint(simObj.CurrPosition, _center, _radius);
}
Vector3 SphereConstraint(Vector3 position, Vector3 center, float radius)
{
var delta = position - center;
var distance = delta.Length();
if (distance < radius)
return (radius - distance) * delta / distance;
return Vector3.Zero;
}
And then I inserted the method in the existing code:
ApplyForces();
Integrate();
for (var i = 0; i < constraintIterations; i++)
{
foreach (Constraint constraint in constraints)
constraint.SatisfyConstraint();
SatisfySphereConstraints(); // <-- I added it here
}
The collision code works fairly well for situations like this (C is the center of the sphere, P is the current particle position, P' is the resolved position):
But the problem occurs if particles are moving very quickly, because then the particle basically jumps to the other side of the sphere (P1 is the previous position, P2 is the current position, P' is how I think it should be resolved), instead of returning back to the previous position:
Since this is a cloth simulation, the cloth basically jumps over the sphere in that case, instead of being "stopped" by the sphere.
Now, I could try to return in the direction of the previous point, but since the sphere might also be moving, I am not sure if P1 is even a valid position (and if it will make sense). Also, it seems to be more computationally expensive - is this how I am supposed to do it, or not?
Cloth like things snapping to the wrong side of an obstacle and getting stuck there is not too uncommon. Even more common is fast moving objects overlapping way too much when the collision is detected.
A common solution is, on detecting a collision, sub divide the previous step until the collision is less severe and then resolve it. I think you will find trying to detect how deep the collision is to be difficult in your case, but if you could limit the top speed of spheres in your system you could binary split the frames in which collisions occur a fixed number of times and assume it will be good enough?
if (it collides at time T and didn't at T-1)
if (it collides at T-0.5)
try T-0.75
else
try T-0.25
etc...
Are you prepared to accept that it will sometimes be wrong, or does it have to be always a good result?

Resources