Pygame - Unknown error in a multiplayer control function - python-3.x

I am making a two player game in which two players can move simultaneously throughout.
The while loop goes like this:
while stop==0:
for event in pygame.event.get():
if event.type == pygame.QUIT:
stop = 1
#For player 1
#on pressing an arrow key
# xv, yv = velocity at which the object moves
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
xv = -1
elif event.key == pygame.K_RIGHT:
xv = 1
elif event.key == pygame.K_UP:
yv = -1
elif event.key == pygame.K_DOWN:
yv = 1
# on releasing an arrow key
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
xv = 0
elif event.key == pygame.K_UP or event.key == pygame.K_DOWN:
yv = 0
#For player 2
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
xv2 = -1
elif event.key == pygame.K_d:
xv2 = 1
elif event.key == pygame.K_w:
yv2 = -1
elif event.key == pygame.K_s:
yv2 = 1
# on releasing an arrow key
elif event.type == pygame.KEYUP:
if event.key == pygame.K_a or event.key == pygame.K_d:
xv2 = 0
elif event.key == pygame.K_w or event.key == pygame.K_s:
yv2 = 0
Using the above code, only player 1 was able to move while player 2 remained still.
but after modifying the code like this it worked,
while stop==0:
for event in pygame.event.get():
if event.type == pygame.QUIT:
stop = 1
#For player 1
#on pressing an arrow key
# xv, yv = velocity at which the object moves
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
xv = -1
elif event.key == pygame.K_RIGHT:
xv = 1
elif event.key == pygame.K_UP:
yv = -1
elif event.key == pygame.K_DOWN:
yv = 1
# on releasing an arrow key
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
xv = 0
elif event.key == pygame.K_UP or event.key == pygame.K_DOWN:
yv = 0
#For player 2
if event.type == pygame.QUIT:
stop = 1
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
xv2 = -1
elif event.key == pygame.K_d:
xv2 = 1
elif event.key == pygame.K_w:
yv2 = -1
elif event.key == pygame.K_s:
yv2 = 1
# on releasing an arrow key
elif event.type == pygame.KEYUP:
if event.key == pygame.K_a or event.key == pygame.K_d:
xv2 = 0
elif event.key == pygame.K_w or event.key == pygame.K_s:
yv2 = 0
The only change made was inserting
if event.type == pygame.QUIT:
stop = 1
before the elif statement of player 2. Can anyone help with this confusion?

You have
if event.type == pygame.QUIT:
elif event.type == pygame.KEYDOWN:
# player1
elif event.type == pygame.KEYUP:
elif event.type == pygame.KEYDOWN: # <-- this will never checked
# player2
Second pygame.KEYDOWN will be never use because first pygame.KEYDOWN catchs all KEYDOWN events.
You need only one pygame.KEYDOWN
if event.type == pygame.QUIT:
elif event.type == pygame.KEYDOWN:
# player1
# player2
elif event.type == pygame.KEYUP:
# player1
# player2
or you have to use two if
if event.type == pygame.QUIT:
elif event.type == pygame.KEYDOWN:
# player1
elif event.type == pygame.KEYUP:
# player1
if event.type == pygame.KEYDOWN:
# player2
elif event.type == pygame.KEYUP:
# player2
BTW. when you will use Classes then you will have two objects with own method to check events
if event.type == pygame.QUIT:
# quit
player1.handle_event(event)
player2.handle_event(event)
and every player will have own
def handle_event(self, event)
if event.type == pygame.KEYDOWN:
# do something
elif event.type == pygame.KEYUP:
# do something

Related

Trying to control the delay by using the keyboard in Pygame

I would like to control delay for my program, now is set to pygame.time.delay(50) as default value, below is my code snippet.
pygame.time.delay(50)
pygame.display.update()
clockobject = pygame.time.Clock()
clockobject.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
quit()
if event.key == pygame.K_1:
print('K_1')
if event.key == pygame.K_2:
print('K_2')
I tried to control it by changing the values.
if event.key == pygame.K_1:
pygame.time.delay(20)
pygame.display.update()
print('K_1')
if event.key == pygame.K_2:
pygame.time.delay(90)
pygame.display.update()
print('K_2')
When i press the keys the print value returns on my terminal but i doesn't slow down or accelerate!
You have to use a variable for the delay:
time_delay = 50
while run:
pygame.time.delay(time_delay)
# [...]
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_1:
if time_delay > 0:
time_delay -= 10
if event.key == pygame.K_2:
if time_delay < 100:
time_delay += 10
Pygame.time.delay() delays the time your code runs on the window, there is no way that pygame.time.delay() delays your keyboard inputs so what you can do is set a variable to like 20 and then if a user presses a, decrease the variable by 1 and if that variable reaches 0 or below, then do what you want to do.

IndentationError: unindent does not match any outer indentation level please help solve [duplicate]

