I am practicing on pygame and I was wondering how can we do so that the framerate does not affect the speed of execution of the game
I would like FPS to not be locked and the game to always run at the same speed.
Until now I used the pygame.time.Clock.tick function but the speed of the character was changing depending on the number of FPS, which I don't want.
You have to calculate the movement per frame depending on the frame rate.
pygame.time.Clock.tick returns the number of milliseconds since the last call. When you call it in the application loop, this is the number of milliseconds that have passed since the last frame. Multiply the objects speed by the elapsed time per frame to get constant movement regardless of FPS.
For instance define the distance in number of pixel, which the player should move per second (move_per_second). Then compute the distance per frame in the application loop:
move_per_second = 500
FPS = 60
run = True
clock = pygame.time.Clock()
while run:
ms_frame = clock .tick(FPS)
move_per_frame = move_per_second * ms_frame / 1000
# [...]
Related
I am practicing on pygame and I was wondering how can we do so that the framerate does not affect the speed of execution of the game
I would like FPS to not be locked and the game to always run at the same speed.
Until now I used the pygame.time.Clock.tick function but the speed of the character was changing depending on the number of FPS, which I don't want.
You have to calculate the movement per frame depending on the frame rate.
pygame.time.Clock.tick returns the number of milliseconds since the last call. When you call it in the application loop, this is the number of milliseconds that have passed since the last frame. Multiply the objects speed by the elapsed time per frame to get constant movement regardless of FPS.
For instance define the distance in number of pixel, which the player should move per second (move_per_second). Then compute the distance per frame in the application loop:
move_per_second = 500
FPS = 60
run = True
clock = pygame.time.Clock()
while run:
ms_frame = clock .tick(FPS)
move_per_frame = move_per_second * ms_frame / 1000
# [...]
This question already has answers here:
How can you rotate the sprite and shoot the bullets towards the mouse position?
(1 answer)
calculating direction of the player to shoot pygame
(1 answer)
Firing particles from a player at a constant speed with cos() and sin() in python pygame
(1 answer)
Moving forward after angle change. Pygame
(1 answer)
Closed 1 year ago.
So I'm trying to test out a simple combat system in Pygame where the player can basically shoot a projectile towards an area based on where the mouse position is. So for example when he clicks on the top left of his screen, the projectile moves towards there at a steady speed. I've created a function that will move each bullet in a list, here's the function.
def move_bullet(bullet_pos, direction):
# TODO Make the speed of the bullet the same no matter which direction it's being fired at
bullet_pos[0] += direction[0]/50
bullet_pos[1] += direction[1]/50
bullet_rect = pygame.Rect((bullet_pos[0], bullet_pos[1]), BULLET_SIZE)
return bullet_rect
The direction is calculated by subtracting the mouse's vector position by the player's vector position when the mousebuttondown event is triggered.
However, I have noticed that the closer I get to the player/origin of the bullet, the slower the bullet goes because the direction vector is smaller so the speed is differs depending on your mouse's position. I've heard of Vector normalization but I have no idea how to implement it because after doing a bit of research, apparently you normalize Vectors by getting it's magnitude and dividing the X and Y values by the magnitude? I got it from Khan Academy but it doesn't actually work. And I'm pulling my hair out over this so I have no choice but to ask this question here.
TL; DR
How do I normalize a Vector in Pygame?
If you have to points
x1 = 10
y1 = 10
x2 = 100
y2 = 500
then you can calculate distance and use pygame.math.Vector2
import pygame
dx = x2-x1
dy = y2-y1
distance = pygame.math.Vector2(dx, dy)
or
v1 = pygame.math.Vector2(x1, y1)
v2 = pygame.math.Vector2(x2, y2)
distance = v2 - v1
and then you can normalize it
direction = distance.normalize()
It should always gives distance 1
print('distance:', direction[0]**2 + direction[1]**2) # 0.999999999999
# or
print('distance:', direction.length() )
And then you move object using speed
pos[0] += direction[0] * speed
pos[1] += direction[1] * speed
EDIT:
If you will use Rect
SIZE = (10, 10)
bullet_rect = pygame.Rect((0, 0), SIZE)
bullet_rect.center = (x1, y1)
then you can also calculate
distance = v2 - bullet_rect.center
direction = distance.normalize()
and move it with one line
bullet_rect.center += direction * speed
Rect has many useful functions. But has one minus - it keeps position as integers so it rounds float values and sometimes it gives strange moves or lost one pixel every few moves.
Doc: PyGame.math
I have a small problem that I really cant figure out how to solve after some time googling.
My project consists of a rasberry pi and a rotary encoder that I will use as a sensor to see how fast a shaft is spinning. This is then coded in Python. My problem then is that I have no clue how to calculate this. The rotary encoder is connected directly to the shaft and will spin at the same speed as the shaft, and if I use this code the variable "counter" will increment with 1 per "click". Assuming thats what I have to go on, I need to know how I can calculate how fast counter increases so I can get the speed of the shaft. This is because the shaft will be spinning at diffrent speeds at all times.
The reason I need to know how fast the shaft is spinning is because I have a UI that will display the speed.
I would also appreciate if you have any other approuches that I have missed.
Thank you in advance.
This is how I would calculate the speed :
first add this at the top
import time
then a start time variable
clk = 17
dt = 18
starttime = time.time() ## used to calculate a duration
if you subtract starttime from time.time() you will get how long it has been since you defined the start time variable
( time.time() - starttime )
therefore you then add this
if dtState != clkState:
counter += 1
timetakentospinshaft = time.time() - starttime ## this is how long the shaft took to spin 360 degrees
starttime = time.time() # resetting the duartion
now you have the time taken, so you can calculate the speed by dividing the distance by the time
( speed = distance / time )
the distance can be calculated by multiplying the length of the shaft by 2π (calculation for circumference)
( distance = length of shaft * 2π )
I'm currently in the early stages of making a classic 2D platformer using pygame for a school project, and I was experimenting with the jump mechanic, when I ran into this rather strange problem. Even though I have factored in the timedelta between updates, the jump length and height both get shorter when the amount of time between frames increases.
Here I've let 3 instances of the Player object jump across the screen, moving right with a constant speed of 700 pixels/second, and an initial upwards speed of 700 pixels/second. They each had an artificially increased minimal delta_time of 0.001s, 0.017s and 0.1s respectively.
This is how the new speed and position vectors are calculated inside of the Player object's update function, which is called once every frame (the delta_time is passed in from the main update loop):
self.speed.y += 1000.0 * delta_time
self.position += self.speed * delta_time
And this is how delta_time is calculated at the end of every cycle of the main update loop (it is initialized with a value of zero for the first frame):
delta_time = time.time() - pre_time
pre_time = time.time()
if delta_time < min_delta_time:
time.sleep(min_delta_time - delta_time)
delta_time += time.time() - pre_time
pre_time = time.time()
The min_delta_time represents the minimal time between frame updates.
After many attempts at fixing this, I'm pretty certain that the flaw lies in the line that updates the speed, but even after double checking the math, I still can't figure out what the problem is. At first I thought that it could be the delta_time being imprecise, but if that was the case the horizontal speed would also be affected, and the trails would still line up.
So can i change anything to make the jump/gravity more consistent?
This isn't an error in coding so much as a logical error in the model: by modeling an acceleration as taking place instantaneously at update points rather than continuously across the full time span, inaccuracies are introduced which will get larger the sparser the updates.
To illustrate this, consider an object accelerating at 1m/s^2 from stop. If we model this as above with a 1-second interval, after six seconds our model will put the object at 21m. Repeating with a 2-second interval, we'll put it at 24m, and a 3-second interval will put it at 27m. However, the real position should be 18m.
The solution is to consider average velocity over the simulated time span rather than the instantaneous velocity at the sample points. In other words, rather than counting the full span's worth of acceleration, then using the result as the velocity for the whole span, add half of the span's acceleration, use that velocity to calculate distance traveled in that span, then add the remaining half of the acceleration.
So your update logic would become something like:
self.speed.y += 500.0 * delta_time
self.position += self.speed * delta_time
self.speed.y += 500.0 * delta_time
I am working on a project where i want to move a virtual joystick (vJoy) x number of pixels. However I am unable to find a method of converting pixels into the Joystick's Axis (Axis are -32768 to 32767). An example might be more helpful to explain:
lets say i would like to move 50 Pixels on the x axis in a given time of 100 milliseconds, therefore i would have to find the exact axis force between -32768 to 32767 which would move the object 50 pixels in the given time.
As i require a great deal of accuracy in the movement, i am stumped on a method which would accomplish this task. Any help is appreciated
Thanks
Figure out the total range the physical joystick axis can traverse. You've given min and max values of -32768 to 32767, for a total range of 65535.
Figure out the total range of pixels you want the virtual joystick (vJoy) to be able to move. Let's say it starts out at pixel position 0, and its min and max allowed values are -100 and 100. This gives us a total range of 200.
Now, figure out how many units the physical joystick should travel per virtual joystick movement. We get that by dividing: 65535 / 200 (physical joystick range / virtual joystick range), which gives us 327.675. This number in hypothetical terms would mean "for every pixel the virtual joystick travels, the physical joystick travels 327.675". Let's assign this value to the variable "axis_per_pixel".
Finally, if we know that the value axis value has changed by amount "a" (from your example 50), we can determine how much the physical joystick value needs to change by multiplying: a * axis_per_pixel. In our example, this would be 50 * 327.675, which is 16383.75. So, when the virtual joystick position increases by 50, the physical joystick position should increase by 16383.75 to match.
I'll give a code example. You tagged this as Python, but I'm going to answer in JavaScript because my Python is still a bit rough. Hopefully it's clear enough.
function getPositionIncrease(
minPixelValue, // lowest allowed pixel position, ie -100
maxPixelValue, // highest allowed pixel position, ie 100
minAxisValue, // lowest allowed axis value, ie -32768
maxAxisValue, // highest allowed axis value, ie 32767,
pixelDelta, // what amount the pixel position has changed by
) {
const distPixel = maxPixelValue - minPixelValue;
const distAxis = maxAxisValue - minAxisValue;
const axisPerPixel = distAxis / distPixel;
const axisDelta = pixelDelta * axisPerPixel; // how much the physical axis needs to change to match
return axisDelta;
}