what is Not BytesIO? - python

I'm kind of new to this site and pygame and I was hoping for a bit of help. So I made this space invader clone which is about 180 lines right, when I run it on Pycharm, it works fine. So I decided to try testing it out further and tried converting it into an .exe file which is where my troubles began. Every time I try running the .exe, this message appears
Traceback (most recent call last):
File "main.py", line 62, in <module>
font = pygame.font.Font('freesansbold.ttf',32)
TypeError: expected str, bytes or os.PathLike object, not BytesIO
I used freeCodeCamp.org's template and applied my own customs, here's a video incase you're interested: https://www.youtube.com/watch?v=FfWpgLFMI7w&t=7041s
Here's the code as well:
import math
import random
import pygame
from pygame import mixer
# Initialize the pygame
pygame.init()
# Create the screen
screen = pygame.display.set_mode((600, 400))
# Background Sound
mixer.music.load('Here he comes.mp3')
mixer.music.play(-1)
# Title and icon
pygame.display.set_caption("Defender of The Blue")
icon = pygame.image.load("Submarine of Vengeance.png")
pygame.display.set_icon(icon)
# Player
playerImg = pygame.image.load('Protagonist.png')
playerX = 250
playerY = 300
playerX_change = 0
# Enemy
enemyImg = []
enemyX = []
enemyY = []
enemyX_change = []
enemyY_change = []
num_of_enemies = 6
for i in range(num_of_enemies):
enemyImg.append(pygame.image.load('Antagonist.png'))
enemyX.append(random.randint(0, 500))
enemyY.append(random.randint(10, 100))
enemyX_change.append(0.1)
enemyY_change.append(20)
# Energy Blast
# Ready - You can't see the bullet state on the screen
# Fire - The blast is currently moving
energyblastImg = pygame.image.load('energy-blasts.png')
energyblastX = 0
energyblastY = 300
energyblastX_change = 0
energyblastY_change = 1
energyblast_state = "ready"
# score
score_value = 0
font = pygame.font.Font('freesansbold.ttf',32)
textX = 10
textY = 10
game_over_font = pygame.font.Font('freesansbold.ttf',50)
# Game Over Text
def show_score(x,y):
score = font.render("Score :" + str(score_value),True, (250,100,0))
screen.blit(score, (x, y))
def game_over_text():
game_over_text = game_over_font.render("GAME OVER",True, (250,0,0))
screen.blit(game_over_text, (150, 100))
def player(x, y):
screen.blit(playerImg, (x, y))
def enemy(x, y, i):
screen.blit(enemyImg[i], (x, y))
def fire_energyblast(x, y):
global energyblast_state
energyblast_state = "fire"
screen.blit(energyblastImg, (x + -1, y + 10))
def isCollison(enemyX, enemyY, energyblastX, energyblastY):
distance = math.sqrt((math.pow(enemyX - energyblastX, 2)) + (math.pow(enemyY - energyblastY, 2)))
if distance < 27:
return True
else:
return False
# Game Loop
running = True
while running:
# RGB = Red, Green, Blue
screen.fill((0, 0, 128))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# if keystroke is pressed check whether its right or left
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerX_change = -1
if event.key == pygame.K_RIGHT:
playerX_change = 1
if event.key == pygame.K_SPACE:
if energyblast_state is "ready":
energyblast_sound = mixer.Sound('Energy Blast.mp3')
energyblast_sound.play()
# Get the current x coordinate of the submarine
energyblastX = playerX
fire_energyblast(energyblastX, energyblastY)
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
# Checking for boundaries of submarine so it doesn't go out of bounds
playerX += playerX_change
if playerX <= 0:
playerX = 0
elif playerX >= 500:
playerX = 500
# enemy movement
for i in range(num_of_enemies):
# Game Over
if enemyY[i] > 272:
for j in range(num_of_enemies):
enemyY[j] = 2000
game_over_text()
break
enemyX[i] += enemyX_change[i]
if enemyX[i] <= 0:
enemyX_change[i] = 1
enemyY[i] += enemyY_change[i]
elif enemyX[i] >= 500:
enemyX_change[i] = -1
enemyY[i] += enemyY_change[i]
# Collision
collison = isCollison(enemyX[i], enemyY[i], energyblastX, energyblastY)
if collison:
explosion_Sound = mixer.Sound('Explode.mp3')
explosion_Sound.play()
energyblastY = 300
energyblast_state = "ready"
score_value += 50
enemyX[i] = random.randint(0, 500)
enemyY[i] = random.randint(10, 100)
enemy(enemyX[i],enemyY[i], i)
# energy blast movement
if energyblastY <= 0:
energyblastY = 300
energyblast_state = "ready"
if energyblast_state is "fire":
fire_energyblast(energyblastX, energyblastY)
energyblastY -= energyblastY_change
player(playerX, playerY)
show_score(textX,textY)
pygame.display.update()
I'm not quite sure what BytesIO is. Is it like having something used twice and cancels out? How can I change this?

