How do I use multiple images with the same sprite on pygame? - python

Im learning how to use pygame and I'm trying to use multiple images with the same sprite. I want the sprites image to change when i press a button on my keyboard. Whenever i press the right arrow key and attempt to change the sprites image I get the error:
Traceback (most recent call last):
File "C:\Users\theotheo36\workspace\NomadsPie\main.py", line 55, in <module>
game.execute()
File "C:\Users\theotheo36\workspace\NomadsPie\main.py", line 50, in execute
self.render()
File "C:\Users\theotheo36\workspace\NomadsPie\main.py", line 32, in render
self.all.draw(self.screen)
File "C:\Users\theotheo36\Downloads\WinPython-64bit-3.4.4.3Qt5\python-3.4.4.amd64\lib\site-packages\pygame\sprite.py", line 475, in draw
self.spritedict[spr] = surface_blit(spr.image, spr.rect)
TypeError: invalid destination position for blit
Here is my code:
import pygame
from pygame.locals import *
class Camel(pygame.sprite.Sprite):
def __init__(self,x,y):
super().__init__()
self.faceleft=True
self.faceright=False
self.image=pygame.image.load('camel.png').convert()
self.rect=self.image.get_rect()
self.rect.x=x
self.rect.y=y
def look(self):
if self.faceleft==True:
self.image=pygame.image.load('camel.png').convert()
self.rect=self.image.get_rect()
elif self.faceright==True:
self.image=pygame.image.load('camelright.png').convert()
self.rect=self.image.get_rect
class Game(Camel):
def __init__(self):
pygame.init()
self.screen=pygame.display.set_mode((800,800))
self.all=pygame.sprite.Group()
self.camel=Camel(200,200)
self.all.add(self.camel)
self.running=True
def render(self):
self.screen.fill((255,255,255))
self.all.draw(self.screen)
pygame.display.update()
def events(self,event):
if event.type==pygame.QUIT:
self.running=False
if event.type==KEYDOWN:
if event.key==K_RIGHT:
self.camel.faceleft=False
self.camel.faceright=True
self.camel.look()
if event.key==K_LEFT:
self.camel.faceright=False
self.camel.faceleft=True
self.camel.look()
def collisons(self):
pass
def execute(self):
while (self.running):
self.render()
for event in pygame.event.get():
self.events(event)
game=Game()
game.execute()

Don't forget the parentheses after self.rect=self.image.get_rect in your look method. Without parenthesis self.rect is assigned to the function instead of the returned rectangle. Since this rectangle is used to draw the image it will cause this position error.

Related

Pygame: error when drawing sprite class to the screen [duplicate]

This question already has an answer here:
What does pygame.sprite.Group() do
(1 answer)
Closed 8 months ago.
I'm trying to draw a sprite to the screen using the class Player, but I get a traceback. It seems to be complaining when I draw the object to the screen, I'm not really sure what's causing it. I'm new to pygame so I figure that there is something that I am using wrong, or that I am missing, that I don't quite understand.
Here is my code:
import pygame
from sys import exit
# initilaization
pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption('Bullet hell')
class Player(pygame.sprite.Sprite):
'''The Main player class'''
def __init__(self):
super().__init__()
self.player_image = pygame.image.load('sprites/player/player.png').convert_alpha()
self.player_rect = self.player_image.get_rect(topleft = (0, 0))
# Player
player = pygame.sprite.GroupSingle()
player.add(Player())
# main game loop
while True:
# event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
player.draw(screen)
pygame.display.update()
It produces this error:
Traceback (most recent call last):
File "/home/linkio/Projects/bullet-hell-game/main.py", line 29, in <module>
player.draw(screen)
File "/home/linkio/.local/lib/python3.10/site-packages/pygame/sprite.py", line 552, in draw
zip(sprites, surface.blits((spr.image, spr.rect) for spr in sprites))
File "/home/linkio/.local/lib/python3.10/site-packages/pygame/sprite.py", line 552, in <genexpr>
zip(sprites, surface.blits((spr.image, spr.rect) for spr in sprites))
AttributeError: 'Player' object has no attribute 'image'
I needed to change my class attribute names. Sprite classes seem to work based on specific keywords as attributes.
class Player(pygame.sprite.Sprite):
'''The Main player class'''
def __init__(self):
super().__init__()
self.image = pygame.image.load('sprites/player/player.png').convert_alpha()
self.rect = self.image.get_rect(topleft = (0, 0))

AttributeError: 'Ballons' object has no attribute 'image'

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

It keeps showing "TypeError: update() takes 1 positional argument but 2 were given"

