I'm practicing with pygame and don't know how to make my character move. If I put 'print' statement, it works, and prints whatever I want when I press 'a' for example, but character stays on his place. I know little about classes, so I think that's the problem
import pygame
pygame.init()
pygame.font.init()
width, height = 924, 500
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption('Priest Beast')
clock = pygame.time.Clock()
BG = pygame.transform.scale2x(pygame.image.load('art/background.png')).convert_alpha()
music = pygame.mixer.Sound('sound/music.mp3')
class Player(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.image = pygame.transform.scale2x(pygame.image.load('art/Player.png')).convert_alpha()
self.rect = self.image.get_rect(center = (800, 300))
self.x = x
self.y = y
def move(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_a]:
self.rect.x += 5
def update(self):
self.move()
#Loop and exit
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
# Sounds
music.play()
music.set_volume(0.1)
screen.blit(BG, (0, 0))
player = pygame.sprite.GroupSingle()
player.add(Player(800,200))
#Update everything
player.draw(screen)
player.update()
pygame.display.update()
clock.tick(60)
You continuously recreate the object in its initial position. You need to create the Sprite and Group before the application loop:
player = pygame.sprite.GroupSingle() # <-- INSERT
player.add(Player(800,200))
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
# [...]
screen.blit(BG, (0, 0))
# DELETE
# player = pygame.sprite.GroupSingle()
# player.add(Player(800,200))
# [...]
Related
I am trying to make objects fall like they would on earth. I already got them to blit where I wanted them to but I can't seem to animate them.
This is the object that I want to fall
import pygame
class circle():
def __init__(self, screen):
planet_color = (255,0,0)
planet_radius = 20
self.screen = screen
ev = pygame.event.get()
self.image = pygame.image.load('../images/jupiter.bmp')
self.image = pygame.transform.scale(self.image, (80, 80))
def blitme(self):
self.x = pygame.mouse.get_pos()
self.rect = self.image.get_rect()
self.rect.center = self.x
self.screen.blit(self.image, self.rect)
And this is the code that runs it. When the mouse is clicked a little picture of Jupiter is made where the mouse was clicked. How do I get this image to fall?
import pygame
import gravfunc as gf
from gravfunc import circle
import sys
def run_game():
screen_height = 670
screen_width = 1270
pygame.init()
screen = pygame.display.set_mode((screen_width, screen_height))
screen.fill((10,10,30))
running = True
circ = circle(screen)
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN:
circ.blitme()
pygame.display.flip()
run_game()
Give your class a self.speed_y attribute and add the GRAVITY to it each frame to accelerate the object. I've also added a self.pos_y attribute because pygame.Rects can't have floating point numbers as their coordinates. So,
increase the speed
add the speed to the position (self.pos_y)
assign the self.pos_y to self.rect.y.
Since you are already using a class, I recommend to make it a pygame sprite subclass (inherit from pygame.sprite.Sprite). Then you can add all circles to a pygame.sprite.Group and update and draw them by calling sprite_group.update() and sprite_grop.draw(screen).
import pygame
GRAVITY = .2 # Pretty low gravity.
class Circle(pygame.sprite.Sprite):
def __init__(self, pos, screen):
super().__init__()
self.screen = screen
self.image = pygame.Surface((80, 80), pygame.SRCALPHA)
pygame.draw.circle(self.image, (30, 90, 150), (40, 40), 40)
self.rect = self.image.get_rect(center=pos)
self.pos_y = pos[1]
self.speed_y = 0
def update(self):
self.speed_y += GRAVITY
self.pos_y += self.speed_y
self.rect.y = self.pos_y
if self.pos_y > self.screen.get_height():
self.kill() # Remove off-screen circles.
def run_game():
pygame.init()
screen = pygame.display.set_mode((1270, 670))
clock = pygame.time.Clock()
running = True
circles = pygame.sprite.Group(Circle((600, 0), screen))
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
elif event.type == pygame.MOUSEBUTTONDOWN:
circles.add(Circle(event.pos, screen))
circles.update()
screen.fill((10, 10, 30))
circles.draw(screen)
pygame.display.flip()
clock.tick(60)
run_game()
pygame.quit()
im trying to get my image (bird) to move up and down on the screen but i cant figure out how to do it here is what i tried im sure its way off but im trying to figure it out if anyone can help that would be great!
import pygame
import os
screen = pygame.display.set_mode((640, 400))
running = 1
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = 0
screen.fill([255, 255, 255])
clock = pygame.time.Clock()
clock.tick(0.5)
pygame.display.flip()
bird = pygame.image.load(os.path.join('C:\Python27', 'player.png'))
screen.blit( bird, ( 0, 0 ) )
pygame.display.update()
class game(object):
def move(self, x, y):
self.player.center[0] += x
self.player.center[1] += y
if event.key == K_UP:
player.move(0,5)
if event.key == K_DOWN:
player.move(0,-5)
game()
im trying to get it to move down on the down button press and up on the UP key press
As stated by ecline6, bird is the least of your worries at this point.
Consider reading this book..
For now, First let's clean up your code...
import pygame
import os
# let's address the class a little later..
pygame.init()
screen = pygame.display.set_mode((640, 400))
# you only need to call the following once,so pull them out of the while loop.
bird = pygame.image.load(os.path.join('C:\Python27', 'player.png'))
clock = pygame.time.Clock()
running = True
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
screen.fill((255, 255, 255)) # fill the screen
screen.blit(bird, (0, 0)) # then blit the bird
pygame.display.update() # Just do one thing, update/flip.
clock.tick(40) # This call will regulate your FPS (to be 40 or less)
Now the reason that your "bird" is not moving is:
When you blit the image, ie: screen.blit(bird, (0, 0)),
The (0,0) is constant, so it won't move.
Here's the final code, with the output you want (try it) and read the comments:
import pygame
import os
# it is better to have an extra variable, than an extremely long line.
img_path = os.path.join('C:\Python27', 'player.png')
class Bird(object): # represents the bird, not the game
def __init__(self):
""" The constructor of the class """
self.image = pygame.image.load(img_path)
# the bird's position
self.x = 0
self.y = 0
def handle_keys(self):
""" Handles Keys """
key = pygame.key.get_pressed()
dist = 1 # distance moved in 1 frame, try changing it to 5
if key[pygame.K_DOWN]: # down key
self.y += dist # move down
elif key[pygame.K_UP]: # up key
self.y -= dist # move up
if key[pygame.K_RIGHT]: # right key
self.x += dist # move right
elif key[pygame.K_LEFT]: # left key
self.x -= dist # move left
def draw(self, surface):
""" Draw on surface """
# blit yourself at your current position
surface.blit(self.image, (self.x, self.y))
pygame.init()
screen = pygame.display.set_mode((640, 400))
bird = Bird() # create an instance
clock = pygame.time.Clock()
running = True
while running:
# handle every event since the last frame.
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit() # quit the screen
running = False
bird.handle_keys() # handle the keys
screen.fill((255,255,255)) # fill the screen with white
bird.draw(screen) # draw the bird to the screen
pygame.display.update() # update the screen
clock.tick(40)
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 or a step-by-step movement.
If you want to achieve a continuously movement, you have to use pygame.key.get_pressed(). 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.
See also Key and Keyboard event and How can I make a sprite move when key is held down.
Minimal example:
import pygame
import os
class Bird(object):
def __init__(self):
self.image = pygame.image.load(os.path.join('C:\Python27', 'player.png'))
self.center = [100, 200]
def move(self, x, y):
self.center[0] += x
self.center[1] += y
def draw(self, surf):
surf.blit(self.image, self.center)
class game(object):
def __init__(self):
self.screen = pygame.display.set_mode((640, 400))
self.clock = pygame.time.Clock()
self.player = Bird()
def run(self):
running = 1
while running:
self.clock.tick(60)
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = 0
keys = pygame.key.get_pressed()
move_x = keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]
move_y = keys[pygame.K_DOWN] - keys[pygame.K_UP]
self.player.move(move_x * 5, move_y * 5)
self.screen.fill([255, 255, 255])
self.player.draw(self.screen)
pygame.display.update()
g = game()
g.run()
I have an array with all the sprites inside of them, and in the loop, if the sprite is clicked then the sprite is killed.
If I click the sprites from left to right, everything is fine. They are cleared one by one independent of each other. But, if I click the sprite most right of the screen, it kills everything to the left of it.
Full code because I've no idea where the important region might be.
import pygame
from pygame.locals import *
import random
pygame.init()
level = 1
cooldown = 1000
class test(pygame.sprite.Sprite):
def __init__(self, w):
super().__init__()
self.image = pygame.Surface([600,600])
self.rect = self.image.get_rect()
self.image = pygame.image.load("index.png")
self.image = pygame.transform.scale(self.image, (w,w))
self.last = pygame.time.get_ticks()
screen = pygame.display.set_mode([600,600])
clock = pygame.time.Clock()
background = pygame.Surface(screen.get_size())
background.fill([0,0,0])
rX = random.randint(0, 500)
rX2 = random.randint(0, 500)
screen.blit(background, (0,0))
sp = []
all_sprites_list = pygame.sprite.Group()
a_1 = test(random.randint(40,60))
a_1.rect.x = rX
a_1.rect.y = -400
sp.append(a_1)
all_sprites_list.add(a_1)
#The steps for a_1 is repeated to make variables a_2, a_3, a_4...
Running = True
while Running:
now = pygame.time.get_ticks()
for x in sp:
x.rect.y+=level
m_pos = pygame.mouse.get_pos()
for event in pygame.event.get():
if event.type == QUIT:
Running = False
if event.type == MOUSEBUTTONDOWN:
for s in sp:
if s.rect.collidepoint(m_pos):
s.kill()
pygame.display.flip()
all_sprites_list.clear(screen, background)
all_sprites_list.draw(screen)
all_sprites_list.update()
clock.tick(60)
Problem is because in class you create Surface with size (600, 600) and you assign this size to self.rect. After that you load image but you forgot to assign its size to self.rect so program always check mouse click with size (600, 600) and when you click most right item then all rect (600, 600) are in area of click.
But you don't have to create Surface if you load image.
My version with many changes.
I removed list sp because I can use all_sprites_list
When it sends MOUSEBUTTONDOWN event then mouse position is in event.pos so I don't need pygame.mouse.get_pos()
import pygame
import random
# --- classes --- (UpperCaseNames)
class Test(pygame.sprite.Sprite):
def __init__(self, w):
super().__init__()
self.image = pygame.image.load("index.png")
self.image = pygame.transform.scale(self.image, (w, w))
self.rect = self.image.get_rect()
self.last = pygame.time.get_ticks()
# --- main ----
level = 1
cooldown = 1000
# - init -
pygame.init()
screen = pygame.display.set_mode((600, 600))
# - items -
background = pygame.Surface(screen.get_size())
background.fill((0, 0, 0))
screen.blit(background, (0,0))
all_sprites_list = pygame.sprite.Group()
for x in range(10):
item = Test(random.randint(40, 60))
item.rect.x = 40 * random.randint(0, 10)
item.rect.y = 0
all_sprites_list.add(item)
# - mainloop -
clock = pygame.time.Clock()
running = True
while running:
now = pygame.time.get_ticks()
for item in all_sprites_list:
item.rect.y += level
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.MOUSEBUTTONDOWN:
for item in all_sprites_list:
if item.rect.collidepoint(event.pos):
item.kill()
pygame.display.flip()
all_sprites_list.clear(screen, background)
all_sprites_list.draw(screen)
all_sprites_list.update()
clock.tick(30)
pygame.quit()
I am trying to make objects fall like they would on earth. I already got them to blit where I wanted them to but I can't seem to animate them.
This is the object that I want to fall
import pygame
class circle():
def __init__(self, screen):
planet_color = (255,0,0)
planet_radius = 20
self.screen = screen
ev = pygame.event.get()
self.image = pygame.image.load('../images/jupiter.bmp')
self.image = pygame.transform.scale(self.image, (80, 80))
def blitme(self):
self.x = pygame.mouse.get_pos()
self.rect = self.image.get_rect()
self.rect.center = self.x
self.screen.blit(self.image, self.rect)
And this is the code that runs it. When the mouse is clicked a little picture of Jupiter is made where the mouse was clicked. How do I get this image to fall?
import pygame
import gravfunc as gf
from gravfunc import circle
import sys
def run_game():
screen_height = 670
screen_width = 1270
pygame.init()
screen = pygame.display.set_mode((screen_width, screen_height))
screen.fill((10,10,30))
running = True
circ = circle(screen)
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN:
circ.blitme()
pygame.display.flip()
run_game()
Give your class a self.speed_y attribute and add the GRAVITY to it each frame to accelerate the object. I've also added a self.pos_y attribute because pygame.Rects can't have floating point numbers as their coordinates. So,
increase the speed
add the speed to the position (self.pos_y)
assign the self.pos_y to self.rect.y.
Since you are already using a class, I recommend to make it a pygame sprite subclass (inherit from pygame.sprite.Sprite). Then you can add all circles to a pygame.sprite.Group and update and draw them by calling sprite_group.update() and sprite_grop.draw(screen).
import pygame
GRAVITY = .2 # Pretty low gravity.
class Circle(pygame.sprite.Sprite):
def __init__(self, pos, screen):
super().__init__()
self.screen = screen
self.image = pygame.Surface((80, 80), pygame.SRCALPHA)
pygame.draw.circle(self.image, (30, 90, 150), (40, 40), 40)
self.rect = self.image.get_rect(center=pos)
self.pos_y = pos[1]
self.speed_y = 0
def update(self):
self.speed_y += GRAVITY
self.pos_y += self.speed_y
self.rect.y = self.pos_y
if self.pos_y > self.screen.get_height():
self.kill() # Remove off-screen circles.
def run_game():
pygame.init()
screen = pygame.display.set_mode((1270, 670))
clock = pygame.time.Clock()
running = True
circles = pygame.sprite.Group(Circle((600, 0), screen))
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
elif event.type == pygame.MOUSEBUTTONDOWN:
circles.add(Circle(event.pos, screen))
circles.update()
screen.fill((10, 10, 30))
circles.draw(screen)
pygame.display.flip()
clock.tick(60)
run_game()
pygame.quit()
im trying to get my image (bird) to move up and down on the screen but i cant figure out how to do it here is what i tried im sure its way off but im trying to figure it out if anyone can help that would be great!
import pygame
import os
screen = pygame.display.set_mode((640, 400))
running = 1
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = 0
screen.fill([255, 255, 255])
clock = pygame.time.Clock()
clock.tick(0.5)
pygame.display.flip()
bird = pygame.image.load(os.path.join('C:\Python27', 'player.png'))
screen.blit( bird, ( 0, 0 ) )
pygame.display.update()
class game(object):
def move(self, x, y):
self.player.center[0] += x
self.player.center[1] += y
if event.key == K_UP:
player.move(0,5)
if event.key == K_DOWN:
player.move(0,-5)
game()
im trying to get it to move down on the down button press and up on the UP key press
As stated by ecline6, bird is the least of your worries at this point.
Consider reading this book..
For now, First let's clean up your code...
import pygame
import os
# let's address the class a little later..
pygame.init()
screen = pygame.display.set_mode((640, 400))
# you only need to call the following once,so pull them out of the while loop.
bird = pygame.image.load(os.path.join('C:\Python27', 'player.png'))
clock = pygame.time.Clock()
running = True
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
screen.fill((255, 255, 255)) # fill the screen
screen.blit(bird, (0, 0)) # then blit the bird
pygame.display.update() # Just do one thing, update/flip.
clock.tick(40) # This call will regulate your FPS (to be 40 or less)
Now the reason that your "bird" is not moving is:
When you blit the image, ie: screen.blit(bird, (0, 0)),
The (0,0) is constant, so it won't move.
Here's the final code, with the output you want (try it) and read the comments:
import pygame
import os
# it is better to have an extra variable, than an extremely long line.
img_path = os.path.join('C:\Python27', 'player.png')
class Bird(object): # represents the bird, not the game
def __init__(self):
""" The constructor of the class """
self.image = pygame.image.load(img_path)
# the bird's position
self.x = 0
self.y = 0
def handle_keys(self):
""" Handles Keys """
key = pygame.key.get_pressed()
dist = 1 # distance moved in 1 frame, try changing it to 5
if key[pygame.K_DOWN]: # down key
self.y += dist # move down
elif key[pygame.K_UP]: # up key
self.y -= dist # move up
if key[pygame.K_RIGHT]: # right key
self.x += dist # move right
elif key[pygame.K_LEFT]: # left key
self.x -= dist # move left
def draw(self, surface):
""" Draw on surface """
# blit yourself at your current position
surface.blit(self.image, (self.x, self.y))
pygame.init()
screen = pygame.display.set_mode((640, 400))
bird = Bird() # create an instance
clock = pygame.time.Clock()
running = True
while running:
# handle every event since the last frame.
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit() # quit the screen
running = False
bird.handle_keys() # handle the keys
screen.fill((255,255,255)) # fill the screen with white
bird.draw(screen) # draw the bird to the screen
pygame.display.update() # update the screen
clock.tick(40)
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 or a step-by-step movement.
If you want to achieve a continuously movement, you have to use pygame.key.get_pressed(). 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.
See also Key and Keyboard event and How can I make a sprite move when key is held down.
Minimal example:
import pygame
import os
class Bird(object):
def __init__(self):
self.image = pygame.image.load(os.path.join('C:\Python27', 'player.png'))
self.center = [100, 200]
def move(self, x, y):
self.center[0] += x
self.center[1] += y
def draw(self, surf):
surf.blit(self.image, self.center)
class game(object):
def __init__(self):
self.screen = pygame.display.set_mode((640, 400))
self.clock = pygame.time.Clock()
self.player = Bird()
def run(self):
running = 1
while running:
self.clock.tick(60)
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = 0
keys = pygame.key.get_pressed()
move_x = keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]
move_y = keys[pygame.K_DOWN] - keys[pygame.K_UP]
self.player.move(move_x * 5, move_y * 5)
self.screen.fill([255, 255, 255])
self.player.draw(self.screen)
pygame.display.update()
g = game()
g.run()