Movement EquationDeltaHeight = (Sin(RunningTime + DeltaTime) - Sin(RunningTime)); - c++

I have started working in Unreal Engine 4 and opened up the most basic tutorial with c++ on their web site. So this is the code they provided
void AFloatingActor::Tick( float DeltaTime )
{
Super::Tick( DeltaTime );
FVector NewLocation = GetActorLocation();
float DeltaHeight = (FMath::Sin(RunningTime + DeltaTime) - FMath::Sin(RunningTime));
NewLocation.Z += DeltaHeight * 20.0f; //Scale our height by a factor of 20
RunningTime += DeltaTime;
SetActorLocation(NewLocation);
}
And this is the explanation of what it should do:
The code we've just written will cause FloatingActors to bob up and down smoothly, using the RunningTime variable we created to keep track of our movement over time.
And when you compile it it does that, but it doesn't tell me anything about how or why it works. The thing that bugs me is as the title say the movement equation :
DeltaHeight = sin(RunningTime + DeltaTime) - sin(RunningTime)
If anyone could explain this to me it would be greatly appreciated. What I'm asking would be Mathematical/Physical explanation behind this equation or the explanation where does this equation come from. Why is it like that.

This function controls the movement (height specifically) of the character such that the amount of movement is controlled via a sine wave over time. That is, at time 0 it starts moving upwards relatively quickly, then slows down upwards movement until it stops moving up and then starts moving down, speeds up downwards eventually slowing down and moving up again. It continues periodically moving up and down in this manner.
So, how this functions works, is that it's called periodically and then time change between this call and the last is DeltaTime. The last time it was called was RunningTime. So compute the new position:
FMath::Sin(RunningTime + DeltaTime)
and the old position:
FMath::Sin(RunningTime)
then calculate the change in position by taking the difference:
float DeltaHeight = (FMath::Sin(RunningTime + DeltaTime) - FMath::Sin(RunningTime));

Related

SFML sf::View::move inconstancy

UPDATE:
I couldn't figure out the exact problem, however I made a fix that's good enough for me: Whenever the player's X value is less then half the screen's width, I just snap the view back to the center (up left corner) using sf::View::setCenter().
So I'm working on a recreating of Zelda II to help learn SFML good enough so I can make my own game based off of Zelda II. The issue is the screen scrolling, for some reason, if link walks away from the wall and initiated the camera to follow him, and then move back toward the wall, the camera won't go all the way back to the end of the wall, which occurs on the other wall at the end of the scene/room. This can be done multiple times to keep making the said camera block get further away from the wall. This happens on both sides of the scene, and I have reason to believe it has something to do with me trying to make the game frame independent, here's an included GIF of my issue to help understand:
My camera function:
void Game::camera() {
if (this->player.getVar('x') >= this->WIDTH / 2 and this->player.getVar('x') < this->sceneWidth - this->WIDTH / 2) {
this->view.move(int(this->player.getVar('v') * this->player.dt * this->player.dtM), 0);
}
}
player.getVar() is a temporary function I'm using to get the players x position and x velocity, using the argument 'x' returns the players x position, and 'v' returns the x velocity. WIDTH is equal to 256, and sceneWidth equals 767, which is the image I'm using for the background's width. dt and dtM are variables for the frame independence I mentioned earlier, this is the deceleration:
sf::Clock sclock;
float dt = 0;
float dtM = 60;
int frame = 0;
void updateTime() {
dt = sclock.restart().asSeconds();
frame += 1 * dt * dtM;
}
updateTime() is called every frame, so dt is updated every frame as well. frame is just a frame counter for Link's animations, and isn't relevant to the question. Everything that moves and is rendered on the screen is multiplied by dt and dtM respectively.
There's a clear mismatch between the movement of the player and the one of the camera... You don't show the code to move the player, but if I guess you don't cast to int the movement there, as you are doing on the view.move call. That wouldn't be a problem if you were setting the absolute position of the camera, but as you are constantly moving it, the little offset accumulates each frame, causing your problem.
One possible solution on is to skip the cast, which is unnecessary because sf::View::move accepts float as arguments.
void Game::camera() {
if (this->player.getVar('x') >= this->WIDTH / 2 and this->player.getVar('x') < this->sceneWidth - this->WIDTH / 2) {
this->view.move(this->player.getVar('v') * this->player.dt * this->player.dtM, 0);
}
}
Or even better, not to use view.move but to directly set the position of the camera each frame. Something like:
void Game::camera() {
if (this->player.getVar('x') >= this->WIDTH / 2 and this->player.getVar('x') < this->sceneWidth - this->WIDTH / 2) {
this->view.setCenter(this->player.getVar('x'), this->view.getCenter().y);
}
}

Function fails to detect event at random times

