Move sprite in pygame without flickering [duplicate] - python

This question already has answers here:
Why is my PyGame application not running at all?
(2 answers)
Why is nothing drawn in PyGame at all?
(2 answers)
Why is the PyGame animation is flickering
(1 answer)
Closed 2 years ago.
So I've been playing around in pygame, and I can draw and use the update method to move my sprite, but when I clear the screen the sprite flickers. How do I move the sprite without the flickering
Here's the code:
class Sprite(pygame.sprite.Sprite):
def __init__(self, pos):
super(Sprite, self).__init__()
self.image = demon
self.rect = self.image.get_rect(center = pos)
def update(self, moveX, moveY):
self.rect.x += moveX
self.rect.y += moveY
screen.fill(BLACK)

The typical Pygame 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()
Remove screen.fill(BLACK) form update:
class Sprite(pygame.sprite.Sprite):
# [...]
def update(self, moveX, moveY):
self.rect.x += moveX
self.rect.y += moveY
# screen.fill(BLACK) <--- DELETE
Implement the following application loop (based on your previous question):
while carryOn == True:
# handle events
for event in pygame.event.get():
if event.type==pygame.QUIT:
carryOn=False
# update
# [...]
# clear display
screen.fill(BLACK)
# draw sprites
all_sprites_list.draw(screen)
# update display
pygame.display.flip()
clock.tick(60)

Related

How to shoot a projectile in the way the player is looking in a TDS [duplicate]

This question already has answers here:
How to move a sprite according to an angle in Pygame
(3 answers)
calculating direction of the player to shoot pygame
(1 answer)
Moving forward after angle change. Pygame
(1 answer)
Closed 1 year ago.
I wanna know how to shoot a projectile towards the direction the player is looking. I would also like to know how to shoot that projectile from the middle of the player. I have got my bullet class sort of ready but don't know my next step.
here is my code and replit...
https://replit.com/#TahaSSS/game-1#main.py
import pygame
from sys import exit
from random import randint
import math
from pygame.constants import K_LSHIFT, K_SPACE, MOUSEBUTTONDOWN
pygame.init()
pygame.mouse.set_visible(True)
class Player(pygame.sprite.Sprite):
def __init__(self, x , y):
super().__init__()
self.x = x
self.y = y
self.image = pygame.image.load('graphics/Robot 1/robot1_gun.png').convert_alpha()
self.rect = self.image.get_rect()
self.orig_image = pygame.image.load('graphics/Robot 1/robot1_gun.png').convert_alpha()
self.rotate_vel = 1
self.cross_image = pygame.image.load('graphics/crosshair049.png')
def draw(self, surface):
""" Draw on surface """
# blit yourself at your current position
surface.blit(self.image, self.rect)
dir_vec = pygame.math.Vector2()
dir_vec.from_polar((180, -self.rotate_vel))
cross_pos = dir_vec + self.rect.center
cross_x, cross_y = round(cross_pos.x), round(cross_pos.y)
surface.blit(self.cross_image, self.cross_image.get_rect(center = (cross_x, cross_y)))
def movement(self):
key = pygame.key.get_pressed()
self.rect = self.image.get_rect(center = (self.x, self.y))
dist = 3 # distance moved in 1 frame, try changing it to 5
if key[pygame.K_DOWN] or key[pygame.K_s]: # down key
self.y += dist # move down
elif key[pygame.K_UP] or key[pygame.K_w]: # up key
self.y -= dist # move up
if key[pygame.K_RIGHT] or key[pygame.K_d]: # right key
self.x += dist # move right
elif key[pygame.K_LEFT] or key[pygame.K_a]: # left key
self.x -= dist # move left
def rotate(self, surface):
keys = pygame.key.get_pressed()
if keys[K_LSHIFT]:
self.rotate_vel += 5
self.image = pygame.transform.rotate(self.orig_image, self.rotate_vel)
self.rect = self.image.get_rect(center=self.rect.center)
surface.blit(self.image, self.rect)
if keys[K_SPACE]:
self.rotate_vel += -5
self.image = pygame.transform.rotate(self.orig_image, self.rotate_vel)
self.rect = self.image.get_rect(center=self.rect.center)
surface.blit(self.image, self.rect)
def update(self):
self.movement()
self.draw(screen)
self.rotate(screen)
class Bullet(pygame.sprite.Sprite):
def __init__(self, x , y):
super().__init__()
self.bullet_image = pygame.image.load('graphics/weapons/bullets/default_bullet.png')
self.bullet_rect = self.bullet_image.get_rect(center = (x,y))
self.bullet_speed = 15
#screen
clock = pygame.time.Clock()
FPS = 60
screen = pygame.display.set_mode((800, 400))
#player
player_sprite = Player(600, 300)
player = pygame.sprite.GroupSingle()
player.add(player_sprite)
#bullet
bullet_group = pygame.sprite.Group()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
#screen
screen.fill('grey')
#player sprite funtions
player.update()
clock.tick(FPS)
pygame.display.update()
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. [...]
A Sprite kan be removed from all Groups and thus delted by calling kill.
Since pygame.Rect is supposed to represent an area on the screen, a pygame.Rect object can only store integral data.
The coordinates for Rect objects are all integers. [...]
The fraction part of the coordinates gets lost when the new position of the object is assigned to the Rect object. If this is done every frame, the position error will accumulate over time.
If you want to store object positions with floating point accuracy, you have to store the location of the object in separate variables respectively attributes and to synchronize the pygame.Rect object. round the coordinates and assign it to the location (e.g. .center) of the rectangle.
Write a Sprite class with an update method that moves the bullet in a certain direction. Destroy the bullet when it goes out of the display:
class Bullet(pygame.sprite.Sprite):
def __init__(self, pos, angle):
super().__init__()
self.image = pygame.image.load('graphics/weapons/bullets/default_bullet.png')
self.image = pygame.transform.rotate(self.image, angle)
self.rect = self.image.get_rect(center = pos)
self.speed = 15
self.pos = pos
self.dir_vec = pygame.math.Vector2()
self.dir_vec.from_polar((self.speed, -angle))
def update(self, screen):
self.pos += self.dir_vec
self.rect.center = round(self.pos.x), round(self.pos.y)
if not screen.get_rect().colliderect(self.rect):
self.kill()
pygame.key.get_pressed() returns a list with the state of each key. If a key is held down, the state for the key is True, otherwise False. Use pygame.key.get_pressed() to evaluate the current state of a button and get continuous movement.
The keyboard events (see pygame.event module) occur only once when the state of a key changes. The KEYDOWN event occurs once every time a key is pressed. KEYUP occurs once every time a key is released. Use the keyboard events for a single action.
Use an keyboard event to generate a new Bullet object (e.g. TAB). Call bullet_group.update(screen) and bullet_group.draw(screen) in the application loop:
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_TAB:
pos = player_sprite.rect.center
dir_vec = pygame.math.Vector2()
new_bullet = Bullet(pos, player_sprite.rotate_vel)
bullet_group.add(new_bullet)
bullet_group.update(screen)
screen.fill('grey')
player.update()
bullet_group.draw(screen)
pygame.display.update()
clock.tick(FPS)

