This question already has an answer here:
How to get if a key is pressed pygame [duplicate]
(1 answer)
Closed 2 years ago.
I am trying to make a tetris game and below is my code to make the blocks move. I want the block to keep moving when an arrow key is held down and to stop when it is released. But when I run the code, it stops the block even if the key isn't released.
def set_keyboard_dirs(cur_block, width, height, events): # events stores pygame.event.get() as I use it multiple times in my code
global move_timer # only moves block one time per set number of frames
cur_block.reset_collisions(height)
for event in events:
if event.type == pygame.KEYDOWN: # sets magnitude and direction of movement
if event.key == pygame.K_RIGHT:
cur_block.dir = (cur_block.length, 0)
elif event.key == pygame.K_LEFT:
cur_block.dir = (-cur_block.length, 0)
elif event.key == pygame.K_DOWN:
cur_block.dir = (0, cur_block.length)
elif event.key == pygame.K_UP:
cur_block.rotate(height, width)
elif event.key == pygame.K_SPACE: # just moves the block instantly to the bottom of the screen by equating it to a 'projection' already there.
cur_block.shape = deepcopy(cur_block.projection)
elif event.type == pygame.KEYUP: # stops block from moving
print(event.key) # I called this to see what's happening, and event.key is printed event when I didn't release the key.
cur_block.dir = (0, 0)
cur_block.move()
Because of the above, the block moves one step at a time instead of continuously (for as long as they are holding it) like I want. How can I fix it please? The rest of the game works so I really want this to work too. Thanks a lot in advance.
EDIT:
I have also tried setting controls using pygame.key.get_pressed() as follows:
def set_keyboard_dirs(cur_block, width, height):
global move_timer, keys
cur_block.reset_collisions(height)
cur_block.dir = (0, 0)
if keys[pygame.K_UP] or keys[pygame.K_w]:
cur_block.rotate(height, width)
elif keys[pygame.K_SPACE]:
cur_block.shape = deepcopy(cur_block.projection)
elif (keys[pygame.K_DOWN] or keys[pygame.K_s]) and 2 not in cur_block.collisions: # 1, 2, 3 are collisions in left, down and right directions
cur_block.dir = (0, cur_block.length)
elif (keys[pygame.K_RIGHT] or keys[pygame.K_d]) and 1 not in cur_block.collisions:
cur_block.dir = (cur_block.length, 0)
elif (keys[pygame.K_LEFT] or keys[pygame.K_a]) and 3 not in cur_block.collisions:
cur_block.dir = (-cur_block.length, 0)
else:
print('ran reset') # this statement print even as i'm holding down a key for some reason
cur_block.dir = (0, 0)
if cur_block.dir != (0, 0) and move_timer == 0:
cur_block.move()
move_timer = 7
in the former case, if I remove the KEYUP event and in the latter case if I remove the else statement, the block moves continuously (but cannot stop) which also shows that it is those statements are what is causing the problem, I think. And this is the only place is my code where I define my cur_block.dir as well.
In your code the movement of the block is canceled if any key is released, not if the special key is released. You would have to implements special cases if on of the cursor keys is released:
elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
# [...]
elif event.key == pygame.K_LEFT:
# [...]
# [...]
I recommend to set the movement direction, dependent on the key states which are returned by pygame.key.get_pressed():
def set_keyboard_dirs(cur_block, width, height, events):
global move_timer
cur_block.reset_collisions(height)
keys = pygame.key.get_pressed()
cur_block = [0, 0]
if key[pygame.K_RIGHT]:
cur_block.dir[0] += cur_block.length
if key[pygame.K_LEFT]:
cur_block.dir[0] -= cur_block.length
if key[pygame.K_DOWN]:
cur_block.dir[1] += cur_block.length
if key[pygame.K_UP]:
cur_block.rotate(height, width)
if key[pygame.K_SPACE]:
cur_block.shape = deepcopy(cur_block.projection)
cur_block.move()
That is probably because your for loop runs 1 time per frame, so if you hold down your button it count as you pressed it 1 time at that specific frame, same with the KEYUP events.
You can try to make two variables outside of the mainloop left=False and right=False
And outside of your current for loop, you check if any button pressed.
#these are outside of the mainloop
left=False
right=False
keys = pygame.key.get_pressed() # checks for key events (put this outside of the for loop, but still be inside your mainloop)
if keys[pygame.K_LEFT]:
right = False
left = True
elif keys[pygame.K_RIGHT]:
left = False
right = True
# if none of those buttons pressed, it sets the values back to False
else:
right = False
left = False
# using the left value, if its true, it will do your action every frame,
#(you can adjust the speed of your block later)
if left:
# do something
cur_block.dir = (-cur_block.length, 0)
if right:
# do something else
and then if you press LEFT key for example, the value of Left will be true, and then you can check: if any of those values true > do something.
Based on your example code, this is the only thing that I can come up with. I hope it works.
Related
This question already has an answer here:
Why is my collision test always returning 'true' and why is the position of the rectangle of the image always wrong (0, 0)?
(1 answer)
Closed 1 year ago.
I read an article about how a mouse cursor can detect a rect, and it includes the line ".get_rect()" but somehow it doesnt work
heres the articles code ->
import pygame
pygame.init()
width=350;
height=400
screen = pygame.display.set_mode( (width, height ) )
pygame.display.set_caption('clicked on image')
redSquare = pygame.image.load("images/red-square.png").convert()
x = 20; # x coordnate of image
y = 30; # y coordinate of image
screen.blit(redSquare , ( x,y)) # paint to screen
pygame.display.flip() # paint screen one time
running = True
while (running):
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.MOUSEBUTTONDOWN:
# Set the x, y postions of the mouse click
x, y = event.pos
if redSquare.get_rect().collidepoint(x, y):
print('clicked on image')
#loop over, quite pygame
pygame.quit()
heres my code ->
import pygame
import os
import sys
pygame.init()
width,height = (1100,800)
WIN = pygame.display.set_mode((width,height))
global bcard
bg_filename = os.path.join('C:\\Users\\USER\\Desktop\\Python\\picture match','background.jpg')
bg = pygame.image.load(bg_filename)
bg = pygame.transform.scale(bg, (width, height)).convert()
card_width=130
card_height=160
blue_card=pygame.image.load(os.path.join('C:\\Users\\USER\\Desktop\\Python\\picture match','blue_card.png'))
red_card=pygame.image.load(os.path.join('C:\\Users\\USER\\Desktop\\Python\\picture match','red_card.png'))
bcard=pygame.transform.scale(blue_card,(card_width,card_height)).convert()
rcard=pygame.transform.scale(red_card,(card_width,card_height)).convert()
text=pygame.image.load(os.path.join('C:\\Users\\USER\\Desktop\\Python\\picture match','text.png'))
global clicking
clicking = False
def pictures():
global card1
card1=WIN.blit(bcard,(30,200))
card2=WIN.blit(rcard,(200,200))
card3=WIN.blit(bcard,(370,200))
card4=WIN.blit(rcard,(550,200))
card5=WIN.blit(bcard,(730,200))
card6=WIN.blit(rcard,(900,200))
card7=WIN.blit(rcard,(30,400))
card8=WIN.blit(bcard,(200,400))
card9=WIN.blit(rcard,(370,400))
card10=WIN.blit(bcard,(550,400))
card11=WIN.blit(rcard,(730,400))
card12=WIN.blit(bcard,(900,400))
card13=WIN.blit(bcard,(30,600))
card14=WIN.blit(rcard,(200,600))
card15=WIN.blit(bcard,(370,600))
card16=WIN.blit(rcard,(550,600))
card17=WIN.blit(bcard,(730,600))
card18=WIN.blit(rcard,(900,600))
card1_rect=pygame.Rect(30,200,130,160)
card1_rect=pygame.Rect(200,200,130,160)
card1_rect=pygame.Rect(370,200,130,160)
card1_rect=pygame.Rect(550,200,130,160)
card1_rect=pygame.Rect(730,200,130,160)
card1_rect=pygame.Rect(900,200,130,160)
WIN.blit(text,(25,0))
def draw():
WIN.blit(bg,(0,0))
pictures()
def main():
global clicking
global card1
global bcard
run = True
mx , my = pygame.mouse.get_pos()
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
if bcard.get_rect().collidepoint(mx, my):
print('clicked on image')
draw()
pygame.display.flip()
main()
its suppose to be a picture match game btw, heres the error code "AttributeError: 'pygame.Surface' object has no attribute 'get_rect'"
pygame.Surface.get_rect.get_rect() returns a rectangle with the size of the Surface object, that always starts at (0, 0) since a Surface object has no position. A Surface is blit at a position on the screen. The position of the rectangle can be specified by a keyword argument. For example, the top left of the rectangle can be specified with the keyword argument topleft:
if bcard.get_rect().collidepoint(mx, my):
if bcard.get_rect(topleft = (30, 200)).collidepoint(mx, my):
print('clicked on image')
I'm developing a pygame video game, and everything was working out perfectly until yesterday. The issues began after I formatted my pc. So when i run the game, the first screen to show up is the 'Menu'. So in this state class I have an event method where when you press the 'p' key it gets you to the 'Play' state. So now it is not working, I don't know why.
I've changed nothing. I just formatted my pc and reinstalled python, pygame and pgu module. But the strange thing comes when I reprogram the videogame so that the first state to show up when you run the game is the 'Play' state, everything works perfectly. It also has an event method where when you press the arrows, the character moves, and when the player presses ESC it takes you to the 'Menu' state.
So again when I'm at the 'Menu' state the game doesn't respond to the input I'm giving to it. I don't really know what's happening.
Here is an example of what I was saying in comments :
Sorry if all comments are not appropriate to your level but I wanted to be sure you understand it all.
import pygame
screen = pygame.display.set_mode((1000, 1000))
class Menu:
pass
class Play:
pass
def main():
running = True # here we define the main variable of the main loop
main_menu = True # when the main loop will begin, main_menu will begin too
game = False # game is false because player didn't press p
options = False # options is false because player didn't go to options
while running: # begin the main loop
while main_menu:
for event in pygame.event.get(): # listen for events
if event.type == pygame.QUIT: # if the player quit, ends up the 'main_menu' loop and 'running' loop too
running = False
main_menu = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_p: # if p key is pressed, exit from main menu and begin 'game' loop
main_menu = False
game = True
if event.key == pygame.K_o: # if o key is pressed, exit from main menu and begin 'options' loop
main_menu = False
options = True
screen.fill((255, 0, 0)) # I fill the screen in red to make the example more explicit
pygame.display.flip() # I update the screen every frame
while game:
for event in pygame.event.get(): # listen for events
if event.type == pygame.QUIT: # if the player quit, ends up 'running' and 'options' loop
running = False
game = False
if event.type == pygame.KEYDOWN: # listen for keys
if event.key == pygame.K_BACKSPACE: # if the player press backspace (delete), ends up 'game' loop
game = False # and begin (again) the 'main_menu' loop
main_menu = True
screen.fill((255, 255, 255)) # I fill the screen in white to make the example more explicit
pygame.display.flip() # I update the screen every frame
while options: # same logic for this one
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
options = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_BACKSPACE:
options = False
main_menu = True
screen.fill((0, 255, 0))
pygame.display.flip()
pygame.init() # initialize pygame
main() # begin main loop
pygame.quit() # quit pygame
Shooting one bullet works but i can only shoot one and after that it stops working. I've tried to change my "bullet_fire" to False after KEYUP but this doesnt work either since then the bullet is only visible while i hold the arrow up key while the problem remain. How should i solve this problem?
Here is the code:
import pygame
pygame.init()
# Skärm
Screen = pygame.display.set_mode((1600, 900))
# Title och Logo
pygame.display.set_caption("Fjärt Spel")
icon = pygame.image.load('planet.png')
pygame.display.set_icon(icon)
# backround
backround = pygame.image.load("0000.png")
# player
playerIMG = pygame.image.load("soldier.png")
playerX = 350
playerY = 836
playerX_Change = 0
playerY_Change = 30
# enemy
enemyIMG = pygame.image.load("terrorist2.png")
enemyX = 500
enemyY = 810
enemyX_Change = 0
enemyY_Change = 0
# bullet
bulletIMG = pygame.image.load("pung(32x32).png")
bulletX = playerX
bulletY = playerY
bulletX_Change = 50
bulletY_Change = 0
bullet_fire = False
offScreen = 1600, 900
def player(x, y):
Screen.blit(playerIMG, (x, y))
def enemy(x, y):
Screen.blit(enemyIMG, (x, y))
Running = True
while Running:
Screen.fill((0, 0, 0))
# backround
Screen.blit(backround, (0, 0))
if bullet_fire == True:
Screen.blit(bulletIMG, (bulletX + 100, playerY))
bulletX += bulletX_Change
if bulletX > 1600:
bullet_fire == False
for event in pygame.event.get():
if event.type == pygame.QUIT:
Running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerX_Change = -10
if event.key == pygame.K_RIGHT:
playerX_Change = 10
if event.key == pygame.K_SPACE:
playerY_Change = -70
if event.key == pygame.K_UP:
bullet_fire = True
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT or event.key == pygame.K_SPACE:
playerX_Change = 0
playerY_Change = 30
# Ha player innan fill!!
playerX += playerX_Change
playerY += playerY_Change
if playerX <= 0:
playerX = 0
elif playerX >= 1436:
playerX = 1436
if playerY <= 0:
playerY = 0
elif playerY >= 836:
playerY = 836
player(playerX, playerY)
enemy(enemyX, enemyY)
pygame.display.update()
if bulletX > 1600:
bullet_fire == False
# ^^
This appears to want to set bullet_fire to False when it reaches a certain ordinate but, in reality, is comparing the two and throwing away the result. That means the first bullet you've fired is still going, has left the screen, and is probably halfway to Jupiter by now :-)
By way of example, this is similar to the following transcript:
>>> a = 7
>>> if a == 7:
... a == 14
... print(a)
...
False
7
You need to use == for comparison and = for assignment.
Keep in mind that's the likely cause of your issue. Since your question does not contain the code that decides whether a new bullet should be generated, it's a little hard to tell for sure. I'm therefore basing it on the assumption that one bullet at a time is all that's permitted (as in quite a few arcade games). Hence, if you never "destroy" the current bullet, you'll never be able to fire another one.
If that turns out to not be the case, you probably need to post more code so we can do an exhaustive analysis.
As an aside, I'm a little concerned about the physics involved in:
Screen.blit(bulletIMG, (bulletX + 100, playerY))
This appears to draw the bullet at the players current Y position meaning that, after the bullet is fired, it will track the player in some weird Einsteinian "spooky action at a distance" manner. While that makes the game a lot easier since you can direct the bullets after firing, I'm not convinced it will get a high score in the realism category :-)
Just started learning Python/Pygame watching videos and reading to learn . I would like to see a example code to cycle 3 images on a rect button from a mouse press and return to first image. Really I want the pictures to be three options and return different results. So be able to cycle image be able to select option and option when triggered execute choice.
Example
import pygame
pygame.init()
screen = pygame.display.set_mode((300,200))
# three images
images = [
pygame.Surface((100,100)),
pygame.Surface((100,100)),
pygame.Surface((100,100)),
]
images[0].fill((255,0,0))
images[1].fill((0,255,0))
images[2].fill((0,0,255))
# image size and position
images_rect = images[0].get_rect()
# starting index
index = 0
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
# check mouse position and pressed button
if event.button == 1 and images_rect.collidepoint(event.pos):
# cycle index
index = (index+1) % 3
screen.blit(images[index], images_rect)
pygame.display.flip()
pygame.quit()
Example using class - to create many buttons
import pygame
class Button(object):
def __init__(self, position, size):
self._images = [
pygame.Surface(size),
pygame.Surface(size),
pygame.Surface(size),
]
self._images[0].fill((255,0,0))
self._images[1].fill((0,255,0))
self._images[2].fill((0,0,255))
self._rect = pygame.Rect(position, size)
self._index = 0
def draw(self, screen):
screen.blit(self._images[self._index], self._rect)
def event_handler(self, event):
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1 and self._rect.collidepoint(event.pos):
self._index = (self._index+1) % 3
pygame.init()
screen = pygame.display.set_mode((320,110))
button1 = Button((5, 5), (100, 100))
button2 = Button((110, 5), (100, 100))
button3 = Button((215, 5), (100, 100))
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
button1.event_handler(event)
button2.event_handler(event)
button3.event_handler(event)
button1.draw(screen)
button2.draw(screen)
button3.draw(screen)
pygame.display.flip()
pygame.quit()
If I understood the question correctly, you need a single button that changes the look every time you click on it, and changes its relative function accordingly.
You should be able to solve your problem by creating a class that takes two list and a counter
1) list of images
2) list of functions
3) the counter tells you which image/function is selected.
The functions needs to be built in the class, but you can provide the image that you want in the class argument (actually, you could pass them as arguments, but I don't think is worth it).
Here is the code, I commented some lines with their intended meaning (in line comments)
import pygame
import sys
pygame.init()
width = 600
height = 400
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("Magic Buttons")
background = pygame.Surface(screen.get_size())
clock = pygame.time.Clock()
class Buttons:
def __init__(self, posX, posY, image1, image2, image3):
self.image_list = [image1, image2, image3] # static list of images
self.function_list = [self.button_function_1,self.button_function_2,self.button_function_3 ]
self.rect_position = (posX, posY) # this is a tuple to identify the upper left corner of the rectangle of the image
self.button_type = 0 # initial value of the button, both for the function and the image
self.image = pygame.image.load(self.image_list[0]) #default image, index number 0 of image_list
self.rect = pygame.Rect(posX, posY, self.image.get_width(), self.image.get_height()) # create a rectangle object same size of the images
def check(self, pos):
if self.rect.collidepoint(pos) ==True:
self.change_button()
else:
pass
def change_button(self):
self.button_type = (self.button_type +1)%3
self.image = pygame.image.load(self.image_list[self.button_type ]) # load the image relative to button_type
self.function_list[self.button_type -1]() # execute the function relative to the new value of button_type
self.draw_button()
def draw_button(self):
screen.blit(self.image, self.rect_position) # blit the new button image
def button_function_1(self):
print ("function 1 in action")
def button_function_2(self):
print ("function 2 in action")
def button_function_3(self):
print ("function 3 in action")
multibutton = Buttons(100,100,"button1.png","button2.png","button3.png") # create an istance of the button in the x=100, y = 100, with the three image button
while True:
background.fill((0,0,0))
clock.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONUP:
pos = pygame.mouse.get_pos() # fetch the position of the mouse
multibutton.check(pos) # check if the mouse is on the button
multibutton.draw_button()
pygame.display.flip()
Long story short:
I followed this tutorial here and the documentation of pygame 1.9.2. According to both it should be possible to adjust the volume for the left and right earphone in stereo mode, however, it doesn't work for me at all. Sounds remain audible on either earphone, no matter what I try.
Here my tries:
Short foreword: I use
pygame.mixer.pre_init(44100, -16, 2, 3072)
This should actually do the job for my system to enable stereo sound in pygame, but maybe I made a mistake here already which I have overlooked, so I mention it.
Try 1:
class MainProgram(object):
def __init__(self, width = 640, height = 640):
# Much Code
# Sounds
self.testsound = pygame.mixer.Sound("data\\sounds\\ping.ogg")
self.chan1 = pygame.mixer.Channel(0)
self.chan2 = pygame.mixer.Channel(1)
self.mainloop()
def mainloop(self):
while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT:
terminate()
if event.type == pygame.KEYDOWN:
self.testsound.play().set_volume(1.0, 0.0)
elif event.type == pygame.KEYUP:
self.testsound.play().set_volume(0.0, 1.0)
# More code here
When I don't adjust the volume, I can hear the sounds at full volume on either side. If I adjust as seen above, then I still hear the sound on either side, just only half the volume (rough estimation by me, but clearly quieter), it's like, instead of setting one side to 0 and the other to 1, pygame just takes the average (0.5) for either side.
Try 2:
class MainProgram(object):
def __init__(self, width = 640, height = 640):
# Much Code
# Sounds
self.testsound = pygame.mixer.Sound("data\\sounds\\ping.ogg")
self.chan1 = pygame.mixer.Channel(0).set_volume(1.0, 0.0)
self.chan2 = pygame.mixer.Channel(1).set_volume(0.0, 1.0)
self.mainloop()
def mainloop(self):
while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT:
terminate()
if event.type == pygame.KEYDOWN:
self.chan1.play(self.testsound)
elif event.type == pygame.KEYUP:
self.chan2.play(self.testsound)
# More code here
This has no effect whatsoever. All sounds are played at full volume.
Try 3:
class MainProgram(object):
def __init__(self, width = 640, height = 640):
# Much Code
# Sounds
self.testsound = pygame.mixer.Sound("data\\sounds\\ping.ogg")
self.chan1 = pygame.mixer.Channel(0)
self.chan2 = pygame.mixer.Channel(1)
self.mainloop()
def mainloop(self):
while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT:
terminate()
if event.type == pygame.KEYDOWN:
self.testsound.play()
self.testsound.set_volume(1.0, 0.0)
elif event.type == pygame.KEYUP:
self.testsound.play()
self.testsound.set_volume(0.0, 1.0)
# More code here
As you can see I just separated try 2's approach into two lines in try 3. Interestingly there's a new issue: I get a
TypeError: function takes exactly 1 argument (2 given)
Which makes everything all the more interesting as using the very same in one line triggers no error, though it doesn't do what it's supposed to.
As I have seen, my program is in stereo mode and according to the tutorials (I've checked others beside) and the documentation either of the two first approaches should yield the result I expected - but neither does...
I'm really grateful for any hints and tips in this issue. It's really important that I can add some kind of 3D-sound. If there's really an issue with pygame itself and not my code, do you know any other module I could use to achieve this effect - best would be if compatible to Pygame, then I don't have to rewrite everything (but I'd do that if necessary...).
Thank you in advance!
Pat
//Short comment by me:
I just saw that Try 2 is doomed anyway, the doc says, that all volumes are reset when the channel is used again, so I can't just set a fixed volume once and for all...
As the documentation states: set_volume takes one parameter, the volume as a float between 0.0 and 1.0.
This means:
ad "Try 1": this is syntactically wrong. play() doesn't return anything so a chained call with set_volume() is just wrong.
ad "Try 2": This actually might work if you set up your channels like this:
self.chan1 = pygame.mixer.Channel(0)
self.chan1.set_volume(1.0, 0.0)
self.chan2 = pygame.mixer.Channel(1)
self.chan2.set_volume(0.0, 1.0)
ad "Try 3: on the Sounds set_volume only one value is allowed.
This is the final version which worked for me. I used Try 2 from my question with a few tweaks. After all, pygame seems not to be that useful when it comes to sounds... Anyway, my code is an experiment to try out a few things, so that just works this way for now - and for the final project I'll anyway write my own sound module as I have a few requirements none covers yet ;)
Here's the final code, a modified version of my Try 2 from the question:
class MainProgram(object):
def __init__(self, width = 640, height = 640):
# Much Code
# Sounds
self.sound = pygame.mixer.Sound("data\\sounds\\ping.ogg")
self.chan1 = pygame.mixer.Channel(0)
self.chan1.set_volume(1.0, 0.0)
self.chan2 = pygame.mixer.Channel(1)
self.chan2.set_volume(0.0, 1.0)
self.mainloop()
def mainloop(self):
while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT:
terminate()
if event.type == pygame.KEYDOWN:
self.chan1.play(self.sound)
# IMPORTANT NOTE! We have to reset the volume after each time
# a sound was played by the respective channel!
self.chan1.set_volume(1.0, 0.0)
elif event.type == pygame.KEYUP:
self.chan2.play(self.sound)
self.chan2.set_volume(0.0, 1.0)
# More code here