Add_internal Attribut Error with sprites and Masks - python

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.

Related

AttributeError: GameObject instance has no attribute - PyGame

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.

Layering sprites in pygame with an unorthodox character class? [duplicate]

I have an image in pygame with multiple instances of the image called in a for loop. is there a way I could move each instance of the image independently without moving the others with the code as is? or will I have to load separate instances of the image individually?
def pawn(self):
y_pos = 100
self.image = pygame.transform.scale(pygame.image.load('pawn.png'), (100,100))
for x_pos in range(0,8,1):
pieceNum = x_pos
screen.blit(self.image, (x_pos*100, y_pos))
I recommend to use pygame.sprite.Sprite and pygame.sprite.Group:
Create a class derived from pygame.sprite.Sprite:
class MySprite(pygame.sprite.Sprite):
def __init__(self, image, pos_x, pos_y):
super().__init__()
self.image = image
self.rect = self.image.get_rect()
self.rect.topleft = (pos_x, pos_y)
Load the image
image = pygame.transform.scale(pygame.image.load('pawn.png'), (100,100))
Create a list of sprites
imageList = [MySprite(image, x_pos*100, 100) for x_pos in range(0,8,1)]
and create a sprite group:
group = pygame.sprite.Group(imageList)
The sprites of a group can be drawn by .draw (screen is the surface created by pygame.display.set_mode()):
group.draw(screen)
The position of the sprite can be changed by changing the position of the .rect property (see pygame.Rect).
e.g.
imageList[0].rect = imageList[0].rect.move(move_x, move_y)
Of course, the movement can be done in a method of class MySprite:
e.g.
class MySprite(pygame.sprite.Sprite):
# [...]
def move(self, move_x, move_y):
self.rect = self.rect.move(move_x, move_y)
imageList[1].move(0, 100)

Using and making sprite groups [duplicate]

I have an image in pygame with multiple instances of the image called in a for loop. is there a way I could move each instance of the image independently without moving the others with the code as is? or will I have to load separate instances of the image individually?
def pawn(self):
y_pos = 100
self.image = pygame.transform.scale(pygame.image.load('pawn.png'), (100,100))
for x_pos in range(0,8,1):
pieceNum = x_pos
screen.blit(self.image, (x_pos*100, y_pos))
I recommend to use pygame.sprite.Sprite and pygame.sprite.Group:
Create a class derived from pygame.sprite.Sprite:
class MySprite(pygame.sprite.Sprite):
def __init__(self, image, pos_x, pos_y):
super().__init__()
self.image = image
self.rect = self.image.get_rect()
self.rect.topleft = (pos_x, pos_y)
Load the image
image = pygame.transform.scale(pygame.image.load('pawn.png'), (100,100))
Create a list of sprites
imageList = [MySprite(image, x_pos*100, 100) for x_pos in range(0,8,1)]
and create a sprite group:
group = pygame.sprite.Group(imageList)
The sprites of a group can be drawn by .draw (screen is the surface created by pygame.display.set_mode()):
group.draw(screen)
The position of the sprite can be changed by changing the position of the .rect property (see pygame.Rect).
e.g.
imageList[0].rect = imageList[0].rect.move(move_x, move_y)
Of course, the movement can be done in a method of class MySprite:
e.g.
class MySprite(pygame.sprite.Sprite):
# [...]
def move(self, move_x, move_y):
self.rect = self.rect.move(move_x, move_y)
imageList[1].move(0, 100)

Constructing images and loading

I have a super class Sprite and a sub class character:
class Sprite(pygame.sprite.Sprite):
def __init__self(self,Image,position):
pygame.sprite.Sprite.__init__(self)
self.image =pygame.image.load(Image)
self.rect = self.image.get_rect()
self.rect.topleft = pos
class Character(Sprite):
character = pygame.sprite.Group()
def __init__(self):
self.finalimage = pygame.Surface([5, 5])
self.image = self.finalimage
self.rect = self.image.get_rect()
In the Character class I have methods setimage and collision.I use the sprite class to check if a character collides with another for example:
sprite = Sprite(self.image,(self.x,self.y))
self.character.add(sprite)
pygame.sprite.spritecollide(sprite, Background.character, True)
So i need to call the sprite class for collisions. My problem is when I try and give a image to the sprite in the sprite class this is the image which stays when I Use this class, when I give the image object from the constructor I get the error :
pygame.error: Can't seek in this data source
from this line: self.image =pygame.image.load(Image)
Is there a neat way of overriding/ providing your own images? Clearly my logic doesnt work.
Thanks in advance!
self.image has to be a filename (or file object) in sprite = Sprite(self.image,(self.x,self.y)) but it seems you have surface in self.image
# class Character
self.finalimage = pygame.Surface([5, 5]) # finalimage is Surface
self.image = self.finalimage # finalimage is Surface so image is Surface
# ...
sprite = Sprite(self.image,(self.x,self.y)) # image is Surface
# class Sprite
def __init__self(self,Image,position): # so Image is Surface
# ...
self.image =pygame.image.load(Image) # so Image is Surface

pygame image AttributeError

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.

Categories

Resources