Are you certain that "freesansbold.ttf" is downloaded and in the same directory as the code youre trying to run, if this isnt possible for whatever reason you should be able to replace the
font = pygame.font.Font('freesansbold.ttf',32)
with
font = pygame.font.Font('(file path)freesansbold.ttf',32)

Related

How to add game restart in this pgame code? [duplicate]

This question already has answers here:
how restarting game on pygame works
(1 answer)
Pygame restart function
(2 answers)
In game loop, how do I restart game properly using nested class or loop?
(1 answer)
Reset and restart pygame program doesn't work
(1 answer)
Closed 3 months ago.
I followed a tutorial guide on how to make this game but they never said how to put in a restart. I'm not quite sure how to do it, would anyone here know off the top of their head? Here's the code.
import pygame
import math
import random
from pygame import mixer
# Start the Program
pygame.init()
# Create the Screen
screen = pygame.display.set_mode((800, 600))
running = True
# Background
background = pygame.image.load('background.png')
# Background Sound
mixer.music.load('theme.mp3')
mixer.music.play(-1)
# Title and Icon
pygame.display.set_caption("Boot Craft")
icon = pygame.image.load('Starcraft.png')
pygame.display.set_icon(icon)
# Player
player_image = pygame.image.load('BC.png')
playerX = 370
playerY = 480
playerX_change = 0
playerY_change = 0
# Enemy
enemy_image = []
enemyX = []
enemyY = []
enemyX_change = []
enemyY_change = []
num_of_enemies = 6
for i in range(num_of_enemies):
enemy_image.append(pygame.image.load('Zergling.png'))
enemyX.append(random.randint(0, 768))
enemyY.append(random.randint(50, 150))
enemyX_change.append(0.2)
enemyY_change.append(40)
# Bullet
# Ready - You can't see the bullet on the screen
# Fire - The bullet is currently moving
bullet_image = pygame.image.load('Bullet.png')
bulletX = 0
bulletY = 480
bulletX_change = 0
bulletY_change = .5
bullet_state = "ready"
# Score
score_value = 0
font = pygame.font.Font('freesansbold.ttf', 32)
textX = 10
textY = 10
# Game Over
over_font = pygame.font.Font('freesansbold.ttf', 64)
def show_score(x,y):
score = font.render('Score: ' + str(score_value), True, (255,255,255))
screen.blit(score, (x, y))
def game_over_text():
over_text = over_font.render('GAME OVER', True, (255, 255, 255))
continue_text = over_font.render('CONTINUE? Y/N', True, (255, 255, 255))
screen.blit(over_text, (200, 250))
screen.blit(continue_text, (160, 350))
def player(x, y):
screen.blit(player_image, (x, y))
def enemy(x, y, i):
screen.blit(enemy_image[i], (x, y))
def fire_bullet(x, y):
global bullet_state
bullet_state = "fire"
screen.blit(bullet_image, (x + 8, y + 10))
def isCollision(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
# Game Loop - Runs Game
while running:
# RGB Color Values 0-255
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 event.type == pygame.KEYDOWN:
if event.key == pygame.K_y:
running = True
# Check Key pressed.
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT or event.key == pygame.K_a:
playerX_change = -0.2
if event.key == pygame.K_RIGHT or event.key == pygame.K_d:
playerX_change = 0.2
if event.key == pygame.K_SPACE:
if bullet_state == "ready":
bullet_sound = mixer.Sound('laser.wav')
bullet_sound.play()
# Get the current X coordinate of the spaceship
bulletX = playerX
fire_bullet(bulletX, bulletY)
# Check Key released.
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT or event.key == pygame.K_a or event.key == pygame.K_d:
playerX_change = 0
playerX += playerX_change
# Adds Boundary
if playerX <= 0:
playerX = 0
elif playerX >= 721:
playerX = 721
# Enemy Movement
for i in range(num_of_enemies):
# Game Over
if enemyY[i] > 440:
for j in range(num_of_enemies):
enemyY[j] = 2000
game_over_text()
enemyX[i] += enemyX_change[i]
if enemyX[i] <= 0:
enemyX_change[i] = 0.2
enemyY[i] += enemyY_change[i]
elif enemyX[i] >= 768:
enemyX_change[i] = -0.2
enemyY[i] += enemyY_change[i]
# Collision
collision = isCollision(enemyX[i],enemyY[i],bulletX,bulletY)
if collision:
explosion_sound = mixer.Sound('explode.wav')
explosion_sound.play()
bulletY = 480
bullet_state = "ready"
score_value += 1
enemyX[i] = random.randint(0, 768)
enemyY[i] = random.randint(50, 150)
enemy(enemyX[i], enemyY[i], i)
# 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(textX, textY)
pygame.display.update()
I'm not sure what to try, as what I googled used different ways of running the game. New to this, so genuinely confused.

Pygame displays a black screen

I did some research to see if I could fix my problem on my own but it has been fruitless so far. I've checked to see if I ran the .display command too much but I haven't, the program will run without error but the screen appears black except when I close the window out, you can catch a glimpse of what it is supposed to display. Any insight into what is wrong? Help is greatly appreciated!
import math
import random
import pygame
from pygame import mixer
# Initialize the pygame
pygame.init()
# create the screen
screen = pygame.display.set_mode((800, 600))
# Background
background = pygame.image.load('space background.png')
# Background Sound
# come back to this from bg music 'mixer.music.load('insert file name')'
# mixer.music.play(-1)
# Title and Icon
pygame.display.set_caption("Space Invaders")
icon = pygame.image.load('ufo.png')
pygame.display.set_icon(icon)
# Player
playerImg = pygame.image.load('ship.png')
playerX = 370
playerY = 480
playerX_change = 0
# Enemy
enemyImg = []
enemyX = []
enemyY = []
enemyX_change = []
enemyY_change = []
num_of_enemies = 6
for i in range(num_of_enemies):
enemyImg.append(pygame.image.load('enemy.png'))
enemyX.append(random.randint(0, 735))
enemyY.append(random.randint(50, 150))
enemyX_change.append(0.3)
enemyY_change.append(40)
# Bullet
# Ready - you cat 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 = 1 # Bullet speed
bullet_state = "ready"
# Score
score_value = 0
font = pygame.font.Font('Minecraft.ttf', 24)
textX = 10
testY = 10 # might have to change back to 'text'
# Game Over text
over_font = pygame.font.Font('Minecraft.ttf', 64)
def show_score(x, y):
score = font.render("Score : " + str(score_value), True, (225, 225, 255))
screen.blit(score, (x, y))
def game_over_text(x, y):
over_text = over_font.render("GAME OVER", True, (225, 225, 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 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(enemyY - bulletY, 2))
if distance < 27:
return True
else:
return False
# Game Loop
running = True
while running:
# 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 keystroke is pressed check whether its right or left
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerX_change = -0.7 # player speed
if event.key == pygame.K_RIGHT:
playerX_change = 0.7
if event.key == pygame.K_SPACE:
if bullet_state == "ready":
bullet_Sound = mixer.Sound('laser.wav')
bullet_Sound.play()
# Get the current X corrdinate of te spaceship
bulletX = playerX
fire_bullet(playerX, 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
# Checking for boundries of spaceship
playerX += playerX_change
if playerX <= 0:
playerX = 0
elif playerX >= 736:
playerX = 736
# Enemy Movement
for i in range(num_of_enemies):
# Game over
if enemyY[i] > 440:
for j in range(num_of_enemies):
enemyY[j] = 2000
game_over_text()
break
enemyX[i] += enemyX_change[i]
if enemyX[i] <= 0:
enemyX_change[i] = 0.3 # enemy speed
enemyY[i] += enemyY_change[i]
elif enemyX[i] >= 736:
enemyX_change[i] = -0.3
enemyY[i] += enemyY_change[i]
# Collision
collision = iscollision(enemyX[i], enemyY[i], bulletX, bulletY)
if collision:
explosion_Sound = mixer.Sound('explosion.wav')
explosion_Sound.play()
bulletY = 480
bullet_state = "ready"
score_value += 100
enemyX[i] = random.randint(0, 736)
enemyY[i] = random.randint(50, 150)
enemy(enemyX[i], enemyY[i], i)
# 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(textX, testY)
pygame.display.update()
All you have to do is indent the last bit of code (the 11 lines under the comment Bullet Movement) one level in. Right now, it's not under the while loop, which explains why the screen is black and why it only appears after you click the close button (which exits the loop and executes the drawing code). Hope this helps!

Pygame Images won't load in after being called

I've been trying to make Space Invaders using PyGame in Python and make a list for the enemy images, and I make a for loop twice to load the images in and append them to the lists; 2 times for 2 rows. Though, the only pictures that appear are the ones from the first for loop.
There are no errors either, so it seems it is working. I also checked to see if the two rows were overlapping each other, but from the way I tested it, I found that they weren't.
I made this before here without using OOP and now I'm using OOP to learn it better, and it isn't working properly, please help.
For Loops Below
EnemyRowBottom = EnemyClass()
EnemyRowTop = EnemyClass()
for i in range(EnemyRowBottom.numEnemies):
EnemyImage1 = pygame.image.load('enemy.png')
EnemyRowBottom.EnemyImage.append( pygame.transform.scale(EnemyImage1, (70, 70)) )
y = i * 10
x = y * 10
EnemyRowBottom.EnemyX.append( x )
EnemyRowBottom.EnemyY.append( 150 )
for i in range(EnemyRowTop.numEnemies):
EnemyImage1 = pygame.image.load('enemy.png')
EnemyRowTop.EnemyImage.append( pygame.transform.scale(EnemyImage1, (70, 70)) )
y = i * 10
x = y * 10
EnemyRowTop.EnemyX.append( x )
EnemyRowTop.EnemyY.append( 50 )
Full Code below
import pygame
import random
import math
from pygame import mixer
import time
# initialize pygame
pygame.init()
# create screen
screenX = 800
screenY = 800
screen = pygame.display.set_mode( (screenX, screenY) )
# background
background = pygame.image.load("background.jpg")
#sounds
mixer.music.load('bgMusic.mp3')
mixer.music.play(-1)
# title and icon
pygame.display.set_caption("Space Invaders")
icon = pygame.image.load('Icon.jpg')
pygame.display.set_icon(icon)
# score
scoreValue = 0
font = pygame.font.Font('freesansbold.ttf', 32)
textX = 10
textY = 10
def show_score(x, y):
global scoreValue
score = font.render("Score: " + str(scoreValue), True, (255, 255, 255))
screen.blit(score, (x, y))
# player
PlayerImage = pygame.image.load('SpaceShip.png')
PlayerImage = pygame.transform.scale(PlayerImage, (84, 84))
playerX = 370
playerY = 650
xChangePlayer = 0
def player(x, y):
screen.blit(PlayerImage, (x, y))
# check collision
def Collision(EX, EX2, EY, EY2, LX, LY):
distance = math.sqrt((math.pow(EX - LX, 2) + math.pow(EY - LY, 2)))
distance2 = math.sqrt((math.pow(EX2 - LX, 2) + math.pow(EY2 - LY, 2)))
if distance <= 35:
return 1
elif distance2 <= 35:
return 2
def DistanceEnemy(EX, EX2, EY, EY2):
distance = math.sqrt((math.pow(EX2 - EX, 2) + math.pow(EY2 - EY, 2)))
if distance <= 70:
return True
# bottom line
Line = pygame.image.load('BottomLine.jpg')
LineX = 0
LineY = 655
def BottomLine(x, y):
global Line
screen.blit(Line, (x, y))
# Laser
LaserImage = pygame.image.load('PlayerLaser.png')
LaserImage = pygame.transform.scale(LaserImage, (50, 50))
LaserX = random.randint(15, (screenX - 85) )
LaserY = 750
xLaserChange = 0
yLaserChange = 1
# can't see bullet on screen until Ready changes to Fire
LaserState = "Ready"
def Firelaser(x, y):
global LaserState
LaserState = "Fire"
screen.blit(LaserImage, (x+17, y+10))
GameOverfont = pygame.font.Font('freesansbold.ttf', 82)
def GameOver():
global GameOverfont
text = GameOverfont.render("GAME OVER", True, (255, 255, 255))
screen.blit(text, (140, 250))
# enemy
class EnemyClass:
EnemyImage = []
EnemyX = []
EnemyY = []
numEnemies = 4
xEnemyChange = 0.2
yEnemyChange = 50
def enemyMovement(self, i):
EnemyClass.EnemyX[i] += EnemyClass.xEnemyChange
if EnemyClass.EnemyX[i] >= 736:
EnemyClass.xEnemyChange = -EnemyClass.xEnemyChange
for x in range(len(EnemyClass.EnemyY)):
EnemyClass.EnemyY[x] += EnemyClass.yEnemyChange
elif EnemyClass.EnemyX[i] <= 0:
EnemyClass.xEnemyChange = .2
for x in range(len(EnemyClass.EnemyY)):
EnemyClass.EnemyY[x] += EnemyClass.yEnemyChange
def enemy(self, i):
screen.blit(EnemyClass.EnemyImage[i], (EnemyClass.EnemyX[i], EnemyClass.EnemyY[i]))
def enemyGameOver(self, x, y):
screen.blit(EnemyClass.EnemyImage[i], (x, y))
def CollisionDetection(self, i, scoreValue, lasery, laserstate):
global LaserY, LaserState
ExplosionSound = mixer.Sound('explosion.wav')
ExplosionSound.play()
LaserY = lasery
LaserState = laserstate
scoreValue += 1
# enemy respawn
OldEnemyY = EnemyClass.EnemyY[i]
EnemyClass.EnemyY[i] = -20
if EnemyClass.EnemyY[i] >= OldEnemyY:
EnemyClass.EnemyY[i] -= 40
EnemyRowBottom = EnemyClass()
EnemyRowTop = EnemyClass()
for i in range(EnemyRowBottom.numEnemies):
EnemyImage1 = pygame.image.load('enemy.png')
EnemyRowBottom.EnemyImage.append( pygame.transform.scale(EnemyImage1, (70, 70)) )
y = i * 10
x = y * 10
EnemyRowBottom.EnemyX.append( x )
EnemyRowBottom.EnemyY.append( 150 )
for i in range(EnemyRowTop.numEnemies):
EnemyImage1 = pygame.image.load('enemy.png')
EnemyRowTop.EnemyImage.append( pygame.transform.scale(EnemyImage1, (70, 70)) )
y = i * 10
x = y * 10
EnemyRowTop.EnemyX.append( x )
EnemyRowTop.EnemyY.append( 50 )
# game loop
running = True
while running:
# setting background
screen.fill( (0, 0, 0) )
screen.blit(background, (0, 0))
# make function that closes program when x pressed
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# keystroke detection
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
xChangePlayer = -0.4
if event.key == pygame.K_RIGHT:
xChangePlayer = +0.4
if event.key == pygame.K_SPACE:
if LaserState == "Ready":
LaserSound = mixer.Sound('shoot.wav')
LaserSound.play()
LaserX = playerX
LaserY = 600
Firelaser(LaserX, LaserY)
LaserY -= yLaserChange
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
xChangePlayer = 0
# player movement
playerX += xChangePlayer
# setting boudries for the player
if playerX < 0:
playerX = 0
elif playerX >= 736:
playerX = 735
# setting boudries for the enemy
for i in range(EnemyRowTop.numEnemies):
BlitEnemy1 = EnemyRowTop.enemy(i)
BlitEnemy2 = EnemyRowBottom.enemy(i)
gameSoundPlayed = 0
if EnemyRowTop.EnemyY[i] >= 600 or EnemyRowBottom.EnemyY[i] >= 600 and (gameSoundPlayed == 0):
GameOver()
BottomLine(LineX, LineY)
player(playerX, playerY)
show_score(textX, textY)
pygame.display.update()
gameSoundPlayed += 1
EnemyRowTop.xEnemyChange = 0
EnemyRowTop.yEnemyChange = 0
EnemyRowBottom.xEnemyChange = 0
EnemyRowBottom.yEnemyChange = 0
mixer.music.stop()
mixer.music.load('GameOverSound.wav')
mixer.music.play()
time.sleep(3)
break
EnemyRowTop.enemyMovement(i)
EnemyRowBottom.enemyMovement(i)
# collision detection
collision = Collision(EnemyRowTop.EnemyX[i], EnemyRowBottom.EnemyX[i], EnemyRowTop.EnemyY[i], EnemyRowBottom.EnemyY[i], LaserX, LaserY)
if collision == 1:
EnemyRowTop.CollisionDetection(i, scoreValue, 600, "Ready")
EnemyDistance = DistanceEnemy(EnemyRowTop.EnemyX[i], EnemyRowBottom.EnemyX[i], EnemyRowTop.EnemyY[i], EnemyRowBottom.EnemyY[i])
if EnemyDistance == True:
EnemyClass.EnemyY[i] -= 50
if collision == 2:
EnemyRowBottom.CollisionDetection(i, scoreValue, 600, "Ready")
EnemyDistance = DistanceEnemy(EnemyRowTop.EnemyX[i], EnemyRowBottom.EnemyX[i], EnemyRowTop.EnemyY[i], EnemyRowBottom.EnemyY[i])
if EnemyDistance == True:
EnemyClass.EnemyY[i] -= 50
BlitEnemy1
BlitEnemy2
# laser movement
if LaserY <= -20:
LaserY = 750
LaserState = "Ready"
if LaserState == "Fire":
Firelaser(LaserX, LaserY)
LaserY -= yLaserChange
# outputting characters
BottomLine(LineX, LineY)
player(playerX, playerY)
show_score(textX, textY)
pygame.display.update()
if gameSoundPlayed == 1:
break
I cant test it but I think I found the problem. You should add a _init_ method to your EnemyClass. There you can define these variables so each row has its own lists of enemies. Because your enemies have the same image you dont need to load the image more than once.
EnemyImage = []
EnemyX = []
EnemyY = []
numEnemies = 4
xEnemyChange = 0.2
yEnemyChange = 50
class EnemyClass:
EnemyImage = pygame.transform.scale(pygame.image.load('enemy.png'), (70, 70))
def __init__(self):
self.EnemyX = []
self.EnemyY = []
self.numEnemies = 4
self.xEnemyChange = 0.2
self.yEnemyChange = 50
EnemyRowBottom = EnemyClass()
EnemyRowTop = EnemyClass()
But it would make more sense to have an object for each enemy instead of the enemy rows.
The problem of your code is, that the list containing the images in your EnemyClass is a class-attribute of your EnemyClass. As a result, every instance of that class accesses the same list of EnemyClass, and has not its own list in EnemyRowBottom and EnemyRowTop.
You can fix this problem by making EnemyImage an object-attribute:
class EnemyClass:
def __init__(self):
self.EnemyImage = []
self.EnemyX = []
self.EnemyY = []
self.numEnemies = 4
self.xEnemyChange = 0.2
self.yEnemyChange = 50
You can then access your images with "self.EnemyImage" inside the methods.
Moreover, to avoid the same image twice, you can put your pygame.image.load-method outside and before the loops, so that the game starts quicker.

Increasing variables that are in use in pygame

I am coding a space invaders game in pygame, and wanted to make it so that when the player reaches 50 points, the game increases the number of invaders from 6 to 10. In the game, the enemies respawn near the top half of the screen immediately after dying. The game functions perfectly normally until you reach 50 points, at which it immediately crashes. How do I make it so that the variable storing the number of enemies (num_of_enemies) increases, while the game is still running?
In the code I have put here, I removed my attempt to change the num_of_enemies variable, but fyi, I placed it just above "pygame.display.update()". my crappy attempt to resolve the issue boiled down to:
if score_value >= 50: num_of_enemies += 10
I have also tried this code while assigning num_of_enemies a global value, but it simply defects the game, and messes up again.
Code:
import pygame
from pygame import mixer
import random
import math
pygame.init()
screen = pygame.display.set_mode((800, 600))
background = pygame.image.load('Background.jpg')
background = pygame.transform.scale(background, (800, 600))
mixer.music.load('background.wav')
mixer.music.play(-1)
pygame.display.set_caption("Space Invaders")
icon = pygame.image.load('ufo.png')
pygame.display.set_icon(icon)
playerImg = pygame.image.load('spaceship.png')
playerX = 370
playerY = 480
playerX_change = 0
enemyImg = []
enemyX = []
enemyY = []
enemyX_change = []
enemyY_change = []
num_of_enemies = 6
for i in range(num_of_enemies):
enemyImg.append(pygame.image.load('ufo.png'))
enemyX.append(random.randint(0, 750))
enemyY.append(random.randint(50, 200))
enemyX_change.append(0.5)
enemyY_change.append(40)
bulletImg = pygame.image.load('bullet.png')
bulletX = 0
bulletY = 480
bulletX_change = 0
bulletY_change = 1
bullet_state = "ready"
score_value = 0
font = pygame.font.Font('freesansbold.ttf', 32)
textX = 10
textY = 10
over_font = pygame.font.Font('freesansbold.ttf', 64)
def show_score(x,y):
score = font.render("Score : " + str(score_value), True, (255, 255, 255))
screen.blit(score, (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 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(enemyY-bulletY,2)))
if distance < 27:
return True
else:
return False
running = True
while running:
screen.fill((0, 0, 0))
screen.blit(background,(0,0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerX_change = -1
if event.key == pygame.K_RIGHT:
playerX_change = 1
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
playerX_change = 0
if event.key == pygame.K_SPACE:
if bullet_state == "ready":
bullet_sound = mixer.Sound('laser.wav')
bullet_sound.play()
bulletX = playerX
fire_bullet(bulletX,bulletY)
playerX += playerX_change
if playerX <= 0:
playerX = 0
elif playerX >= 768:
playerX = 768
for i in range(num_of_enemies):
if enemyY[i] > 440:
for j in range(num_of_enemies):
enemyY[j] = 2000
game_over_text()
break
enemyX[i] += enemyX_change[i]
if enemyX[i] <= 0:
enemyX_change[i] = 0.5
enemyY[i] += enemyY_change[i]
elif enemyX[i] >= 768:
enemyX_change[i] = -0.5
enemyY[i] += enemyY_change[i]
collision = isCollision(enemyX[i], enemyY[i], bulletX, bulletY)
if collision:
explosion_Sound = mixer.Sound('explosion.wav')
explosion_Sound.play()
bulletY = 480
bullet_state = "ready"
score_value += 1
print(f"score = {score_value}")
enemyX[i] = random.randint(50, 768)
enemyY[i] = random.randint(50, 200)
enemy(enemyX[i], enemyY[i], i)
if bulletY <= 0:
bulletY = 480
bullet_state = "ready"
if bullet_state == "fire":
fire_bullet(bulletX,bulletY)
bulletY -= bulletY_change
player(playerX, playerY)
show_score(textX, textY)
pygame.display.update()```
IT is not enough just to change num_of_enemies you also need to add new items in the lists.
Write a function that crates the enemies:
def create_enemies(new_enemies):
global num_of_enemies
enemy_image = pygame.image.load('ufo.png')
for i in range(new_enemies):
enemyImg.append(enemy_image)
enemyX.append(random.randint(0, 750))
enemyY.append(random.randint(50, 200))
enemyX_change.append(0.5)
enemyY_change.append(40)
# now the number of enemies has changed
num_of_enemies += new_enemies
Call the function at the begin of the application:
enemyImg = []
enemyX = []
enemyY = []
enemyX_change = []
enemyY_change = []
num_of_enemies = 0 # 0! actually you have 0 enemies
create_enemies(6) # create 6 new enemies
Call the function again if you want to change the number of enemies:
# create 4 more enemies, now the number of enemies changes from 6 to 10
create_enemies(4)

how to make bullet come out according to the object

i am still learning on how to use pygame and i just created a space invader inspired game. but one issue that i have right now is that the bullet does not come out accordingly to my object's location. instead it only comes out from the bottom of the screen. i want my bullet to come out accordingly to my object no matter if its moving up, down, right or left. thank you in advance!!
import pygame
import random
import math
#intialize the pygame
pygame.init()
#create the screen
screen = pygame.display.set_mode((700,583))
#Caption and icon
pygame.display.set_caption("Yoshi & Fruits")
icon = pygame.image.load("Yoshi_icon.png")
pygame.display.set_icon(icon)
#Player
playerImg = pygame.image.load("YoshiMario.png")
playerX = 370
playerY = 480
playerX_change = 0
playerY_change = 0
#Enemy
enemyImg = pygame.image.load('msh1.png')
enemyX = random.randint(0,735)
enemyY = random.randint(50,150)
enemyX_change = 2
enemyY_change = 30
#Knife
# ready - you cant see the knife on the screen
# fire - the knife is currently moving
knifeImg = pygame.image.load('diamondsword3.png')
knifeX = 0
knifeY = 480
knifeX_change = 0
knifeY_change = 10
knife_state = "ready"
score = 0
def player(x,y):
screen.blit(playerImg, (x, y))
def enemy(x,y):
screen.blit(enemyImg, (x, y))
def fire_knife(x,y):
global knife_state
knife_state = "fire"
screen.blit(knifeImg,(x + 16, y + 10))
def isCollision(enemyX,enemyY,knifeX,knifeY):
distance = math.sqrt((math.pow(enemyX - knifeX,2)) + (math.pow(enemyY - knifeY,2)))
if distance < 27:
return True
else:
return False
#game loop
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
#if keystroke is pressed check whether its right or left
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerX_change = -2
if event.key == pygame.K_RIGHT:
playerX_change = 2
if event.key == pygame.K_UP:
playerY_change = -2
if event.key == pygame.K_DOWN:
playerY_change = 2
if event.key == pygame.K_SPACE:
if knife_state is "ready":
# get the current x coordinate of yoshi
knifeX = playerX
fire_knife(playerX,knifeY)
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
playerX_change = 0
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
playerY_change = 0
# RGB - Red, Green, Blue
screen.fill((0, 255, 0))
#add a wallpaper
bgimage=pygame.image.load("Background.png")
screen.blit(bgimage, (0, 0))
# 5 = 5 + -0.1 ->5 = 5 - 0.1
# 5 = 5 + 0.1
# checking for boundaries of yoshi/mushroom so it doesnt go out of bounds
playerX += playerX_change
if playerX < 0:
playerX = 0
elif playerX > 645:
playerX = 645
playerY += playerY_change
if playerY < 0:
playerY = 0
elif playerY > 500:
playerY = 500
# enemy movement
enemyX += enemyX_change
if enemyX <= 0:
enemyX_change = 2
enemyY += enemyY_change
elif enemyX > 645:
enemyX_change = -2
enemyY += enemyY_change
# knife movement
if knifeY <= 0:
knifeY = 480
knife_state = "ready"
if knife_state is "fire":
fire_knife(knifeX,knifeY)
knifeY -= knifeY_change
# collision
collision = isCollision(enemyX,enemyY,knifeX,knifeY)
if collision:
knifeY = 480
knife_state = "ready"
score += 1
print(score)
enemyX = random.randint(0,735)
enemyY = random.randint(50,150)
player(playerX,playerY)
enemy(enemyX,enemyY)
pygame.display.update()
I assume by "bullet" you are referring to "knife" in the code.
The code is not tracking the change in the knife's co-ordinates. Sure it's created at the player's X co-ordinate, but nothing remembers this change. So let's modify fire_knife() to simply remember the changes in the state of the knife, including the new X & Y.
def fire_knife( x, y ):
""" Start a knife flying upwards from the player """
global knife_state, knifeX, knifeY
knifeX = x + 16
knifeY = y + 10
knife_state = "fire"
And create a collision handler that automatically resets the knife back to "ready":
def knife_hits( enemyX, enemyY ):
""" Return True if the knife hits the enemy at the given (x,y).
If so, prepare the knife for firing again. """
global knife_state, knifeX, knifeY
collision_result = False
if ( knife_state == "fire" and isCollision( enemyX, enemyY, knifeX, knifeY ) ):
knife_state = "ready"
collision_result = True
return collision_result
Then create another function to separately draw the knife, if it's in the correct state.
def draw_knife( screen ):
""" If the knife is flying, draw it to the screen """
global knife_state, knifeImg, knifeX, knifeY
if ( knife_state == "fire" ):
screen.blit( knifeImg, ( knifeX, knifeY ) )
And, for the sake of completeness, a function to update the knife's position, and reset the knife_state when it goes off-screen.
def update_knife():
""" Make any knife fly up the screen, resetting at the top """
global knife_state, knifeX, knifeY, knifeY_change
# if the knife is already flying, move it
if ( knife_state == "fire" ):
knifeY -= knifeY_change
if ( knifeY <= 0 ):
knife_state = "ready" # went off-screen
So that gives a new main loop calling these functions:
#game loop
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
#if keystroke is pressed check whether its right or left
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerX_change = -2
if event.key == pygame.K_RIGHT:
playerX_change = 2
if event.key == pygame.K_UP:
playerY_change = -2
if event.key == pygame.K_DOWN:
playerY_change = 2
if event.key == pygame.K_SPACE:
if knife_state is "ready":
# Fire the knife at the coordinates of yoshi
fire_knife( playerX, playerY ) # create a new flying knife
# ...
# enemy movement
enemyX += enemyX_change
if enemyX <= 0:
enemyX_change = 2
enemyY += enemyY_change
elif enemyX > 645:
enemyX_change = -2
enemyY += enemyY_change
update_knife() # move the flying knife (if any)
if ( knife_hits( enemyX, enemyY ) ): # is there a knife-enemy-collision?
score += 1
print(score)
enemyX = random.randint(0,735)
enemyY = random.randint(50,150)
else:
draw_knife( screen ) # paint the flying knife (if any)
player(playerX,playerY)
enemy(enemyX,enemyY)
pygame.display.update()
Putting all the modifications to the knife position into functions makes your main loop simpler, and keeps most knife-code contained into a single group of functions. It would probably be better again to make a Knife class with these functions, but this is a simple start.

Categories

Resources