Why aren't my variables working in the while loop - pygame

for some reason when i blit my image and try to move my cube, it doesn't work and my text doesn't work either.
import pygame
from random import randint
pygame.init()
pygame.font.init()
HEIGHT = 600
WIDTH = 800
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Cube game")
clock = pygame.time.Clock()
TP_usage = 0
FPS = 60
Cube_Vel = 4
HP = 3
CubeX = 400
CubeY = 400
TP_staff = pygame.image.load("Game imag/TP staff.png")
TP_staff_rect = TP_staff.get_rect(center=(randint(10, 500), (randint(10, 770))))
No_tp_text = pygame.font.Font(None, 50)
No_tp_Warning = No_tp_text.render("NO TP USAGE", False, "white")
TP_usage_Stat_Font = pygame.font.Font(None, 30)
TP_usage_Stat = TP_usage_Stat_Font.render(f"TP usages: {TP_usage}", False, "white")
Cube_player = pygame.image.load("Game imag/Cube.png")
Cube_player_rect = Cube_player.get_rect(center=(CubeX, CubeY))
while True:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
#part that is not updating
screen.fill((0, 0, 0))
screen.blit(TP_usage_Stat, (500, 600))
screen.blit(Cube_player, Cube_player_rect)
screen.blit(TP_staff, TP_staff_rect)
if Cube_player_rect.colliderect(TP_staff_rect):
TP_usage += 1
print(TP_usage)
if TP_usage > 1:
TP_usage = 1
print(TP_usage)
keys = pygame.key.get_pressed()
if keys[pygame.K_a] and CubeX - Cube_Vel > 0:
CubeX -= Cube_Vel
if keys[pygame.K_d] and CubeX + Cube_Vel < WIDTH:
CubeX += Cube_Vel
if keys[pygame.K_w] and CubeY - Cube_Vel > 0:
CubeY -= Cube_Vel
if keys[pygame.K_s] and CubeY + Cube_Vel < HEIGHT:
CubeY += Cube_Vel
pressed_keys = pygame.mouse.get_pressed()
if (pressed_keys[0]) and TP_usage > 0:
TP_usage -= 1
print(TP_usage)
mx, my = pygame.mouse.get_pos()
CubeX = mx
CubeY = my
if (pressed_keys[0]) and TP_usage < 0:
screen.blit(No_tp_Warning, (400, 500))
pygame.display.update()
before i had it something like this
import pygame
from random import randint
pygame.init()
pygame.font.init()
HEIGHT = 600
WIDTH = 800
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Cube game")
clock = pygame.time.Clock()
TP_usage = 0
PhoX = 100
PhoY = -200
FPS = 60
Cube_Vel = 4
HP = 3
CubeX = 400
CubeY = 400
TP_staff = pygame.image.load("Game imag/TP staff.png")
TP_usage_Stat_Font = pygame.font.Font(None, 30)
TP_usage_Stat = TP_usage_Stat_Font.render(f"TP usages: {TP_usage}", False, "white")
Cube_player = pygame.image.load("Game imag/Cube.png")
# Timer
obstacle_timer = pygame.USEREVENT + 1
pygame.time.set_timer(obstacle_timer, 5000)
TP_staff_rect = TP_staff.get_rect(center=(randint(10, 500), (randint(10, 770))))
game_on = True
while True:
No_tp_text = pygame.font.Font(None, 50)
No_tp_Warning = No_tp_text.render("NO TP USAGE", False, "white")
Cube_player_rect = Cube_player.get_rect(center=(CubeX, CubeY))
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
screen.fill((0, 0, 0))
screen.blit(TP_usage_Stat, (500, 600))
screen.blit(Cube_player, Cube_player_rect)
screen.blit(TP_staff, TP_staff_rect)
if event.type == obstacle_timer:
TP_staff_rect = TP_staff.get_rect(center=(randint(10, 500), (randint(10, 770))))
if Cube_player_rect.colliderect(TP_staff_rect):
TP_usage += 1
print(TP_usage)
if TP_usage > 1:
TP_usage = 1
print(TP_usage)
keys = pygame.key.get_pressed()
if keys[pygame.K_a] and CubeX - Cube_Vel > 0:
CubeX -= Cube_Vel
if keys[pygame.K_d] and CubeX + Cube_Vel < WIDTH:
CubeX += Cube_Vel
if keys[pygame.K_w] and CubeY - Cube_Vel > 0:
CubeY -= Cube_Vel
if keys[pygame.K_s] and CubeY + Cube_Vel < HEIGHT:
CubeY += Cube_Vel
pressed_keys = pygame.mouse.get_pressed()
if (pressed_keys[0]) and TP_usage > 0:
TP_usage -= 1
print(TP_usage)
mx, my = pygame.mouse.get_pos()
CubeX = mx
CubeY = my
if (pressed_keys[0]) and TP_usage < 0:
screen.blit(No_tp_Warning, (400, 500))
pygame.display.update()
the problem was it was going everywhere 60 times a sec so i tried to move the staff rect out of the while loop and then everything else as will but now nothing is updating like normal

