I am trying to make a game but when I run the code the game makes 5 enemies appear on the screen. It says "invalid position for blit". However, I don't know where to put the blit otherwise. I don't know what to do because I'm still learning. The code was fine before adding the copies. Not sure why that changed anything.
This is the full code:
import pygame
import random
import math
from pygame import mixer
#Imports the pygame, random, math and mixer module.
pygame.init()
#Initializes Pygame
screen = pygame.display.set_mode((800,600))
#Sets the screen to pygame looks and not normal python looks.
pygame.display.set_caption("Draft")
#Changes the title
icon = pygame.image.load('C:/Users/user/Desktop/Python/CodingBee/doctor.png')
pygame.display.set_icon(icon)
#Changing the Icon
#Adding Background Music
mixer.music.load('C:/Users/user/Desktop/Python/CodingBee/sb_indreams.mp3')
mixer.music.play(-1)
#Loads the music and plays if until the window is closed
#Colors
white = (255,255,255)
black = (0,0,0)
red = (255,0,0)
green = (0,255,0)
blue = (0,0,255)
#Setting color variables to make it easier to access later in the code.
#Player
player_img = pygame.image.load('C:/Users/user/Desktop/Python/CodingBee/Doctor_Running-removebg-preview (1).png')
playerx = 20
playery = 390
playerx_change = 0
playery_change = 100
#Making the Player Variables.
#Health Kit
HealthImg = pygame.image.load('C:/Users/user/Desktop/Python/CodingBee/first-aid-kit.png')
HealthX = 20
HealthY = 405
HealthX_Change = -10
HealthY_Change = 0
Health_State = "ready"
#Making the Health_Kit Variables.
#Enemy
enemyImg = []
enemyX = []
enemyY = []
enemyX_change = []
enemyY_change = []
number_of_enemies = 5
#Making a list for all 5 enemies image, x value, y value, x value change, y value change. All variables are a seperate list
for i in range(number_of_enemies):
enemyImg.append(pygame.image.load('C:/Users/user/Desktop/Python/CodingBee/zombie.png'))
enemyX.append(random.randint(0, 736))
enemyY.append(random.randint(50, 150))
enemyX_change.append(0.45)
enemyY_change.append(40)
#Score
Score_Value = 0
font = pygame.font.Font('C:/Users/user/Desktop/Python/Pygame/Space_Invaders/Mostery.ttf', 25)
#The pygame font extension requires 2 values, the font and the font size.
#.ttf is a font extension
#Making the score variable
ScoreX = 10
ScoreY = 25
#Making a variable for the fonts x and y position
#Heading
headingfont = pygame.font.Font('C:/Users/user/Desktop/Python/Pygame/Space_Invaders/Bouncy-PERSONAL_USE_ONLY.otf', 45)
HeadingX = 230
HeadingY = 10
#Game Over
game_over_font = pygame.font.Font('C:/Users/user/Desktop/Python/Pygame/Space_Invaders/Bouncy-PERSONAL_USE_ONLY.otf', 64)
#Creating Classes
class Background():
def __init__(self):
self.bgimage = pygame.image.load('C:/Users/user/Desktop/Python/CodingBee/Ground.png')
self.rectBGimg = self.bgimage.get_rect()
self.bgY1 = 485
self.bgX1 = 0
self.bgY2 = 485
self.bgX2 = self.rectBGimg.width
self.moving_speed = 7
def update(self):
self.bgX1 -= self.moving_speed
self.bgX2 -= self.moving_speed
if self.bgX1 <= -self.rectBGimg.width:
self.bgX1 = self.rectBGimg.width
if self.bgX2 <= -self.rectBGimg.width:
self.bgX2 = self.rectBGimg.width
def render(self):
screen.blit(self.bgimage, (self.bgX1, self.bgY1))
screen.blit(self.bgimage, (self.bgX2, self.bgY2))
class Player():
def draw_player():
screen.blit(player_img,(playerx,playery))
def player_jump():
global playery
playery -= playery_change
class Enemy():
def draw_enemy(enemyx,enemyy,i):
screen.blit(enemyImg[i],(enemyx,enemyy))
def move_enemy():
global enemyX
enemyX[i] += enemyX_change[i]
class Health():
def fire_Health (x,y):
global Health_State
Health_State = "fire"
screen.blit(HealthImg, ( x + 70, y + 10))
class Other():
def isCollision(enemyX, enemyY, HealthX, HealthY):
distance = math.sqrt(math.pow(enemyX - HealthX, 2) + (math.pow(enemyY - HealthY, 2)))
if distance < 27:
return True
else:
return False
def show_heading():
Heading = headingfont.render("Health Run!", True, (255,255,255))
screen.blit(Heading,( HeadingX, HeadingY))
def show_score():
Score = font.render("Score = " + str(Score_Value), True, (255,255,255))
screen.blit(Score,( ScoreX, ScoreY))
def game_over():
Game_Over = headingfont.render("GAME OVER!", True, (255,255,255))
screen.blit(Game_Over,( 200, 400))
Score_Value = 0
#def states an event. The event will not occur unless you call the event in the main game loop.
back_ground = Background()
#Main Game Loop
clock = pygame.time.Clock()
SCEEN_UPDATE = pygame.USEREVENT
pygame.time.set_timer(SCEEN_UPDATE,150)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
Player.player_jump()
if event.key == pygame.K_SPACE:
if Health_State == "ready":
Health_Fire_Sound = mixer.Sound('C:/Users/user/Desktop/Python/Pygame/Space_Invaders/laser.wav')
Health_Fire_Sound.play()
Health.fire_Health(HealthX , HealthY)
HealthY = playery + 10
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP:
playery += playery_change
screen.fill(blue)
back_ground.update()
back_ground.render()
#Health Kit Movement
if HealthX >= 800:
HealthX = 20
Health_State = "ready"
if Health_State == "fire":
Health.fire_Health(HealthX , HealthY)
HealthX -= HealthX_Change
#Enemy Movement and collision check
for i in range(number_of_enemies):
if enemyX[i] > 20:
for j in range(number_of_enemies):
enemyY = 2000
Other.game_over()
break
Enemy.move_enemy()
collision = Other.isCollision(enemyX[i],enemyY[i],HealthX,HealthY)
if collision:
BulletY = 480
Bullet_State = "ready"
enemyX[i] = random.randint(800,900)
enemyY[i] = 405
HealthX = 20
Health_State = "ready"
Score_Value += 1
# draw objects
Player.draw_player()
Enemy.draw_enemy(enemyX,enemyY, i)
Other.show_heading()
Other.show_score()
# update display
pygame.display.update()
clock.tick(60)
enemyX
and enemyY
are list of coordinates. You have 2 options:
pass items of the lists to draw_enemy
:
class Enemy():
def draw_enemy(enemyx, enemyy, i):
screen.blit(enemyImg[i], (enemyx, enemyy))
Enemy.draw_enemy(enemyX[i], enemyY[i], i)
Get the items from the lists in draw_enemy
:
class Enemy():
def draw_enemy(enemyx, enemyy, i):
screen.blit(enemyImg[i], (enemyx[i], enemyy[i]))
Enemy.draw_enemy(enemyX, enemyY, i)
Anyway, I suggest to create an Enemy
class with attributes (see Classes). Note that the following code is not complete, it is just an example of how to implement classes and use object instances. I'll leave it up to you as an exercise to incorporate it into your code.
class Enemy():
def __init__(self, image, x, y, changeX, changeY):
self.image = image
self.x = x
self.y = y
self.changeX = changeX
self.changeY = changeY
def move(self):
self.x += self.changeX
self.y += self.changeY
def draw(self):
screen.blit(self.image, (self.x, self.y))
number_of_enemies = 5
enemies = []
enemyImg = pygame.image.load('C:/Users/user/Desktop/Python/CodingBee/zombie.png')
for i in range(number_of_enemies):
x = random.randint(0, 736)
y = random.randint(50, 150)
enemy = Enemy(enemyImg, x, y, 0.45, 0)
enemies.append(enemy)
running = True
while running:
# [...]
for enemy in enemies:
enemy.move()
# [...]
for enemy in enemies:
enemy.draw()
# [...]