how to animate the sprite? - python

from numpy import size
import pygame
import sys
# --- constants --- # PEP8: `UPPER_CASE_NAMES` for constants
WHITE = (255, 255, 255) # PE8: space after `,`
SIZE = (700, 500)
FPS = 120 # there is no need to use `500` because Python can't run so fast,
# and monitors runs with 60Hz (eventually 120Hz) which can display 60 FPS (120 FPS)
# --- classes --- # PEP8: `CamelCaseNames` for classes
class MySprite(pygame.sprite.Sprite):
def __init__(self, x, y, picture, colorkey):
super().__init__()
# you need one of them
# load image
self.image = pygame.image.load(picture)
# OR
# create surface
# self.image = pygame.Surface((10, 10))
# self.image.fill((255, 0, 0))
# ----
self.rect = self.image.get_rect()
self.rect.center = (x, y)
self.image.set_colorkey(colorkey)
def update(self):
if event.type == pygame.MOUSEBUTTONDOWN:
mouse = pygame.mouse.get_pos()
print(mouse[:])
# --- main ---
pygame.init()
window_game = pygame.display.set_mode(SIZE)
backGround = pygame.image.load('bg.jpg').convert_alpha(window_game)
backGround = pygame.transform.smoothscale(backGround,SIZE)
backGround.set_colorkey(WHITE)
#placeSP_group = pygame.sprite.Group()
placeSP_group = pygame.sprite.OrderedUpdates() # Group which keep order
sprite1 = [MySprite(0, 0, 'crossHair.png', WHITE),MySprite(0, 0, 'crossHair_2.png', WHITE)]
placeSP_group.add([sprite1[0],sprite1[1]])
pygame.mouse.set_visible(False)
clock = pygame.time.Clock() # PEP8: `lower_case_names` for variables
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
#running = False
pygame.quit()
exit()
# create new Sprite
global x,y
x, y = pygame.mouse.get_pos()
new_sprite = sprite1[:]
# add new Sprite at the end of OrderedUpdates()
placeSP_group.add([new_sprite])
# remove Sprite at the beginning of OrderedUpdates()
placeSP_group.sprites()[0].kill()
placeSP_group.update()
# ---
pygame.display.flip()
window_game.fill('white')
window_game.blit(backGround,(0,0)).size
placeSP_group.draw(window_game)
clock.tick(FPS)
when i assignee new_sprite to all the assigned sprites in placeSP
it dosen't show any thing can you help me with that i am not sure why is that happening but can you fix it ... this an edited question. And i didn't got any answer .... but i have the concept in my head can and i also don't wan't to modify my code that much can you help me with that...

