why is not pygame blit not working in a class

Viewed 625

I am trying to create my own game using pygame with classes and my problem is that I cannot understand why my program is not working properly

import pygame
import time
import random
import sys

pygame.init()
screen = pygame.display.set_mode((1280, 720))
pygame.display.set_caption("this game")


class Background:

    def __init__(self, x, y):
        self.xpos = x
        self.ypos = y

    picture = pygame.image.load("C:/images/dunes.jpg")
    picture = pygame.transform.scale(picture, (1280, 720))

    def draw(self):
        pygame.surface.Surface.blit(picture, (self.xpos, self.ypos))



class Monster:
    def __init__(self, x, y):
        self.xpos = x
        self.ypos = y

    def move_left(self):
        self.xpos =- 5

    def move_right(self):
        self.xpos =+ 5

    def jump(self):
        for x in range(1, 10):
            self.ypos =-1
            pygame.display.show()

        for x in range(1, 10):
            self.ypos =+1
            pygame.display.show()

    picture = pygame.image.load("C:/pics/hammerhood.png")
    picture = pygame.transform.scale(picture, (200, 200))

    def draw(self):
        pygame.surface.Surface.blit(picture, (self.xpos, self.ypos))




class enemy:
    def __init__(self, x, y):
        self.xpos = x
        self.ypos = y

    picture = pygame.image.load("C:/pics/dangler_fish.png")
    picture = pygame.transform.scale(picture, (200, 200))


    def teleport(self):
        self.xpos = random.randint(1, 1280)
        self.pos= random.randint(1, 720)

    def draw(self):
        pygame.surface.Surface.blit(picture, (self.xpos, self.ypos))






while True:
    ice = Background(720, 360)
    hammerhood = Monster(200, 500)
    fish = enemy(0, 0)
    fish.teleport()


    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        if pygame.event == pygame.K_d:
            hammerhood.move_right()

        if pygame.event == pygame.K_a:
            hammerhood.move_left()

        if pygame.event == pygame.K_w:
            hammerhood.jump()

    hammerhood.draw()
    ice.draw()
    fish.draw()

what it is saying to me is, line 49, in the draw

pygame.surface.Surface.blit(picture, (self.xpos, self.ypos))
NameError: name 'picture' is not defined

I have tried everything and there is another project I copied from the internet and this has the exact same way of blitting the picture in the class but in this one, it is not working

2 Answers

you define picture at the class top level which makes it a class attribute. To access it from a method you have to use self. picture

The picture attributes are class attributes (defined outside of the __init__ method) but they can be accessed like any other attributes by prepending them with self.. Also, you most likely want to blit the pictures onto the screen surface, so just call the blit method of this surface:

def draw(self):
    screen.blit(self.picture, (self.xpos, self.ypos))

Note that class attributes are shared between all instances, so if you modify one surface/image, they'll be changed for all sprites.

There are a few more problems:

  • The event handling doesn't work.
  • The sprites won't move continuously. Define some speed attributes and add them to the positions each frame.
  • You should almost always call the convert or convert_alpha methods to improve the blit performance of the surfaces.

Here's a fixed version (except for the jumping) with some comments:

import pygame
import random
import sys


pygame.init()
screen = pygame.display.set_mode((1280, 720))
clock = pygame.time.Clock()  # A clock to limit the frame rate.
pygame.display.set_caption("this game")


class Background:
    picture = pygame.image.load("C:/images/dunes.jpg").convert()
    picture = pygame.transform.scale(picture, (1280, 720))

    def __init__(self, x, y):
        self.xpos = x
        self.ypos = y

    def draw(self):
        # Blit the picture onto the screen surface.
        # `self.picture` not just `picture`.
        screen.blit(self.picture, (self.xpos, self.ypos))


class Monster:
    picture = pygame.image.load("C:/pics/hammerhood.png").convert_alpha()
    picture = pygame.transform.scale(picture, (200, 200))

    def __init__(self, x, y):
        self.xpos = x
        self.ypos = y
        # If you want to move continuously you need to set these
        # attributes to the desired speed and then add them to
        # self.xpos and self.ypos in an update method that should
        # be called once each frame.
        self.speed_x = 0
        self.speed_y = 0

    def update(self):
        # Call this method each frame to update the positions.
        self.xpos += self.speed_x
        self.ypos += self.speed_y

    # Not necessary anymore.
#     def move_left(self):
#         self.xpos -= 5  # -= not = -5 (augmented assignment).
# 
#     def move_right(self):
#         self.xpos += 5  # += not = +5 (augmented assignment).

    def jump(self):
        # What do you want to do here?
        for x in range(1, 10):
            self.ypos -= 1  # -= not =-
            # pygame.display.show()  # There's no show method.

        for x in range(1, 10):
            self.ypos += 1
            # pygame.display.show()

    def draw(self):
        screen.blit(self.picture, (self.xpos, self.ypos))


class Enemy:  # Use upper camelcase names for classes.
    picture = pygame.image.load("C:/pics/dangler_fish.png").convert_alpha()
    picture = pygame.transform.scale(picture, (200, 200))

    def __init__(self, x, y):
        self.xpos = x
        self.ypos = y

    def teleport(self):
        self.xpos = random.randint(1, 1280)
        self.pos= random.randint(1, 720)

    def draw(self):
        screen.blit(self.picture, (self.xpos, self.ypos))


# Create the instances before the while loop.
ice = Background(0, 0)  # I pass 0, 0 so that it fills the whole screen.
hammerhood = Monster(200, 500)
fish = Enemy(0, 0)

while True:
    # Handle events.
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        # Check if the `event.type` is KEYDOWN first.
        elif event.type == pygame.KEYDOWN:
            # Then check which `event.key` was pressed.
            if event.key == pygame.K_d:
                hammerhood.speed_x = 5
            elif event.key == pygame.K_a:
                hammerhood.speed_x = -5
            elif event.key == pygame.K_w:
                hammerhood.jump()
        elif event.type == pygame.KEYUP:
            # Stop moving when the keys are released.
            if event.key == pygame.K_d and hammerhood.speed_x > 0:
                hammerhood.speed_x = 0
            elif event.key == pygame.K_a and hammerhood.speed_x < 0:
                hammerhood.speed_x = 0

    # Update the game.
    hammerhood.update()
    fish.teleport()

    # Draw everything.
    ice.draw()  # Blit the background to clear the screen.
    hammerhood.draw()
    fish.draw()
    pygame.display.flip()
    clock.tick(60)  # Limit the frame rate to 60 FPS.
Related