Search code examples
pythonuser-interfacepygameblit

pygame "invalid position for blit"


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.

ERROR MESSAGE

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)

Solution

  • enemyX and enemyY are list of coordinates. You have 2 options:

    1. 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)
      
    2. 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()
    
        # [...]