Create a sprite class with a list of images. Add an attribute that counts the frames. Get image from image list in the update method based on number of frames:
class MySprite(pygame.sprite.Sprite):
def __init__(self, x, y, image_list):
super().__init__()
self.frame = 0
self.image_list = image_list
self.image = self.image_list[0]
self.rect = self.image.get_rect()
self.rect.center = (x, y)
def update(self, event_list):
animation_interval = 20
self.frame += 1
if self.frame // animation_interval >= len(self.image_list):
self.frame = 0
self.image = self.image_list[self.frame // animation_interval]
for event in event_list:
if event.type == pygame.MOUSEBUTTONDOWN:
mouse = event.pos
print(mouse[:])
However, instead of constantly creating and killing the sprite every frame, you need to create the sprite once before the application loop. Change the position of the sprite and update the sprite in the application loop:
file_list = ['crossHair.png', 'crossHair_2.png', 'crossHair_3.png']
image_list = []
for name in file_list:
image = pygame.image.load(name)
image.set_colorkey(WHITE)
image_list.append(image)
# create sprite
sprite1 = MySprite(0, 0, image_list)
placeSP_group = pygame.sprite.OrderedUpdates()
placeSP_group.add([sprite1])
clock = pygame.time.Clock()
running = True
while running:
# handle events
event_list = pygame.event.get()
for event in event_list:
if event.type == pygame.QUIT:
running = False
# update sprite
x, y = pygame.mouse.get_pos()
placeSP_group.sprites()[0].rect.center = (x, y)
placeSP_group.update(event_list)
# draw scene
window_game.fill('white')
window_game.blit(backGround,(0,0)).size
placeSP_group.draw(window_game)
pygame.display.flip()
clock.tick(FPS)
pygame.quit()
exit()
See also:
how to create an illusion of animations in pygame
Animated sprite from few images
How do I create animated sprites using Sprite Sheets in Pygame?

Related

Pygame. Sprite is still drawing after killing itself

I want to remove the sprite and not display it on screen after click. The screenshot show that the sprite is successfully removed from the group, but it is still drawn on the screen. I would be happy to get help on this matter.
import pygame as pg
class Figure1(pg.sprite.Sprite):
def __init__(self, width: int, height: int):
super().__init__()
self.image = pg.Surface((width, height))
self.image.fill((0,0,0))
self.rect = self.image.get_rect()
class Game:
def __init__(self, main_surface: pg.Surface):
self.main_surface = main_surface
self.group = pg.sprite.Group()
self.main_sprite = Figure1(40,40)
self.group.add(self.main_sprite)
self.group.draw(self.main_surface)
self.selected = None
def btn_down(self, pos, btn):
if btn == 1:
if self.main_sprite.rect.collidepoint(pos):
print(self.group.sprites())
print(self.main_sprite.alive())
self.main_sprite.kill()
print(self.group.sprites())
print(self.main_sprite.alive())
self.group.draw(self.main_surface)
pg.init()
clock = pg.time.Clock()
screen = pg.display.set_mode((200,200))
screen.fill((100,100,100))
pg.display.update()
g = Game(screen)
run = True
while run:
for event in pg.event.get():
if event.type == pg.QUIT:
pg.quit()
run = False
if event.type == pg.MOUSEBUTTONDOWN:
g.btn_down(event.pos, event.button)
clock.tick(60)
pg.display.update()
The sprite doesn't disappear just because you stop drawing it. Of course, you need to clear the screen. You have to clear the screen in every frame. The typical PyGame application loop has to:
limit the frames per second to limit CPU usage with pygame.time.Clock.tick
handle the events by calling either pygame.event.pump() or pygame.event.get().
update the game states and positions of objects dependent on the input events and time (respectively frames)
clear the entire display or draw the background
draw the entire scene (blit all the objects)
update the display by calling either pygame.display.update() or pygame.display.flip()
import pygame as pg
class Figure1(pg.sprite.Sprite):
def __init__(self, width: int, height: int):
super().__init__()
self.image = pg.Surface((width, height))
self.image.fill((0,0,0))
self.rect = self.image.get_rect()
class Game:
def __init__(self, main_surface: pg.Surface):
self.main_surface = main_surface
self.group = pg.sprite.Group()
self.main_sprite = Figure1(40,40)
self.group.add(self.main_sprite)
self.selected = None
def btn_down(self, pos, btn):
if btn == 1:
if self.main_sprite.rect.collidepoint(pos):
self.main_sprite.kill()
def draw(self):
self.group.draw(self.main_surface)
pg.init()
clock = pg.time.Clock()
screen = pg.display.set_mode((200,200))
g = Game(screen)
run = True
while run:
# limit the frames per second
clock.tick(60)
# handle the events and update objects
for event in pg.event.get():
if event.type == pg.QUIT:
run = False
if event.type == pg.MOUSEBUTTONDOWN:
g.btn_down(event.pos, event.button)
# clear the screen
screen.fill((100,100,100))
# draw the objects
g.draw()
# update the display
pg.display.update()
pg.quit()

i want to kill my sprite. how to kill it?

import pygame as pygame , sys,time
pygame.init()
size = (700,500)
window_game = pygame.display.set_mode(size)
_run_ = True
white = (255,255,255)
mouse_pos = pygame.mouse.get_pos()
class mySprite(pygame.sprite.Sprite):
def __init__ (self,cord_x,cord_y,picture,colorkey):
super().__init__()
self.image = pygame.Surface([0,0])
self.image = pygame.image.load(picture)
self.image.set_colorkey(colorkey)
self.rect = self.image.get_rect()
self.rect.center = [cord_x,cord_y]
self.kill()
placeSP_group = pygame.sprite.Group()
Clock = pygame.time.Clock()
FPS = 500
while _run_:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.QUIT
sys.exit()
mouse_pos = pygame.mouse.get_pos()
placeSP = [mySprite(mouse_pos[0],mouse_pos[1],'sp_1.png',white)]
pygame.display.flip()
placeSP_group.draw(window_game)
placeSP_group.add(placeSP[:])
Clock.tick(FPS)
now i want that my sprite get's killed and get the new mouse position
and window_game.fill('black')
dosen't work is there any thing you can do to fix it pls tell me...
what i wan't is every time my mouse moves i wan't kill the last sprite and create the other one with the current sprite pos.
You use kill() in wrong moment.
kill() works when Sprite is inside Group but you first create Sprite which try to use kill() and later you add this sprite to Group.
You should first create Sprite, next add to Group and later run kill() for first Sprite in Group
placeSP_group.sprites()[0].kill()
but normal Group doesn't have to keep sprites in order and better use
placeSP_group = pygame.sprite.OrderedUpdates()
Full working code. It display 5 sprites which follow mouse.
import pygame
import sys
# --- constants --- # PEP8: `UPPER_CASE_NAMES` for constants
WHITE = (255, 255, 255) # PE8: space after `,`
SIZE = (700, 500)
FPS = 50 # there is no need to use `500` because Python can't run so fast,
# and monitors runs with 60Hz (eventually 120Hz) which can display 60 FPS (120 FPS)
# --- classes --- # PEP8: `CamelCaseNames` for classes
class MySprite(pygame.sprite.Sprite):
def __init__(self, x, y, picture, colorkey):
super().__init__()
# you need one of them
# load image
#self.image = pygame.image.load(picture)
# OR
# create surface
self.image = pygame.Surface((10, 10))
self.image.fill((255, 0, 0))
# ----
self.rect = self.image.get_rect()
self.rect.center = (x, y)
self.image.set_colorkey(colorkey)
# --- main ---
pygame.init()
window_game = pygame.display.set_mode(SIZE)
#placeSP_group = pygame.sprite.Group()
placeSP_group = pygame.sprite.OrderedUpdates() # Group which keep order
sprite1 = MySprite(0, 0, 'sp_1.png', WHITE)
sprite2 = MySprite(0, 0, 'sp_1.png', WHITE)
sprite3 = MySprite(0, 0, 'sp_1.png', WHITE)
sprite4 = MySprite(0, 0, 'sp_1.png', WHITE)
sprite5 = MySprite(0, 0, 'sp_1.png', WHITE)
placeSP_group.add([sprite1, sprite2, sprite3, sprite4, sprite5])
clock = pygame.time.Clock() # PEP8: `lower_case_names` for variables
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
#running = False
pygame.quit()
exit()
# create new Sprite
x, y = pygame.mouse.get_pos()
new_sprite = MySprite(x, y, 'sp_1.png', WHITE)
# add new Sprite at the end of OrderedUpdates()
placeSP_group.add([new_sprite])
# remove Sprite at the beginning of OrderedUpdates()
placeSP_group.sprites()[0].kill()
# ---
pygame.display.flip()
window_game.fill('black')
placeSP_group.draw(window_game)
clock.tick(FPS)

How to prevent images overlapping each other in pygame?

When I run the code the target images overlap each other
so if we shoot the target images which are overlapped are also removed
this is a big issue in my game help me to solve this
Like this:
import pygame, sys
import os
import random
pygame.mixer.init()
pygame.init()
class Crosshair(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load(os.path.join("files", 'crosshair.png'))
self.rect = self.image.get_rect()
self.shot_sound = pygame.mixer.Sound(os.path.join('files','shot.wav'))
def sound(self):
self.shot_sound.play()
pygame.sprite.spritecollide(crosshair,target_group, True)
def update(self):
self.rect.center = pygame.mouse.get_pos()
class Target(pygame.sprite.Sprite):
def __init__(self, target ,x,y):
super().__init__()
self.image = pygame.image.load(target)
self.rect = self.image.get_rect()
self.rect.center = [x,y]
# Screeen
width, height = 1000,700
screen = pygame.display.set_mode((width,height))
clock = pygame.time.Clock()
bg = pygame.transform.scale2x(pygame.transform.scale2x(pygame.image.load(os.path.join('files','bg.png'))))
pygame.display.set_caption("Shotting Game")
pygame.mouse.set_visible(False)
# crosshair
crosshair = Crosshair()
crosshair_group = pygame.sprite.Group()
crosshair_group.add(crosshair)
# Target
target_group = pygame.sprite.Group()
for target in range(20):
draw_target = Target(os.path.join('files','target.png'),random.randint(0,width), random.randint(0,height))
target_group.add(draw_target)
# Main loop
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
crosshair.sound()
screen.fill((255,255,255))
screen.blit(bg,(0,0))
target_group.draw(screen)
crosshair_group.draw(screen)
crosshair_group.update()
pygame.display.update()
clock.tick(50)
Use pygame.sprite.spritecollide to see if a new target intersects with another. Only add the target if it doesn't overlap:
target_group = pygame.sprite.Group()
while len(target_group) < 20:
draw_target = Target(os.path.join('files','target.png'),random.randint(0,width), random.randint(0,height))
if not pygame.sprite.spritecollide(draw_target, target_group, False):
target_group.add(draw_target)
If you want to generate continuous targets, you can use the application loop:
# Target
target_group = pygame.sprite.Group()
# Main loop
while True:
if len(target_group) < 20:
draw_target = Target(os.path.join('files','target.png'),random.randint(0,width), random.randint(0,height))
if not pygame.sprite.spritecollide(draw_target, target_group, False):
target_group.add(draw_target)

Im trying to make a movable rectangle. When you run this code it displays the pygame window but nothing else. Any ideas? [duplicate]

This question already has an answer here:
Python only running while loop once
(1 answer)
Closed 2 years ago.
This is my code for my game. I am trying to display a rectangle i can move with wasd or arrow keys. But when I run it the window is just black and that's it. No rectangle.
import pygame
class window:
def __init__(self, height, width):
self.height = height
self.width = width
window.height = 800
window.width = 600
class Player(object):
def __init__(self):
self.rect = pygame.rect.Rect((64, 54, 16, 16))
def handle_keys(self):
key = pygame.key.get_pressed()
dist = 1
if key[pygame.K_LEFT]:
self.rect.move_ip(-1, 0)
def draw(self, surface):
# Im guessing this is where the problem is
screen.fill(255, 255, 255)
pygame.draw.rect(screen, (0, 0, 128), self.rect)
#making thi window
def makeWindow():
pygame.init()
screen = pygame.display.set_mode((window.height, window.width))
# pygame loop
def loop():
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if __name__ == "__main__":
makeWindow()
player = Player()
loop()
To move the player with wasd, you have to evaluate the state of the keys in Player.handle_keys and to change the position of self.rect:
class Player(object):
# [...]
def handle_keys(self):
key = pygame.key.get_pressed()
dist = 1
if key[pygame.K_a]:
self.rect.move_ip(-1, 0)
if key[pygame.K_d]:
self.rect.move_ip(1, 0)
if key[pygame.K_w]:
self.rect.move_ip(0, -1)
if key[pygame.K_s]:
self.rect.move_ip(0, 1)
The argument to pygame.Surface.fill() has to be a tuple with 3 or 4 arguments:
screen.fill(255, 255, 255)
screen.fill((255, 255, 255))
screen has to be a variable in global namespace. Use the global statement:
def makeWindow():
global screen
pygame.init()
screen = pygame.display.set_mode((window.height, window.width))
In the main main application loop has to:
handle the events by either pygame.event.pump() or pygame.event.get().
update the game states and positions of objects dependent on the input events and time (respectively frames)
clear the entire display or draw the background
draw the entire scene (blit all the objects)
update the display by either pygame.display.update() or pygame.display.flip()
def loop():
running = True
while running:
# handle events
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# update position of player
player.handle_keys()
# clear display
screen.fill((255, 255, 255))
# draw scene
player.draw(screen)
# update display
pygame.display.flip()
See the complete example code:
import pygame
class window:
def __init__(self, height, width):
self.height = height
self.width = width
window.height = 800
window.width = 600
class Player(object):
def __init__(self):
self.rect = pygame.rect.Rect((64, 54, 16, 16))
def handle_keys(self):
key = pygame.key.get_pressed()
dist = 1
if key[pygame.K_a]:
self.rect.move_ip(-1, 0)
if key[pygame.K_d]:
self.rect.move_ip(1, 0)
if key[pygame.K_w]:
self.rect.move_ip(0, -1)
if key[pygame.K_s]:
self.rect.move_ip(0, 1)
def draw(self, surface):
# Im guessing this is where the problem is
pygame.draw.rect(surface, (0, 0, 128), self.rect)
#making thi window
def makeWindow():
global screen
pygame.init()
screen = pygame.display.set_mode((window.height, window.width))
# pygame loop
def loop():
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.fill((255, 255, 255))
player.handle_keys()
player.draw(screen)
pygame.display.flip()
if __name__ == "__main__":
makeWindow()
player = Player()
loop()

Pygame sprite creating duplicate instead of moving

I am fairly new to Pygame.
I am attempting to re-create Pong in Python using Pygame, but I have hit a roadblock.
Here is my code:
import pygame
pygame.init()
UP = "up"
DOWN = "down"
white = (255,255,255)
black = (0,0,0)
pygame.mouse.set_visible(True)
resolution = (800,600)
window = pygame.display.set_mode(resolution)
pygame.display.set_caption("Pong!")
clock = pygame.time.Clock()
sprites_list = pygame.sprite.Group()
running = True
class Paddle(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface((25,100))
self.image.fill(white)
pygame.draw.rect(self.image,white, (0,0,25,100))
self.rect = self.image.get_rect()
def move(self,direction,pixels):
if direction == DOWN:
self.rect.y -= pixels
if direction == UP:
self.rect.y += pixels
player1 = Paddle()
player1.rect.x = 0
player1.rect.y = 200
sprites_list.add(player1)
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
keys = pygame.key.get_pressed()
if keys[pygame.K_DOWN]:
player1.move(DOWN, 5)
if keys[pygame.K_UP]:
player1.move(UP, 5)
sprites_list.update()
sprites_list.draw(window)
pygame.display.flip()
clock.tick(60)
pygame.quit()
I am trying to make player1, a Paddle object, move up or down depending on which key is pressed. When I run this code, player1 is stretched out after the up or down arrows are pressed; 5 pixels are added onto player1.rect.
What am I doing wrong and why will sprites_list.update() not put player1 in its new position?
You have to clear screen before you draw elements in new loop.
You can fill window with black color window.fill((0,0,0)) or draw background image in every loop.
This is your code after reorganization and adding window.fill(BLACK)
import pygame
# --- constants --- (UPPER_CASE_NAMES)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
UP = "up"
DOWN = "down"
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
# --- classes ---- (CamelCaseNames)
class Paddle(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface((25,100))
self.image.fill(WHITE)
# you don't have to draw white rect if all surface already is white
#pygame.draw.rect(self.image,white, (0,0,25,100))
self.rect = self.image.get_rect()
def move(self, direction, pixels):
if direction == DOWN:
self.rect.y += pixels
if direction == UP:
self.rect.y -= pixels
# --- functions --- (lower_case_names)
# empty
# --- main --- (lower_case_names)
# - init -
pygame.init()
pygame.mouse.set_visible(True)
window = pygame.display.set_mode(resolution)
pygame.display.set_caption("Pong!")
# - objects -
sprites_list = pygame.sprite.Group()
player1 = Paddle()
player1.rect.x = 0
player1.rect.y = 200
sprites_list.add(player1)
# - mainloop -
clock = pygame.time.Clock()
running = True
while running:
# - events -
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
keys = pygame.key.get_pressed()
if keys[pygame.K_DOWN]:
player1.move(DOWN, 5)
if keys[pygame.K_UP]:
player1.move(UP, 5)
# - updates (without draws) -
sprites_list.update()
# - draws (without updates) -
window.fill(BLACK) # <--- clear screen
sprites_list.draw(window)
pygame.display.flip()
clock.tick(60)
# - end -
pygame.quit()

Categories

Resources