I'm currently in the process of writing a larger program in python. It is a simple game, but I've got an Error. Can someone help me?
Error
Traceback (most recent call last):
File "C:/Users/kkuja/Desktop/game.py", line 36, in <module>
MainWindow.MainLoop()
File "C:/Users/kkuja/Desktop/game.py", line 17, in MainLoop
self.chicken_sprites.draw(self.screen)
File "C:\Users\kkuja\AppData\Local\Programs\Python\Python35\lib\site-packages\pygame\sprite.py", line 475, in draw
self.spritedict[spr] = surface_blit(spr.image, spr.rect)
AttributeError: 'Chicken' object has no attribute 'rect'
Code
import os, sys
import pygame
class Game:
def __init__(self, width=640, height=480):
pygame.init()
self.width = width
self.height = height
self.screen = pygame.display.set_mode([self.width, self.height])
def MainLoop(self):
self.ChickenLoad();
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
self.chicken_sprites.draw(self.screen)
pygame.display.flip()
def ChickenLoad(self):
self.chicken = Chicken()
self.chicken_sprites = pygame.sprite.Group(self.chicken)
class Chicken(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("chic.jpg")
if __name__ == "__main__":
MainWindow = Game()
MainWindow.MainLoop()
Thanks in advance!
In the function self.chicken_sprites.draw(self.screen) in your code chicken.rect is trying to be accessed, but you did not define it.
If you refer to the official documentation you can find this piece of code:
class Block(pygame.sprite.Sprite):
# Constructor. Pass in the color of the block,
# and its x and y position
def __init__(self, color, width, height):
# Call the parent class (Sprite) constructor
pygame.sprite.Sprite.__init__(self)
# Create an image of the block, and fill it with a color.
# This could also be an image loaded from the disk.
self.image = pygame.Surface([width, height])
self.image.fill(color)
# Fetch the rectangle object that has the dimensions of the image
# Update the position of this object by setting the values of rect.x and rect.y
self.rect = self.image.get_rect()
You do not set self.rect in your Chicken, it should look like this.
class Chicken(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("chic.jpg")
self.rect = self.image.get_rect(); #here rect is created
Related
I am trying to make a Towerdefense Game
to check if the Enemy is in the hitcircle of the tower I want to use the function pygame.sprite.collide_mask to find out if they are touching.
This is the output:
AttributeError: 'pygame.mask.Mask' object has no attribute 'add_internal'
How can I make it work? Am I even remotely in the right direction of detecting the collision for the game?
I hope this code can work as much as it needs
import pygame
pygame.init()
class Tower(pygame.sprite.Sprite):
def __init__(self, window):
self.collision_circle =
pygame.image.load('assets/Towers&Projectiles/Collision_Circle/collision_circle.png')
self.tower_mask = pygame.mask.from_surface(self.collision_circle)
class Enemy(pygame.sprite.Sprite):
def __init__(self, window):
self.enemy_mask_image = pygame.image.load('Assets/Enemy/WALK_000.png')
self.enemy_mask = pygame.mask.from_surface(self.enemy_mask_image)
pygame.display.set_caption("Tower Defense")
width = 1200
height = 840
display_surface = pygame.display.set_mode((width, height))
my_enemy = Enemy(display_surface)
my_tower = Tower(display_surface)
while True:
enemy_sprite = pygame.sprite.GroupSingle(my_enemy.enemy_mask)
tower_sprite = pygame.sprite.GroupSingle(my_tower.tower_mask)
if pygame.sprite.spritecollide(enemy_sprite.sprite,tower_sprite,False,pygame.sprite.collide_mask()):
print("collision")
collide_mask use the .rect and .mask object of the Spirte. Therefore the name of the Mask attribute must be mask, but not tower_mask or enemy_mask.
In addition, the objects must have an attribute named rect, which is a pygame.Rect object with the position of the sprite.
Also the super calls a missing from your class constructors. e.g.:
class TowerCircle(pygame.sprite.Sprite):
def __init__(self, centerx, centery):
super().__init__()
self.image = pygame.image.load('assets/Towers&Projectiles/Collision_Circle/collision_circle.png')
self.mask = pygame.mask.from_surface(self.collision_circle)
self.rect = self.image.get_rect(center = (centerx, centery))
class Enemy(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.image = pygame.image.load('Assets/Enemy/WALK_000.png')
self.mask = pygame.mask.from_surface(self.enemy_mask_image)
self.rect = self.image.get_rect(topleft = (x, y))
See Pygame mask collision and Make a line as a sprite with its own collision in Pygame.
I can't find the mistake. Trying for hours.
When I run the code, I get the message:
Ballons' object has no attribute 'image'
The message in detail:
Traceback (most recent call last):
File "c:\pythonprogramm\ballon_jagd copy.py", line 47, in
ballon_sprites.draw(spielfeld)
File "C:\Users\chef\AppData\Local\Programs\Python\Python39\lib\site-packages\pygame\sprite.py", line 546, in draw
surface.blits((spr.image, spr.rect) for spr in sprites)
File "C:\Users\chef\AppData\Local\Programs\Python\Python39\lib\site-packages\pygame\sprite.py", line 546, in
surface.blits((spr.image, spr.rect) for spr in sprites)
AttributeError: 'Ballons' object has no attribute 'image'
Here is the code:
class Ballons(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
z_bild = pygame.image.load("Bilder/ballons/ballon1.png")
self.einzel_bild = z_bild
self.rect = self.einzel_bild.get_rect()
self.rect_x = random.randint(100,1800)
self.rect_y = 700
def update(self):
self.rect_y -=5
def draw_bg():
spielfeld.fill(bg)
#Allgemein..............................................
pygame.init()
clock = pygame.time.Clock()
bg = (50,250,50)
#Spielfeld..............................................
bild_breite = 1920
bild_hoehe = 1080
spielfeld = pygame.display.set_mode((bild_breite,bild_hoehe))
#Erstellung Sprite und Group
ballon_sprites = pygame.sprite.Group()
ballon = Ballons()
ballon_sprites.add(ballon)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
#Zeichnen
draw_bg()
ballon_sprites.draw(spielfeld)
ballon_sprites.update()
pygame.display.flip()
clock.tick(60)nter code here
pygame.sprite.Group.draw() uses the image and rect attributes of the contained pygame.sprite.Sprites to draw the objects. See pygame.sprite.Group.draw():
Draws the contained Sprites to the Surface argument. This uses the Sprite.image attribute for the source surface, and Sprite.rect. [...]
Therefore a Ballon must have an attribute with the name image:
class Ballons(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("Bilder/ballons/ballon1.png")
self.rect = self.image.get_rect()
self.rect_x = random.randint(100,1800)
self.rect_y = 700
def update(self):
self.rect_y -=5
I have tried everything I can think of to fix this, but I can't seem to find it. I know it is probably a simple fix, but I cannot find what is making this happen. This is the first part of my code :
import pygame, sys, time
from pygame.locals import *
pygame.init()
WINDOWWIDTH = 900
WINDOWHEIGHT = 400
MOVERATE = 5
screen = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
TEXTCOLOR = (255, 255, 255)
BACKGROUNDCOLOR = (0, 0, 0)
FPS = 40
clock = pygame.time.Clock()
x = 200
y = 150
class player(pygame.sprite.Sprite):
def __init__(self, x, y):
super(player, self).__init__()
temp_image = pygame.image.load("stand_down.png").convert_alpha()
self.image_down = pygame.transform.scale(temp_image, (100, 200))
temp_image = pygame.image.load("standleft.png").convert_alpha()
self.image_left = pygame.transform.scale(temp_image, (100, 200))
temp_image = pygame.image.load("standright.png").convert_alpha()
self.image_right = pygame.transform.scale(temp_image, (100, 200))
self.image = self.image_down
# keep position and size in pygame.Rect()
# to use it in collision checking
self.rect = self.image.get_rect(x=x, y=y)
def draw(self, x, y):
screen.blit(self.image, self.rect)
def handle_event(self):#, event)
self.image = self.image_down.get_rect()
self.image = pygame.Surface((x, y))
key = pygame.key.get_pressed()
if key[K_LEFT]:
self.rect.x -= 50
self.image = self.image_left
if key[K_RIGHT]:
self.rect.x += 50
self.image = self.image_right
class room1():
#bedroom
def __init__(self):
self.x, self.y = 16, WINDOWHEIGHT/2
self.speed = 3
def draw(self):
background = pygame.image.load("bedroom.jpg").convert()
background = pygame.transform.scale(background, (WINDOWWIDTH, WINDOWHEIGHT))
screen.blit(background, (0, 0))
And this is my main function :
def main():
while True:
for event in pygame.event.get():
player.handle_event.get(event)
player.handle_event(screen)
room1.draw(screen)
player.draw(screen, x, y)
pygame.display.update()
pygame.display.flip()
clock.tick(FPS)
main()
I keep getting the same error :
File "C:\Python32\Project3\proj3pt2.py", line 220, in handle_event
self.image = self.image_down.get_rect()
AttributeError: 'pygame.Surface' object has no attribute 'image_down'
I know it's probably an easy fix, but I don't know where to look for it, and how I messed up. If someone could explain that, it would be much appreciated!
When you have an instance and call one of its methods, the instance gets automatically passed as the first argument, self. So if you have a class MyClass and an instance my_instance and you call its handle_event method, it's the same as calling MyClass.handle_event(my_instance).
In your program you never create an instance of the player class and so you're passing the screen as the self argument directly to the class (the screen is actually a pygame.Surface). That means the self in the handle_event method actually refers to the screen surface and since surfaces don't have an image_down attribute, Python raises an error when the self.image_down.get_rect() part is reached.
To fix this problem, you have to create an instance (also called object) of the player class and must not pass an argument to handle_event (unless you add more parameters to the method):
player_instance = player(x_position, y_position)
Then use the instance inside of the while and event loops:
while True:
player_instance.handle_event()
You also have to create an instance of the room1 class instead of using the class directly.
Here's a complete example with some comments about other problems:
import pygame
pygame.init()
WINDOWWIDTH = 900
WINDOWHEIGHT = 400
screen = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
FPS = 40
clock = pygame.time.Clock()
# Load images once globally and reuse them in the program.
background = pygame.image.load("bedroom.jpg").convert()
background = pygame.transform.scale(background, (WINDOWWIDTH, WINDOWHEIGHT))
temp_image = pygame.image.load("stand_down.png").convert_alpha()
image_down = pygame.transform.scale(temp_image, (100, 200))
temp_image = pygame.image.load("standleft.png").convert_alpha()
image_left = pygame.transform.scale(temp_image, (100, 200))
temp_image = pygame.image.load("standright.png").convert_alpha()
image_right = pygame.transform.scale(temp_image, (100, 200))
class player(pygame.sprite.Sprite):
def __init__(self, x, y):
super(player, self).__init__()
self.image_down = image_down
self.image_left = image_left
self.image_right = image_right
self.image = self.image_down
# keep position and size in pygame.Rect()
# to use it in collision checking
self.rect = self.image.get_rect(x=x, y=y)
# You don't have to pass x and y, since you already
# use the `self.rect` as the blit position.
def draw(self, screen):
screen.blit(self.image, self.rect)
def handle_event(self):
# These two lines don't make sense.
#self.image = self.image_down.get_rect()
#self.image = pygame.Surface((x, y))
# I guess you want to switch back to image_down.
self.image = self.image_down
key = pygame.key.get_pressed()
if key[pygame.K_LEFT]:
self.rect.x -= 5
self.image = self.image_left
if key[pygame.K_RIGHT]:
self.rect.x += 5
self.image = self.image_right
class room1():
def __init__(self):
self.x, self.y = 16, WINDOWHEIGHT/2
# Reference to the background image.
self.background = background
def draw(self, screen): # Pass the screen.
screen.blit(self.background, (0, 0))
def main():
# Create player and room instances.
player_instance = player(200, 150)
room1_instance = room1()
while True:
for event in pygame.event.get():
# Users can press the "X" button to quit.
if event.type == pygame.QUIT:
return
player_instance.handle_event()
room1_instance.draw(screen)
player_instance.draw(screen)
# You don't need both update and flip.
# pygame.display.update()
pygame.display.flip()
clock.tick(FPS)
main()
pygame.quit()
Side note: PEP 8 recommends uppercase names for classes, so Player instead of player. Then you could call the instance player.
I suspect you do somewhere something like this
player = player.transform.scale(player.image)
player is Sprite but scale returns Surface - so you replace Sprite with Surface and later you have problems.
(BTW: I saw the same problem in some question few days ago)
If you have to rescale image then do it in __init__ as you already do with some images.
In real game you should create images with correct sizes using any Image Editor so you don't have to use scale()
BTW: in handle_event you do
self.image = self.image_down.get_rect()
self.image = pygame.Surface((x, y))
You assign Rect to Surface (self.image) and later you assing new empty Surface with size x, y. Surface doesn't keep positon, it uses only width, height.
You have self.rect to keep positiona and you already change it with
self.rect.x -= 50
and
self.rect.x += 50
BTW: use UpperCaseNames for classes to make code more readable
class Player(...)
class Room1(...)
Event Stackoverflow knows this rule and it uses light blue color for classes to make code more readable.
More: PEP 8 -- Style Guide for Python Code
BTW: in room1.draw() you read and rescale image again and again - it can slow down program. Do it in room.__init__
class GameObject:
def __init__(self, x=0, y=0, width=0, high=0, imName="", imAlpha=False ):
self.x = x # on screen
self.y = y
self.width = width
self.high = high
self.imageName = imName
self.imageAlpha = imAlpha
self.image
def loadImage(self):
self.image = pygame.image.load(self.imageName)
self.image = pygame.transform.scale(self.image, (self.width, self.high))
if self.imageAlpha == True:
self.image = self.image.convert_alpha()
else:
self.image = self.image.convert()
pygame.init()
player = GameObject(px0, py0, width, high, "player.png", True)
player.loadImage()
Any ideas why I have the following error?
AttributeError: GameObject instance has no attribute 'image'
It's bad practice not to do so, but you don't need to declare object attributes in the constructor (init). When you wrote self.image, it tried accessing an attribute that didn't exist yet.
I'd advise on doing self.image = None until you load it, but removing that line entirely would work as well.
In the last line of __init__, which is called when you define player, you are attempting to access self.image, which does not exist.
I am trying to create a pacman game with pygame but I have run into a few problems. It it saying that the 'Food' has no image.
This is my pacman game [code redacted].
The problem is this area here something is wrong and it tells me that food has no attribute image
class Food(pygame.sprite.Sprite):
def __init__(self,x,y,color):
pygame.sprite.Sprite.__init__(self)
pygame.image = pygame.Surface([7,7])
self.image.fill(color)
self.rect = self.image.get_rect()
self.rect.top = y
self.rect.left = x
def update (self,player):
collidePlayer = pygame.sprite.spritecollide(self,player,False)
if collidePlayer:
food.remove
Removing all the irrelevant bits, do you see the difference between the following Sprite subclasses' __init__ methods?
class Wall(pygame.sprite.Sprite):
def __init__(self,x,y,width,height, color):#For when the walls are set up later
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([width, height]) # <-------------
self.image.fill(color)
class player(pygame.sprite.Sprite):
def __init__ (self,x,y):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([13,13]) # <-------------
self.image.fill(white)
class Food(pygame.sprite.Sprite)
def __init__(self,x,y,color):
pygame.sprite.Sprite.__init__(self)
pygame.image = pygame.Surface([7,7]) # <----- this one is different!
self.image.fill(color)
The reason you're getting an error saying that self doesn't have an image attribute is because you didn't set self.image, you stored the image in the pygame module itself.
PS: The lines which look like
food.remove
seem suspicious to me. If remove is a method, it'd be called by food.remove(), and food.remove wouldn't do anything.