Your game updates normally. The problem is that you move with Cube_player and you also draw Cube_player_rect. Here's how to solve it:
keys = pygame.key.get_pressed()
if keys[pygame.K_a] and Cube_player_rect.x - Cube_Vel > 0:
Cube_player_rect.x -= Cube_Vel
if keys[pygame.K_d] and Cube_player_rect.x + Cube_Vel < WIDTH - Cube_player_rect.w:
Cube_player_rect.x += Cube_Vel
if keys[pygame.K_w] and Cube_player_rect.y - Cube_Vel > 0:
Cube_player_rect.y -= Cube_Vel
if keys[pygame.K_s] and Cube_player_rect.y + Cube_Vel < HEIGHT - Cube_player_rect.h:
Cube_player_rect.y += Cube_Vel
pressed_keys = pygame.mouse.get_pressed()
if (pressed_keys[0]) and TP_usage > 0:
TP_usage -= 1
print(TP_usage)
mx, my = pygame.mouse.get_pos()
Cube_player_rect.x = mx
Cube_player_rect.y = my
if (pressed_keys[0]) and TP_usage < 0:
screen.blit(No_tp_Warning, (400, 400))
The font does not draw to you because it has y coordinates outside the image. TP_usage is not updated because you draw an old variable. Try my function for drawing text:
def draw_text(text, color, size, x, y):
font = pygame.font.Font(None, size)
text = font.render(text, False, color)
text_rect = text.get_rect(center=(x, y))
screen.blit(text, text_rect)
This is how you use in main loop:
draw_text(f"TP usages: {TP_usage}", "white", 30, 500, 500)
I hope it will help you, Adam

Related

screen.blit() function executing even after pygame.quit() is used

I am making a basic pong game in pygame with a separate menu screen. I have figured out all the gameplay (physics of ball,score system etc.).However, when i quit the game no matter from the menu screen or from the main game loop, i get this error:pygame.error: display Surface quit. I have seen all the posts about this error on stackoverflow, as well as other websites. I understand that the error is occuring because even after the pygame.quit() function, the next screen.blit(player1,(player1x,player1y)) is being executed. Following is the my code :
import pygame
import random
pygame.init()
#screen
screenw = 1000
screenh = 600
screen = pygame.display.set_mode((screenw, screenh))
bg = pygame.image.load("bg.jpg")
dp = pygame.image.load("ping-pong.png")
pygame.display.set_caption("PONG")
pygame.display.set_icon(dp)
def main():
# score
font = pygame.font.Font('font.otf', 24)
winfont = pygame.font.Font('font.otf', 50)
score_value_p1 = 0
scorexp1 = 10
scoreyp1 = 0
score_value_p2 = 0
scorexp2 = screenw - 145
scoreyp2 = 0
#toss
toss = random.choice([-1,1])
#players
def initial_bars():
global player1,player1x,player1y,player1_change,player2,player2x,player2y,player2_change
player1 = pygame.image.load("danda.png")
player1 = pygame.transform.scale(player1,(25,128))
player1x = 10
player1y = 232
player1_change = 0
player2 = pygame.image.load("danda.png")
player2 = pygame.transform.scale(player1,(25,128))
player2x = 965
player2y = 232
player2_change = 0
#ball
def initial_ball():
global ball,ballx,bally,ballx_change,bally_change
ball = pygame.image.load("ball.png")
ballx = 484
bally = 284
ballx_change = 0.4*toss
bally_change = 0.0
initial_bars()
initial_ball()
global player1,player1x,player1y,player1_change,player2,player2x,player2y,player2_change,ball,ballx,bally,ballx_change,bally_change,running
#functions
def player1bar():
screen.blit(player1,(player1x,player1y))
def player2bar():
screen.blit(player2,(player2x,player2y))
def balll():
screen.blit(ball,(ballx,bally))
def show_score():
scorep1 = font.render("Score : " + str(score_value_p1), True, (255, 50, 50))
screen.blit(scorep1, (scorexp1 , scoreyp1))
scorep2 = font.render("Score : " + str(score_value_p2), True, (255, 50, 50))
screen.blit(scorep2, (scorexp2 , scoreyp2))
#game window
running = True
while running:
screen.fill((0, 0, 0))
pygame.draw.line(screen,(255,255,30),(499,0),(499,600), 10)
pygame.draw.circle(screen,(255,255,30),(500,300), 40, 10)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
# player1 movement
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_s :
player1_change = 0.6
if event.key == pygame.K_w:
player1_change = -0.6
if event.type == pygame.KEYUP:
if event.key == pygame.K_s or event.key == pygame.K_w:
player1_change = 0
# player2 movement
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_DOWN :
player2_change = 0.6
if event.key == pygame.K_UP:
player2_change = -0.6
if event.type == pygame.KEYUP:
if event.key == pygame.K_DOWN or event.key == pygame.K_UP:
player2_change = 0
player1y += player1_change
player2y += player2_change
# player1 boundary
if player1y <= 0:
player1y = 0
elif player1y >= 472:
player1y = 472
# player2 boundary
if player2y <= 0:
player2y = 0
elif player2y >= 472:
player2y = 472
#ball move
ballx += ballx_change
bally += bally_change
toss = random.choice([-1,1])
if ballx < 35 and ballx > 30 and (player1y == bally or (player1y < bally and player1y > bally - 128) or (player1y > bally and player1y < bally + 32)):
ballx_change *= -1
if ballx_change < 1:
ballx_change += 0.05
bally_change = ballx_change*toss
if ballx > 933 and ballx < 938 and (player2y == bally or (player2y < bally and player2y > bally - 128) or (player2y > bally and player2y < bally + 32)):
ballx_change *= -1
if ballx_change > -1:
ballx_change -= 0.05
bally_change = ballx_change*toss
# ball boundary
if bally < 0 or bally > screenh - 32:
bally_change *= -1
#score
if ballx > screenw:
score_value_p1 += 1
if ballx < -32:
score_value_p2 += 1
#respawn
if ballx > screenw or ballx < -32:
initial_ball()
initial_bars()
player1bar()
player2bar()
balll()
show_score()
#winner
if score_value_p1 == 5:
winner = winfont.render("The Winner is Player 1", True, (50, 255, 50))
winner_rect = winner.get_rect(center=(screenw/2, screenh/2))
pygame.draw.rect(screen, (0,0,0), pygame.Rect(winner_rect))
screen.blit(winner, winner_rect)
if score_value_p2 == 5:
winner = winfont.render("The Winner is Player 2", True, (50, 255, 50))
winner_rect = winner.get_rect(center=(screenw/2, screenh/2))
pygame.draw.rect(screen, (0,0,0), pygame.Rect(winner_rect))
screen.blit(winner, winner_rect)
pygame.display.update()
if score_value_p1 == 5 or score_value_p2 == 5:
pygame.time.delay(2000)
menu_screen()
if ballx == 484 and bally == 284:
pygame.time.delay(1250)
ballx_change = 0.4*toss
def menu_screen():
menufont = pygame.font.Font('font.otf', 50)
tipfont = pygame.font.Font('font.otf', 30)
running = True
while running:
screen.blit(bg,(0,0))
title = menufont.render("Multiplayer Pong", True, (255, 255, 20))
screen.blit(title, (220,70))
tip = tipfont.render("Click Anywhere to Play", True, (50, 255, 50))
screen.blit(tip, (275,500))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
if event.type == pygame.MOUSEBUTTONDOWN:
running = False
pygame.display.update()
main()
menu_screen()
I have tried methods like adding break,pygame.quit(),declaring running as a global variable. However, i have not been able to get rid of this problem. Can anyone please try o provide a solution for this problem. Following is the complete error i recieved :
Traceback (most recent call last):
File "c:\Users\jaism\OneDrive\Desktop\Codes\Minor Project CSE\main.py", line 208, in <module>
menu_screen()
File "c:\Users\jaism\OneDrive\Desktop\Codes\Minor Project CSE\main.py", line 206, in menu_screen
main()
File "c:\Users\jaism\OneDrive\Desktop\Codes\Minor Project CSE\main.py", line 158, in main
player1bar()
File "c:\Users\jaism\OneDrive\Desktop\Codes\Minor Project CSE\main.py", line 63, in player1bar
screen.blit(player1,(player1x,player1y))
pygame.error: display Surface quit
pygame.quit() uninitialize all pygame modules that have previously been initialized. So you can't call any pygame API function after pygame.quite(). pygame.quite() must be the very last pygame function called after the application loop:
def main():
# [...]
running = True
while running:
# [...]
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# pygame.quit() <-- DELETE
# [...]
def menu_screen():
# [...]
run_main = True
running = True
while running:
# [...]
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
run_main = False
# pygame.quit() <-- DELETE
# [...]
if run_main:
main()
menu_screen()
pygame.quit() # <-- INSERT