Pygame unresponsive display

So I am attempting to create the foundation for a basic 2D python game with X and Y movement using a sprite.
However the display is unresposive despite the code here attempting to screen.fill and screen.blit
playerX = 50
playerY = 50
player = pygame.image.load("player.png")
width, height = 64*8, 64*8
screen=pygame.display.set_mode((width, height))
screen.fill((255,255,255))
screen.blit(player, (playerX, playerY))
Am I missing something important?
A minimal, typical PyGame application
has a game loop
has to handle the events, by either pygame.event.pump() or pygame.event.get().
has to update the Surface whuch represents the display respectively window, by either pygame.display.flip() or pygame.display.update().
See pygame.event.get():
For each frame of your game, you will need to make some sort of call to the event queue. This ensures your program can internally interact with the rest of the operating system.
See also Python Pygame Introduction
Minimal example: repl.it/#Rabbid76/PyGame-MinimalApplicationLoop
import pygame
pygame.init()
playerX = 50
playerY = 50
player = pygame.image.load("player.png")
width, height = 64*8, 64*8
screen = pygame.display.set_mode((width, height))
# main application loop
run = True
while run:
# event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
# clear the display
screen.fill((255,255,255))
# draw the scene
screen.blit(player, (playerX, playerY))
# update the display
pygame.display.flip()

Pygame sprite constantly redrawn to screen and not moving

