简体   繁体   English

Pygame KEYUP,KEYDOWN导致幻影移动

[英]Pygame KEYUP, KEYDOWN causing ghost movement

I took a stab at learning KEYUP and KEYDOWN. 我在学习KEYUP和KEYDOWN时遇到了麻烦。 Bascily, after the user crashes into any side of the window the game resets like intended. 基本上,在用户崩溃到窗口的任意一侧后,游戏会按预期重置。 What is not intended is for the square to begin moving again even though no key has been pressed or released. 即使没有按下或释放任何键,也不希望正方形再次开始移动。

Ideal series of events: - User Crashes - Game resets with square in the original starting potion (stationary) - press a movement key and square moves 理想的事件系列:-用户崩溃-游戏在原始起始位置(固定)以正方形重置-按下移动键并进行正方形移动

Any insight into why this is happening would be great. 对于为什么会发生这种情况的任何见解都会很棒。

Thanks 谢谢

import pygame
import time

pygame.init()

display_width = 800
display_height = 600

black = (0, 0, 0)
white = (255, 255, 255)
red = (255, 0, 0)

car_width = 75

gameDisplay = pygame.display.set_mode((display_width, display_height))
pygame.display.set_caption('A bit Racey')
clock = pygame.time.Clock()


def text_objects(text, font):
    textSurface = font.render(text, True, black)
    return textSurface, textSurface.get_rect()


def message_display(text):
    largeText = pygame.font.Font('freesansbold.ttf', 115)
    TextSurf, TextRect = text_objects(text, largeText)
    TextRect.center = ((display_width / 2), (display_height / 2))
    gameDisplay.blit(TextSurf, TextRect)

    pygame.display.update()

    time.sleep(2)

    game_loop()


def crash():
    message_display('You Crashed')


def game_loop():
    x = 200
    y = 200

    x_change = 0
    y_change = 0

    gameExit = False

    while not gameExit:

        # Movement logic
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RIGHT:
                    x_change += 5
                if event.key == pygame.K_LEFT:
                    x_change += -5

            if event.type == pygame.KEYUP:
                if event.key == pygame.K_RIGHT:
                    x_change += -5
                if event.key == pygame.K_LEFT:
                    x_change += 5

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_UP:
                    y_change += -5
                if event.key == pygame.K_DOWN:
                    y_change += 5

            if event.type == pygame.KEYUP:
                if event.key == pygame.K_UP:
                    y_change += 5
                if event.key == pygame.K_DOWN:
                    y_change += -5

        x += x_change
        y += y_change

        gameDisplay.fill(white)
        pygame.draw.rect(gameDisplay, red, [x, y, 75, 75])

        # Check if border hit
        if x > display_width - car_width or x < 0:
            crash()
        if y > display_height - car_width or y < 0:
            crash()

        pygame.display.update()
        clock.tick(60)


game_loop()
pygame.quit()
quit()

Screw global variables, events and lots of flags. 修改全局变量,事件和大量标志。

Just use pygame.key.get_pressed to get the current state of the keyboard. 只需使用pygame.key.get_pressed即可获取键盘的当前状态。 Assign each arrow key a movement vector, add them up, normalize it, and there you go. 为每个箭头键分配一个运动矢量,将其累加,归一化,然后就可以了。

Also, if you want to do something with something rectangular, just use the Rect class. 另外,如果您想对矩形做某事,只需使用Rect类。 It will make your live a lot easier. 这将使您的生活更加轻松。

Here's a running example: 这是一个正在运行的示例:

import pygame
import time

pygame.init()

display_width = 800
display_height = 600

black = (0, 0, 0)
white = (255, 255, 255)
red = (255, 0, 0)

car_width = 75

gameDisplay = pygame.display.set_mode((display_width, display_height))
pygame.display.set_caption('A bit Racey')
clock = pygame.time.Clock()


def text_objects(text, font):
    textSurface = font.render(text, True, black)
    return textSurface, textSurface.get_rect()


def message_display(text):
    largeText = pygame.font.Font('freesansbold.ttf', 115)
    TextSurf, TextRect = text_objects(text, largeText)
    TextRect.center = ((display_width / 2), (display_height / 2))
    gameDisplay.blit(TextSurf, TextRect)

    pygame.display.update()

    time.sleep(2)

    game_loop()


def crash():
    message_display('You Crashed')

keymap = {
    pygame.K_RIGHT: pygame.math.Vector2(1, 0),
    pygame.K_LEFT: pygame.math.Vector2(-1, 0),
    pygame.K_UP: pygame.math.Vector2(0, -1),
    pygame.K_DOWN: pygame.math.Vector2(0, 1)
}

