This question already has answers here:
How can I play a sine/square wave using Pygame?
(1 answer)
Trying to play a sound wave on python using pygame
(1 answer)
Closed 5 months ago.
I am making a program trying simulate a piano so when a key is pressed i want a not to be played its entire length. But whenever i release the key the wav file cuts of. Thank you for anyone who can help.
import pygame
import sys
pygame.mixer.pre_init(44100, 16, 2, 4096)
pygame.init()
pygame.display.set_mode()
soundC4 = pygame.mixer.Sound("scale_marimba/Marimba_C4.wav")
while True:
for event in pygame.event.get():
if event.type == pygame.K_1:
pygame.quit()
sys.exit()
break
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_o:
empty_channel = pygame.mixer.find_channel()
empty_channel.play(soundC4)
Related
This simple piece of code crashes (the window is not responding) after a few seconds (around 5).
import pygame
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((640, 480), 0, 24)
#clock = pygame.time.Clock()
#font = pygame.font.Font(None, 32)
cycles = 0
while True:
screen.fill(0)
# text = font.render('Cycles : %d' % cycles, True, (255, 255, 255))
# screen.blit(text, (100, 100))
cycles += 1
pygame.display.update()
If I uncomment the commented lines, I can clearly see the program going out of control when displaying values between 47 and 50.
I use python 2.7 and pygame 1.9.2, Windows 8 (64 bits) and Eclipse + PyDev.
Call pygame.event.get() at the beginning of the while loop.
You need to regularly make a call to one of four functions in the pygame.event module in order for pygame to internally interact with your OS. Otherwise the OS will think your game has crashed. So make sure you call one of these:
pygame.event.get() returns a list of all events currently in the event queue.
pygame.event.poll() returns a single event from the event queue or pygame.NOEVENT if the queue is empty.
pygame.event.wait() returns a single event from the event queue or waits until an event can be returned.
pygame.event.pump() allows pygame to handle internal actions. Useful when you don't want to handle events from the event queue.
The window does not respond (freeze), because you do not handle the events. You have to handle the events by either pygame.event.pump() or pygame.event.get(), to keep the window responding.
See the documentation of pygame.event.pump():
For each frame of your game, you will need to make some sort of call to the event queue. This ensures your program can internally interact with the rest of the operating system.
Add an event loop, for instance:
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
# [...]
Alternatively just pump the events:
while True:
pygame.event.pump()
# [...]
Minimal example: repl.it/#Rabbid76/PyGame-MinimalApplicationLoop
I have a simple Pygame program:
#!/usr/bin/env python
import pygame
from pygame.locals import *
pygame.init()
win = pygame.display.set_mode((400,400))
pygame.display.set_caption("My first game")
But every time I try to run it, I get this:
pygame 2.0.0 (SDL 2.0.12, python 3.8.3)
Hello from the pygame community. https://www.pygame.org/contribute.html
And then nothing happens.
Why I can't run this program?
Your application works well. However, you haven't implemented an application loop:
import pygame
from pygame.locals import *
pygame.init()
win = pygame.display.set_mode((400,400))
pygame.display.set_caption("My first game")
clock = pygame.time.Clock()
run = True
while run:
# handle events
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
# update game objects
# [...]
# clear display
win.fill((0, 0, 0))
# draw game objects
# [...]
# update display
pygame.display.flip()
# limit frames per second
clock.tick(60)
pygame.quit()
The typical PyGame application loop has to:
handle the events by calling either pygame.event.pump() or pygame.event.get().
update the game states and positions of objects dependent on the input events and time (respectively frames)
clear the entire display or draw the background
draw the entire scene (blit all the objects)
update the display by calling either pygame.display.update() or pygame.display.flip()
limit frames per second to limit CPU usage with pygame.time.Clock.tick
repl.it/#Rabbid76/PyGame-MinimalApplicationLoop See also Event and application loop
This is interesting. Computer read your program line by line[python]. When all the line are interpreted, the program closed. To solve this problem you need to add a while loop to make sure the program will continue until you close the program.
import pygame,sys
from pygame.locals import *
pygame.init()
pygame.display.set_caption("My first game")
win = pygame.display.set_mode((400,400))
#game loop keeps the game running until you exit the game.
game_running=True
while game_running:
for event in pygame.event.get():
if event.type==QUIT:
pygame.quit()
sys.exit()
win.fill((0, 250, 154)) #Fill the pygame window with specific color. You can use hex or rgb color
pygame.display.update() #Refresh the pygame window
You can check more pygame Examples.
https://github.com/01one/Pygame-Examples
I think this will be helpful.
in the experiment I am preparing sounds are played from a csv file and timing is measured in frames. Given the fact that each sound lasts 300ms this equals to 18 frames.
from psychopy import data
from psychopy import core, visual, gui, data, event
from psychopy.tools.filetools import fromFile, toFile
import numpy, random, csv, time
from psychopy import logging, prefs
prefs.general['audioLib'] = ['pyo'] # Set the Audio Library [pyo (highest performer, check it), sounddevice (looks promessing, check it) or pygame (not good with timing)]
prefs.general['audioDriver']=['coreaudio']
from psychopy import sound
win = visual.Window([400,300], monitor="testMonitor", units="cm", fullscr=False)
stimuli = []
datafile = open("audioStim.csv", "rb")
reader = csv.reader(datafile, delimiter=";")
for row in reader:
stimuli.append(row[0])
#print (stimuli)
datafile.close()
clock = core.Clock()
for stimulus in stimuli:
#print (stimuli)
for frameN in range(18):
#print clock.getTime()
sound_stimulus = sound.Sound(stimulus)
sound_stimulus.play()
win.callOnFlip(clock.reset)
win.flip()
## Closing Section
win.close()
core.quit()
When running the experiment the sounds seem to blend with each other. They do not sound discrete.
The result is a bit problematic, is this an issue with Psychopy (not good quality when sounds are so short?) or with the code?
Thank you for your time!
Any other recommendations or suggestions for improvement of the code are very welcome.
Your code starts playing a sound on each frame, i.e., 60 times a second. Do this:
for stimulus in stimuli:
#print (stimuli)
for frameN in range(18):
#print clock.getTime()
win.flip()
if frameN == 0:
sound_stimulus = sound.Sound(stimulus)
sound_stimulus.play()
clock.reset() # Time zero is stimulus onset
I did two things here. First, I only start the sound_stimulus.play() and clock.reset() at flip onset only - not at subsequent updatings. Second, I started the sound AFTER win.flip so that it is timed to the flip. If you play before the flip, the sound can start can be anywhere in the 16.7 ms interval (but probably only will be for the very first trial).
BTW, since you don't really use the variable sound_stimulus, you could simplify the code even further:
if frameN == 0:
sound.Sound(stimulus).play()
I am unable to close out the game window after insertion of pygame.time.wait(1000) in my main game loop, for example:
while True:
ev = pygame.event.wait()
if ev.type == pygame.QUIT:
break
...
pygame.display.update()
pygame.time.wait(1000)
what is the issue here and is there any work around?
Problem is because 1000ms is 1s and it is long time for program. At this time program doesn't check pygame.event so it can't break mainloop (while True) and you can't quit - better use smaller value - 100ms (0.1s) or smaller.
If you use 40ms it gives you 1000ms/40ms = 25 FPS (Frames Per Seconds)
You can use Clock() to set FPS more precisely
clock = pygame.time.Clock()
# mainloop
clock.tick(25)
I'm making a game with pygame and I encountered a problem with the following code :
while not self.end: # main game loop
keys = pygame.key.get_pressed()
if keys[K_LEFT]:
adddirection(LEFT)
elif keys[K_RIGHT]:
adddirection(RIGHT)
elif keys[K_UP]:
adddirection(UP)
elif keys[K_DOWN]:
adddirection(DOWN)
When I hold TOP arrow or DOWN arrow, if I press any right or left key, nothing will happen, the elif does not resolves. Why ? Should I do this another way ?
If I replace all the 'elif' by 'if' the opposite happens. If I hold left or right, top and down will never resolves.
I would like to understand that weird mechanic.
The code would be like
for event in pygame.event.get():
if event.type==QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if (event.key == K_LEFT):
//
elif (event.key == K_RIGHT):
//
elif (event.key == K_UP):
//
elif (event.key == K_DOWN):
//
keys_pressed = key.get_pressed()
if keys_pressed[K_LEFT]:
//
if keys_pressed[K_RIGHT]:
if keys_pressed[K_UP]:
//
if keys_pressed[K_DOWN]:
//
Replace // with your condtions
So, as per the nature of elif stacks, if one resolves as true, it wont test the others and simply skip, loop up how if elif else works online somewhere.
so you need to either use "if" for each, or split it in to a for loop.
However since you say when you use if for all of them, you still don't get your expected behaviour. I suspect this could be caused by "adddirection()", could you post that too if you cannot solve this issue?
As is mentioned in another answer, you can also use pygame events to deal with keypresses
The problem may be unsolvable. The way keyboards work is every key sends a signal on a copper wire through the USB cable. Mechanical (gaming) keyboards have a copper wire for each key, however to reduce the cost of cheap keyboards, many keys share a wire, and as a result only one of the keys which share a wire can be pressed at once. The arrow keys are on the same wire which may be contributing to your issue. The reason WASD is generally used for movement in games is because the 4 keys run along different wires.
TLDR: You may have better luck using WASD instead of your arrow keys