This question already has answers here:
I'm getting an IndentationError. How do I fix it?
(6 answers)
Closed 1 year ago.
when i run my code is get IndentationError: unindent does not match any outer indentation level
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
if bullet_state == "ready":
bulletX = playerX
fire_bullet(playerX, bulletY)
if event.key == pygame.K_LEFT:
playerX_change = -0.3
if event.key == pygame.K_RIGHT:
playerX_change = 0.3
You have space at the beginning everywhere! Also, sometimes there is inconsistent spacing meaning you used tabs somewhere and spaces somewhere else. Depending on the editor you are using, it does not correct it.
following should work:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
if bullet_state == "ready":
bulletX = playerX
fire_bullet(playerX, bulletY)
if event.key == pygame.K_LEFT:
playerX_change = -0.3
if event.key == pygame.K_RIGHT:
playerX_change = 0.3

pygame switching between menu causes crash: "video system not initializated"

I'm new to pygame, and I'm trying to make a menu for my game. For now, I want two different screens, one that will show in the menu and other that will show in the "custom" part of the game. I tried to create a main loop and two inner loops that only run when they are supposed to.
For now, the transition between menu and custom is done thought pressing key "d". The transition menu to custom is done perfectly, but the transition custom to menu is crashing the game
This is the main loop:
while running:
while menu:
pygame.display.flip()
screen.blit(bg, (0, 0))
for event in pygame.event.get():
if (event.type == pygame.QUIT) or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
running = 0
menu = 0
elif (event.type == pygame.KEYDOWN and event.key == pygame.K_d):
custom = 1
menu = 0
while custom:
pygame.display.flip()
screen.blit(bgCustom, (0, 0))
for event in pygame.event.get():
if (event.type == pygame.QUIT) or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
running = 0
custom = 0
elif (event.type == pygame.KEYDOWN and event.key == pygame.K_d):
custom = 0
menu = 1
pygame.quit()
The error I'm getting when I'm in "while custom" and press "d" to go back to the menu is "pygame.error: video system not initializated". The logic seems the same for both so I'm bewildered. Also, I have already initializated pygame, using pygame.init(), so that is not the problem here. Any thoughts?
Thanks in advance!
EDIT: As Rabbid76 stated, in his answer, the error was my identation in "pygame.quit()". It stopped my video system. The only problem was the last line. Correct loop below:
while running:
while menu:
pygame.display.flip()
screen.blit(bg, (0, 0))
for event in pygame.event.get():
if (event.type == pygame.QUIT) or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
running = 0
menu = 0
elif (event.type == pygame.KEYDOWN and event.key == pygame.K_d):
custom = 1
menu = 0
elif (event.type == pygame.KEYDOWN and event.key == pygame.K_1):
playMusic(1)
elif (event.type == pygame.KEYDOWN and event.key == pygame.K_2):
playMusic(2)
elif (event.type == pygame.KEYDOWN and event.key == pygame.K_0):
playMusic(0)
elif (event.type == pygame.KEYDOWN and event.key == pygame.K_3):
playMusic(3)
while custom:
pygame.display.flip()
screen.blit(bgCustom, (0, 0))
for event in pygame.event.get():
if (event.type == pygame.QUIT) or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
running = 0
custom = 0
elif (event.type == pygame.KEYDOWN and event.key == pygame.K_d):
custom = 0
menu = 1
pygame.quit()
It is a matter of Indentation. The last statement in the while loop is pygame.quit(). pygame.quit() uninitialize all pygame modules.
Invoke pygame.quit() after the loop. rather than in the loop:
while running:
while menu:
# [...]
while custom:
# [...]
#<--| INDENTATION
pygame.quit()

I made a game where blocks fall and you have to dodge it but can't get the hitboxes right

