I'm doing a project for my Computer Science class where we're using pygame to move an object around the screen. I'm not using the pygame sprites, but rather images imported into pygame and using those to act as custom sprites. When i try to move the Bunny, or "Player" object across the screen it does seem to update the position. This is the Player object i'm trying to change position:
class Player(object):
def __init__(self, x, y, filename):
self.x = x
self.y = y
self.image = pygame.transform.scale(pygame.image.load(filename), (150, 200))
self.moving_left = False
self.moving_right = False
self.moving_up = False
self.moving_down = False
def moveUpdate(self):
if self.moving_left:
self.x -= 25
pygame.display.update()
if self.moving_right:
self.y += 25
pygame.display.update()
if self.moving_up:
self.y -= 25
pygame.display.update()
if self.moving_down:
self.y += 25
pygame.display.update()
def moveEvent(self, event):
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
self.moving_left = True
if event.key == pygame.K_RIGHT:
self.moving_right = True
if event.key == pygame.K_UP:
self.moving_up = True
if event.key == pygame.K_DOWN:
self.moving_down = True
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
self.moving_left = False
if event.key == pygame.K_RIGHT:
self.moving_right = False
if event.key == pygame.K_UP:
self.moving_up = False
if event.key == pygame.K_DOWN:
self.moving_down = False
def draw(self, screen):
screen.blit(self.image, (self.x, self.y))
And this is the class i'm using to run the game itself:
class Game(object):
def __init__(self):
self.screensize = [1000, 1000]
self.white = [255, 255, 255]
self.black = [0, 0, 0]
self.screen = pygame.display.set_mode(self.screensize)
#self.bunny = pygame.transform.scale(pygame.image.load('bunny.png'), (150, 200))
self.clock = pygame.time.Clock()
self.player = Player(500, 500, 'bunny.png')
def Run(self):
run = True
while run:
self.clock.tick(60)
self.screen.fill(self.white)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.quit()
exit()
elif event.type == pygame.K_ESCAPE:
run = False
pygame.quit()
exit()
# - Objects Event Handle -
self.player.moveEvent(event)
# - Updates -
#self.player.moveUpdate()
# - Draws -
self.player.draw(self.screen)
pygame.display.flip()
game = Game()
game.Run()
Remove the event loop from the Player.moveEvent:
class Player(object):
# [...]
def moveEvent(self, event):
# for event in pygame.event.get(): <----- to be removed
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
self.moving_left = True
if event.key == pygame.K_RIGHT:
self.moving_right = True
if event.key == pygame.K_UP:
self.moving_up = True
if event.key == pygame.K_DOWN:
self.moving_down = True
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
self.moving_left = False
if event.key == pygame.K_RIGHT:
self.moving_right = False
if event.key == pygame.K_UP:
self.moving_up = False
if event.key == pygame.K_DOWN:
self.moving_down = False
Note, the method is called in an event loop and the event is passed to the method. The method has to handle the input parameter event:
while run:
self.clock.tick(60)
self.screen.fill(self.white)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.quit()
exit()
elif event.type == pygame.K_ESCAPE:
run = False
pygame.quit()
exit()
# - Objects Event Handle -
self.player.moveEvent(event)
# - Updates -
self.player.moveUpdate()
Related
I'm currently trying to build a game through vscode using pygame lib.
My code to move character around with keyboard arrow keys won't apply to my module.
My module won't close even though I click exit button or esc.
Any thoughts why its not working?
import pygame
import os
pygame.init()
screen_width = 480
screen_height = 640
screen = pygame.display.set_mode((screen_width,screen_height))
pygame.display.set_caption("June's Game")
background = pygame.image.load("D:/Python/pygame_basic/background.png")
character = pygame.image.load("D:/Python/pygame_basic/character.png")
character_size = character.get_rect().size
character_width = character_size[0]
character_height = character_size[1]
character_x_position = (screen_width / 2) - (character_width / 2)
character_y_position = screen_height - character_height
to_x = 0
to_y = 0
running = True #게임이 진행중인가
while running:
for event in pygame.event.get():
if event == pygame.QUIT:
running = False
if event == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
to_x -= 5
elif event.key == pygame.K_RIGHT:
to_x += 5
elif event.key == pygame.K_UP:
to_y -= 5
elif event.key == pygame.K_DOWN:
to_y += 5
if event == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
to_x = 0
elif event.key == pygame.K_UP or event.key == pygame.K_DOWN:
to_y = 0
character_x_position += to_x
character_y_position += to_y
#screen.fill((0,0,255))
screen.blit(background, (0,0))
screen.blit(character, (character_x_position,character_y_position))
pygame.display.update()
pygame.quit()
i coudln't get it to work
event is an object. You have to get the type of the event, e.g.:
if event == pygame.KEYDOWN
if event.type == pygame.KEYDOWN:
You have to limit the frames per second to limit CPU usage with pygame.time.Clock.tick and to control the speed of the game. Otherwise, the player moves much too fast and immediately disappears from the screen. The method tick() of a pygame.time.Clock object, delays the game in that way, that every iteration of the loop consumes the same period of time.
clock = pygame.time.Clock()
running = True
while running:
clock.tick(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
to_x -= 5
elif event.key == pygame.K_RIGHT:
to_x += 5
elif event.key == pygame.K_UP:
to_y -= 5
elif event.key == pygame.K_DOWN:
to_y += 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
to_x = 0
elif event.key == pygame.K_UP or event.key == pygame.K_DOWN:
to_y = 0
character_x_position += to_x
character_y_position += to_y
#screen.fill((0,0,255))
screen.blit(background, (0,0))
screen.blit(character, (character_x_position,character_y_position))
pygame.display.update()
However, there is a better method to move an object when a key is held down (See How can I make a sprite move when key is held down):
to_x = 0
to_y = 0
speed = 5
clock = pygame.time.Clock()
running = True
while running:
clock.tick(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
keys = pygame.key.get_pressed()
to_x = (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * speed
to_y = (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * speed
character_x_position += to_x
character_y_position += to_y
screen.blit(background, (0,0))
screen.blit(character, (character_x_position,character_y_position))
pygame.display.update()
I am trying to make a pong game in pygame. So I needed to make a rectangle controlled by player. I defined some variables for this purpose.
The variables
player = pygame.Rect(s_width - 10, s_height/2 - 35, 5, 70)
player_speed = 0
In the loop
player.y += player_speed
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if pygame.key == pygame.K_DOWN:
player_speed += 5
if pygame.key == pygame.K_UP:
player_speed -= 5
if event.type == pygame.KEYUP:
if pygame.key == pygame.K_DOWN:
player_speed = 0
if pygame.key == pygame.K_UP:
player_speed = 0
There is just one problem in your code; you don't check
if pygame.key == pygame.K_...
You need to replace the pygame.key to event.key:
if event.key == pygame.K_...
import pygame
pygame.init()
s_width, s_height = 600, 600
wn = pygame.display.set_mode((s_width, s_height))
player = pygame.Rect(s_width - 10, s_height/2 - 35, 5, 70)
player_speed = 0
clock = pygame.time.Clock()
while True:
clock.tick(60)
player.y += player_speed
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_DOWN:
player_speed += 5
print(player_speed)
if event.key == pygame.K_UP:
player_speed -= 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_DOWN:
player_speed = 0
if event.key == pygame.K_UP:
player_speed = 0
wn.fill((0, 0, 0))
pygame.draw.rect(wn, (255, 0, 0), player)
pygame.display.update()
Output:
There is no error when running the code but the ship is unable to move left or right and I'm sure I did everything right so here's all the code. The ship displays correctly but does not move at all.
import pygame
from ship import Ship
import game_functions as gf
from settings import Settings
def run_game():
pygame.init()
game_settings = Settings()
screen = pygame.display.set_mode((game_settings.screen_width, game_settings.screen_height))
pygame.display.set_caption("Alien Invasion")
space_ship = Ship(screen)
while True:
gf.check_events(space_ship)
gf.update_screen(game_settings, screen, space_ship)
space_ship.update()
run_game()
settings.py
class Settings:
def __init__(self):
self.screen_width = 800
self.screen_height = 600
self.bg_colour = (0, 0, 255)
ship.py
import pygame
class Ship:
def __init__(self, screen):
# Initializing the ship
self.screen = screen
# Load the ship and get the rect attribute
self.image = pygame.image.load("spaceship.png")
self.rect = self.image.get_rect()
self.screen_rect = screen.get_rect()
# Start each new ship at the bottom of the screen
self.rect.centerx = self.screen_rect.centerx
self.rect.bottom = self.screen_rect.bottom
# Movement flag
self.moving_right = False
self.moving_left = False
def blitme(self):
self.screen.blit(self.image, self.rect)
def update(self):
if self.moving_right:
self.rect.centerx += 1
if self.moving_left:
self.rect.centerx -= 1
game_functions.py
import sys
import pygame
def check_events(spaceship):
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.type == pygame.K_RIGHT:
spaceship.moving_right = True
elif event.type == pygame.K_LEFT:
spaceship.moving_left = True
elif event.type == pygame.KEYUP:
if event.type == pygame.K_RIGHT:
spaceship.moving_right = False
elif event.type == pygame.K_LEFT:
spaceship.moving_left = False
def update_screen(game_settings, screen, spaceship):
screen.fill(game_settings.bg_colour)
spaceship.blitme()
pygame.display.flip()
That is all the code I have been able to do. Does anyone have a solution to this problem?
In pygame, use event.type to check for a key event. Use event.key to check which key is pressed.
def check_events(spaceship):
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN: # event.type
if event.key == pygame.K_RIGHT: # event.key
spaceship.moving_right = True
elif event.key == pygame.K_LEFT:
spaceship.moving_left = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
spaceship.moving_right = False
elif event.key == pygame.K_LEFT:
spaceship.moving_left = False
I use VIDEORESIZE to update the window and when i scale the window the background update to the new size.
Now when i put an ship into this windows then when i scale the window or fullsize the winodw the ship can't touch the bottom of the window, it can't update to the new screen size and the ship speed become very very slowly
How can i fix it?
Here's the codes:
#!/usr/bin/python
import sys
import pygame
class Setting():
'''set for the screen'''
def __init__(self,width,height):
self.w=width
self.h=height
self.flag=pygame.RESIZABLE
self.color=(255,255,255)
self.screen=pygame.display.set_mode((self.w,self.h),self.flag)
self_title=pygame.display.set_caption("Muhaha")
class Ship():
'''set for the background and ship'''
def __init__(self,screen,setting):
self.bk=pygame.image.load("/home/finals/python/alien/image/muha.png").convert()
self.bkg=pygame.transform.smoothscale(self.bk,(setting.w,setting.h))
temp=pygame.image.load("/home/finals/python/alien/image/title.jpg").convert_alpha()
self.ship=pygame.transform.smoothscale(temp,(200,200))
self.screen=screen
self.screen_rect=screen.get_rect()
self.ship_rect=self.ship.get_rect()
'''make the ship at the middle bottom of the screen'''
self.ship_rect.centerx=self.screen_rect.centerx
self.ship_rect.bottom=self.screen_rect.bottom
def blit(self):
self.screen.blit(self.bkg,(0,0))
self.screen.blit(self.ship,self.ship_rect)
class Check_event():
def __init__(self):
self.moving_up = False
self.moving_down = False
self.moving_left = False
self.moving_right = False
def event(self,ship,setting):
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
'''set for moving ship'''
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
self.moving_up=True
elif event.key == pygame.K_DOWN:
self.moving_down=True
elif event.key == pygame.K_LEFT:
self.moving_left=True
elif event.key == pygame.K_RIGHT:
self.moving_right=True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_UP:
self.moving_up=False
elif event.key == pygame.K_DOWN:
self.moving_down=False
elif event.key == pygame.K_LEFT:
self.moving_left=False
elif event.key == pygame.K_RIGHT:
self.moving_right=False
'''set for scale the window'''
elif event.type == pygame.VIDEORESIZE:
w,h = event.w,event.h
setting.screen = pygame.display.set_mode((w,h),setting.flag,0)
ship.bkg=pygame.transform.smoothscale(ship.bk,(w,h))
'''set for the ship not move out of the screen'''
if self.moving_up == True and ship.ship_rect.top >= 0:
ship.ship_rect.centery -= 1
if self.moving_down == True and ship.ship_rect.bottom <= setting.h:
ship.ship_rect.centery += 1
if self.moving_left == True and ship.ship_rect.left >= 0:
ship.ship_rect.centerx -= 1
if self.moving_right == True and ship.ship_rect.right <= setting.w:
ship.ship_rect.centerx += 1
def game():
pygame.init()
setting=Setting(1200,800)
screen=setting.screen
ship=Ship(screen,setting)
check_event=Check_event()
while True:
check_event.event(ship,setting)
ship.blit()
pygame.display.flip()
game()
Update the ship.screen_rect and compute the scale factor of the window (scale_x, scale_y). Finally scale the position of the ship by the scale factor:
class Check_event():
# [...]
def event(self,ship,setting):
for event in pygame.event.get():
# [...]
elif event.type == pygame.VIDEORESIZE:
w,h = event.w,event.h
setting.screen = pygame.display.set_mode((w,h),setting.flag,0)
ship.bkg=pygame.transform.smoothscale(ship.bk,(w,h))
current_rect = ship.screen_rect
ship.screen_rect = ship.bkg.get_rect()
scale_x = ship.screen_rect.width / current_rect.width
scale_y = ship.screen_rect.height / current_rect.height
ship.ship_rect.centerx = round(ship.ship_rect.centerx * scale_x)
ship.ship_rect.bottom = round(ship.ship_rect.bottom * scale_y)
Been trying to turn my main character into a class that I can call in my game. This is because I know it will get a lot more complex later in the development due to plans to implement enemies and spawn-able power-ups.
For some reason, my sprite will be drawn but the methods to get make it detect my key and then move (getkey, animandmove) don't seem to work as pressing any of the inputs does not move it. Please help?
import pygame
from pygame.locals import *
import sys
import pyganim # used for animations
pygame.init()
pygame.mixer.init()
WINDOWWIDTH = 1600
WINDOWHEIGHT = 900
# x = 100
# y = 100
# vel = 10
# width = 64
# height = 64
# moveleft = moveright = moveup = movedown = False
# direction = 'left'
background = pygame.image.load('sprites/background1.png')
leftidle = pygame.image.load("sprites/left.png")
rightidle = pygame.image.load("sprites/right.png")
upidle = pygame.image.load("sprites/up.png")
downidle = pygame.image.load("sprites/down.png")
charanim = {"walkleft": pyganim.PygAnimation(
[("sprites/left2.png", 100), ("sprites/left.png", 100), ("sprites/left3.png", 100), ("sprites/left.png", 10)]),
"walkright": pyganim.PygAnimation(
[("sprites/right2.png", 100), ("sprites/right.png", 100), ("sprites/right3.png", 100),
("sprites/right.png", 10)]), "walkup": pyganim.PygAnimation(
[("sprites/up2.png", 100), ("sprites/up.png", 100), ("sprites/up3.png", 100), ("sprites/up.png", 10)]),
"walkdown": pyganim.PygAnimation(
[("sprites/down2.png", 100), ("sprites/down.png", 100), ("sprites/down3.png", 100), ("sprites/down.png", 10)])}
moveConductor = pyganim.PygConductor(charanim)
mainmenuanim = {"splashscreen": pyganim.PygAnimation([("sprites/splash1.png", 500), ("sprites/splash2.png", 500)])}
mainmenuConductor = pyganim.PygConductor(mainmenuanim)
muzzleflashanim = {"fire": pyganim.PygAnimation(
[("sprites/muzzleflash.png", 100), ("sprites/muzzleflash2.png", 100), ("sprites/muzzleflash3.png", 100),
("sprites/muzzleflash4.png", 100)])}
mainwin = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
pygame.display.set_caption("2084 Ver 0.1.1.1")
def mainmenu():
global running
menulive = True
pygame.mixer.music.load('track0.ogg')
pygame.mixer.music.play(-1)
while menulive:
mainmenuConductor.play()
mainmenuanim["splashscreen"].blit(mainwin, (0, 0))
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_RETURN:
pygame.mixer.music.stop()
mainloop()
if event.type == pygame.QUIT:
running = False
pygame.quit()
pygame.display.update()
def mainloop():
global running
running = True
char1 = Character()
pygame.mixer.music.load("track1.ogg")
pygame.mixer.music.play(-1)
char1.__init__()
while running:
mainwin.blit(background, (0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
char1.getkey()
char1.animandmove()
pygame.display.update()
class Character:
def __init__(self):
self.x = 100
self.y = 100
self.vel = 10
self.width = 64
self.height = 64
self.moveleft = False
self.moveright = False
self.moveup = False
self.movedown = False
self.direction = 'left'
def animandmove(self):
if self.moveleft or self.moveright or self.moveup or self.movedown:
moveConductor.play()
# draws animations for each of the directions
if self.direction == "left":
charanim["walkleft"].blit(mainwin, (self.x, self.y))
elif self.direction == "right":
charanim["walkright"].blit(mainwin, (self.x, self.y))
elif self.direction == "up":
charanim["walkup"].blit(mainwin, (self.x, self.y))
elif self.direction == "down":
charanim["walkdown"].blit(mainwin, (self.x, self.y))
# moving the physicial character
if self.moveleft and self.x > 0:
self.x -= self.vel
if self.moveright and self.x < (WINDOWWIDTH - 64):
self.x += self.vel
if self.moveup and self.y > 0:
self.y -= self.vel
if self.movedown and self.y < (WINDOWHEIGHT - 64):
self.y += self.vel
else:
moveConductor.stop()
if self.direction == "left":
mainwin.blit(pygame.image.load("sprites/left.png"), (self.x, self.y))
elif self.direction == "right":
mainwin.blit(pygame.image.load("sprites/right.png"), (self.x, self.y))
elif self.direction == "up":
mainwin.blit(pygame.image.load("sprites/up.png"), (self.x, self.y))
elif self.direction == "down":
mainwin.blit(pygame.image.load("sprites/down.png"), (self.x, self.y))
def getkey(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
if event.key == K_LEFT or event.key == K_a:
self.moveleft = True
self.moveright = False
if not self.moveup and not self.movedown:
self.direction = "left"
elif event.key == K_RIGHT or event.key == K_d:
self.moveleft = False
self.moveright = True
if not self.moveup and not self.movedown:
self.direction = "right"
elif event.key == K_UP or event.key == K_w:
self.moveup = True
self.movedown = False
if not self.moveleft and not self.moveright:
self.direction = "up"
elif event.key == K_DOWN or event.key == K_s:
self.moveup = False
self.movedown = True
if not self.moveleft and not self.moveright:
self.direction = "down"
elif event.type == KEYUP:
if event.key == K_LEFT or event.key == K_a:
self.moveleft = False
if self.moveup:
self.direction = "up"
if self.movedown:
self.direction = "down"
elif event.key == K_RIGHT or event.key == K_d:
self.moveright = False
if self.moveup:
self.direction = "up"
if self.movedown:
self.direction = "down"
elif event.key == K_UP or event.key == K_w:
self.moveup = False
if self.moveleft:
self.direction = "left"
if self.moveright:
self.direction = "right"
elif event.key == K_DOWN or event.key == K_s:
self.movedown = False
if self.moveleft:
self.direction = "left"
if self.moveright:
self.direction = "right"
pygame.display.update()
mainmenu()
pygame.quit()
The main problem is that you have two event loops.
In your main loop, you call pygame.event.get() to get all events which will clear the event queue.
Later, you call pygame.event.get() again in char1.getkey(). At this point, the event queue is already empty (this may happen vice versa, of course).
The easy way to fix it is to just pass every event from the main loop to char1:
while running:
mainwin.blit(background, (0, 0))
for event in pygame.event.get():
char1.getkey(event)
if event.type == pygame.QUIT:
pygame.quit()
char1.animandmove()
pygame.display.update()
and handle them in getkey:
def getkey(self, event):
if event.type == ...
...
There are several other issues with your code but that's out of scope of this question/answer.