I am trying to code a game with Python, but it keeps showing the error "TypeError: update() takes 1 positional argument but 2 were given". I have checked multiple forums including stackoverflow multiple times, but all of them were saying that the error occurs when we forget a 'self' argument. However, that is not my case.
Below, you can see my tiles.py file. It shows the Tile class.
import pygame
class Tile(pygame.sprite.Sprite):
def __init__(self,pos,size):
super().__init__()
self.image = pygame.Surface((size,size))
self.image.fill('grey')
self.rect = self.image.get_rect(topleft = pos)
def update(self,x_shift):
self.rect.x += x_shift
As you can see, both the __init__() and the update() functions has the self argument. When I run the update part in level.py:
import pygame
from tiles import Tile
from settings import tile_size
from player import Player
class Level:
def __init__(self,level_data,surface):
self.display_surface = surface
self.setup_level(level_data)
self.world_shift = 0
def setup_level(self,layout):
self.tiles = pygame.sprite.Group()
self.player = pygame.sprite.GroupSingle()
for row_index,row in enumerate(layout):
for col_index,cell in enumerate(row):
x = col_index * tile_size
y = row_index * tile_size
if cell == 'X':
tile = Tile((x,y),tile_size)
self.tiles.add(tile)
if cell == 'P':
player_sprite = Player((x,y))
self.tiles.add(player_sprite)
def run(self):
#level tiles
self.tiles.update(self.world_shift)
self.tiles.draw(self.display_surface)
#player
self.player.update()
self.player.draw(self.display_surface)
The run function's self.tiles.update(self.world_shift), as you can see, also has an argument in it, which is the x_shift argument. However, when I run the run function in my main.py file:
import pygame, sys
from settings import *
from level import Level
#Setup
pygame.init()
screen = pygame.display.set_mode((screen_width,screen_height))
clock = pygame.time.Clock()
level = Level(level_map,screen)
pygame.display.set_caption('Pirates Run')
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
screen.fill('black')
level.run()
pygame.display.update()
clock.tick(60)
When I have run the code, the only output I get is a black screen that appears for less than a second and then closes, and then an error that looks like this:
Traceback (most recent call last):
File "c:\Users\User\OneDrive\Desktop\Blazel\Pirates Run\code\main.py", line 19, in <module>
level.run()
File "c:\Users\User\OneDrive\Desktop\Blazel\Pirates Run\code\level.py", line 26, in run
self.tiles.update(self.world_shift)
File "C:\Users\User\AppData\Local\Programs\Python\Python39\lib\site-
packages\pygame\sprite.py", line 531, in update
sprite.update(*args, **kwargs)
TypeError: update() takes 1 positional argument but 2 were given
Please help me solve this problem! Thanks!
First some basics:
pygame.sprite.Group.draw() and pygame.sprite.Group.update() are methods which are provided by pygame.sprite.Group.
The latter delegates to the update method of the contained pygame.sprite.Sprites — you have to implement the method. See pygame.sprite.Group.update():
Calls the update() method on all Sprites in the Group. [...]
The former uses the image and rect attributes of the contained pygame.sprite.Sprites to draw the objects — you have to ensure that the pygame.sprite.Sprites have the required attributes. 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. [...]
You add player_sprite to the self.tiles Group.
self.tiles.add(player_sprite)
The Tile object has an update methode:
def update(self,x_shift):
The Player object has an update method with a different argument list. This causes the error.
Do not add player_sprite to tiles, but create a separate Group for the player to solve the issue (e.g. pygame.sprite.GroupSingle).

'Chicken' object has no attribute 'rect'

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

sprite not showing up in pygame & invalid rectstyle object

I am following a tutorial on PyGame and in one of the tutorial we are creating a simple Space Invaders game. I have a few problems.
The spaceship sprite won't show on the screen, and 2. I get an error. (more details on that below)
Code:
import pygame, sys
from pygame.locals import *
clock = pygame.time.Clock() #framerate
size = x,y=800,600
screen = pygame.display.set_mode((size)) #creates window, with resolution of 1600,900
pygame.mouse.set_visible(0)
ship = pygame.image.load('ship.png')
ship_top = screen.get_height() - ship.get_height() #makes it so ship is in the centre at the bottom
ship_left = screen.get_width()/2 - ship.get_width()/2
while True: #main game loop
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
screen.fill(0,0,0)
screen.blit(ship,(ship_left,ship_top))
clock.tick(60)
pygame.display.update
Error:
Traceback (most recent call last):
File "D:\python_tuts\space_invaders.py", line 24, in <module>
screen.fill(0,0,0)
ValueError: invalid rectstyle object
So the sprites do not show, and I get that error.
Thanks,
The fill method looks like this:
fill(color, rect=None, special_flags=0) -> Rect
Since you are calling it like this:
screen.fill(0,0,0)
It assigns 0 to rect and special_flags. I think you meant to do this:
screen.fill((0,0,0))
It's even better to define color tuples at the start of your code
BLACK = (0,0,0)
screen.fill(BLACK)

Categories

Resources