I have written a code which aims to move a horse when pressing the right arrow key, but when I press it, it doesnt move. I can't seem notice where the problem is. I have typed print(a.locx) in def char() to see a.locx is increasing or not but its not and also in class Horse()'s method def location() when I press right arrow key self.locx is increasing and then instantly decreasing.
import pygame
from pygame import locals
def main():
global window,width,height
pygame.init()
width ,height = 500,500
window = pygame.display.set_mode((width,height))
while True:
window.fill((0,0,0))
for event in pygame.event.get():
if pygame.event == pygame.QUIT:
pygame.quit()
char()
pygame.display.update()
def char():
a = Horse()
window.blit(a.horse1,(a.locx,a.locy))
print(a.locx)
a.location()
class Horse():
def __init__(self):
self.horse1 = pygame.image.load("C:/Users/niimet/Desktop/pygeym/blitz/Horse_Walk3.png")
self.horse2 = []
for horse in range(0,8):
self.horse2.append(pygame.image.load(("C:/Users/niimet/Desktop/pygeym/blitz/Horse_Walk{}.png").format(horse+1)))
self.horse3 = []
for horse in self.horse2:
self.horse3.append(pygame.transform.flip(horse,True,False))
self.locx = 0
self.locy = width - self.horse1.get_size()[1]
def location(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_RIGHT]:
print(self.locx,"1")
self.locx += 200
print(self.locx,"2")
main()
The issue is that you crate a new Horse object in every frame and so the horse continuously "starts" at its initial position.
def char():
a = Horse() # <--- creates new Hors object with "self.locx = 0"
# [...]
Create a Horse in global name space and use this object:
def main():
global window, width, height, a
pygame.init()
width, height = 500,500
window = pygame.display.set_mode((width,height))
a = Horse()
while True:
window.fill((0,0,0))
for event in pygame.event.get():
if pygame.event == pygame.QUIT:
pygame.quit()
char()
pygame.display.update()
def char():
window.blit(a.horse1,(a.locx,a.locy))
print(a.locx)
a.location()
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()
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 a very simple program. What I want is items in the thing class to move on their own.
import pygame
import time
import random
import threading
#initilasies it
pygame.init()
#variables for height and width
global display_width
display_width= 800
global display_height
display_height= 600
#declares colours uses RGB as reference
white= (255,255,255)
black = (0,0,0)
#sets the dispaly (must be inside a tuple ())
gameDisplay = pygame.display.set_mode((display_width,display_height))
#changes the name of the window
pygame.display.set_caption("Robot Quest")
#times stuff (is gonna be used for FPS)
clock = pygame.time.Clock()
#loads up an image (not shown) must be in same directory
tankImg = pygame.image.load("tank.png")
blockImg = pygame.image.load("block.png")
class things:
def __init__(self,width,height,speed):
self.width = width
self.height = height
#if display.width doesn't work just pass the screen dimensions
self.X = display_width - self.width
self.Y= display_height - self.height
self.speed = speed
def move(self):
self.X -= self.speed
pos = self.X
return pos
def drawImage(self,imageName,x,y):
gameDisplay.blit(imageName,(x,y))
def game_loop():
#game exit value is set
game_exit = False
#when true you exit the loop, logic goes here
while not game_exit:
for event in pygame.event.get():
#method below on what to do if they press x in the corner
if event.type == pygame.QUIT:
#exit the loop
pygame.quit()
quit()
#fills the background
gameDisplay.fill(white)
block = things(100,100,4)
block.drawImage(blockImg,block.X,block.Y)
block.move()
pygame.display.update()
clock.tick(30)
game_loop()
pygame.quit()
quit()
In the program block.move() executes once but that's all, so the object stays in the same place, having shifted only once place. I've tried to put the block.move() function in a for and while loop, but the program doesn't run if I do so. Can anyone advise me how fix my code so the object moves continuously, so it moves from end to the screen to another?
You seem to initialize your block in each loop. Try moving block = things(100,100,4) to before the while loop.
The problem is that you're re-initializing your block inside of your while loop, so in each iteration you're resetting it to its original position then moving it. Try moving the initialization outside of the while loop:
def game_loop():
#game exit value is set
game_exit = False
block = things(100,100,4)
#when true you exit the loop, logic goes here
while not game_exit:
for event in pygame.event.get():
#method below on what to do if they press x in the corner
if event.type == pygame.QUIT:
#exit the loop
pygame.quit()
quit()
#fills the background
gameDisplay.fill(white)
block.drawImage(blockImg,block.X,block.Y)
block.move()
pygame.display.update()
clock.tick(30)
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 am trying to animate a spritesheet when you press a button on the keyboard. My initial idea was to just blit the images on keypress. I moved the animation code from the main loop to the user input loop. That did not work because the game loop handles individual state for the entire game. What technique is used to trigger animations from user input? I want an animation system that can handle animations both by user input and also in the background on their own.
if __name__ == "__main__":
print "the game"
pygame.init()
screen = pygame.display.set_mode((800,600))
images = load_sliced_sprites(100, 71, "spinning_roundhouse_kick.png")
spritesheet = AnimatedSprite(images, 20)
#while pygame.event.poll().type != KEYDOWN:
while True:
screen.fill((255,255,255))
event = pygame.event.poll()
if event.type == KEYDOWN:
#print "keydown"
for image in images:
screen.blit(image, (0,0))
#time = pygame.time.get_ticks()
#spritesheet.update(time)
#screen.blit(spritesheet.image, (0,0))
pygame.display.update()
Looks like you should be doing something like this..
sprite = AnimatedSprite(images, 20)
if event.type == KEYDOWN:
sprite.update(pygame.time.get_ticks())
screen.blit(sprite.getimage())
What should happen, is your sprite class should get an update with the time delta, and count time before changing to a new frame. Draw your animation whenever the key is down.
I solved the issue by tracking the frames of animation and using another while true loop.
import os
import pygame
from pygame.locals import *
def load_sliced_sprites(w, h, filename):
'''
Specs :
Master can be any height.
Sprites frames width must be the same width
Master width must be len(frames)*frame.width
Assuming you ressources directory is named "resources"
'''
images = []
master_image = pygame.image.load(os.path.join('resources', filename)).convert_alpha()
master_width, master_height = master_image.get_size()
for i in xrange(int(master_width/w)):
images.append(master_image.subsurface((i*w,0,w,h)))
return images
class AnimatedSprite(pygame.sprite.Sprite):
def __init__(self, images, fps = 10):
pygame.sprite.Sprite.__init__(self)
self._images = images
# Track the time we started, and the time between updates.
# Then we can figure out when we have to switch the image.
self._start = pygame.time.get_ticks()
self._delay = 1000 / fps
self._last_update = 0
self._frame = 0
# Call update to set our first image.
self.update(pygame.time.get_ticks())
def update(self, t):
# Note that this doesn't work if it's been more that self._delay
# time between calls to update(); we only update the image once
# then, but it really should be updated twice.
if t - self._last_update > self._delay:
self._frame += 1
#if self._frame >= len(self._images): self._frame = 0
if self._frame < len(self._images):
self.image = self._images[self._frame]
self._last_update = t
def getimage(self):
return self.image
def isfinished(self):
if self._frame == len(self._images):
return True
else:
return False
def reset(self):
if self._frame >= len(self._images): self._frame = 0
if __name__ == "__main__":
print "the game"
pygame.init()
screen = pygame.display.set_mode((800,600))
images = load_sliced_sprites(100, 71, "spinning_roundhouse_kick.png")
sprite = AnimatedSprite(images, 20)
#while pygame.event.poll().type != KEYDOWN:
while True:
screen.fill((255,255,255))
event = pygame.event.poll()
if event.type == KEYDOWN and event.key == K_a:
#print "keydown"
#for image in images:
while True:
#print "frame"
#print sprite._frame
#print sprite.isfinished()
time = pygame.time.get_ticks()
sprite.update(time)
screen.blit(sprite.getimage(), (0,0))
pygame.display.update()
#sprite.reset()
if sprite.isfinished() == True:
sprite.reset()
break
#time = pygame.time.get_ticks()
#sprite.update(time)
#screen.blit(sprite.image, (0,0))
pygame.display.update()