I can't see what's wrong with the below code. All I want to do is make the frog move across the screen, but it is simply redrawing many, many frogs all one pixel apart. How do I move the frog rather than just draw it again?
import pygame
from pygame.constants import *
pygame.init()
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
class Frog(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.transform.scale(pygame.image.load('frog.png'), (64, 64))
self.rect = self.image.get_rect()
self.dx = 1
def update(self, *args):
self.rect.x += self.dx
running = True
frog = Frog()
entities = pygame.sprite.Group()
entities.add(frog)
while running:
for event in pygame.event.get():
if event.type == QUIT:
running = False
entities.update()
entities.draw(screen)
That is how you do it in Pygame, you just redraw objects every iteration to give the illusion that they're moving but you must cover up the previous drawn objects by filling your window with a solid color e.g.
screen.fill((255, 255, 255))
This should be at the start of your game loop so you have a fresh canvas for drawing your objects each iteration.
while running:
screen.fill((255,255,255))
for event in pygame.event.get():
if event.type == QUIT:
running = False
entities.update()
entities.draw(screen)
pygame.display.update()
You may have to use the pygame.display.update() function to update the whole screen rather than just your entities.

Having difficulty making sprites move in Pygame [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I'm trying to make a cursor move across an image, but I'm having problems making my cursor image (redcircle.png) move. When I run my program the circle jumps to my mouse pointer like it should, but then refuses to move until I reload it.
I'm very new to python, this stuff sends me through a loop, but none of the 55 pages and tutorials and crap I have open on it rn seem to give me a clear answer.
import pygame, random
pygame.init()
pygame.mouse.set_visible(True)
screen_width = 1250
screen_height = 800
size = screen_width, screen_height
speed = [60, 60]
black = (0, 0, 0)
WHITE = (255,255,255)
red = (255,0,0,125)
screen = pygame.display.set_mode(size)
clock = pygame.time.Clock()
FPS = 60
bg = pygame.image.load("redtest.png")
bgrect = bg.get_rect()
all_sprites_list = pygame.sprite.Group()
class Block(pygame.sprite.Sprite):
def __init__(self, color, width, height):
super().__init__()
self.image = pygame.image.load("redcircle.png").convert_alpha()
self.rect = self.image.get_rect()
block = Block(black, 20, 15)
all_sprites_list.add(block)
screen.fill(black)
screen.blit(bg, bgrect)
all_sprites_list.draw(screen)
def main():
while True:
pos = pygame.mouse.get_pos()
block.rect.x = pos[0]
block.rect.y = pos[1]
clock.tick(FPS)
pygame.display.update()
pygame.display.flip()
main()
You have to draw the background and to redraw the Group of Sprites in every frame. Furthermore you have to handle the events.
The 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 (draw the Sprites objects)
update the display by either pygame.display.update() or pygame.display.flip()
e.g:
def main():
run = True
while run:
clock.tick(FPS)
# event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
# update objects
pos = pygame.mouse.get_pos()
block.rect.x = pos[0]
block.rect.y = pos[1]
# draw background
screen.blit(bg, bgrect)
# d raw sprotes
all_sprites_list.draw(screen)
# update display
pygame.display.update()

Identify individual sprite from group in Pygame

Original Post:
With pygame is it possible to identify a random sprite from a Group?
I'm trying to learn Python and have been trying to enhance the Alien Invasion program. for the aliens themselves an alien with the alien class and a group is created from this with 4 rows of 8 aliens.
I'd like to periodically have a random alien fly down to the bottom of the screen. Is it possible to do this with a group or do I have to come up with some other means of creating my fleet if I want to have this functionality?
I've came across a few cases where other people seem to have been trying something similar but there isn't any information stating if they were successful or not.
Update:
I've looked into this a little further. I tried creating an alien_attack function in game_functions.py. It was as follows:
def alien_attack(aliens):
for alien in aliens:
alien.y += alien.ai_settings.alien_speed_factor
alien.rect.y = alien.y
I called it from the while loop in alien_invasion.py with gf.alien_attack(aliens). Unfortunately this caused 3 rows to vanish and one row to attack in the manner I desire except that the whole row did this instead of an individual sprite.
I also tried changing aliens = Group() to aliens = GroupSingle() in alien_attack.py. This caused the game to start with only one sprite on the screen. It attacked in the manner I desire but I'd like all the other sprites to appear also but not attack. How is this done?
You can pick a random sprite by calling random.choice(sprite_group.sprites()) (sprites() returns a list of the sprites in the group). Assign this sprite to a variable and do whatever you want with it.
Here's a minimal example in which I just draw an orange rect over the selected sprite and call its move_down method (press R to select another random sprite).
import random
import pygame as pg
class Entity(pg.sprite.Sprite):
def __init__(self, pos):
super().__init__()
self.image = pg.Surface((30, 30))
self.image.fill(pg.Color('dodgerblue1'))
self.rect = self.image.get_rect(center=pos)
def move_down(self):
self.rect.y += 2
def main():
pg.init()
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
all_sprites = pg.sprite.Group()
for _ in range(20):
pos = random.randrange(630), random.randrange(470)
all_sprites.add(Entity(pos))
# Select a random sprite from the all_sprites group.
selected_sprite = random.choice(all_sprites.sprites())
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
elif event.type == pg.KEYDOWN:
if event.key == pg.K_r:
selected_sprite = random.choice(all_sprites.sprites())
all_sprites.update()
# Use the selected sprite in the game loop.
selected_sprite.move_down()
screen.fill((30, 30, 30))
all_sprites.draw(screen)
# Draw a rect over the selected sprite.
pg.draw.rect(screen, (255, 128, 0), selected_sprite.rect, 2)
pg.display.flip()
clock.tick(30)
if __name__ == '__main__':
main()
pg.quit()

Categories