The hitbox seems to be on the left side of the cube, so it feels like the game is ending without me even hitting anything. I want to make it that the hitbox is exactly on the red rectangle, so that it's obvious that the black rectangle had hit you.
the up and down controls are just for future movement option if needed.
here's the code
import pygame as pg,pygame
import random
import sys
pygame.init()
WIDTH = 1000
HEIGHT = 800
# Positions, sizes
SPEED = 10
MIDDLE = [500, 400]
score = 0
player_size = 90
player_pos = [WIDTH/2, HEIGHT-2*player_size]
playerX_move = 0
playerY_move = 0
enemy_size = 50
enemy_pos = [random.randint(0,WIDTH - enemy_size), 30]
enemy_list = [enemy_pos]
# Colors
WHITE = [255, 255, 255]
GREY = [25, 25, 25]
BLUE = [65,105,225]
BLACK = [0,0,0]
GREEN = [65,255,105]
RED = [255,0,0]
# -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
screen = pygame.display.set_mode((WIDTH,HEIGHT))
game_over = False
clock = pygame.time.Clock()
def drop_enemies(enemy_list):
delay = random.random()
if len(enemy_list) < 10 and delay < 0.1:
x_pos = random.randint(0,WIDTH-enemy_size)
y_pos = 30
enemy_list.append([x_pos, y_pos])
def draw_enemies(enemy_list):
for enemy_pos in enemy_list:
pygame.draw.rect(screen,BLACK, (enemy_pos[0], enemy_pos[1], enemy_size, enemy_size))
def update_enemy_positions(enemy_list, score):
for idx, enemy_pos in enumerate(enemy_list):
if enemy_pos[1] >= 0 and enemy_pos[1] < HEIGHT:
enemy_pos[1] += SPEED
else:
enemy_list.pop(idx)
score += 1
return score
def collision_check(enemy_list, player_pos):
for enemy_pos in enemy_list:
if detect_collision(enemy_pos, player_pos):
return True
return False
def detect_collision(player_pos, enemy_pos):
p_x = player_pos[0]
p_y = player_pos[1]
e_x = enemy_pos[0]
e_y = enemy_pos[1]
if (e_x >= p_x and e_x < (p_x + player_size)) or (p_x >= e_x and p_x < (e_x+enemy_size)):
if (e_y >= p_y and e_y < (p_y + player_size)) or (p_y >= e_y and p_y < (e_y+enemy_size)):
return True
return False
while not game_over:
player_pos[0] += playerX_move
player_pos[1] += playerY_move
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerX_move = -5
if event.key == pygame.K_RIGHT:
playerX_move = 5
# if event.key == pygame.K_UP:
# playerY_move = -5
# if event.key == pygame.K_DOWN:
# playerY_move = 5
if event.key == pygame.K_a:
playerX_move = -15
if event.key == pygame.K_d:
playerX_move = 15
# if event.key == pygame.K_w:
# playerY_move = -15
# if event.key == pygame.K_s:
# playerY_move = 15
if event.key == pg.K_SPACE:
print("SPACE")
if event.type == pygame.KEYUP:
if event.key == pygame.K_a or event.key == pygame.K_d or event.key == pygame.K_s or event.key == pygame.K_w:
playerX_move = 0
playerY_move = 0
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT or event.key == pygame.K_DOWN or event.key == pygame.K_UP:
playerX_move = 0
playerY_move = 0
screen.fill(BLACK)
drop_enemies(enemy_list)
score = update_enemy_positions(enemy_list,score)
if collision_check(enemy_list, player_pos):
game_over = True
draw_enemies(enemy_list)
pygame.draw.rect(screen, RED, (player_pos[0], player_pos[1], 90, 90))
clock.tick(30)
pygame.display.update()
I would recommend using a list of pygame.Rects instead of a List with the positions of your enemies. This would also allow you to use pygame.Rect.colliderect() instead of your detect_collision function.
I've also linked the Pygame Docs.

Pygame Creating Sprites While Moving Mouse

So, I'm working on a basic Pygame and one of the mechanics is having a bullet sprite follow the mouse and explode. But I'm having just two bugs.
BUG 1: Removing the bullets removes all bullets in bullet_list. I understand why this happens but I don't know how to correct it. Solved
BUG 2: Moving the mouse seems to override the detection of key presses. You cannot move or shoot bullets while moving the mouse.
Update
#Checking Keys
for event in pygame.event.get():
print("CAKE")
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_DOWN:
pPlayer.image = pDown
pPlayer.chy = 2
elif event.key == pygame.K_UP:
pPlayer.image = pUp
pPlayer.chy = -2
elif event.key == pygame.K_LEFT:
pPlayer.image = pLeft
pPlayer.chx = -2
elif event.key == pygame.K_RIGHT:
pPlayer.image = pRight
pPlayer.chx = 2
elif event.key == pygame.K_SPACE:
if pPlayer.canFire == True:
bullet = Bullet()
bullet.rect.x = int(player.x)
bullet.rect.y = int(player.y)
all_sprites_list.add(bullet)
bullet_list.add(bullet)
pPlayer.canFire = False
elif event.key == pygame.K_ESCAPE:
if gameState.togglePause == True:
if gameState.pause == True:
gameState.game = True
gameState.pause = False
elif gameState.pause == False:
gameState.game = False
gameState.pause = True
gameState.togglePause = False
elif event.type == pygame.KEYUP:
if event.key == pygame.K_DOWN or event.key == pygame.K_UP:
pPlayer.chy = 0
elif event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
pPlayer.chx = 0
elif event.key == pygame.K_SPACE:
pPlayer.canFire = True
elif event.key == pygame.K_ESCAPE:
gameState.togglePause = True
else:
pPlayer.chx = 0
pPlayer.chy = 0
New Bug! I'm unfamiliar with pygame.event.get() and I'm probably doing something wrong here but the examples provided by the pygame docs don't quite help. I can't tell if it has fixed the handling of multiple events because it doesn't seem to even register them. The code prints out "cake" rarely and very delayed and very seldom do any bullets fire when I hit space.
I don't know how well this answer applies because your code is only a sample, but I'll do my best.
Bug 1: For if dist < 30, dist is not updating because you're calculating it in a different for-loop. From your sample, it looks like you can just include the kill check at the end of the first "for bullet in bullet_list" loop.
Bug 2: You're only checking for one event per step, so when multiple events happen (ie mouse motion and a keypress) you only handle on of them. To fix this, iterate through a list of all events:
for event in pygame.event.get():
#Your "Checking Keys" code goes here

Resources