Okay here's my code:
def toggleMusic():
if pygame.mixer.music.get_busy():
pygame.mixer.music.pause()
else:
pygame.mixer.music.unpause()
---event handling---
if pressed 'm' it should toggle whether the music is paused and not paused
toggleMusic()
It can pause the music but not unpause, any explanation?
Had the same problem. For others' reference, my solution was to use a simple class.
class Pause(object):
def __init__(self):
self.paused = pygame.mixer.music.get_busy()
def toggle(self):
if self.paused:
pygame.mixer.music.unpause()
if not self.paused:
pygame.mixer.music.pause()
self.paused = not self.paused
# Instantiate.
PAUSE = Pause()
# Detect a key. Call toggle method.
PAUSE.toggle()
It doesn't unpause the music because pygame.mixer.music.pause() doesn't affect the state of pygame.mixer.music.get_busy().
To get the behavior you are looking for you will need to your maintain your own variable which keeps track of the paused/unpaused state. You can do this in a class:
class mixerWrapper():
def __init__(self):
self.IsPaused = False
def toggleMusic(self):
if self.IsPaused:
pygame.mixer.music.unpause()
self.IsPaused = False
else:
pygame.mixer.music.pause()
self.IsPaused = True
this one is good, i use it for games
source https://youtu.be/kzTloDq1FiQ
is_paused = False
def toggle_pause():
global is_paused
if is_paused == True:
is_paused = False
else:
is_paused = True
wn.listen()
wn.onkeypress(toggle_pause, " ")
while True:
if not is_paused:
bob.fd(1)
bob.lt(1)
else:
wn.update()
Related
I was working on a snake game using turtle graphics in python. The game worked well.
Then, I wanted to improve on it and add a pause function to it. When I just wrote the lines of code for the pause function inside the game code, it worked, but my aim is to create the pause function in a class and be able to use its instance for my subsequent projects instead of just writing the whole functionality again every time.
Since the snake game code is long, I decided to try the pause function on a simple turtle animation to get the hang of it before implementing in my snake game but writing it in a class just isn't working.
Here's when I wrote it in the code, which worked:
from turtle import Turtle, Screen
tim = Turtle()
screen = Screen()
is_paused = False
def toggle_pause():
global is_paused
if is_paused:
is_paused = False
else:
is_paused = True
screen.listen()
screen.onkey(toggle_pause, "p")
while True:
if not is_paused:
tim.forward(12)
tim.left(10)
else:
screen.update()
Here's when I wrote my pause function in a class, which didn't work.
class Pause:
def __init__(self, is_paused):
self.is_paused = is_paused
def toggle_pause(self):
if self.is_paused:
is_paused = False
return is_paused
else:
is_paused = True
return is_paused
from turtle import Turtle, Screen
from pause import Pause
ps = Pause(False)
tim = Turtle()
screen = Screen()
screen.listen()
screen.onkeypress(ps.toggle_pause, "p")
pause = ps.toggle_pause()
while True:
if not pause:
tim.forward(12)
tim.left(10)
else:
screen.update()
Can you please tell me what I did wrong? Thanks.
You need to do two things to get the pausing to work in your game using the class:
Change the definition of the Pause class so it updates its is_paused attribute when its toggle_pause() method is called by adding a self. prefix to the is_paused variable name:
class Pause:
def __init__(self, is_paused):
self.is_paused = is_paused
def toggle_pause(self):
self.is_paused = not self.is_paused
return self.is_paused
Change the way the pause state is checked in the while loop in the main program:
...
while True:
if not ps.is_paused:
tim.forward(12)
tim.left(10)
else:
screen.update()
The variable pause is only updated once, outside the while loop. You should use the class variable self.is_paused to test the state of the game.
Is there any way to tell whether a song has finished playing in pygame?
Here's the code:
from tkinter import *
import pygame
root = Tk()
pygame.init()
def play():
pygame.mixer.music.load("test.ogg")
pygame.mixer.music.play(loops = 0)
def pause():
global paused
if paused == False:
pygame.mixer.music.pause()
paused = True
elif paused:
pygame.mixer.music.unpause()
paused = False
def check_if_finished():
if pygame.mixer.music.get_busy():
print("Song is not finished")
else:
print("Song is finshed")
paused = False
play_button = Button(root , text = "Play Song" , command = play)
play_button.grid(row = 0 , column = 0)
pause_button = Button(root , text = "Pause Song" , command = pause)
pause_button.grid(row = 1 , column = 0 , pady = 15)
check_button = Button(root , text = "Check" , command = check_if_finished)
check_button.grid(row = 2 , column = 0)
mainloop()
Here, I used the pygame.mixer.music.get_busy() function to check whether the song has finished, but the problem is that the check_if_finished() function is not giving me the expected output when I pause the song. What I want is to not print "The song is finished" when I pause the song.
Is there any way to achieve this in pygame?
It would be great if anyone could help me out.
What I want is to not print "The song is finished" when I pause the song.
You are right. See pygame.mixer.music.get_busy():
Returns True when the music stream is actively playing. When the music is idle this returns False. In pygame 2.0.1 and above this function returns False when the music is paused.
You can deal with this by simply adding an additional condition:
def check_if_finished():
if paused or pygame.mixer.music.get_busy():
print("Song is not finished")
else:
print("Song is finshed")`
As I said, I'm pretty new to coding and python, and I need to make an auto clicker that toggles when I hold left click and stops when i release the button. The current code makes a key bind that toggles it off and on. I was searching the web for the last few days and couldn't find anything. Thanks in advance!
import time
import threading
import random
from pynput.mouse import Button, Controller
from pynput.keyboard import Listener, KeyCode
x = (0.7, 0.8, 0.9, 0.11)
delay = random.choice(x)
button = Button.left
start_stop_key = KeyCode(char='s')
exit_key = KeyCode(char='e')
class ClickMouse(threading.Thread):
def __init__(self, delay, button):
super(ClickMouse, self).__init__()
self.delay = delay
self.button = button
self.running = False
self.program_running = True
def start_clicking(self):
self.running = True
def stop_clicking(self):
self.running = False
def exit(self):
self.stop_clicking()
self.program_running = False
def run(self):
while self.program_running:
while self.running:
mouse.click(self.button)
time.sleep(self.delay)
time.sleep(0.1)
mouse = Controller()
click_thread = ClickMouse(delay, button)
click_thread.start()
def on_press(key):
if key == start_stop_key:
if click_thread.running:
click_thread.stop_clicking()
else:
click_thread.start_clicking()
elif key == exit_key:
click_thread.exit()
listener.stop()
with Listener(on_press=on_press) as listener:
listener.join()
mouse = Controller()
click_thread = ClickMouse(delay, button)
click_thread.start()
def on_press(key):
if key == start_stop_key:
if click_thread.running:
click_thread.stop_clicking()
else:
click_thread.start_clicking()
elif key == exit_key:
click_thread.exit()
listener.stop()
with Listener(on_press=on_press) as listener:
listener.join()
For what it is worth, I would look to this approach:
PyAutoGUI Chapter
With full documentation here:
PyAutoGUI Docs:
First, sorry for my poor English.
I'm writing a game with Python 3.4 and Pygame. Game includes scenes what provide view of screen, and music, etc, parsed from XML scripts.
I expect music plays instantly, but not plays at next scene.
and cannot find similar problem on web.
how can I rewrite code to play music scene-instantly?
I wrote code like it:
(graphic part removed)
xml file is here : https://pastebin.com/bSBiv1jX
import pygame
import xml.etree.ElementTree as ET
class Script():
def __init__(self, name, filename):
self.name = name
self.parsed = ET.parse(filename)
self.root = self.parsed.getroot()
self.scene_list = self.root.findall("scene")
self.flag_list = str(self.root.findtext("flags")).split(",")
for flag in self.flag_list:
setattr(self, flag, False)
def music_play(self, number):
scene = self.scene_list[number]
if scene.findtext("music") == 'stop':
pygame.mixer.music.stop()
elif scene.findtext("music") != '':
pygame.mixer.music.load(scene.findtext("music"))
pygame.mixer.music.play(-1, 0.0)
def goto(self, number):
string = self.scene_list[number].findtext("goto")
if string == '':
return number
elif isNumber(string) == True:
return int(string)
elif isNumber(string) == False:
return string
def if_goto(self, string, number):
iflist = string.split(', ')
if getattr(self, iflist[0]) == True
return int(iflist[1])
else:
return number + 1
def isNumber(s):
try:
float(s)
return True
except ValueError:
return False
def runGame():
pygame.init()
windowSurface = pygame.display.set_mode((200, 200))
clock = pygame.time.Clock()
run = True
scene_number = 0
script = Script('dummy', 'scenario/dummy.xml')
while run:
# 입력 처리
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
if scene_number == script.goto(scene_number):
scene_number += 1
elif scene_number != script.goto(scene_number):
if isNumber(script.goto(scene_number)):
scene_number = script.goto(scene_number)
else:
scene_number = script.if_goto(script.goto(scene_number), scene_number)
script.music_play(scene_number)
pygame.display.update()
clock.tick(30)
pygame.quit()
def main():
runGame()
if __name__ == "__main__":
main()
https://www.pygame.org/docs/ref/music.html#pygame.mixer.music.load
If a music stream is already playing it will be stopped
https://www.pygame.org/docs/ref/music.html#pygame.mixer.music.play
If the music is already playing it will be restarted.
At every iteration of your game loop you call music_play and restart the music. You should only start the music if it's not already running.
You could, for instance, only call this when a scene changes.
I do not understand completely how to use pyglet's event system. What I need to do is to get each event for each frame. In Pygame I can do it in the following way:
import sys, pygame
pygame.init()
size = width, height = 320, 240
screen = pygame.display.set_mode(size)
while 1:
for event in pygame.event.get():
print event
if event.type == pygame.QUIT: sys.exit()
screen.fill((0,0,0))
pygame.display.flip()
I accomplish something similar with pyglet, using 'pyglet.window.event.WindowEventLogger()' but I do not how to acces to the information that the WindowEventLogger prints, and it prints the same event more than once.
How could I obtain a pyglet version of the pygame code above?
Here's a basic example of a working class that dispatches events.
#!/usr/bin/python
import pyglet
from time import time, sleep
class Window(pyglet.window.Window):
def __init__(self, refreshrate):
super(Window, self).__init__(vsync = False)
self.frames = 0
self.framerate = pyglet.text.Label(text='Unknown', font_name='Verdana', font_size=8, x=10, y=10, color=(255,255,255,255))
self.last = time()
self.alive = 1
self.refreshrate = refreshrate
def on_draw(self):
self.render()
def render(self):
self.clear()
if time() - self.last >= 1:
self.framerate.text = str(self.frames)
self.frames = 0
self.last = time()
else:
self.frames += 1
self.framerate.draw()
self.flip()
def on_close(self):
self.alive = 0
def run(self):
while self.alive:
self.render()
event = self.dispatch_events() # <-- This is the event queue
sleep(1.0/self.refreshrate)
win = Window(23) # set the fps
win.run()
However note that normally I never encounter any events at all in this event queue. Most likely because Pyglet works with function decorators/hooks.
So for instance, if you want to catch keyboard events, you would simply add the following code to this awesome class:
def on_key_release(self, symbol, modkey):
print(symbol, modkey)
There's also on_mouse_motion etc :)