I have these functions:
void apply_gravity(double delta){
velocity.y+=9.8*100*delta;
}
void move_body(double delta){
location.x+=velocity.x*delta;
location.y+=velocity.y*delta;
}
void processPhysics(double delta){
apply_gravity(delta);
move_body(delta);
if(location.y>=SCREENY){
velocity.y=-coefficient_of_restitution*velocity.y;
}
}
delta is the time elapsed between two calls to the function.
velocity contains two parts, x and y which represent the increment per second to the location's x and y.
coefficient of restitution represents how much of the original velocity the body retains after collision.
Basically, here is what I want this code to do:
Accelerate downwards by 9.8*100px per second. When the body goes below a limit (SCREENY px), it should bounce back, just like if it is hitting a floor. The collision should be perfectly elastic, and for now, SCREENY does not vary at all.
The code perfectly works for most of the times. BUT, sometimes, instead of "bouncing", the body just passes through the "floor". Basically, it seems that velocity.y does NOT negate even when the body crosses SCREENY. The comparision (location.y>=SCREENY) just fails at random times. Sometimes it works, sometimes it doesn't.
That should not happen.
What is going wrong here?
Your object is still allowed to pass through the floor, only updating the velocity. However, in the next frame, the object may still be in the floor, and have its velocity negated a second time (and third, and fourth). I imagine it would look like it gets stuck and vibrates a bit of a distance within the wall. If the object is within the wall, you should instead calculate where it should be if it had bounced, and update the position AND velocity accordingly. Not just the velocity.
A possible solution could look like:
void apply_gravity(double delta){
velocity.y += 9.8 * 100 * delta;
}
void move_body(double delta){
location.x += velocity.x * delta;
location.y += velocity.y * delta;
}
void processPhysics(double delta){
apply_gravity(delta);
move_body(delta);
if(location.y > SCREENY) // change to > from >= (eliminates edge case)
{
location.y = SCREENY - coefficient_of_restitution * (location.y - SCREENY); // update position as well, accounting for loss of velocity due to bounce
velocity.y = -coefficient_of_restitution * velocity.y;
}
}
The above solution will yield an error if the object is moving greater than one screen length in a single physics tic, so be careful about high speeds. You'll need a slightly more complicated algorithm to handle those situations.

SFML How to orbit around around the center of the screen while moving down?

So i have to move a sprite that orbits around the center of the screen (which is the original position of the object in X) while moving down. I have yet to find the way to get it to work, since the sprite flickers everywhere around the screen.
move(0, speed);
angle = getRotation();
rotate(+1);
move(origPosX + cosf(angle) * speed, origPosY + sinf(angle) * speed);
I can only assume you're running the code in your question every frame, in which case, you should be using setPosition, not move, otherwise it will be adding the position offset for the rotation constantly.
You also add 1 to the rotation every frame, which unless you lock your framerate, is going to be inconsistent, so I recommend multiplying by the time since last frame (AKA "delta time").
Also, rotation in SFML is done in degrees, but cosf takes arguments in radians, so you need to convert that.
You want to do something like this:
position += sf::Vector2f(0.f, speed);
rotate(1.f * deltaTime);
setPosition(position.y + cosf(toRadians(angle)), position.y + sinf(toRadians(angle)));

In SFML Why does my projectile slows as it gets closer to target

I am creating a small 2D top-down program that will have a projectile created when the left mouse is pressed. Then the projectile moves toward a goal. My issue is that the projectile slows when it moves closer to the goal. It should remain the same speed. I looked into normalize thinking that would help but have had a hard time finding much on SFML normalize. What I did find has not helped.
Here is my update for my projectile (agents):
void agent::update(const sf::CircleShape* goal, sf::Time delta) {
direction = goal->getPosition() - body.getPosition();
sf::Vector2f newPos = body.getPosition() + sf::Vector2f(direction.x * speed * delta.asSeconds(), direction.y * speed * delta.asSeconds());
body.setPosition(newPos);
}
ps. I have it in asSeconds instead of asMilliseconds or it goes weird and lags.

SFML - Move object towards coord

so I am working on an AI system with C++ and SFML in which I want the enemies to follow the player. Im going to create it so the enemies are moving towards the point at which the player was 30 frames ago (so it will constantly updating). But my question is simple, what is the math behind getting the enemy to move to a specific point? Like let's say the player is at (230, 400) and the enemy is at (100, 200) how do I get the enemy (using the .move() function with a speed of 3) to move to that point? Any help would be fantastic!
---UPDATED BELOW WITH CURRENT CODE FOR HANDLING MOVEMENT-----
float angle = atan2(v2iEnemyPos[1].y - rsPlayer.getPosition().y, v2iEnemyPos[1].x - rsPlayer.getPosition().x);
angle =angle * 180 / (atan(1) * 4);
sf::Vector2f newpos((cos(angle))*2, (sin(angle))*2);
std::cout << newpos.x << " " << newpos.y << std::endl;
rsEnemy[1].move(newpos.x, newpos.y);
rwWinOne.draw(rsPlayer);
rwWinOne.display();
rwWinOne.clear();
The direction to move your enemy into is simply the difference between the player position and the enemy position. However, you want the enemies to move with constant speed, so you need to normalize the result. This will give you the direction as a vector of length 1.
Vector2u direction = normalize(player.getPosition() - enemy.getPosition());
You can now multiply this direction by the speed constant of that enemy's type. The result is a vector with it's length depending on the speed factor instead of the distance to the player. Just use the result to move your enemy.
enemy.move(speed * direction);
However, you perform that once a frame and framerates can vary between machines and configurations. Therefore, you should add a the elapsed time since the last move call, which might be your frame time, as factor to the equation. This way, if a frame takes a longer than usual, the enemy will be moved further to comprehend this, and vice versa.
// Initialize a timer
sf::Clock clock;
// Get elapsed time at the beginning of a frame
// I multiply this by target framerate to get a value around one
float delta = clock.restart().asSeconds() * 60;
// Move all objects based on elapsed time
Vector2u direction = normalize(player.getPosition() - enemy.getPosition());
enemy.move(delta * speed * direction);
By the way, basic knowledge of linear algebra is needed very often in game development, so you might pay out to attend an online course.
You should consider the elapsed time (since last frame) - dt - in your calculation.
The enemy has a given speed: enemy_velocity.
I won't use the move() function, but the SetPosition().
You have to calculate the new position of the enemy:
enemy.x += dt * enemy_velocity * cos(angle);
enemy.y += dt * enemy_velocity * sin(angle);
And affect it with SetPosition().