How to get the position of music in pygame that is playing? - python

I want to play music and get its position in seconds or minutes of when the music is playing. I used the pygame.mixer.music.get_pos() but the code is not working.
def f5secforward():
print(pygame.mixer.music.get_pos())
pygame.mixer.music.play(0,pygame.mixer.music.get_pos()//1000+5)
print(pygame.mixer.music.get_pos())
the first 'get_pos' works but after I change the current position of the song with pygame.mixer.music.play(loop,time) it assigns the value of the get_pos to 0
I have searched more and I just found out that get_pos() is not taking where the music is playing it just get the time that the Python mixer is busy.
Is there any solutions?

If you store the first get_pos as an integer (say "oldsongtime") then add the time the second get_pos produces (in your function it will be close to 0) and the time you're adding on (5000) you should get about the right time.
I say about because when I tried to make my own fast forward function the track sometimes jumped much further forward than it should have. Might be something to do with my pre_init not using the default frequency (on all the PCs I've used 44,100 Hz is too slow).
def f5secforward():
oldsongtime = pygame.mixer.music.get_pos()
change = 5000
print(oldsongtime)
pygame.mixer.music.play(0, (oldsongtime+change)/5000)
addedtime = pygame.mixer.music.get_pos()
print(addedtime)
currenttime = oldsongtime+change+addedtime
return currenttime

Related

Using python-vlc, can I log to a file the time at which each frame of a video is displayed on screen?

I have already programed an experiment using the python-vlc module, which plays my videos smoothly and in fullscreen as expected. Now I'd like to log to a file the time at each frame displayed on screen. Actually the log file comes from another machine and the logging part is solved with a simple function. What I need is access to the timing of frames actually displayed on screen. Is there a function in the module that could help on this?
The short answer is No, frames are not accessible in Vlc.
In fact you'll be lucky to get more granularity than 1/4 of a second on the time itself.
However, you can calculate a frame number based on the current playing time and the number of frames per second. Your best bet to calculate this, is function like the following:
def mspf(self):
# Milliseconds per frame.
return int(1000 // (self.player.get_fps() or 25))
Then based on the current playing time in seconds you can calculate an approximate frame number.
You can get the current frame time by get_time().
Check out the API documentation (https://www.olivieraubert.net/vlc/python-ctypes/doc/)
From above,
libvlc_media_player_get_time(p_mi)
Get the current movie time (in ms).
Parameters:
p_mi - the Media Player.
Returns:
the movie time (in ms), or -1 if there is no media.
Here's a simple example.
import vlc
import time
# Get VLC instance and load a video
vlc_instance = vlc.Instance()
player = vlc_instance.media_player_new()
media = vlc.Media("YOUR VIDEO PATH")
player.set_media(media)
player.play()
time.sleep(0.1)
# Check out the current play time periodically
while player.get_state() == vlc.State.Playing:
t = player.get_time()
print(t) # Treat t as you need
time.sleep(1/120) # adjust a check out period
I usually run the above while loop part in a sub-thread and compare the previous and the current time to avoid duplicate.

pyautogui changing MINIMUM_SLEEP makes moveTo function not use duration input

So, this piece of code:
import pyautogui
pyautogui.PAUSE = 0
pyautogui.MINIMUM_SLEEP = 0
pyautogui.MINIMUM_DURATION = 0
pyautogui.moveTo(100,100,duration=1)
Makes the mouse takes 20+ second to reach its destination. The cause is the MINIMUM_SLEEP value, no matter the duration added it will take the same time (ages). Is there a way around this? - Is there any way to make the mouse movement smooth and still set the duration?
I am very surprised I haven't seen any comments on this. Thanks.

how to sleep in one function without sleeping the whole program

So I am trying to make a game, in this game I call upon a function that I want to slowly execute, but when I use "time.sleep(x)" it pauses everything in the file instead of just pausing the process of the function. I am trying to add a jump feature to a 2-d game, so if there is a better way to do it then I would be grateful for any advice but this is just the first idea that game to me.
for n in range(15):
Dino.rect.bottom -= 5
update_screen(Dino, screen, cactus)
time.sleep(0.01)
time.sleep(0.25)
inair = False
for n in range(15):
Dino.rect.bottom += 5
update_screen(Dino, screen, cactus)
time.sleep(0.01)
so I have it so that when I jump, it gives me a slow jump instead of just teleporting but like I said, it pauses everything while jumping.
This is not a good approach to timing. As you say, this sleeps the entire program. Multi-threading is a bit complex for simply moving a sprite.
A simple way to solve this problem is to use the PyGame function time.get_ticks() which returns an ever-increasing time in milliseconds.
Using this time-stamp, record the previous-time of an operation, but then do not update again until enough time has elapsed.
For example:
DINO_UPDATE_DELAY = 100 # milliseconds
next_dino_update = 0 # time next move due
[...]
# Move dino, if necessary
time_now = pygame.time.get_ticks()
if ( time_now > next_dino_update ):
Dino.rect.bottom += 5
next_dino_update = time_now + DINO_UPDATE_DELAY # in the future
# Paint the dino, wherever it is
update_screen(Dino, screen, cactus)
It's also possible to request a timer to send the event-loop a message in the future.
MOVE_DINO_EVENT = pygame.USEREVENT + 1
[...]
pygame.time.set_timer( MOVE_DINO_EVENT, DINO_UPDATE_DELAY )
EDIT: More in-depth explanation.
So basically you're implementing an animation, like an anime/cartoon. The thing on the display moves at some speed. In the above code, you seem to be moving a "dino" in the direction of y + 5 every 0.01 seconds (10 milliseconds).
Right now, you paint the dino, then sleep(), then move & paint again. When it hits the apogee of the jump, you wait 250 milliseconds, then repeat the previous phase for the down-jump.
So the problem with using sleep() is that it holds up the whole program (including the event loop, which can cause bad stuff to happen).
So instead of sleeping for some time period, the above example simply looks at the PyGame clock to determine if that same time-period has past. This allows the program to know if the animation needs to be updated.
The whole idea is to keep looking at the clock, using the time as the arbiter of what/where to draw next, rather than multiple calls to sleep().

What is the best way to make a player move at every interval in pygame?

Is there a library or a simple way to only loop something every 0.5 seconds without interrupting the rest of the program?
I have just started using pygame and have made a simple platformer and a Pong replica so far. I decided to try and make a Snake replica (I only currently have the head) and I need the snake to only move every 0.5 seconds while inputs can be registered at the 30 fps which I have the rest of the game running at. This is my current workaround:
while running: #this is tabbed back in my code
# keep loop running at the right speed
clock.tick(FPS)
# get time at each iteration
currentTime = str(time.time()).split(".")[0]
gameTime = int (currentTime) - int (startTime)
# this is used to check for something every 0.5 second (500 ms)
currentTimeMs = str(time.time()).split(".")[1]
# snake will move evry 0.5 second in a direction
if currentTimeMs[0] in ["5","0"] and moveDone == False:
moveDone = True
player1.move(direction)
elif currentTimeMs[0] not in ["5","0"]:
moveDone = False
There is more code within the while running: loop to get the direction and display the sprites but its not necessary for this. My current code works fine and will repeat the move function for my player1 every time that x in mm:ss:x is 0 or 5 (0.5 seconds apart) and will not repeat if it is that multiple times over a few frames.
This code needs to work within the running loop and not stop the program so time.sleep() doesn't work. I have also tried using the schedule library but it will not work as it cannot seem to allow the direction variable to change when passing it into the function.
My question therefore is; Is there a library or a shorter way to accomplish what I need?
Thanks in advance and I can message you the whole code if you need.
I suggest using pygames event mechanics and pygame.time.set_timer() (see here for docs).
You would do something like this:
pygame.time.set_timer(pygame.USEREVENT, 500)
and in the event loop look for the event type.
if event.type == pygame.USEREVENT:
If this is the only user defined event that you are using in your program you can just use USEREVENT.
When you detect the event the timer has expired and you move your snake or whatever. A new timer can be set for another 1/2 second. If you need more accuracy you can keep tabs on the time and set the timer for the right amount of time, but for you situation just setting it for 1/2 sec each time is okay.
If you need multiple timers going and need to tell them apart, you can create an event with an attribute that you can set to different values to track them. Something like this (though I have not run this particular code snippet, so there could be a typo):
my_event = pygame.event.Event(pygame.USEREVENT, {"tracker": something})
pygame.time.set_timer(my_event , 500)
You can store the moment of last move and then compare to actual time. To do it you can use perf_counter from time. Here is an example
last_move_time = perf_counter()
while running:
if perf_counter() - last_move_time > 0.5:
# move player
last_move_time = perf_counter()

Slowing down PyGame sprite animation without lowering frame rate

I am trying to learn pygame sprite animation. I have tried to follow a tutorial and everything is fine. There is just one problem that I can't get my head around.
In the below code I am trying to run a sprite animation of simples square.
This is the sprite:
https://www.dropbox.com/s/xa39gb6m3k8085c/playersprites.png
I can get it working, but the animation is too fast. I want it to be little smoother so that the fading effect can be seen. I saw some solutions using clock.tick but that would slow down the whole game I guess.
how can I get the animation slower while maintaing the usual frame rate for my window?
Below is my code:
lightblue=(0,174,255)
import pygame
pygame.init()
screen = pygame.display.set_mode((400, 300))
done = False
screen.fill(lightblue)
images=pygame.image.load('playersprites.png')
noi=16
current_image=0
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
pygame.quit()
quit()
if(current_image>noi-1):
current_image=0
else:
current_image+=1
screen.blit(images,(50,100),(current_image*32,0,32,32))
pygame.display.flip()
Use an integer value which you add to in the loop and check for divisibility. See here for more.
You could use time
So your sprite has 16 frames and lets say it wants to run at ten frames a second regardless of the frame rate of the game.
You could do something along the lines of
import time
start_frame = time.time()
noi = 16
frames_per_second = 10
Then in your loop put
current_image = int((time.time() - start_frame) * frames_per_second % noi)
time.time() counts up in seconds and has several decimal places after it. If you leave leave out frames_per_second then just use the modulo operator on noi (presumably "number of images"), every time a second has gone by, the result will tick up one until it reaches 16 and return to 0.
When you multiply the difference between start_frame and current time (time.time()), you force the "seconds" to go by frames_per_second times as fast.
Coercing the result which will be a float to an int, will allow you to use it as an index.
Now if the frame rate of the game fluctuates, it won't matter because the frame rate of the sprite is tied to the system clock. The sprites should still run at as close to exactly the chosen frame rate as can be rendered.
Clock.tick() is the correct solution.
While you may want to run the code of your game as fast as possible, you don't want the animation to run at an arbitrary speed. Animation is always "frames per second" and this value should be stable; otherwise it will look ugly or confusing. A good value is the same as the refresh rate of your monitor (usually 60 FPS) to avoid tearing.

Categories