I am following a video about pygame and I saw this code
crosshair = pygame.sprite.Group()
Could someone explain me this?
Read the documentation of pygame.sprite.Group.
pygame.sprite.Group.update() and pygame.sprite.Group.draw() are methods which are provided by pygame.sprite.Group.
The former delegates the to the update method of the contained pygame.sprite.Sprites - you have to implement the method.
pygame.sprite.Group.update()
Calls the update() method on all Sprites in the Group.
The later 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
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 for the position.
The Sprites in the Groups can be removed and thus destroyed by calling pygame.sprite.Sprite.kill. When the object is no longer referenced, it is destroyed:
The Sprite is removed from all the Groups that contain it. This won't change anything about the state of the Sprite. It is possible to continue to use the Sprite after this method has been called, including adding it to Groups.
See also Sprite Groups
Minimal example:
import pygame
class Player(pygame.sprite.Sprite):
def __init__(self, center_pos):
super().__init__()
self.image = pygame.Surface((40, 40))
self.image.fill((255, 255, 0))
self.rect = self.image.get_rect(center = center_pos)
class Bullet(pygame.sprite.Sprite):
def __init__(self, center_pos):
super().__init__()
self.image = pygame.Surface((20, 10))
self.image.fill((0, 255, 255))
self.rect = self.image.get_rect(center = center_pos)
def update(self):
self.rect.x += 10
if self.rect.right > 300:
self.kill()
pygame.init()
window = pygame.display.set_mode((400, 300))
clock = pygame.time.Clock()
player = Player((25, window.get_height() // 2))
all_sprites = pygame.sprite.Group(player)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
all_sprites.add(Bullet(player.rect.center))
all_sprites.update()
print(len(all_sprites))
window.fill(0)
pygame.draw.rect(window, (255, 0, 0), (300, 0, 10, window.get_height()))
all_sprites.draw(window)
pygame.display.flip()
pygame.quit()
exit()
Related
I am following a video about pygame and I saw this code
crosshair = pygame.sprite.Group()
Could someone explain me this?
Read the documentation of pygame.sprite.Group.
pygame.sprite.Group.update() and pygame.sprite.Group.draw() are methods which are provided by pygame.sprite.Group.
The former delegates the to the update method of the contained pygame.sprite.Sprites - you have to implement the method.
pygame.sprite.Group.update()
Calls the update() method on all Sprites in the Group.
The later 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
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 for the position.
The Sprites in the Groups can be removed and thus destroyed by calling pygame.sprite.Sprite.kill. When the object is no longer referenced, it is destroyed:
The Sprite is removed from all the Groups that contain it. This won't change anything about the state of the Sprite. It is possible to continue to use the Sprite after this method has been called, including adding it to Groups.
See also Sprite Groups
Minimal example:
import pygame
class Player(pygame.sprite.Sprite):
def __init__(self, center_pos):
super().__init__()
self.image = pygame.Surface((40, 40))
self.image.fill((255, 255, 0))
self.rect = self.image.get_rect(center = center_pos)
class Bullet(pygame.sprite.Sprite):
def __init__(self, center_pos):
super().__init__()
self.image = pygame.Surface((20, 10))
self.image.fill((0, 255, 255))
self.rect = self.image.get_rect(center = center_pos)
def update(self):
self.rect.x += 10
if self.rect.right > 300:
self.kill()
pygame.init()
window = pygame.display.set_mode((400, 300))
clock = pygame.time.Clock()
player = Player((25, window.get_height() // 2))
all_sprites = pygame.sprite.Group(player)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
all_sprites.add(Bullet(player.rect.center))
all_sprites.update()
print(len(all_sprites))
window.fill(0)
pygame.draw.rect(window, (255, 0, 0), (300, 0, 10, window.get_height()))
all_sprites.draw(window)
pygame.display.flip()
pygame.quit()
exit()
I'm new at pygame, so I don't know so much about sprites. I wanted to make my code more clean so I used a sprite. And to display my image with rect I wrote:
self.frame_index = 0
self.surf = self.frames[self.frame_index]
self.frame_rect = self.surf.get_rect(midtop = (self.x_pos, self.y_pos))
But it raised AttributeError: 'Enemy' object has no attribute 'image' error. Enemy is my class' name. When I used self.image and self.rect instead of self.surf and self.frame_rect my code worked properly.
My main question is: Why we have to use self.rect and self.image when we use a sprite to determine our surface and rect?
My main question is: Why we have to use self.rect and self.image when we use a sprite to determine our surface and rect?
This is related to the pygame.sprite.Group. Groups are used to manage Sprites. pygame.sprite.Group.draw() and pygame.sprite.Group.update() are methods which are provided by pygame.sprite.Group.
The former delegates the 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 later 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. [...]
Minimal example:
import pygame
pygame.init()
window = pygame.display.set_mode((400, 400))
clock = pygame.time.Clock()
class Player(pygame.sprite.Sprite):
def __init__(self, center_pos):
super().__init__()
self.image = pygame.Surface((40, 40))
self.image.fill((0, 255, 0))
self.rect = self.image.get_rect(center = center_pos)
def update(self, surf):
keys = pygame.key.get_pressed()
self.rect.x += (keys[pygame.K_d]-keys[pygame.K_a]) * 5
self.rect.y += (keys[pygame.K_s]-keys[pygame.K_w]) * 5
self.rect.clamp_ip(surf.get_rect())
all_sprites = pygame.sprite.Group([Player(window.get_rect().center)])
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
all_sprites.update(window)
window.fill(0)
all_sprites.draw(window)
pygame.display.flip()
pygame.quit()
exit()
I am making a game and when the sprite "Bomb" goes under 450 on the y axis, it is supposed to be deleted.
import pygame
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREY = (129, 129, 129)
class SpriteSheet(object):
def __init__(self, file_name):
self.sprite_sheet = pygame.image.load(file_name).convert()
def get_image(self, x, y, width, height, colour):
image = pygame.Surface([width, height]).convert()
image.set_colorkey(colour)
image.blit(self.sprite_sheet, (0, 0), (x, y, width, height))
return image
class Bomb(pygame.sprite.Sprite):
change_x =0
change_y = 0
def __init__(self):
super().__init__()
sprite_sheet = SpriteSheet("Untitled.png")
self.image = sprite_sheet.get_image(2, 2, 48, 48, WHITE)
self.rect = self.image.get_rect()
def move(self, y):
self.rect.y += y
if self.rect.y > 450:
self.kill()
print (self.rect.y)
pygame.init()
screen_width = 1000
screen_height = 500
screen = pygame.display.set_mode([screen_width, screen_height])
pygame.display.set_caption("Game")
clock = pygame.time.Clock()
done = False
bomb = Bomb()
all_sprites = pygame.sprite.Group()
all_sprites.add(bomb)
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
screen.fill(WHITE)
all_sprites.draw(screen)
bomb.move(2)
clock.tick(60)
pygame.display.flip()
pygame.quit()
(Note that I'm printing the y axis of the bomb to check if it's deleted or not.) I tried to use the "kill()" method, but what happens is, it does disappear, but the y axis continues to print, which I think is not supposed to happen.
I tried to use the kill() method in another piece of code. It gets deleted and the y axis stops printing. The only difference between the 2 codes is that in this one, I am blitting an image onto the screen to use as a sprite, and in that one, I am using "Rect" to make the sprite.
Can someone please guide me on what else can I do to permanently remove the sprite from the memory, or is it okay if the values of the y axis are printing all the time (the sprite should be deleted)?
The kill() method does not magically remove objects from memory. All it does is removing a Sprite from all it's Groups.
So in your code, the bomb is no longer displayed because it's no longer in all_sprites after kill() is called. But you still have a reference to the object (bomb), and you still call the move function every frame on the object. So the print statement is executed.
What do you expect to happen to your bomb variable after you called kill()?
Usually, you should implement all sprite logic in a method called update, and not call this method directly, but via the group, too, like the draw method.
Something like this:
class Bomb(pygame.sprite.Sprite):
change_x =0
change_y = 0
def __init__(self):
super().__init__()
sprite_sheet = SpriteSheet("Untitled.png")
self.image = sprite_sheet.get_image(2, 2, 48, 48, WHITE)
self.rect = self.image.get_rect()
self.speed = 2
def update(self, y):
self.rect.y += self.speed
if self.rect.y > 450:
self.kill()
print (self.rect.y)
...
all_sprites = pygame.sprite.Group()
all_sprites.add(Bomb())
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
screen.fill(WHITE)
all_sprites.draw(screen)
all_sprites.update()
clock.tick(60)
pygame.display.flip()
pygame.quit()
This way, after kill() is called, no references to the object remain (and the python runtime will remove it from memory eventually).
I am following a video about pygame and I saw this code
crosshair = pygame.sprite.Group()
Could someone explain me this?
Read the documentation of pygame.sprite.Group.
pygame.sprite.Group.update() and pygame.sprite.Group.draw() are methods which are provided by pygame.sprite.Group.
The former delegates the to the update method of the contained pygame.sprite.Sprites - you have to implement the method.
pygame.sprite.Group.update()
Calls the update() method on all Sprites in the Group.
The later 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
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 for the position.
The Sprites in the Groups can be removed and thus destroyed by calling pygame.sprite.Sprite.kill. When the object is no longer referenced, it is destroyed:
The Sprite is removed from all the Groups that contain it. This won't change anything about the state of the Sprite. It is possible to continue to use the Sprite after this method has been called, including adding it to Groups.
See also Sprite Groups
Minimal example:
import pygame
class Player(pygame.sprite.Sprite):
def __init__(self, center_pos):
super().__init__()
self.image = pygame.Surface((40, 40))
self.image.fill((255, 255, 0))
self.rect = self.image.get_rect(center = center_pos)
class Bullet(pygame.sprite.Sprite):
def __init__(self, center_pos):
super().__init__()
self.image = pygame.Surface((20, 10))
self.image.fill((0, 255, 255))
self.rect = self.image.get_rect(center = center_pos)
def update(self):
self.rect.x += 10
if self.rect.right > 300:
self.kill()
pygame.init()
window = pygame.display.set_mode((400, 300))
clock = pygame.time.Clock()
player = Player((25, window.get_height() // 2))
all_sprites = pygame.sprite.Group(player)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
all_sprites.add(Bullet(player.rect.center))
all_sprites.update()
print(len(all_sprites))
window.fill(0)
pygame.draw.rect(window, (255, 0, 0), (300, 0, 10, window.get_height()))
all_sprites.draw(window)
pygame.display.flip()
pygame.quit()
exit()
I am following a video about pygame and I saw this code
crosshair = pygame.sprite.Group()
Could someone explain me this?
Read the documentation of pygame.sprite.Group.
pygame.sprite.Group.update() and pygame.sprite.Group.draw() are methods which are provided by pygame.sprite.Group.
The former delegates the to the update method of the contained pygame.sprite.Sprites - you have to implement the method.
pygame.sprite.Group.update()
Calls the update() method on all Sprites in the Group.
The later 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
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 for the position.
The Sprites in the Groups can be removed and thus destroyed by calling pygame.sprite.Sprite.kill. When the object is no longer referenced, it is destroyed:
The Sprite is removed from all the Groups that contain it. This won't change anything about the state of the Sprite. It is possible to continue to use the Sprite after this method has been called, including adding it to Groups.
See also Sprite Groups
Minimal example:
import pygame
class Player(pygame.sprite.Sprite):
def __init__(self, center_pos):
super().__init__()
self.image = pygame.Surface((40, 40))
self.image.fill((255, 255, 0))
self.rect = self.image.get_rect(center = center_pos)
class Bullet(pygame.sprite.Sprite):
def __init__(self, center_pos):
super().__init__()
self.image = pygame.Surface((20, 10))
self.image.fill((0, 255, 255))
self.rect = self.image.get_rect(center = center_pos)
def update(self):
self.rect.x += 10
if self.rect.right > 300:
self.kill()
pygame.init()
window = pygame.display.set_mode((400, 300))
clock = pygame.time.Clock()
player = Player((25, window.get_height() // 2))
all_sprites = pygame.sprite.Group(player)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
all_sprites.add(Bullet(player.rect.center))
all_sprites.update()
print(len(all_sprites))
window.fill(0)
pygame.draw.rect(window, (255, 0, 0), (300, 0, 10, window.get_height()))
all_sprites.draw(window)
pygame.display.flip()
pygame.quit()
exit()