Problem creating new enemies when player levels up - pygame

i'm working on a simple clone of Space Invaders for an University project. The idea is that when the players levels up, the amount of enemies increase, but when i try to do it, the enemies creates infinitly while the stablished condition is true. I can't dettect the problem, so if one of you can help me, i'll apreciate it.
import random
import csv
import operator
import pygame
import time
from pygame import mixer
# Intialize the pygame
pygame.init()
# create the screen
screen = pygame.display.set_mode((800, 600))
# Background
background = pygame.image.load('background.png')
# Sound
mixer.music.load("background.wav")
mixer.music.play(-1)
#Reloj
clock = pygame.time.Clock()
# Caption and Icon
pygame.display.set_caption("Space Invader")
icon = pygame.image.load('ufo.png')
pygame.display.set_icon(icon)
# Score
score_value = 0
level_value = 1
level_up_value = ""
font = pygame.font.Font('freesansbold.ttf', 20)
game_over = False
high_scores = []
names = []
with open('high_scores.csv') as csvfile:
reader = csv.reader(csvfile)
sortedlist = sorted(reader, key=operator.itemgetter(1), reverse=True)
for i in sortedlist:
names.append(i[0])
high_scores.append(i[1])
scoreX = 10
scoreY = 10
level_textX = 10
level_textY = 80
levelX = 10
levelY = 40
# Game Over
over_font = pygame.font.Font('freesansbold.ttf', 64)
menu_font = pygame.font.Font('freesansbold.ttf', 48)
scores_font = pygame.font.Font('freesansbold.ttf', 45)
#Número de vidas
num_vidas = 3
font = pygame.font.Font('freesansbold.ttf', 32)
vidasX = 650
vidasY = 10
# Player
playerImg = pygame.image.load('player.png')
playerX = 370
playerY = 480
playerX_change = 0
# Enemy
enemyImg = []
bichoImg = []
meteoroImg = []
enemyX = []
enemyY = []
enemyY_change = []
bichoX = []
bichoY = []
bichoY_change = []
meteoroX = []
meteoroY = []
meteoroY_change = []
num_of_enemies_10 = 5
num_of_enemies_20 = 4
num_of_enemies_30 = 3
for i in range(num_of_enemies_10):
enemyImg.append(pygame.image.load('enemy.png'))
enemyX.append(random.randint(0, 736))
enemyY.append(random.randint(50, 150))
enemyY_change.append(0.5)
for i in range(num_of_enemies_20):
bichoImg.append(pygame.image.load('bicho.png'))
bichoX.append(random.randint(0, 736))
bichoY.append(random.randint(10, 120))
bichoY_change.append(0.5)
for i in range(num_of_enemies_30):
meteoroImg.append(pygame.image.load('meteoro.png'))
meteoroX.append(random.randint(0, 736))
meteoroY.append(random.randint(0, 150))
meteoroY_change.append(0.5)
# Bullet
# Ready - You can't see the bullet on the screen
# Fire - The bullet is currently moving
bulletImg = pygame.image.load('bullet.png')
bulletX = 0
bulletY = 480
bulletX_change = 0
bulletY_change = 10
bullet_state = "ready"
def show_score(x, y):
score = font.render("Score : " + str(score_value), True, (255, 255, 255))
screen.blit(score, (x, y))
def show_level(x, y):
level = font.render("Level: " + str(level_value), True, (255, 255, 255))
screen.blit(level, (x, y))
def level_up_text(x, y):
level_text = font.render(level_up_value, True, (255, 255, 0))
screen.blit(level_text, (level_textX, level_textY))
def show_vidas(x, y):
vidas = font.render("Vidas : " + str(num_vidas), True, (255, 255, 255))
screen.blit(vidas, (x, y))
def game_over_text():
over_text = over_font.render("GAME OVER", True, (255, 255, 255))
screen.blit(over_text, (200, 250))
def player(x, y):
screen.blit(playerImg, (x, y))
def enemy(x, y, i):
screen.blit(enemyImg[i], (x, y))
def bicho(x, y, i):
screen.blit(bichoImg[i], (x, y))
def meteoro(x, y, i):
screen.blit(meteoroImg[i], (x, y))
def fire_bullet(x, y):
global bullet_state
bullet_state = "fire"
screen.blit(bulletImg, (x + 16, y + 10))
#Colisiones para cada tipo de enemigo
def isCollision1(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 isCollision2(bichoX, bichoY, bulletX, bulletY):
distance = math.sqrt(math.pow(bichoX - bulletX, 2) + (math.pow(bichoY - bulletY, 2)))
if distance < 27:
return True
else:
return False
def isCollision3(meteoroX, meteoroY, bulletX, bulletY):
distance = math.sqrt(math.pow(meteoroX - bulletX, 2) + (math.pow(meteoroY - bulletY, 2)))
if distance < 27:
return True
else:
return False
# Pause Loop
def show_pause():
paused = True
while paused:
# RGB = Red, Green, Blue
screen.fill((0, 0, 0))
# Background Image
screen.blit(background, (0, 0))
pause_title = menu_font.render("PAUSED", True, (255, 255, 0))
pauseRect = pause_title.get_rect()
pauseRect.centerx = screen.get_rect().centerx
pauseRect.centery = screen.get_rect().centery - 50
screen.blit(pause_title, pauseRect)
high_title = menu_font.render("HIGH SCORES", True, (255, 255, 255))
highRect = high_title.get_rect()
highRect.centerx = screen.get_rect().centerx
highRect.centery = screen.get_rect().centery + 50
screen.blit(high_title, highRect)
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
paused = False
break
if event.type == pygame.MOUSEBUTTONDOWN:
mpos = pygame.mouse.get_pos()
if highRect.collidepoint(mpos):
show_high_scores_menu()
break
pygame.display.update()
# High Scores Loop
def show_high_scores_menu():
high_scores_menu = True
global high_scores, names
high_scores.clear()
names.clear()
with open('high_scores.csv') as csvfile:
reader = csv.reader(csvfile)
sortedlist = sorted(reader, key=operator.itemgetter(1), reverse=True)
for i in sortedlist:
names.append(i[0])
high_scores.append(i[1])
while high_scores_menu:
# RGB = Red, Green, Blue
screen.fill((0, 0, 0))
# Background Image
screen.blit(background, (0, 0))
high_title = menu_font.render("HIGH SCORES", True, (255, 255, 0))
highRect = high_title.get_rect()
highRect.centerx = screen.get_rect().centerx
highRect.centery = 100
screen.blit(high_title, highRect)
score1 = scores_font.render(names[0] + " : " + str(high_scores[0]), True, (255, 255, 255))
score1Rect = score1.get_rect()
score1Rect.centerx = screen.get_rect().centerx
score1Rect.centery = 250
screen.blit(score1, score1Rect)
score2 = scores_font.render(names[1] + " : " + str(high_scores[1]), True, (255, 255, 255))
score2Rect = score1.get_rect()
score2Rect.centerx = screen.get_rect().centerx
score2Rect.centery = 300
screen.blit(score2, score2Rect)
score3 = scores_font.render(names[2] + " : " + str(high_scores[2]), True, (255, 255, 255))
score3Rect = score3.get_rect()
score3Rect.centerx = screen.get_rect().centerx
score3Rect.centery = 350
screen.blit(score3, score3Rect)
score4 = scores_font.render(names[3] + " : " + str(high_scores[3]), True, (255, 255, 255))
score4Rect = score4.get_rect()
score4Rect.centerx = screen.get_rect().centerx
score4Rect.centery = 400
screen.blit(score4, score4Rect)
score5 = scores_font.render(names[4] + " : " + str(high_scores[4]), True, (255, 255, 255))
score5Rect = score1.get_rect()
score5Rect.centerx = screen.get_rect().centerx
score5Rect.centery = 450
screen.blit(score5, score5Rect)
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
high_scores_menu = False
show_pause()
break
pygame.display.update()
def save_high_scores():
# RGB = Red, Green, Blue
screen.fill((0, 0, 0))
# Background Image
screen.blit(background, (0, 0))
name = ""
while len(name) < 3:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.unicode.isalpha():
name += event.unicode
elif event.key == pygame.K_BACKSPACE:
name = name[:-1]
name = name.upper()
screen.fill((0, 0, 0))
screen.blit(background, (0, 0))
high_title = menu_font.render("High Score!", True, (255, 255, 0))
highRect = high_title.get_rect()
highRect.centerx = screen.get_rect().centerx
highRect.centery = 100
screen.blit(high_title, highRect)
inpt = font.render("Enter a 3-letter name", True, (255, 255, 255))
inptRect = inpt.get_rect()
inptRect.centerx = screen.get_rect().centerx
inptRect.centery = 200
screen.blit(inpt, inptRect)
namedisplay = menu_font.render(name, True, (255, 255, 255))
namedisplayRect = namedisplay.get_rect()
namedisplayRect.center = screen.get_rect().center
screen.blit(namedisplay, namedisplayRect)
pygame.display.update()
#replace lowest
lowest = high_scores[0]
lowest_index = 0
for i in range(len(high_scores)):
if high_scores[i] <= lowest:
lowest = high_scores[i]
lowest_index = i
high_scores[lowest_index] = score_value
names[lowest_index] = name
with open('high_scores.csv', 'w',newline='') as csvfile:
writer = csv.writer(csvfile)
for i in range(len(names)):
writer.writerow([str(names[i]), str(high_scores[i])])
show_high_scores_menu()
BLACK = (0, 0, 0)
#Agregar imágenes para explosión
explosión_anim = []
for i in range(9):
file = "Explosión/Explosión 0{}.png".format(i)
img = pygame.image.load(file).convert()
img.set_colorkey(BLACK)
img_scale = pygame.transform.scale(img, (70, 70))
explosión_anim.append (img_scale)
def explosión1():
image = explosión_anim[0]
center = image.get_rect()
frame = 0
last_update = pygame.time.get_ticks()
frame_rate = 50 #Velocidad de la explosión
screen.blit(image, (enemyX[i], enemyY[i]))
now = pygame.time.get_ticks()
if now - last_update > frame_rate:
last_update = now
frame += 1
if frame == len(explosión_anim):
kill()
else:
center = rect.center
image = explosión_anim[frame]
rect = image.get_rect()
rect.center = center
def explosión2():
image = explosión_anim[0]
center = image.get_rect()
frame = 0
last_update = pygame.time.get_ticks()
frame_rate = 50 #Velocidad de la explosión
screen.blit(image, (bichoX[i], bichoY[i]))
now = pygame.time.get_ticks()
if now - last_update > frame_rate:
last_update = now
frame += 1
if frame == len(explosión_anim):
kill()
else:
center = rect.center
image = explosión_anim[frame]
rect = image.get_rect()
rect.center = center
def explosión3():
image = explosión_anim[0]
center = image.get_rect()
frame = 0
last_update = pygame.time.get_ticks()
frame_rate = 50 #Velocidad de la explosión
screen.blit(image, (meteoroX[i], meteoroY[i]))
now = pygame.time.get_ticks()
if now - last_update > frame_rate:
last_update = now
frame += 1
if frame == len(explosión_anim):
kill()
else:
center = rect.center
image = explosión_anim[frame]
rect = image.get_rect()
rect.center = center
# Game Loop
en_partida = True
while en_partida:
clock.tick(60)
en_final = False
# RGB = Red, Green, Blue
screen.fill((0, 0, 0))
# Background Image
screen.blit(background, (0, 0))
# if player levels up
if score_value < 40:
level_value = 1
elif score_value <= 80:
level_value = 2
elif score_value <= 120:
level_value = 3
elif score_value <= 160:
level_value = 4
if (score_value >= 40 and score_value <= 42):
level_up_value = "LEVEL UP!"
elif (score_value >= 80 and score_value <= 82):
level_up_value = "LEVEL UP!"
elif (score_value >= 120 and score_value <= 122):
level_up_value = "LEVEL UP!"
else:
level_up_value = ""
for event in pygame.event.get():
if event.type == pygame.QUIT:
en_partida = False
# if keystroke is pressed check whether its 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":
bulletSound = mixer.Sound("laser.wav")
bulletSound.play()
# Get the current x cordinate of the spaceship
bulletX = playerX
fire_bullet(bulletX, bulletY)
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
playerX_change = 0
# 5 = 5 + -0.1 -> 5 = 5 - 0.1
# 5 = 5 + 0.1
playerX += playerX_change
if playerX <= 0:
playerX = 0
elif playerX >= 736:
playerX = 736
# Enemy Movement
for i in range(num_of_enemies_10):
# Game Over
enemyY[i] += enemyY_change[i]
if enemyY[i] > 440:
for j in range(num_of_enemies_10):
enemyY[j] = 2000
game_over_text()
break
for i in range(num_of_enemies_20):
# Game Over
bichoY[i] += bichoY_change[i]
if bichoY[i] > 440:
for j in range(num_of_enemies_20):
bichoY[j] = 2000
game_over_text()
break
for i in range(num_of_enemies_30):
# Game Over
meteoroY[i] += meteoroY_change[i]
if meteoroY[i] > 440:
for j in range(num_of_enemies_30):
meteoroY[j] = 2000
game_over_text()
break
# Collision
collision1 = isCollision1(enemyX[i], enemyY[i], bulletX, bulletY)
collision2 = isCollision2(bichoX[i], bichoY[i], bulletX, bulletY)
collision3 = isCollision3(meteoroX[i], meteoroY[i], bulletX, bulletY)
enemy(enemyX[i], enemyY[i], i)
bicho(bichoX[i], bichoY[i], i)
meteoro(meteoroX[i], meteoroY[i], i)
if collision1:
explosionSound = mixer.Sound("explosion.wav")
explosionSound.play()
explosión1()
bulletY = 480
bullet_state = "ready"
score_value += 10
num_of_enemies_10 -= 1
if collision2:
explosionSound = mixer.Sound("explosion.wav")
explosionSound.play()
explosión2()
bulletY = 480
bullet_state = "ready"
score_value += 20
num_of_enemies_20 -= 1
if collision3:
explosionSound = mixer.Sound("explosion.wav")
explosionSound.play()
explosión3()
bulletY = 480
bullet_state = "ready"
score_value += 30
num_of_enemies_30 -= 1
#Aumento de enemigos por nivel
enemy_created = False
flag = False
if(level_value == 2 and flag == True):
flag = True
enemyX[i] = random.randint(0,736)
enemyY[i] = random.randint(50,150)
enemy(enemyX[i], enemyY[i], i)
enemy_created = True
# Bullet Movement
if bulletY <= 0:
bulletY = 480
bullet_state = "ready"
if bullet_state == "fire":
fire_bullet(bulletX, bulletY)
bulletY -= bulletY_change
player(playerX, playerY)
show_score(scoreX, scoreY)
show_level(levelX, levelY)
level_up_text(levelX + 100, levelY)
show_vidas(vidasX, vidasY)
pygame.display.update()
pygame.quit()

Set the flag before the game loop:
# Game Loop
flag = True # set flag here
en_partida = True
while en_partida:
clock.tick(60)
....................
#Aumento de enemigos por nivel
enemy_created = False
if(level_value == 2 and flag == True): # check flag
flag = False # reset flag
enemyX[i] = random.randint(0,736)
enemyY[i] = random.randint(50,150)
enemy(enemyX[i], enemyY[i], i)
enemy_created = True

Related

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.

PyGame surface locked during blit [duplicate]

I am trying to draw text to a screen in a space above a bunch of rects that are all in the 2d array square. When i try and draw text to the screen it says that "Surfaces must not be locked during blit."
I have tried unlocking, it makes no difference.
import sys, time, random, pygame
from pygame import *
from time import time,sleep
pygame.init()
global isDragging, inDrag, rightDrag, lastDrag, inDragRight, mouseX,mouseY, borderHeight
isDragging = False
isAuto = False
inDrag= False
inDragRight = False
isFilling = False
done = False
lastDrag = None
rightDrag = None
tickTime = 300
font = pygame.font.SysFont(None, 12,False,False)
dragDelay = 2
BLACK = ( 0, 0, 0)
WHITE = ( 255, 255, 255)
GREEN = ( 0, 255, 0)
RED = ( 255, 0, 0)
PINK = ( 255, 150, 200)
BLUE = ( 0, 0, 255)
RED = GREEN
width, height, margin = 100, 100, 1
noWidth, noHeight = 6,6
speed = [2, 2]
borderHeight = 50
size = (width*noWidth,height*noHeight + borderHeight)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("PieStone")
clock = pygame.time.Clock()
pixArray = pygame.PixelArray(screen)
font = pygame.font.SysFont("monospace", 15)
word = font.render("test", 1, (0, 0, 0))
class Null:
pass
square = [[Null() for i in range(noHeight)]for i in range(noWidth)]
for d1 in range(noWidth):
for d2 in range(noHeight):
square[d1][d2].man = False
square[d1][d2].visits = 0
square[d1][d2].colour = BLACK
square[d1][d2].margin = 1
a = 1
i = 1
def text(word,size,pos1,pos2,pos3):
word = font.render(str(word),size,(pos1,pos2,pos3))
return word
def colide(obj,mouseX,mouseY):
if obj.collidepoint(mouseX,mouseY) == 1:
return True
else:
return False
def click(mouseX,mouseY):
#rint("left")
global inDrag,lastDrag
for d1 in range(noWidth):
for d2 in range(noHeight):
if colide(square[d1][d2].rect,mouseX,mouseY):
square[d1][d2].man = True
#print("square",d1,d2,"has been clicked")
try:
if square[d1][d2] != lastDrag:
inDrag = True
lastDrag = square[d1][d2]
else:
inDrag = False
except UnboundLocalError:
print("error")
lastDrag = square[d1][d2]
#print(inDrag)
if square[d1][d2].margin == 0 and inDrag:
square[d1][d2].margin = 1
square[d1][d2].visits = square[d1][d2].visits + 1
elif square[d1][d2].margin == 1 and inDrag:
square[d1][d2].margin = 0
square[d1][d2].visits = square[d1][d2].visits + 1
break
'''if square[d1][d2].visits >= 5 and square[d1][d2].colour == BLACK:
square[d1][d2].visits = 0
square[d1][d2].colour = RED
elif square[d1][d2].visits >= 5 and square[d1][d2].colour == RED:
square[d1][d2].visits = 0
square[d1][d2].colour = BLACK'''
def rightClick(mouseX,mouseY):
#print("right")
global inDragRight, lastRight
for d1 in range(noWidth):
for d2 in range(noHeight):
if colide(square[d1][d2].rect,mouseX,mouseY):
square[d1][d2].man = True
#print("colide")
try:
if square[d1][d2] != lastRight:
inDragRight = True
lastRight = square[d1][d2]
else:
inDragRight = False
except:
print("error")
lastRight = square[d1][d2]
#print(inDragRight)
if square[d1][d2].colour == RED and inDragRight:
square[d1][d2].colour = BLACK
#print("black")
elif square[d1][d2].colour == BLACK and inDragRight:
square[d1][d2].colour = RED
#print("red")
break
while not done:
screen.blit(word, (0, 0))
(mouseX,mouseY) = pygame.mouse.get_pos()
#print(str(mouseX)+",",mouseY)
for event in pygame.event.get(): # User did something
if event.type == pygame.QUIT: # If user clicked close
done = True # Flag that we are done so we exit this loop
elif event.type == pygame.MOUSEBUTTONDOWN:
#print(mouseX,mouseY)
if pygame.mouse.get_pressed()[0] == 1:
isDragging = True
if pygame.mouse.get_pressed()[2] == 1:
isFilling = True
elif pygame.mouse.get_pressed()[1] == 1:
isAuto = True
#print(pygame.mouse.get_pressed())
elif event.type == pygame.MOUSEBUTTONUP:
#print("up")
isDragging = False
isFilling = False
lastDrag = None
lastRight = False
if pygame.mouse.get_pressed()[0] == 1:
isDragging = True
if pygame.mouse.get_pressed()[2] == 1:
isFilling = True
if isAuto:
rnd1 = random.randint(0,1)
if rnd1 == 1:
isDragging = True
isFilling = False
else:
isDragging = False
isFilling = True
(mouseX,mouseY) = (random.randint(0,width*noWidth),random.randint(0,height*noHeight)+borderHeight)
#print(mouseX,mouseY)
if isDragging:
click(mouseX,mouseY)
if isFilling:
rightClick(mouseX,mouseY)
screen.fill(WHITE)
# --- Game logic should go here
i = 0
for d1 in range(noWidth):
if noHeight % 2 == 0:
'''if i == 0:
i = 1
else:
i = 0'''
for d2 in range(noHeight):
#if i % a == 0:
try:
if i == 0:
pass
elif i == 1:
pass
except AttributeError:
print("AttributeError")
square[d1][d2].margin = random.randint(0,1)
#print(square[d1][d2].visits)
square[d1][d2].rect = pygame.draw.rect(screen, square[d1][d2].colour, [(d1*width), ((d2*height)+borderHeight),width,(height)],square[d1][d2].margin)
#print("d1*width:",d1*width,"d2*height:",d2*height,"d1*width+width:",d1*width+width,"d2*height+height:",d2*height+height)
pygame.display.flip()
clock.tick(tickTime)
# Close the window and quit.
# If you forget this line, the program will 'hang'
# on exit if running from IDLE.
pygame.quit()
You're using a PixelArray:
pixArray = pygame.PixelArray(screen)
But using a PixelArray locks your Surface, as stated in the documentation:
During its lifetime, the PixelArray locks the surface, thus you explicitly have to delete it once its not used anymore and the surface should perform operations in the same scope.
Just remove the line, since you're not using it anyway.

The continue button doesn't work when the game is paused

I have made a game where you have to dodge objects. You can also pause the game by pressing p. Once you pause the game you get an option if you want to continue or quit. For me, the quit button is working but the continue button isn't. Where it says define unpause() is where the code starts for the pause button.
import time
import random
pygame.init()
display_width = 800
display_height = 600
red = (200,0,0)
orange = (255, 165, 0)
yellow = (255, 242, 0)
green = (0,200,0)
blue = (0,0,255)
indigo = (75, 0, 130)
violet = (238, 130, 238)
black = (0,0,0)
white = (255,255,255)
bright_red = (255,0,0)
bright_green = (0,255,0)
car_width = 86
gameDisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption("Racing Game")
clock = pygame.time.Clock()
carImg = pygame.image.load("download.png")
carImg = pygame.transform.scale(carImg,(100,160))
pause = False
def things_dodged(count):
font = pygame.font.SysFont(None, 25)
text = font.render ("Dodged: "+str(count), True, black)
gameDisplay.blit(text,(0,0))
def things(thingx, thingy, thingw, thingh, color):
pygame.draw.rect(gameDisplay, color, [thingx, thingy, thingw, thingh])
def car(x,y):
gameDisplay.blit(carImg, (x,y))
def text_objects(text, font):
textSurface = font.render(text, True, black)
return textSurface, textSurface.get_rect()
def message_display(text):
largeText = pygame.font.Font("freesansbold.ttf",100)
TextSurf, TextRect = text_objects(text, largeText)
TextRect.center = ((display_width/2),(display_height/2))
gameDisplay.blit(TextSurf, TextRect)
pygame.display.update()
game_loop()
time.sleep(2000)
def crash():
message_display ("YOU CRASHED")
def button(msg,x,y,w,h,ic,ac,action = None):
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
print(click)
if x + w > mouse [0] > x and y + h > mouse [1] > y:
pygame.draw.rect(gameDisplay, ac, (x,y,w,h))
if click[0] == 1 and action != None:
if action == "play":
game_loop()
elif action == "quit":
pygame.quit()
quit()
else:
pygame.draw.rect(gameDisplay, ic, (x,y,w,h))
smallText = pygame.font.Font("freesansbold.ttf",20)
textSurf, textRect = text_objects(msg, smallText)
textRect.center = ( (x+(w/2)), (y+(h/2)) )
gameDisplay.blit(textSurf, textRect)
def quitgame():
pygame.quit()
quit
def unpause():
global pause
pause = False
def paused():
while paused:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
gameDisplay.fill(white)
largeText = pygame.font.Font("freesansbold.ttf",100)
TextSurf, TextRect = text_objects("PAUSED", largeText)
TextRect.center = ((display_width/2),(display_height/2))
gameDisplay.blit(TextSurf, TextRect)
button ("Continue!",150,450,100,50,green,bright_green,unpause)
button ("Quit!",550,450,100,50,red,bright_red,"quit")
pygame.display.update()
clock.tick(15)
def game_intro():
intro = True
while intro:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
gameDisplay.fill(white)
largeText = pygame.font.Font("freesansbold.ttf",100)
TextSurf, TextRect = text_objects("Racing Game", largeText)
TextRect.center = ((display_width/2),(display_height/2))
gameDisplay.blit(TextSurf, TextRect)
button ("GO!",150,450,100,50,green,bright_green,"play")
button ("QUIT!",550,450,100,50,red,bright_red,"quit")
pygame.display.update()
clock.tick(15)
def game_loop():
global pause
x = (display_width * 0.45)
y = (display_height * 0.72)
x_change = 0
thing_startx = random.randrange(0, display_width)
thing_starty = -600
thing_speed = 7
thing_width = 100
thing_height = 100
thingCount = 1
dodged = 0
gameExit = False
while not gameExit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = -5
if event.key == pygame.K_RIGHT:
x_change = 5
if event.key == pygame.K_p:
pause = True
paused()
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
x += x_change
gameDisplay.fill(white)
things(thing_startx, thing_starty, thing_width, thing_height, black)
thing_starty += thing_speed
car (x,y)
things_dodged(dodged)
if x > display_width - car_width or x < -10:
crash()
if thing_starty > display_height:
thing_starty = 0 - thing_height
thing_startx = random.randrange(0,display_width)
dodged += 1
thing_speed += 1
#thing_width += (dodged * 0.5)
if y < thing_starty + thing_height:
if x > thing_startx and x < thing_startx + thing_width or x + car_width > thing_startx and x + car_width < thing_startx + thing_width:
crash()
pygame.display.update()
clock.tick(100)
game_intro()
game_loop()
pygame.quit()
quit()
Please try to help. I am saying Thank You in advance for all your guy's help.
You have typo in while paused: in def paused()- it has to be while pause:
def paused():
while pause: # <- pause instead of paused