def game_loop():

    # we want to draw a rect, so we simple use Rect
    rect = pygame.rect.Rect(200, 200, 75, 75)

    gameExit = False

    while not gameExit:

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

        # get the state of the keyboard
        pressed = pygame.key.get_pressed()
        # get all the direction vectors from the keymap of all keys that are pressed
        vectors = (keymap[key] for key in keymap if pressed[key])
        # add them up to we get a single vector of the final direction
        direction = pygame.math.Vector2(0, 0)
        for v in vectors:
            direction += v

        # if we have to move, we normalize the direction vector first
        # this ensures we're always moving at the correct speed, even diagonally
        if direction.length() > 0:
            rect.move_ip(*direction.normalize()*5)

        gameDisplay.fill(white)
        pygame.draw.rect(gameDisplay, red, rect)

        # Check if border hit
        # See how easy the check is
        if not gameDisplay.get_rect().contains(rect):
            crash()

        pygame.display.update()
        clock.tick(60)


game_loop()
pygame.quit()
quit()

There are some other issues with your code: 您的代码还有其他一些问题:

For example, if you use time.sleep(2) , your entire program will freeze. 例如,如果使用time.sleep(2) ,则整个程序将冻结。 This means you can't close the window while waiting and the window will not be redrawn by the window manager etc. 这意味着您无法在等待时关闭窗口,并且窗口管理器等将不会重新绘制窗口。

Also, your code contains an endless loop. 另外,您的代码包含一个无限循环。 If you hit the wall often enough, you'll run into a stack overflow, because game_loop calls crash which in turn calls game_loop again. 如果您经常碰壁,就会遇到堆栈溢出的情况,因为game_loop调用会crash ,从而又调用game_loop This is probably not a big issue at first, but something to keep in mind. 起初这可能不是一个大问题,但要记住一点。

What you need is to set your game variables (x, y, x_change, y_change) back to defaults, most probably in crash() function after crash. 您需要将游戏变量(x,y,x_change,y_change)设置为默认值,很可能是在crash()后使用crash crash()函数。 pygame won't do that for you. pygame不会为您做到这一点。

Either make your variables global, or use some mutable object (like dictionary) to access them from other methods. 要么使变量成为全局变量,要么使用一些可变对象(例如字典)从其他方法访问它们。

As Daniel Kukiela says, you can make "x_change" and "y_change" into global variables, along with giving them the value of 0 at the start, here is the working project as far as I understand. 正如Daniel Kukiela所说,您可以将“ x_change”和“ y_change”设置为全局变量,并在开始时将它们的值设置为0,据我所知,这是工作项目。

import pygame
import time

pygame.init()

display_width = 800
display_height = 600

black = (0, 0, 0)
white = (255, 255, 255)
red = (255, 0, 0)

car_width = 75
x_change = 0
y_change = 0

gameDisplay = pygame.display.set_mode((display_width, display_height))
pygame.display.set_caption('A bit Racey')
clock = pygame.time.Clock()


def text_objects(text, font):
    textSurface = font.render(text, True, black)
    return textSurface, textSurface.get_rect()


def message_display(text):
    largeText = pygame.font.Font('freesansbold.ttf', 115)
    TextSurf, TextRect = text_objects(text, largeText)
    TextRect.center = ((display_width / 2), (display_height / 2))
    gameDisplay.blit(TextSurf, TextRect)

    pygame.display.update()

    time.sleep(2)

    game_loop()


def crash():
    message_display('You Crashed')


def game_loop():
    x = 200
    y = 200
    global x_change
    x_change == 0
    global y_change
    y_change == 0



    gameExit = False

    while not gameExit:

        # Movement logic
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RIGHT:
                    x_change += 5
                if event.key == pygame.K_LEFT:
                    x_change += -5

            if event.type == pygame.KEYUP:
                if event.key == pygame.K_RIGHT:
                    x_change += -5
                if event.key == pygame.K_LEFT:
                    x_change += 5

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_UP:
                    y_change += -5
                if event.key == pygame.K_DOWN:
                    y_change += 5

            if event.type == pygame.KEYUP:
                if event.key == pygame.K_UP:
                    y_change += 5
                if event.key == pygame.K_DOWN:
                    y_change += -5

        x += x_change
        y += y_change

        gameDisplay.fill(white)
        pygame.draw.rect(gameDisplay, red, [x, y, 75, 75])

        # Check if border hit
        if x > display_width - car_width or x < 0:
            crash()
        if y > display_height - car_width or y < 0:
            crash()

        pygame.display.update()
        clock.tick(60)


game_loop()
pygame.quit()
quit()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM