Mark.S
Mark.S

Reputation: 165

pygame slowing down an object with KEYUP?

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

Answers (3)

unutbu
unutbu

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

OliasailO
OliasailO

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

Bartlomiej Lewandowski
Bartlomiej Lewandowski

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

Related Questions