public void update(float deltaTime){
position.x = position.x + (ballSpeed* deltaTime);
position.y = position.y + (ballSpeed* deltaTime);
}
The code above is part of my update method where i basically get the ball to move around the screen, and when it hits the walls it bounces off.
However i put the value of 'ballSpeed' to be 10, it moves fine. Increase it to 30 and it practically doesn't move. Increased it to 120 and it moves slightly faster but not as fast as when the value is 10.
I'm not sure why it does this. Any one help ?
Related
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;
I got a problem with a game of mine. It is a top down shooter and if I am pressing the mouse a bullet should shoot in the direction of where the mouse was.
The problem is that with my attempt the bullet would be faster when the distance between player and mouse is bigger and slower when the distance is smaller. I want that speed to be constant no matter what.
This is what my logic looks like so far:
In the constructor I give the bullet a xDir and a yDir:
b.xDir = (float64(mouseX) - b.x)
b.yDir = (float64(mouseY) - b.y)
Then in the update function I multiply it with deltaTime and the bullets movementSpeed and add it to the corresponding position axis:
b.x += b.movementSpeed * dt * b.xDir
b.y += b.movementSpeed * dt * b.yDir
With that logic the bullet speed is depending on the distance between mouse and player. I would appreciate an answer which would not mess with the speed but would still go in the direction of the mouse click.
Thanks in advance :)
The problem is that your b.xDir and b.yDir values are directly calculated from the distance, so the farther the mouse click from the player, the higher the values will be. When they are multiplied by dt, it makes them move faster.
What you need is to normalize your vector, so you only have a direction and not a magnitude carried over from the original click distance. You probably want to use a vector library, but if you're going to do it by scratch, it would look like this:
magnitude := math.Sqrt(b.XDir * b.xDir + y.xDir * y.xDir)
b.xDir /= magnitude
b.yDir /= magnitude
At that point the value of your variables is purely a direction, and multiplying by speed and dt will have the expected effects.
Does something like this work? The idea is to create a 0 to 1 value for the direction. To do that you divide both values by the greatest of the two. You can then multiply this by the speed of the bullet. I've not detailed the playerPosition function but hopefully you can infer what it would do.
func Max(x, y float64) float64 {
if x < y {
return y
}
return x
}
type Bullet struct {
x, y, xDir, yDir float64
}
func getDirection(b *Bullet) {
directionX = float64(mouseX) - playerPosition().x
directionY = float64(mouseY) - playerPosition().y
greatest = Max(mouseX, mouseY)
b.xDir = directionX / greatest
b.yDir = directionY / greatest
}
Syntax might be off a bit, I'm mostly a js dev ;(
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.
Hi I have the following implementation of ball to ball collision detection in ruby, which works fine for most collisions. How ever there are some flaws when balls hit each other at certain angels.
I have put my implementation down here if you need more info tell me. But Im wondering more in general terms. What causes the balls to swirl around each other at certain angels of impact.
def ball_collider! ball
for ball2 in #balls do
next if ball.object_id == ball2.object_id
next unless box_overlap ball2.boundbox, ball.boundbox
next unless ball_overlap ball, ball2
dx = ball2.x - ball.x
dy = ball2.y - ball.y
dist=Math.sqrt(dx**2 + dy**2)
bonuce_point_x = ball2.x - (ball.radii + ball2.radii) * dx / dist
bonuce_point_y = ball2.y - (ball.radii + ball2.radii) * dy / dist
bounce_line = [[bonuce_point_x,bonuce_point_y],[bonuce_point_x-dy,bonuce_point_y+dx]]
ball2.bounce! bounce_line
ball.bounce! bounce_line
motion_left = ball.unmove! bounce_line, true
ball_controller! ball if motion_left > 0.1
end
end
def box_overlap box1, box2
return (box1[:width] + box2[:width] > (box1[:x] - box2[:x]).abs) && (box1[:width] + box2[:width] > (box1[:y] - box2[:y]).abs)
end
def ball_overlap ball1, ball2
dx = ball2.x - ball1.x
dy = ball2.y - ball1.y
return (dx**2 + dy**2) < (ball1.radii+ball2.radii)**2
end
In your physics model, you are presumably updating positions and doing collision checks at discrete time intervals. This means that when you detect a collision between a pair of balls, the actual collision would have taken place somewhat before that time, and your calculations will thus be based on the wrong movement vectors. You could do calculations to get the correct time of impact, but this could get messy due to other objects being involved in collisions with the two objects you're checking within the same time interval. Try increasing the frequency (ie. reducing your time intervals) to limit the problem.
As for why you get the "swirl" effect: the calculations will cause the balls to still be colliding with each other after your modify their vectors, even when they are now moving away from each other, which will again cause your next iteration to pull them towards each other's center again, and so on and so forth.
I'm trying to build a to scale model of the solar system. I wanted to see if someone could explain to me how the rotation speed works. Here's the important piece:
objects[index].rotation.y += calculateRotationSpeed(value.radius,value.revolution) * delta;
How does the rotation speed relate to actual time? So if you have a speed of 1, is that a movement of 1 px per millisecond? Or if you have a speed of 0.1, is that less that a px a second?
Basically I'm trying to calculate the correct rotation speed for the planets given their radius and amount of hours in a day. So if you were on earth, it would complete 1 rotation in 24 hours. Here's the function that I wrote that's doing the calculation now:
/* In a day */
function calculateRotationSpeed(radius,hrs,delta) {
var cir = findCircumference(radius);
if(delta) {
var d = delta;
} else {
var d = 1;
}
var ms = hrs2ms(hrs) * d;
var pxPerMS = km2px(cir) / ms;
return pxPerMS;
}
I gave it a try and it still seems to be moving too fast. I also need something similar to calculate orbit speeds.
Rotation and Units
Rotation in Three.JS is measured in radians. For those that are completely unfamiliar with radians (a small excerpt from an old paper of mine):
Like the mathematical constant Pi, a radian (roughly 57.3 degrees) is derived from the relationship between a circle's radius (or diameter) and its circumference. One radian is the angle which will always span an arc on the circumference of a circle which is equal in length to the radius of that same circle (true for any circle, regardless of size). Similarly, Pi is the ratio of circumference over diameter, such that the circumference of the unit circle is precisely Pi. Radians and degrees are not actually true units, in fact angles are in general dimensionless (like percentages and fractions, we do not use actual units to describe them).
However, unlike the degree, the radian was not defined arbitrarily, making it the more natural choice in most cases; often times being much easier and much more elegant, clear, and concise than using degrees in mathematical formulae. The Babylonians probably gave us the degree, dividing their circle into 6 equal sections (using the angle of an equilateral triangle). each of these 6 sections were probably further subdivided into 60 equal parts given their sexagesimal (base 60) number system. This would also allow them to use such a system for astronomy because the estimated number of days in a year was much less accurate during their time and was often considered 360.
Basic Rotation in Three.JS
So now, knowing you're working in radians, if you increment the rotation of an object by 1 you will be incrementing the rotation of the object by one radian. For example, consider making the following calls in the callback to requestAnimationFrame:
mesh.rotation.x += 1; // Rotates by 1 radian per frame
mesh.rotation.x += Math.PI / 180; // Rotates by 1 degree per frame
mesh.rotation.x += 45 * Math.PI / 180 // Rotates by 45 degrees per frame
As the above examples show, we can easily convert a value in degrees into a value in radians by multiplying by a constant factor of Math.PI / 180.
Taking Framerate Into Account
In your case, you will also need to take into consideration how much time passes with each frame. This is your delta. Think about it like this: What framerate are we running at? We'll declare a global clock variable which will store a THREE.Clock object which has an interface to the information we require:
clock = new THREE.Clock();
Then, in the callback to requestAnimationFrame, we can use clock to get two values that will be useful for our animation logic:
time = clock.getElapsedTime(); // seconds since clock was instantiated
delta = clock.getDelta(); // seconds since getDelta was last called
The delta value is meant to represent the time between each frame. However, note that this is only true when clock.getDelta is called consistently, exactly once in the same place somewhere within the callback to requestAnimationFrame. If clock.getDelta somehow gets called more than once or is called inconsistently it's going to screw things up.
Rotating With A Delta Factor
Now, if your scene doesn't bog down the processor or the GPU, then Three.JS and it's included requestAnimationFrame will try to keep things running at a smooth 60 frames per second. This means that ideally we will have approximately 1/60 = .016666 seconds between each frame. This is your delta value which can be obtained by calling clock.getDelta each frame.
We can use the delta value to decouple the rate at which we animate objects by multiplying as shown below. In this case, multiplying by delta will allow us to update our rotation at a rate defined in terms of seconds (as opposed to updating the rotation per frame as we did before). Multiplying by the delta value will also allow us to smoothly animate objects at a constant velocity without being effected by any small variations in the framerate from frame to frame and will even maintain that velocity even in the case that the framerate drops below the target 60fps (for example 30FPS, 45FPS, etc).
So, the examples we considered previously now become:
mesh.rotation.x += delta * 1; // Rotates 1 radian per second
mesh.rotation.x += delta * Math.PI / 180; // Rotates 1 degree per second
mesh.rotation.x += delta * 45 * Math.PI / 180; // Rotates 45 degrees per second
Rotational Speed and Units
Because radians and degrees are not actually units defined in terms of distance/size), then when we we calculate our rotational speed (angular velocity) you'll see that it is going to be a function only of time and is not dependent on the radius as in your code.
Calculating Rotational Speeds Based On Time
For example, you don't need the radius of a planet to calculate its angular velocity, instead you can calculate it using only the number of hours in a day or the amount of time it takes for the planet to complete a single revolution (ie. the duration it takes for the planet to rotate 2 * PI radians on it's axis).
If we assume that the Earth has exactly 24 hours = 24 * 60 * 60 = 86,400 seconds in a day (it doesn't). Then, given that there are 2 * PI radians in a complete revolution (360 deg), we can calculate the Earth's constant angular velocity in radians as:
radsPerRevolution = 2 * Math.PI;
secsPerRevolution = 24 * 60 * 60;
angularVelocity = radsPerRevolution / secsPerRevolution ; // 0.0000727 rad/sec
The above only needs to be calculated once, outside of the callback to requestAnimationFrame, as the value never changes. You could probably find textbook values that will be more accurate than this (taking into account a more accurate measurement than our 24 hour flat figure for the amount of time it takes for Earth to complete a revolution).
At this point, rotating our mesh with the same angular velocity as Earth would be as simple as updating its rotation every frame by incrementing its value by delta multiplied by the constant angularVelocity. If angularVelocity is defined as above, this can be done by calling the following in the callback to requestAnimationFrame:
mesh.rotation.x += delta * angularVelocity;
In Conclusion
I wouldn't worry about making sure you have all of the angular velocities for the planets exactly correct. Instead, a better idea might be to work out what the ratios between each of the angular velocities (of the planets) are and use those. This might work better since it will allow you to speed up or slow down the animation as desired, and as when working with any model (particularly astronomical models) the most important thing is that you keep it to scale, not necessarily, the scale doesn't necessarily have to be 1:1.