1
votes

So I'm new to python and I'm trying to learn the pygame module by programming a little cars game. The "engine" of the game is based on scrolling background that moves down when the user press the "up" key.

I'm trying to make a deceleration of the car (when the user release the "up" key) instead of immediate stop. So for that I've tried to use a float for loop (using numpy module) that decrease the speed of the background movement from 5 to 0 by -0.1, but it doesn't work properly. What actually happened is that when I release the "up" key, the game freeze for a sec and then the background unsmoothly moves a few pixels down.

This is my code, hope you can help me fix that:

import pygame
import numpy

pygame.init()
clock = pygame.time.Clock()
run = True

# screen & bg setting
wnw = 500
wnh = 700
wn = pygame.display.set_mode((wnw, wnh))
bgcolor = (70, 190, 255)
bg = pygame.image.load('road.jpg')
bgy = 0
bgy2 = -bg.get_height()

# loading objects
class Car():
    sprite = pygame.image.load('car.gif')
    w = 100
    h = 100
    x = 200
    y = 350
    ver_spd = 5
    hor_spd = 2
car = Car()

def drawbg():
    wn.blit(bg, (0, bgy))
    wn.blit(bg, (0, bgy2))
drawbg()

while run:

    clock.tick(60)

    # keys binding
    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT]:
        if car.x + car.hor_spd > 0:
            drawbg()
            car.x -= car.hor_spd
    if keys[pygame.K_RIGHT]:
        if car.x + car.hor_spd < wnw - car.w:
            drawbg()
            car.x += car.hor_spd
    if keys[pygame.K_UP]:
        if car.y - car.ver_spd > 0:
            bgy, bgy2 = bg_movement(bgy, bgy2, car.ver_spd)
    def bg_movement(bgy, bgy2, spd):
        drawbg()
        bgy += float(spd)
        bgy2 += float(spd)
        if bgy > bg.get_height():
            bgy = -bg.get_height()
        if bgy2 > bg.get_height():
            bgy2 = -bg.get_height()
        return bgy, bgy2


    for event in pygame.event.get():
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_UP:
                for i in numpy.arange(5.0, 0.0, -0.1):
                    bgy, bgy2 = bg_movement(bgy, bgy2, float(i))

    wn.blit(car.sprite, (car.x, car.y))

    pygame.display.update()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        print(event)

pygame.quit()
1

1 Answers

1
votes

First of pygame.event.get() get all the messages and remove them from the queue. So either the 1st or the 2nd loop gets an event, but never both loops will get all events. That causes that some events seems to be missed.
implement 1 event loop in your application.

Once UP is released, you've to set a decelerate state. Decrease the variable and move the care forward by the amount in every frame as long decelerate > 0:

def drawbg():
    wn.blit(bg, (0, int(bgy)))
    wn.blit(bg, (0, int(bgy2)))
drawbg()

def bg_movement(bgy, bgy2, spd):
        bgy += float(spd)
        bgy2 += float(spd)
        if bgy > bg.get_height():
            bgy = -bg.get_height()
        if bgy2 > bg.get_height():
            bgy2 = -bg.get_height()
        return bgy, bgy2

decelerate = 0
while run:

    clock.tick(60)

    # keys binding
    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT]:
        if car.x + car.hor_spd > 0:

            car.x -= car.hor_spd
    if keys[pygame.K_RIGHT]:
        if car.x + car.hor_spd < wnw - car.w:
            car.x += car.hor_spd
    if keys[pygame.K_UP]:
        decelerate = 0
        if car.y - car.ver_spd > 0:
            bgy, bgy2 = bg_movement(bgy, bgy2, car.ver_spd)

    if decelerate > 0:
        bgy, bgy2 = bg_movement(bgy, bgy2, decelerate)
        decelerate -= 0.1


    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_UP:
                decelerate = car.ver_spd


    drawbg()
    wn.blit(car.sprite, (car.x, car.y))

    pygame.display.update()