Reputation: 165
making a simple game in pygame. have imported an image for my charactater and can move him around freely. I was wondering how to make the character slowly stop when the;
event.type == KEYUP:
as in, When I release the key the character will take say, 50 pixels from when the key has been released to the character slowly stopping.
I have tried a few different things but nothing seems to work. below is my code. any help would be great =]
bg="bg.jpg"
staticCharacter="toon.png"
import pygame, sys, time
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((640,360),0,32)
background=pygame.image.load(bg).convert()
staticToon = pygame.image.load(characterMid).convert_alpha()
x = 0
y = 0
movex = 0
movey = 0
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_LEFT:
movex = -0.20
elif event.key == K_RIGHT:
movex = +0.20
elif event.key == K_UP:
movey = -0.20
elif event.key == K_DOWN:
movey = +0.20
if event.type == KEYUP:
if event.key == K_LEFT:
movex = 0
elif event.key == K_RIGHT:
movex = 0
elif event.key == K_UP:
movey = 0
elif event.key == K_DOWN:
movey = 0
x += movex
y += movey
if x > 560:
x = 560
if y > 280:
y = 280
if x < 0:
x = 0
if y < 0:
y = 0
screen.blit(background,(0,0))
screen.blit(staticToon,(x,y))
pygame.display.update()
Upvotes: 0
Views: 2467
Reputation: 880239
distance = speed*time
Instead of augmenting the position (through movex
or movey
), you want to augment the speed:
delta = {
pygame.K_LEFT: (-20, 0),
pygame.K_RIGHT: (+20, 0),
pygame.K_UP: (0, -20),
pygame.K_DOWN: (0, +20),
}
...
elif event.type == pygame.KEYDOWN:
deltax, deltay = delta.get(event.key, (0, 0))
ball.speed[0] += deltax
ball.speed[1] += deltay
Now, to slow down the object (a ball in my example below), add some friction:
ball.speed[0] *= 0.95
ball.speed[1] *= 0.95
This diminishes the speed by a little bit each time through the event loop.
Move the object a distance equal to speed * time
. To make things simple, let's just take change in time to be 1.
self.rect = self.rect.move(self.speed)
Here is a runnable example: (just add a correct path for staticCharacter
.)
import sys
import pygame
import os
'''
Based on http://www.pygame.org/docs/tut/intro/intro.html
Draws a red ball bouncing around in the window.
Pressing the arrow keys moves the ball
'''
staticCharacter = "toon.png"
delta = {
pygame.K_LEFT: (-20, 0),
pygame.K_RIGHT: (+20, 0),
pygame.K_UP: (0, -20),
pygame.K_DOWN: (0, +20),
}
class Ball(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(staticCharacter)
self.rect = self.image.get_rect()
self.speed = [2, 2]
self.area = pygame.display.get_surface().get_rect()
def update(self):
self.rect = self.rect.move(self.speed)
if self.rect.left < 0 or self.rect.right > self.area.width:
self.speed[0] = -self.speed[0]
if self.rect.top < 0 or self.rect.bottom > self.area.height:
self.speed[1] = -self.speed[1]
class Main(object):
def __init__(self):
self.setup()
def setup(self):
pygame.init()
size = (self.width, self.height) = (640,360)
self.black = (0, 0, 0)
self.screen = pygame.display.set_mode(size, 0, 32)
self.ball = Ball()
self.setup_background()
def setup_background(self):
self.background = pygame.Surface(self.screen.get_size())
self.background = self.background.convert()
self.background.fill(self.black)
self.screen.blit(self.background, (0, 0))
pygame.display.flip()
def draw(self):
self.screen.blit(self.background, (0, 0))
self.screen.blit(self.ball.image, self.ball.rect)
pygame.display.flip()
def event_loop(self):
ball = self.ball
while True:
for event in pygame.event.get():
if ((event.type == pygame.QUIT) or
(event.type == pygame.KEYDOWN and
event.key == pygame.K_ESCAPE)):
sys.exit()
elif event.type == pygame.KEYDOWN:
deltax, deltay = delta.get(event.key, (0, 0))
ball.speed[0] += deltax
ball.speed[1] += deltay
ball.speed = [0.99*s for s in ball.speed]
ball.update()
self.draw()
pygame.time.delay(10)
if __name__ == '__main__':
app = Main()
app.event_loop()
Upvotes: 1
Reputation: 512
My advice: Go to the following website: http://karpathy.ca/phyces/tutorial1.php Download pygamehelper and startercode (I promise it will make your life easier). FPS is built-in so you don't need to make the adjustments within your movement logic. Review some of the other tutorials if you want further clarification and use the vector library if you want some extra snaz.
Upvotes: 0
Reputation: 11180
Normally, character movement is made to be independent from the machine speed. In your example, you do not know how many times per second the While loop goes, it is dependent on the computer speed. So firstly, you should use the pygame Clock to calculate the time difference between each call to move().
myclock = pygame.Clock()
delta = myclock.tick()
when you have the time difference, you can use a distance equation such as this:
position += speed * direction * delta
delta
is in ms, so you need to set your speed
accordingly. The direction
would be -1 or +1 depending on the current key pressed. A keyup would set direction to 0.
Now back to the question. You would have to change the above a bit differently. A keyup would subtract a small value from direction.
Then check if direction isn't 1 or -1 and then subtract a value from your direction. You would do this every loop. This way it will get smaller and smaller, and it will appear that your character is slowing down. It is good to also multiply the value that you subtract by delta so it will be deacceleration will constant on every computer.
Upvotes: 0