How to make your character move without tapping repeatedly on buttons?

我怕爱的太早我们不能终老 提交于 2020-01-05 04:26:09

问题


I'm working on a racing game. I have been using this code but my player keeps moving once only. How do I solve this problem?

change = 7
dist = 7
change_r = 0
change_l = 0
dist_u = 0
dist_d = 0
pygame.display.update()  


for event in pygame.event.get():
    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_RIGHT:
           change_r = True

        elif event.key == pygame.K_LEFT:
            change_l = True


        elif event.key == pygame.K_UP:
            dist_u = True     

        elif event.key == pygame.K_DOWN:
            dist_d = True



    if event.type == pygame.KEYUP:
        if event.key == pygame.K_RIGHT or event.key == pygame.K_LEFT or event.key == pygame.K_UP or event.key == pygame.K_DOWN:
            change_r = False
            change_l = False
            dist_u = False
            dist_d = False
    clock.tick(60)     

    if change_r == True:
        x += change
    if change_l == True:
        x -= change
    if dist_u == True:
        y -= dist
    if dist_d == True:
        y += dist

回答1:


There are different ways you could go about making move-able shapes/sprites using Pygame. The code you posted in your question seems overly complex. I'll give you two different ways that are simpler, and easier to use. Using a sprite class, and using a function.

It may not seem like I'm answering your question, but if I just told you what to fix in your code you posted, I'd just be knowingly steering you down a road that will lead to many problems, and much complexity in the future.

Method 1: Using a sprite class

To make a your race car sprite, you could use a sprite class like the one below.

class Player(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface((50, 50))
        self.image.fill((255, 0, 0))
        self.rect = self.image.get_rect()
        self.rect.x = WIDTH / 2
        self.rect.y = HEIGHT / 2
        self.vx = 0
        self.vy = 0

    def update(self):
        self.vx = 0
        self.vy = 0
        key = pygame.key.get_pressed()
        if key[pygame.K_LEFT]:
            self.vx = -5
        elif key[pygame.K_RIGHT]:
            self.vx = 5
        if key[pygame.K_UP]:
            self.vy = -5
        elif key[pygame.K_DOWN]:
            self.vy = 5
        self.rect.x += self.vx
        self.rect.y += self.vy

Since your class is inheriting from Pygame's sprite class, You must name your image self.image and you must name your rectangle for the image self.rect. As you can also see, the class has two main methods. One for creating the sprite(__init__) and one for updating the sprite(update)

To use your class, make a Pygame sprite group to hold all your sprites, and then add your player object to the group:

sprites = pygame.sprite.Group()
player = Player()
sprtites.add(player)

And to actual render your sprites to the screen call sprites.update() and sprites.draw() in your game loop, where you update the screen:

sprites.update()
window_name.fill((200, 200, 200))
sprites.draw(window_name)
pygame.display.flip()

The reason i highly recommended using sprite classes, is that it will make your code look much cleaner, and be much easier to maintain. You could even move each sprite class to their own separate file.

Before diving fully into the method above however, you should read up on pygame.Rect objects and pygame.sprite objects, as you'll be using them.

Method 2: Using A function

If you prefer not to get into sprite classes, you can create your game entities using a function similar to the one below.

def create_car(surface, x, y, w, h, color):
    rect = pygame.Rect(x, y, w, h)
    pygame.draw.rect(surface, color, rect)
    return rect

If you would still like to use a sprites, but don't want to make a class just modify the function above slightly:

def create_car(surface, x, y, color, path_to_img):
    img = pygame.image.load(path_to_img)
    rect = img.get_rect()
    surface.blit(img, (x, y))

Here is an example of how i would use the functions above to make a movable rectangle/sprite:

import pygame

WIDTH = 640
HEIGHT = 480
display = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Moving Player Test")
clock = pygame.time.Clock()
FPS = 60

def create_car(surface, x, y, w, h, color):
    rect = pygame.Rect(x, y, w, h)
    pygame.draw.rect(surface, color, rect)
    return rect

running = True
vx = 0
vy = 0
player_x = WIDTH / 2 # middle of screen width
player_y = HEIGHT / 2 # middle of screen height
player_speed = 5
while running:
    clock.tick(FPS)
    for e in pygame.event.get():
        if e.type == pygame.QUIT:
            running = False
            pygame.quit()
            quit()
        if e.type == pygame.KEYDOWN:
            if e.key == pygame.K_LEFT:
                vx = -player_speed
            elif e.key == pygame.K_RIGHT:
                vx = player_speed
            if e.key == pygame.K_UP:
                vy = -player_speed
            elif e.key == pygame.K_DOWN:
                vy = player_speed
        if e.type == pygame.KEYUP:
            if e.key == pygame.K_LEFT or e.key == pygame.K_RIGHT or\
               e.key == pygame.K_UP or e.key == pygame.K_DOWN:
                vx = 0
                vy = 0

    player_x += vx
    player_y += vy
    display.fill((200, 200, 200))
    ####make the player#####
    player = create_car(display, player_x, player_y, 10, 10, (255, 0, 0))
    pygame.display.flip()

As you may see above, your code for moving your race car can be simplified.

I should note, I'm assuming a few things with each method outlined above.

  1. That your either using a circle, square, or some type of pygame shape object.

  2. Or that your using a sprite.

If your not currently using any of the methods outlined above, I suggest that you do. Doing so will make your code much eaiser to maintain once you begin to build larger and more complex games.




回答2:


You should have a global loop irrespective of your event handling. You should place your clock.tick() and your movement there. Namely:

#some constants here
while True:    
    pygame.display.update()  
    clock.tick(60)
    #update you game state
    if change_r == True:
        x += change
    if change_l == True:
        x -= change
    if dist_u == True:
        y -= dist
    if dist_d == True:
        y += dist

    for event in pygame.event.get():
        # react to player input by changing the game state


来源:https://stackoverflow.com/questions/38933399/how-to-make-your-character-move-without-tapping-repeatedly-on-buttons

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!