How to make enemies move to the centre of screen? [duplicate]

i'm learning python by myself, and started with a simple game with pygame.
The game consists, so far, in a ball that's been chased by other balls, i have created a loop that avoid the chasing balls to overlap.
The way the loop works its by a nested loop that moves thru a list that includes all the chasing balls, then measures the distance between them, if the distance is less than the ball radius, it is moved away.
It seems to work most of the time, but sometimes a ball overlaps. I dont know why, if anyone can take a look at my code and give me a hint i would apreciate it, i think the error happens when there are more than 3 balls and at the moment when the player's ball (pelota) collides.
import pygame, random, math
pygame.init()
ancho , alto = 800 , 600
negro = (0,0,0)
blanco=(255,255,255)
FPS = 60
velocidad = 7
velocidadnalguis = velocidad - 2
contadordecolisiones = 1
perseguidores = []
pantalla=pygame.display.set_mode((ancho,alto))
pygame.display.set_caption("un jueguito")
reloj=pygame.time.Clock()
class Pelota(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("pelota.png").convert()
self.image = pygame.transform.scale(self.image, (30, 30))
self.image.set_colorkey(negro)
self.rect = self.image.get_rect()
self.rect.center = (ancho/2,alto/2)
self.speed = 0
def update(self):
self.speedx = 0
self.speedy = 0
tecla = pygame.key.get_pressed()
if tecla[pygame.K_LEFT]:
self.speedx = -velocidad
if tecla[pygame.K_RIGHT]:
self.speedx = velocidad
if tecla[pygame.K_UP]:
self.speedy = -velocidad
if tecla[pygame.K_DOWN]:
self.speedy = velocidad
self.rect.x += self.speedx
self.rect.y += self.speedy
if self.rect.right > ancho:
self.rect.right = ancho
if self.rect.bottom > alto:
self.rect.bottom = alto
if self.rect.left < 0:
self.rect.left = 0
if self.rect.top < 0:
self.rect.top = 0
pelota = Pelota()
class Perseguidor(pygame.sprite.Sprite):
def __init__(self,):
super().__init__()
self.image = pygame.image.load('nalguis.png').convert()
self.image = pygame.transform.scale(self.image, (30, 30))
self.image.set_colorkey(negro)
self.rect = self.image.get_rect()
self.velocidad = velocidadnalguis
self.radius = self.rect.width/2
self.center = self.rect.center
self.contadordecolisiones = 1
self.enerandom = random.randint(0,4)
if self.enerandom == 0:
self.rect.center = (random.randrange(-130,-30),random.randrange(-130,alto+130))
if self.enerandom == 1:
self.rect.center = (random.randrange(-130,ancho+130),random.randrange(-130,-30))
if self.enerandom == 2:
self.rect.center = (random.randrange(ancho+30,ancho+130),random.randrange(-130,alto+130))
if self.enerandom == 3:
self.rect.center = (random.randrange(-130,ancho+130),random.randrange(alto+30,alto+130))
def update(self):
self.pely = pelota.rect.y
self.pelx = pelota.rect.x
self.perx = self.rect.x
self.pery = self.rect.y
self.dist = math.sqrt(((self.pely-self.pery)**2) + ((self.pelx-self.perx)**2))/velocidadnalguis
self.angulo = math.atan2(self.pely-self.pery,self.pelx-self.perx)
self.speedx = 0
self.speedy = 0
self.speedx = math.cos(self.angulo)
self.speedy = math.sin(self.angulo)
if self.dist>=1:
self.rect.x += velocidadnalguis * self.speedx
self.rect.y += velocidadnalguis * self.speedy
all_sprites = pygame.sprite.Group()
perseguidor_grupo = pygame.sprite.Group()
all_sprites.add(pelota)
terminar=False
while not terminar:
reloj.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
terminar=True
if len(perseguidor_grupo)<1:
perseguidor=Perseguidor()
perseguidor_grupo.add(perseguidor)
all_sprites.add(perseguidor)
hit = pygame.sprite.spritecollide(pelota, perseguidor_grupo, True, pygame.sprite.collide_circle)
if hit:
if len(perseguidor_grupo)<25:
perseguidor = Perseguidor()
perseguidor1 = Perseguidor()
all_sprites.add(perseguidor, perseguidor1)
perseguidor_grupo.add(perseguidor, perseguidor1)
perseguidores.append(perseguidor1)
perseguidores.append(perseguidor)
else :
perseguidor = Perseguidor()
all_sprites.add(perseguidor)
perseguidor_grupo.add(perseguidor)
perseguidores.append(perseguidor)
dist=1
for i in range (len(perseguidores)):
for j in range(i+1,len(perseguidores)):
perseguidoresxy = [perseguidores[i].rect.centerx,perseguidores[i].rect.centery]
dist=math.hypot(perseguidores[i].rect.centerx - perseguidores[j].rect.centerx , perseguidores[i].rect.centery - perseguidores[j].rect.centery)
if dist <= perseguidor.radius*2:
if perseguidores[i].rect.centerx < perseguidores[j].rect.centerx:
perseguidores[i].rect.centerx -= 3
if perseguidores[i].rect.centery < perseguidores[j].rect.centery:
perseguidores[i].rect.centery -= 3
if perseguidores[i].rect.centerx > perseguidores[j].rect.centerx:
perseguidores[i].rect.centerx += 3
if perseguidores[i].rect.centery > perseguidores[j].rect.centery:
perseguidores[i].rect.centery -= 3
if len(perseguidores)> len(perseguidor_grupo):
del perseguidores [0]
all_sprites.update()
pantalla .fill(negro)
all_sprites.draw(pantalla)
pygame.display.flip()
pygame.quit()
quit()
[...] then measures the distance between them, if the distance is less than the ball radius, it is moved away. It seems to work most of the time, but sometimes a ball overlaps. [...]
Of course.You only consider 2 balls when moving a ball away.
This means that if you move a ball away from one ball, it can happen that you move it straight onto another ball.
You need to check that there is no other ball in the position where you are moving the ball.
Make sure the balls don't overlap as they spawn:
requested_balls = 1
while not terminar:
# [...]
hit = pygame.sprite.spritecollide(pelota, perseguidor_grupo, True, pygame.sprite.collide_circle)
if hit:
requested_balls = min(25, requested_balls+1)
if len(perseguidor_grupo) < requested_balls:
perseguidor = Perseguidor()
if not pygame.sprite.spritecollide(perseguidor, perseguidor_grupo, True, pygame.sprite.collide_circle):
all_sprites.add(perseguidor)
perseguidor_grupo.add(perseguidor)
perseguidores.append(perseguidor)
Only move a ball if the new position of the ball is not yet occupied by a ball:
class Perseguidor(pygame.sprite.Sprite):
# [...]
def update(self):
# [...]
old_rect = self.rect.copy()
if self.dist>=1:
self.rect.x += velocidadnalguis * self.speedx
self.rect.y += velocidadnalguis * self.speedy
hit = pygame.sprite.spritecollide(self, perseguidor_grupo, False, pygame.sprite.collide_circle)
if len(hit) > 1: # at last 1, because the ball hits itself
if random.randrange(2) == 0:
self.rect.x = old_rect.x
else:
self.rect.y = old_rect.y
hit = pygame.sprite.spritecollide(self, perseguidor_grupo, False, pygame.sprite.collide_circle)
if len(hit) > 1:
self.rect = old_rect
Complete example:
import pygame, random, math
pygame.init()
ancho , alto = 800 , 600
negro = (0,0,0)
blanco=(255,255,255)
FPS = 60
velocidad = 7
velocidadnalguis = velocidad - 2
contadordecolisiones = 1
perseguidores = []
pantalla=pygame.display.set_mode((ancho,alto))
pygame.display.set_caption("un jueguito")
reloj=pygame.time.Clock()
class Pelota(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("pelota.png").convert()
self.image = pygame.transform.scale(self.image, (30, 30))
self.image.set_colorkey(negro)
self.rect = self.image.get_rect()
self.rect.center = (ancho/2,alto/2)
self.speed = 0
def update(self):
self.speedx = 0
self.speedy = 0
tecla = pygame.key.get_pressed()
if tecla[pygame.K_LEFT]:
self.speedx = -velocidad
if tecla[pygame.K_RIGHT]:
self.speedx = velocidad
if tecla[pygame.K_UP]:
self.speedy = -velocidad
if tecla[pygame.K_DOWN]:
self.speedy = velocidad
self.rect.x += self.speedx
self.rect.y += self.speedy
if self.rect.right > ancho:
self.rect.right = ancho
if self.rect.bottom > alto:
self.rect.bottom = alto
if self.rect.left < 0:
self.rect.left = 0
if self.rect.top < 0:
self.rect.top = 0
pelota = Pelota()
class Perseguidor(pygame.sprite.Sprite):
def __init__(self,):
super().__init__()
self.image = pygame.image.load('nalguis.png').convert()
self.image = pygame.transform.scale(self.image, (30, 30))
self.image.set_colorkey(negro)
self.rect = self.image.get_rect()
self.velocidad = velocidadnalguis
self.radius = self.rect.width/2
self.center = self.rect.center
self.contadordecolisiones = 1
self.enerandom = random.randint(0,4)
if self.enerandom == 0:
self.rect.center = (random.randrange(-130,-30),random.randrange(-130,alto+130))
if self.enerandom == 1:
self.rect.center = (random.randrange(-130,ancho+130),random.randrange(-130,-30))
if self.enerandom == 2:
self.rect.center = (random.randrange(ancho+30,ancho+130),random.randrange(-130,alto+130))
if self.enerandom == 3:
self.rect.center = (random.randrange(-130,ancho+130),random.randrange(alto+30,alto+130))
def update(self):
self.pely = pelota.rect.y
self.pelx = pelota.rect.x
self.perx = self.rect.x
self.pery = self.rect.y
self.dist = math.sqrt(((self.pely-self.pery)**2) + ((self.pelx-self.perx)**2))/velocidadnalguis
self.angulo = math.atan2(self.pely-self.pery,self.pelx-self.perx)
self.speedx = 0
self.speedy = 0
self.speedx = math.cos(self.angulo)
self.speedy = math.sin(self.angulo)
old_rect = self.rect.copy()
if self.dist>=1:
self.rect.x += velocidadnalguis * self.speedx
self.rect.y += velocidadnalguis * self.speedy
hit = pygame.sprite.spritecollide(self, perseguidor_grupo, False, pygame.sprite.collide_circle)
if len(hit) > 1: # at last 1, because the ball hits itself
if random.randrange(2) == 0:
self.rect.x = old_rect.x
else:
self.rect.y = old_rect.y
hit = pygame.sprite.spritecollide(self, perseguidor_grupo, False, pygame.sprite.collide_circle)
if len(hit) > 1:
self.rect = old_rect
all_sprites = pygame.sprite.Group()
perseguidor_grupo = pygame.sprite.Group()
all_sprites.add(pelota)
terminar=False
requested_balls = 1
while not terminar:
reloj.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
terminar=True
if len(perseguidor_grupo)<1:
perseguidor=Perseguidor()
perseguidor_grupo.add(perseguidor)
all_sprites.add(perseguidor)
hit = pygame.sprite.spritecollide(pelota, perseguidor_grupo, True, pygame.sprite.collide_circle)
if hit:
requested_balls = min(25, requested_balls+1)
if len(perseguidor_grupo) < requested_balls:
perseguidor = Perseguidor()
if not pygame.sprite.spritecollide(perseguidor, perseguidor_grupo, True, pygame.sprite.collide_circle):
all_sprites.add(perseguidor)
perseguidor_grupo.add(perseguidor)
perseguidores.append(perseguidor)
dist=1
if len(perseguidores)> len(perseguidor_grupo):
del perseguidores [0]
all_sprites.update()
pantalla .fill(negro)
all_sprites.draw(pantalla)
pygame.display.flip()
pygame.quit()
quit()

Pygame error 'pow expected 2 arguments, got 1'

They pygame game i made has run into an error i cannot figure out how to fix. I am new to pygame. I am using pycharm and python version 3.
The error is stopping me from doing anything and it won't even let me run it
Here is the error
TypeError: pow expected 2 arguments, got 1
Here is the code:
import math
import random
import pygame
pygame.init()
# Screen (Pixels by Pixels (X and Y (X = right and left Y = up and down)))
screen = pygame.display.set_mode((800, 600))
running = True
# Title and Icon
pygame.display.set_caption("Space Invaders")
icon = pygame.image.load('Icon.png')
pygame.display.set_icon(icon)
# Player Icon/Image
playerimg = pygame.image.load('Player.png')
playerX = 370
playerY = 480
playerX_change = 0
def player(x, y):
# Blit means Draw
screen.blit(playerimg, (x, y))
def enemy(x, y):
# Blit means Draw
screen.blit(enemyimg, (x, y))
def fire_bullet(x, y):
global bullet_state
bullet_state = "fire"
screen.blit(bulletimg, (x + 16, y + 10))
def isCollision(enemyX, enemyY, bulletX, bulletY):
distance = math.sqrt(math.pow(enemyX - bulletX, 2) + math.pow(math.pow(enemyY - bulletY,2)))
if distance < 27:
return True
else:
return False
background = pygame.image.load('247.jpg')
enemyimg = pygame.image.load('space-invaders.png')
enemyX = random.randint(0, 800)
enemyY = random.randint(50, 150)
enemyX_change = 4
enemyY_change = 40
bulletimg = pygame.image.load('bullet.png')
bulletX = 0
bulletY = 450
bulletX_change = 480
bulletY_change = 10
bullet_state = "ready"
score = 0
# Game loop (Put most of code for game in this loop)
while running:
screen.fill((255, 0, 0))
# BAckground
screen.blit(background, (0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# if keystroke is pressed check whether is right or left
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerX_change = -5
if event.key == pygame.K_RIGHT:
playerX_change = 5
if event.key == pygame.K_SPACE:
if bullet_state == "ready":
bulletX = playerX
fire_bullet(playerX, bulletY)
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
playerX_change = 0
# RGB (screen.fill) = red green blue
# 5 = 5 + - 0.1 -> 5 = 5 - 0.1
# making so nothing can go out of bounds
enemyX += enemyX_change
if enemyX <= 0:
enemyX_change = 4
enemyY += enemyY_change
elif enemyX >= 736:
enemyX_change = -4
enemyY += enemyY_change
playerX += playerX_change
if playerX <= 0:
playerX = 0
elif playerX >= 736:
playerX = 736
# Bullet movement
if bulletY <= 0:
bulletY = 480
bullet_state = "ready"
if bullet_state == "fire":
fire_bullet(bulletX, bulletY)
bulletY -= bulletY_change
# Collison
collision = isCollision(enemyX,enemyY,bulletX,bulletY)
if collision:
bulletY = 480
bullet_state = "ready"
score +=1
player(playerX, playerY)
enemy(enemyX, enemyY)
pygame.display.update()
I believe you are trying to do this:
c = sqrt(pow(a,2) + pow(b,2))
But your code has one pow() too many. Happens to me too, when I make I make game sounds in my head, while coding (pew pew pew)
Try to remove one pow()
from
math.pow(math.pow(enemyY - bulletY,2))
to
math.pow(enemyY - bulletY,2)

I want to create multiple enemies but keep getting same error code

Blockquote I just started coding in this coronatime and I am running into a problem.
The error code is
enemy_icon = [i]
NameError: name 'i' is not defined
And i'm not sure why. I having been looking online but couldn't find any answers.
Hopefully this has given enough resources to be a good enough question.
import pygame
import random
import math
pygame.init()
# game over logo
game_over = pygame.image.load("game-over.png")
# create screen
screen = pygame.display.set_mode((1000, 600))
background = pygame.image.load("8717.jpg")
# Title + Logo
pygame.display.set_caption("Space Invader")
icon = pygame.image.load("chicken.png")
pygame.display.set_icon(icon)
# Player icon
player_icon = pygame.image.load("spaceship.png")
playerX = 400
playerY = 500
player_changeX = 0
player_changeY = 0
# multiple enemy players
enemy_icon = [i]
enemyX = [i]
enemyY = [i]
enemy_changeX = [i]
enemy_changeY = [i]
num_of_enemies = 2
for i in range(num_of_enemies):
enemy_icon.append(pygame.image.load("space-invaders.png"))
enemyX.append(random.randint(0, 936))
enemyY.append(random.randint(-100, -50))
enemy_changeX.append(random.randint(-2, 2))
enemy_changeY.append(random.randint(1, 2))
# bullet #ready you can't see bullet. fire you can
bullet = pygame.image.load("bullet.png")
bulletX = 0
bulletY = 0
bulletY_change = 2
bulletX_change = 0
bullet_state = "ready"
# score
score = 0
def player(x, y):
screen.blit(player_icon, (x, y))
def enemy(x, y, i):
screen.blit(enemy_icon[i], (x, y))
def fire_bullet(x, y):
global bullet_state
bullet_state = "fire"
screen.blit(bullet, (x + 16, y + 10))
def has_collided(enemyX, enemyY, bulletX, bulletY):
distance = math.sqrt((math.pow(enemyX - bulletX, 2)) + (math.pow(enemyY - bulletY, 2)))
if distance < 27:
return True
else:
return False
def collided(enemyX, enemyY, playerX, playerY):
distance2 = math.sqrt((math.pow(enemyX - playerX, 2)) + (math.pow(enemyY - playerY, 2)))
if distance2 < 27:
return True
else:
return False
# game loop
running = True
while running:
# background round colour RGB
screen.fill((0, 0, 0))
# background image
screen.blit(background, (0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# If key pressed check whether its right or left
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player_changeX = -5
if event.key == pygame.K_RIGHT:
player_changeX = 5
if event.key == pygame.K_UP:
player_changeY = -5
if event.key == pygame.K_DOWN:
player_changeY = 5
# bullet shot
if event.key == pygame.K_SPACE:
if bullet_state == "ready":
bulletX = playerX
bulletY = playerY
fire_bullet(bulletX, bulletY)
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
player_changeX = 0
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
player_changeY = 0
# If player reaches boarder
if playerX >= 936:
playerX = 20
if playerX <= 0:
playerX = 936
if playerY <= 0:
playerY = 0
if playerY >= 550:
playerY = 550
# enemy control
for i in range(num_of_enemies):
if enemyX[i] >= 936:
enemyX[i] = 20
if enemyX[i] <= 0:
enemyX[i] = 936
if enemyY[i] <= 0:
enemyY[i] = 0
if enemyY[i] >= 550:
enemyY[i] = random.randint(-100, -50)
# collision bullet and enemy
collision = has_collided(enemyX[i], enemyY[i], bulletX, bulletY)
if collision:
bulletY = playerY
bulletX = playerX
bullet_state = "ready"
score += 1
print(score)
enemyX[i] = random.randint(0, 936)
enemyY[i] = random.randint(-100, -50)
enemy_changeX[i] = random.randint(-2, 2)
enemy_changeY[i] = random.randint(1, 2)
collision2 = collided(enemyX[i], enemyY[i], playerX, playerY)
if collision2:
screen.blit(game_over, (400, 100))
score = 0
playerY = 400
playerX = 500
enemy(enemyX[i], enemyY[i], i)
# bullet movement
if bullet_state == "fire":
fire_bullet(bulletX, bulletY)
bulletY -= bulletY_change
if bulletY <= 0:
bullet_state = "ready"
# collision enemy and player
# Player coordinates
playerX += player_changeX
playerY += player_changeY
# enemy change in coordinates
enemyX += enemy_changeX
enemyY += enemy_changeY
# bullet change in y
bulletY -= bulletY_change
# Results
player(playerX, playerY)
pygame.display.update()
The error seems pretty clear. You have this line in you code:
# multiple enemy players
enemy_icon = [i]
This line says that you are trying to create a variable enemy_icon and initialize it to a list with one element in it. That element is the variable i which has not been previously defined. I suspect that the i is a typo and that you are really trying to initialize with an empty list, in which case just remove the i like this:
# multiple enemy players
enemy_icon = []
The same is true for the 4 variables right after that.

Enemy Sprite is hit and disappears but is not fixed later if it was hit on the sides

I have a code solved for this issue Image does not remain on screen after executing for loop in pygame. So I decided to put some platforms as a result of what I learned from pygame. I also decided to make the cowboy move to the right and left and go down to the bottom of the screen.
But when a collision occurs on the right or left side of the cowboy as shown in the Diagram, the class PlayerShip is not executed as expected in the main loop through the def draw_reaction () function because I do not see the image of the cowboy represented by player_sprite fixed in position (60, 48). It only works correctly if the cowboy is hit from below.
Assets
missile.png
cowboy.png
police.png
Diagram:
|missile| <--<-- (is touched its right side by the missile)|cowboy| <--<-- direction
^
|
^
|
(fire missile direction vertical)
^
|
d
i
r
e
c
t
i
o
n
My MWE coding:
import pygame
import random
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
PURPLE = (255, 0, 255)
GRAY = (128,128,128)
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
class PlayerShip( pygame.sprite.Sprite ):
def __init__(self):
super().__init__()
self.image = pygame.image.load( "cowboy.png" )
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.rect.topleft = ( 60, 48 )
player_sprite = PlayerShip()
class Platform(pygame.sprite.Sprite):
def __init__(self, width, height):
super().__init__()
self.image = pygame.Surface([width, height])
self.image.fill(GREEN)
self.rect = self.image.get_rect()
class MovingPlatform(Platform):
change_x = 0
change_y = 0
boundary_top = 0
boundary_bottom = 0
boundary_left = 0
boundary_right = 0
player = None
level = None
def update(self):
self.rect.x += self.change_x
hit = pygame.sprite.collide_rect(self, self.player)
if hit:
if self.change_x < 0:
self.player.rect.right = self.rect.left
else:
self.player.rect.left = self.rect.right
self.rect.y += self.change_y
hit = pygame.sprite.collide_rect(self, self.player)
if hit:
if self.change_y < 0:
self.player.rect.bottom = self.rect.top
else:
self.player.rect.top = self.rect.bottom
if self.rect.bottom > self.boundary_bottom or self.rect.top < self.boundary_top:
self.change_y *= -1
cur_pos = self.rect.x - self.level.world_shift
if cur_pos < self.boundary_left or cur_pos > self.boundary_right:
self.change_x *= -1
class Level(object):
def __init__(self, player):
self.platform_list = pygame.sprite.Group()
self.enemy_list = pygame.sprite.Group()
self.player = player
self.background = None
self.world_shift = 0
self.level_limit = -1000
def update(self):
self.platform_list.update()
self.enemy_list.update()
def draw(self, screen):
screen.fill(GRAY)
self.platform_list.draw(screen)
self.enemy_list.draw(screen)
def shift_world(self, shift_x):
self.world_shift += shift_x
for platform in self.platform_list:
platform.rect.x += shift_x
for enemy in self.enemy_list:
enemy.rect.x += shift_x
class Room(object):
wall_list = None
enemy_sprites = None
def __init__(self):
self.wall_list = pygame.sprite.Group()
self.enemy_sprites = pygame.sprite.Group()
class Level_01(Level):
def __init__(self, player):
Level.__init__(self, player)
self.level_limit = -1500
level = [[210, 70, 500, 500],
[210, 70, 800, 400],
[210, 70, 1000, 500],
[210, 70, 1120, 280],
[210, 70, -120, 500],
]
for platform in level:
block = Platform(platform[0], platform[1])
block.rect.x = platform[2]
block.rect.y = platform[3]
block.player = self.player
self.platform_list.add(block)
block = MovingPlatform(70, 40)
block.rect.x = 1350
block.rect.y = 280
block.boundary_left = 1350
block.boundary_right = 1600
block.change_x = 10
block.player = self.player
block.level = self
self.platform_list.add(block)
class Level_02(Level):
def __init__(self, player):
Level.__init__(self, player)
self.level_limit = -1000
level = [[210, 70, 500, 550],
[210, 70, 800, 400],
[210, 70, 1000, 500],
[210, 70, 1120, 280],
]
for platform in level:
block = Platform(platform[0], platform[1])
block.rect.x = platform[2]
block.rect.y = platform[3]
block.player = self.player
self.platform_list.add(block)
block = MovingPlatform(70, 70)
block.rect.x = 1500
block.rect.y = 300
block.boundary_top = 100
block.boundary_bottom = 550
block.change_y = -1
block.player = self.player
block.level = self
self.platform_list.add(block)
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
width = 40
height = 60
self.image = pygame.image.load("police.png").convert()
self.rect = self.image.get_rect()
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.change_x = 0
self.change_y = 0
self.level = None
def update(self):
self.calc_grav()
self.rect.x += self.change_x
block_hit_list = pygame.sprite.spritecollide(self, self.level.platform_list, False)
for block in block_hit_list:
if self.change_x > 0:
self.rect.right = block.rect.left
elif self.change_x < 0:
self.rect.left = block.rect.right
self.change_y += 0
self.rect.y += self.change_y
block_hit_list = pygame.sprite.spritecollide(self, self.level.platform_list, False)
for block in block_hit_list:
if self.change_y > 0:
self.rect.bottom = block.rect.top
elif self.change_y < 0:
self.rect.top = block.rect.bottom
self.change_y = 0
if isinstance(block, MovingPlatform):
self.rect.x += block.change_x
def calc_grav(self):
if self.change_y == 0:
self.change_y = 1
else:
self.change_y += .35
if self.rect.y >= SCREEN_HEIGHT - self.rect.height and self.change_y >= 0:
self.change_y = 0
self.rect.y = SCREEN_HEIGHT - self.rect.height
def jump(self):
self.rect.y += 2
platform_hit_list = pygame.sprite.spritecollide(self, self.level.platform_list, False)
self.rect.y -= 2
if len(platform_hit_list) > 0 or self.rect.bottom >= SCREEN_HEIGHT:
self.change_y = -10
def go_left(self):
self.change_x = -6
def go_right(self):
self.change_x = 6
def stop(self):
self.change_x = 0
class Cowboy(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load("cowboy.png").convert()
self.rect = self.image.get_rect()
self.image.set_colorkey(BLACK)
class Missile(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load("missile.png").convert()
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
def update(self):
self.rect.y += -3
def main():
pygame.init()
size = [SCREEN_WIDTH, SCREEN_HEIGHT]
screen = pygame.display.set_mode(size)
block_list = pygame.sprite.Group()
all_sprites_list = pygame.sprite.Group()
bullet_list = pygame.sprite.Group()
pygame.display.set_caption("Platformer with moving platforms")
apple = pygame.image.load("missile.png").convert()
block = Cowboy()
player_image = pygame.image.load("cowboy.png").convert()
player = Player()
level_list = []
level_list.append(Level_01(player))
level_list.append(Level_02(player))
current_level_no = 0
current_level = level_list[current_level_no]
block_list.add(block)
all_sprites_list.add(block)
all_sprites_list.add(player)
active_sprite_list = pygame.sprite.Group()
player.level = current_level
player.rect.x = 340
player.rect.y = SCREEN_HEIGHT - player.rect.height
active_sprite_list.add(player)
done = False
clock = pygame.time.Clock()
x_speed = 0
y_speed = 0
rect_x = 50
rect_y = 50
rect_change_x = 1
rect_change_y = 90
x = rect_x
y = rect_y
player.rect.y = rect_x
player.rect.y = 480
score = 0
size = (1366, 768)
screen = pygame.display.set_mode(size, pygame.RESIZABLE)
while not done:
x += x_speed
y += y_speed
rect_x += rect_change_x
if rect_x > 280:
rect_change_x *= -1
rect_x += rect_change_x
rect_y += rect_change_y
if rect_x < 0:
rect_change_x *= -1
rect_x += rect_change_x
rect_y += rect_change_y
block.rect.x = rect_x
block.rect.y = rect_y
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.MOUSEBUTTONDOWN:
bullet = Missile()
bullet.rect.x = player.rect.x
bullet.rect.y = player.rect.y
all_sprites_list.add(bullet)
bullet_list.add(bullet)
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player.go_left()
if event.key == pygame.K_RIGHT:
player.go_right()
if event.key == pygame.K_UP:
player.jump()
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT and player.change_x < 0:
player.stop()
if event.key == pygame.K_RIGHT and player.change_x > 0:
player.stop()
for bullet in bullet_list:
block_hit_list = pygame.sprite.spritecollide(bullet, block_list, True)
for block in block_hit_list:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
score += 1
print(score)
screen.blit(player_image, [60, 48])
if bullet.rect.y < -10:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
def draw_reaction():
for bullet in bullet_list:
block_hit_list = pygame.sprite.spritecollide(bullet, block_list, True)
for block in block_hit_list:
all_sprites_list.add( player_sprite )
break
all_sprites_list.update()
active_sprite_list.update()
current_level.update()
if player.rect.right >= 1500:
diff = player.rect.right - 500
player.rect.right = 500
current_level.shift_world(-diff)
if player.rect.left <= 120:
diff = 120 - player.rect.left
player.rect.left = 120
current_level.shift_world(diff)
current_position = player.rect.x + current_level.world_shift
if current_position < current_level.level_limit:
if current_level_no < len(level_list)-1:
player.rect.x = 120
current_level_no += 1
current_level = level_list[current_level_no]
player.level = current_level
else:
done = True
current_level.draw(screen)
active_sprite_list.draw(screen)
x += x_speed
y += y_speed
all_sprites_list.draw(screen)
draw_reaction()
clock.tick(60)
pygame.display.flip()
pygame.quit()
if __name__ == "__main__":
main()
UPDATE EDIT: If current_level.draw(screen) is not used in the main loop then the code works as expected. But I still don't know what causes it.
I simply added all_sprites_list.add (player_sprite) to the for block in block_hit_list:. In my view this would be necessary to track self.image.get_rect (). Then:
Before:
for bullet in bullet_list:
block_hit_list = pygame.sprite.spritecollide(bullet, block_list, True)
for block in block_hit_list:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
score += 1
print(score)
screen.blit(player_image, [60, 48])
if bullet.rect.y < -10:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
Later:
for bullet in bullet_list:
block_hit_list = pygame.sprite.spritecollide(bullet, block_list, True)
for block in block_hit_list:
all_sprites_list.add(player_sprite)
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
score += 1
print(score)
screen.blit(player_image, [60, 48])
if bullet.rect.y < -10:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
But I would like someone to explain to me how it really happened behind the code by making more experienced references to the documentation or the style of the code itself. Thankful if anyone can make that explanation.