I created a class of the player and I instantiated it and it doesn't work when I try to move it.
I don't understand what is wrong.
I thought the problem was in the order of the functions but isn't it.
Here is the code:
import pygame
from variabile import *
pygame.init()
screen = pygame.display.set_mode((1000,1000))
def ecranAlb():
WHITE = (255,255,255)
screen.fill(WHITE)
class Player():
def __init__(self,x,y):
self.x = x
self.y = y
def display(self):
rect = pygame.Rect(self.x,self.y,100,100)
pygame.draw.rect(screen,(255,255,0),rect)
def move(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_UP]:
self.x = self.x + 2
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
a = Player(100,100)
ecranAlb()
a.move()
a.display()
pygame.display.flip()
You have to create the instance object of the Player class before the application loop. When you do it in the loop, then the a new object at the initial position is generated in each frame:
a = Player(100,100) # <--- INSERET
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# a = Player(100,100) <--- DELETE
ecranAlb()
a.move()
a.display()
pygame.display.flip()
Related
I'm creating a small game in pygame with obstacles that fall from the top of the screen to the bottom. At each event tick, an obstacle is created. However, at each new tick (1500milliseconds) the current obstacle is removed before it can reach the bottom and a new one is created. I need the obstacles to stay on the screen while new ones are generated.
I'm trying to get this done with classes and functions only.
So I want to create an obstacle_movement() function within the obstacle class.
Can you help please?
My code is below.
import pygame
import sys
from random import randint
from pygame import surface
import time
import os
class obstacle(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
Obstacle_directory = r'C:\\Users\\ctcar\\Documents\\CompSci\\GameDev\\selfgame\\Graphics\\Obstacles'
obstacle_lst = []
self.obstacle_frames = []
for filename in sorted(os.listdir(Obstacle_directory), key = len):
if filename.endswith('.png'):
obstacle_lst.append('Graphics/Obstacles/' + filename)
for sprite in obstacle_lst:
alpha_sprite = pygame.image.load(sprite).convert_alpha()
self.obstacle_frames.append(alpha_sprite)
y_pos = -20
self.obstacle_idx = 0
self.frames = self.obstacle_frames
self.image = self.frames[self.obstacle_idx]
self.rect = self.image.get_rect(midbottom = (randint(50, 750), y_pos))
def obstacle_animation(self):
self.obstacle_idx += 0.1
if self.obstacle_idx >= len(self.frames):
self.obstacle_idx = 0
self.image = self.frames[int(self.obstacle_idx)]
def update(self):
self.obstacle_animation()
self.rect.y += 4
obstacle_group = pygame.sprite.GroupSingle()
obstacle_timer = pygame.USEREVENT + 1
pygame.time.set_timer(obstacle_timer, randint(1000, 1100))
game_active = True
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if game_active:
screen.blit(sky_surface,(0,0))
screen.blit(ground_surface,(100,710))
if event.type == obstacle_timer:
obstacle_group.add(obstacle())
obstacle_group.draw(screen)
obstacle_group.update()
pygame.display.update()
clock.tick(60)
You need to use a pygame.sprite.Group insterad of a pygame.sprite.GroupSingle:
obstacle_group = pygame.sprite.GroupSingle()
obstacle_group = pygame.sprite.Group()
See obstacle_group = pygame.sprite.GroupSingle():
The GroupSingle container only holds a single Sprite. When a new Sprite is added, the old one is removed.
Furthermore, the events must be handled in the event loop:
game_active = True
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if game_active:
if event.type == obstacle_timer:
obstacle_group.add(obstacle())
if game_active:
screen.blit(sky_surface,(0,0))
screen.blit(ground_surface,(100,710))
obstacle_group.draw(screen)
obstacle_group.update()
pygame.display.update()
clock.tick(60)
pygame.quit()
sys.exit()
import pygame
from sys import exit
import random
WIDTH, HEIGHT = 1400,750
FPS = 60
HEADWAY_GAP = 40
vehicleColor = {0:"red",1:"blue",2:"yellow"}
directions = ["Right", "Left"]
classofVehicle = ["Car","Bike","Bus"]
coord = {"Right":(0,300), "Left":(1400,350)}
objects = {"Right":[],"Left":[]}
pygame.init()
myWindow = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()
road = pygame.image.load("Required_images/Road/Road_final.png")
class Vehicle(pygame.sprite.Sprite):
def __init__(self, ClassofVehicle, Color_Code, direction, pos):
super().__init__()
self.Class = ClassofVehicle
self.Color_Code = Color_Code
self.direction = direction
self.pos = pos
path = "Required_images/"+ClassofVehicle+"/"+ClassofVehicle+"_"+Color_Code+".png"
self.image = pygame.image.load(path)
self.rect = self.image.get_rect()
if self.direction == "Right":
self.rect.midright = pos
else:
self.rect.midleft = pos
self.index = len(objects[direction])-1
def movingVehicles(self):
if self.direction == "Right":
if self.index == 0 or (self.rect.x + self.rect.width < objects[self.direction][self.index].rect.x - HEADWAY_GAP):
self.rect.x += 1
elif self.direction == "Left":
if self.index == 0 or (self.rect.x - self.rect.width > objects[self.direction][self.index].rect.x + HEADWAY_GAP):
self.rect.x -= 1
def update(self):
self.movingVehicles()
Object_timer = pygame.USEREVENT+1
pygame.time.set_timer(Object_timer, 1000)
objectsGroup = pygame.sprite.Group()
def generatingObjects():
Dir = random.choice(directions)
po = coord[Dir]
color_code = random.choice([0,1,2])
cla = random.choice(classofVehicle)
object = Vehicle(cla,vehicleColor[color_code],Dir,po)
objectsGroup.add(object)
objects[Dir].append(object)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == Object_timer:
generatingObjects()
myWindow.fill((0,0,0))
objectsGroup.update()
objectsGroup.draw(myWindow)
pygame.display.update()
clock.tick(FPS)
I have created a sprite class and a sprite group. I also created an user defined event to generate vehicles for every 1000ms. To display the vehicles on the screen instead of looping through all the elements of the sprite group separately I used group_name.draw() method. But when I run the code, some of the images are getting stuck on the screen for some time and are moving after sometime. I tried to look for any error in the logic but I couldn't find it. If you have any knowledge or able to find the error, please help and also any kind of suggestions are appreciated.
It is a matter of Indentation. You have to draw the scene in the application loop instead of after the application loop:
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == Object_timer:
generatingObjects()
# INDENTATION
#->|
myWindow.fill((0,0,0))
objectsGroup.update()
objectsGroup.draw(myWindow)
pygame.display.update()
clock.tick(FPS)
make sure to indent the elements in your while loop and use a pygame.display.flip() at the very end of your loop.
so it looks like
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == Object_timer:
generatingObjects()
myWindow.fill((0,0,0))
objectsGroup.update()
objectsGroup.draw(myWindow)
clock.tick(FPS)
pygame.display.flip()
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()
Currently, I have small image that I move using the D and A keys on the keyboard. The code works just how I want it to, but it seems to be a bit unnecessarily complicated. Is there a more efficient way of doing this?
In the main loop, my code checks to see what key is pressed through the events, but after that, if a key is no longer pressed, it checks to see if another key is pressed, just in case a user pressed a key while another key was initially pressed.
Here is my code:
import pygame
import sys
from pygame.locals import *
SCREENX = 640
SCREENY = 480
LEFT = 'left'
RIGHT = 'right'
class Character(pygame.sprite.Sprite):
def __init__(self, image_file):
super().__init__()
temp_image = pygame.image.load(image_file)
self.image = pygame.transform.scale(temp_image, (100, 100))
self.rect = self.image.get_rect()
self.moving = False
self.direction = RIGHT
def start_move(self, direction):
self.moving = True
if direction != self.direction:
self.image = pygame.transform.flip(self.image, True, False)
self.direction = direction
def stop_move(self):
if self.moving:
self.moving = False
def move(self):
if self.direction == RIGHT:
self.rect.x += 5
if self.direction == LEFT:
self.rect.x -= 5
def update(self):
if self.moving:
self.move()
def main():
pygame.init()
surface = pygame.display.set_mode((SCREENX, SCREENY))
clock = pygame.time.Clock()
sprites = pygame.sprite.Group()
girl = Character("assets/girl.png")
girl.rect.x = SCREENX/2
girl.rect.y = SCREENY - girl.rect.height
sprites.add(girl)
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if not girl.moving:
if event.key == K_d:
girl.start_move(RIGHT)
if event.key == K_a:
girl.start_move(LEFT)
if event.type == KEYUP:
if event.key == K_a or event.key == K_d:
girl.stop_move()
keys_pressed = pygame.key.get_pressed()
if keys_pressed[K_d]:
girl.start_move(RIGHT)
if keys_pressed[K_a]:
girl.start_move(LEFT)
surface.fill((255, 255, 255))
sprites.update()
sprites.draw(surface)
pygame.display.update()
clock.tick(60)
if __name__ == '__main__':
main()
Yes, you can get rid of most of the event handling, you can generalize your main loop, and you can get rid of some fields of your Character class.
See my explanatory notes in the comments:
import pygame
import sys
from pygame.locals import *
SCREENX = 640
SCREENY = 480
class Character(pygame.sprite.Sprite):
def __init__(self, image_file):
pygame.sprite.Sprite.__init__(self)
temp_image = pygame.image.load(image_file)
# only to the flipping of the image once
self.image_r = pygame.transform.scale(temp_image, (100, 100))
self.image_l = pygame.transform.flip(self.image_r, True, False)
self.image = self.image_l
self.rect = self.image.get_rect()
def update(self, pressed_keys):
move = 0
if pressed_keys[K_d]: move += 1
if pressed_keys[K_a]: move -= 1
self.rect.move_ip(move*5, 0)
# check which direction we're facing and set the image
self.image = self.image_l if move < 0 else self.image_r
def main():
pygame.init()
surface = pygame.display.set_mode((SCREENX, SCREENY))
clock = pygame.time.Clock()
sprites = pygame.sprite.Group()
girl = Character("assets/girl.png")
girl.rect.x = SCREENX / 2
girl.rect.y = SCREENY - girl.rect.height
sprites.add(girl)
while True:
for event in pygame.event.get():
# since we are in a function, we can simply return.
# we don't care here what happens after we quit the main loop
if event.type == QUIT: return pygame.quit()
# get all pressed keys, and just let all sprites
# decide what they want to do with it
keys_pressed = pygame.key.get_pressed()
# you could wrap this information in a more
# general container represeting the game state
# See how the game loop does not care what a
# Sprite does with this information
sprites.update(keys_pressed)
surface.fill((255, 255, 255))
sprites.draw(surface)
pygame.display.update()
clock.tick(60)
if __name__ == '__main__':
main()
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()