簡體   English   中英

Pygame:在相反方向按下鍵時停止角色移動

[英]Pygame: stopping character movement when a key is pressed in the opposite direction

基本上,我的游戲涉及在屏幕上移動角色,並帶有可收集的矩形和障礙物。 那不是我遇到的問題。 我的問題出現在“簡單”模式下,我希望角色在按下與他們移動方向相反的鍵時停止移動。 例如,如果角色向左移動並且按下了向右箭頭,我希望他們停止移動。 我認為問題在於程序認為當它阻止角色移動時正確的壓力會繼續過去,因此檢測到它只是試圖向右移動。 如果您足夠快地敲擊該鍵,則不會發生。 這只是我為自己做的一個項目,所以真的很煩人。 另外請原諒代碼有多么混亂,我嘗試了許多不同的方法,所以如果任何東西看起來沒有任何進展,那是因為它沒有。

import os, random, pygame, time

difficulty = input("Enter difficulty level. \nEASY\nNORMAL\n>>> ")
while difficulty.lower() not in ("easy", "normal"):
    difficulty = input("Enter difficulty level. \nEASY\nNORMAL\n>>> ")
if "easy" in difficulty:
    easy = True
else:
    easy = False


pygame.init()

# Defining variables
SCREEN_W, SCREEN_H = 600, 600
MAP_W, MAP_H = 2000, 2000
BACKGROUND = pygame.transform.scale(pygame.image.load(
    os.path.join("Assets", "image.png")), (MAP_W, MAP_H)) # Change this to work with whatever images you have

cameraOffset = [MAP_W//2-SCREEN_W//2, MAP_H//2-SCREEN_H//2]
move_dir = ""

objects = []
apples = []
deadly_objects = []
wallobjects = []
start_of_game = True

wall_text, wall_pop_text = None, None

SPEED = 10
WIN = pygame.display.set_mode((SCREEN_W, SCREEN_H))
FPS = 60
clock = pygame.time.Clock()
delay = 8
    
PLAYER_W, PLAYER_H = 40, 40



player = pygame.Rect(MAP_W//2-PLAYER_W, MAP_H//2-PLAYER_H, PLAYER_W, PLAYER_H)
for i in range(5):
    apple = pygame.Rect(i*200, i*200, 30, 30)
    apples.append(apple)

right_wall, left_wall = pygame.Rect(MAP_W, 0, 200, MAP_H+30), pygame.Rect(20, 0, 20, MAP_H+30)
up_wall = pygame.Rect(0,20,MAP_W,20)
down_wall = pygame.Rect(0, MAP_H, MAP_W, 20)
for i in range(10):
    if random.randint(0,1) == 1:
        mid_wall = pygame.Rect(random.randint(100, MAP_W-100), random.randint(100, MAP_H-100), 20, 80)
    else:
        mid_wall = pygame.Rect(random.randint(100, MAP_W-100), random.randint(100, MAP_H-100), 80, 20)
    for i in apples:
        while pygame.Rect.colliderect(mid_wall, i):
            if random.randint(0,1) == 1:
                mid_wall = pygame.Rect(random.randint(100, MAP_W-100), random.randint(100, MAP_H-100), 20, 80)
            else:
                 mid_wall = pygame.Rect(random.randint(100, MAP_W-100), random.randint(100, MAP_H-100), 80, 20)
    objects.append(mid_wall)
wallobjects.append(right_wall)
wallobjects.append(left_wall)
wallobjects.append(up_wall)
wallobjects.append(down_wall)
    
text_font = pygame.font.SysFont("times new roman", 40)
death_font = pygame.font.SysFont("times new roman",60)
press_font = pygame.font.SysFont("times new roman",30, False, True)
notification = pygame.font.SysFont("times new roman", 15, True, True)
notification_big = pygame.font.SysFont("times new roman", 20, True, True)

score = 0

def collision(x, y): # Looking for a collision with an object
    global player, objects, wallobjects
    new_player = pygame.Rect(x,y, PLAYER_W, PLAYER_H)
    for i in objects:
        if pygame.Rect.colliderect(i, new_player):
            return True
    for i in wallobjects:
        if pygame.Rect.colliderect(i, new_player):
            return True
    return False

def display_death_screen():
    global move_dir, score
    score = 0
    move_dir = ""
    
    player.x, player.y = MAP_W//2, MAP_H//2
    text = death_font.render("YOU DIED", 1, (0,0,255))
    WIN.blit(text, (SCREEN_W//2-SCREEN_W//3, SCREEN_H//2-50))
    press_enter = press_font.render("Press enter to respawn...", 0, (255,0,50))
    WIN.blit(press_enter, (SCREEN_W//2-140, SCREEN_H//2+10))

    if wall_pop_text != None and pygame.time.get_ticks() < wall_end_pop:
        WIN.blit(wall_pop_text, (SCREEN_W-140, 15))
    
    pygame.display.update()
    
def handle_movement(pressed, player): # Problem is in this function I think
    global cameraOffset, playerScreenPos, move_dir, start_of_game
    # The collision checking could probably be done better but it works like this (actually probably the case with most of this code lol)

    movement_window = pygame.time.get_ticks() + # Even if you put a ridiculous number here it makes no difference
    
    if easy == False:
        if (pressed[pygame.K_a] or pressed[pygame.K_LEFT] or move_dir == "left") and player.x - (SPEED + player.width//2) > 0 and move_dir != "right": # left
            move_dir = "left"
            player.x -= SPEED

        if (pressed[pygame.K_d] or pressed[pygame.K_RIGHT] or move_dir == "right") and player.x + (SPEED + player.width//2) < MAP_W and move_dir != "left": # right
            move_dir = "right"
            player.x += SPEED

        if (pressed[pygame.K_w]or pressed[pygame.K_UP] or move_dir == "up") and player.y - (SPEED + player.width//2) > 0 and move_dir != "down": # up
            move_dir = "up"
            player.y -= SPEED
    
        if (pressed[pygame.K_s] or pressed[pygame.K_DOWN] or move_dir == "down") and player.y + (SPEED + player.height//2) < MAP_H and move_dir != "up": # down
            move_dir = "down"
            player.y += SPEED

        
    else:
        if move_dir == "":
            if pygame.time.get_ticks() < movement_window:
                start_of_game = False
                move_dir = "."
        
        if (pressed[pygame.K_a] or pressed[pygame.K_LEFT] or move_dir == "left") and player.x - (SPEED + player.width//2) > 0 and move_dir != "": # left
            if move_dir == "right":
                move_dir = ""
            if move_dir != "" and not start_of_game:
                move_dir = "left"
                player.x -= SPEED

        if (pressed[pygame.K_d] or pressed[pygame.K_RIGHT] or move_dir == "right") and player.x + (SPEED + player.width//2) < MAP_W and move_dir != "": # right
            if move_dir == "left":
                move_dir = ""
            if move_dir != "" and not start_of_game:
                move_dir = "right"
                player.x += SPEED

        if (pressed[pygame.K_w]or pressed[pygame.K_UP] or move_dir == "up") and player.y - (SPEED + player.width//2) > 0 and move_dir != "": # up
            if move_dir == "down":
                move_dir = ""
            if move_dir != ""and not start_of_game:
                move_dir = "up"
                player.y -= SPEED
    
        if (pressed[pygame.K_s] or pressed[pygame.K_DOWN] or move_dir == "down") and player.y + (SPEED + player.height//2) < MAP_H and move_dir != "": # down
            if move_dir == "up":
                move_dir = ""
            if move_dir != "" and not start_of_game:
                move_dir = "down"
                player.y += SPEED

    cameraOffset[0] += (player.x - cameraOffset[0] - (SCREEN_W * 0.5)) / delay
    cameraOffset[1] += (player.y - cameraOffset[1] - (SCREEN_H * 0.5)) / delay

    cameraOffset[0] = max(0, min(cameraOffset[0], MAP_W - SCREEN_W))
    cameraOffset[1] = max(0, min(cameraOffset[1], MAP_H - SCREEN_H))



def add_wall():
    global mid_wall, objects, wall_text, wall_end

    wall_text = notification.render("Wall added", 1, (255,0,0))
    wall_end = pygame.time.get_ticks() + 3000
        
    if random.randint(0,1) == 1:
        mid_wall = pygame.Rect(random.randint(100, MAP_W-100), random.randint(100, MAP_H-100), 20, 80)
    else:
        mid_wall = pygame.Rect(random.randint(100, MAP_W-100), random.randint(100, MAP_H-100), 80, 20)
    for i in apples:
        while pygame.Rect.colliderect(mid_wall, i) or pygame.Rect.colliderect(mid_wall, pygame.Rect(player.x-100, player.y-100, player.width+100, player.height+100)):
            if random.randint(0,1) == 1:
                mid_wall = pygame.Rect(random.randint(100, MAP_W-100), random.randint(100, MAP_H-100), 20, 80)
            else:
                mid_wall = pygame.Rect(random.randint(100, MAP_W-100), random.randint(100, MAP_H-100), 80, 20)
    
    objects.append(mid_wall)

def remove_wall():
    global wall_pop_text, wall_end_pop
    if len(objects) > 0:
        wall_remove = random.choice(objects)
    
        wall_pop_text = notification.render("Wall removed", 1, (255,0,0))
        wall_end_pop = pygame.time.get_ticks() + 3000

        objects.remove(wall_remove)

def handle_apple():
    global score
    for i in apples:
        x, y = i.x-cameraOffset[0], i.y-cameraOffset[1]
        pygame.draw.circle(WIN, (255,0,0), (x, y), i.width//2)
        if pygame.Rect.colliderect(player, i):
            apples.remove(i)
            score += 1
            if score % 5 == 0 and score != 0:
                add_wall()
            xx, yy = random.randint(40,MAP_H-40), random.randint(40,MAP_H-40)
            for i in objects:
                while pygame.Rect.colliderect(pygame.Rect(xx, yy, 30, 30), i):
                    xx, yy = random.randint(40,MAP_H-40), random.randint(40,MAP_H-40)
            apple = pygame.Rect(xx, yy, 30, 30)
            apples.append(apple)
            
            

def draw_screen(player): # Drawing to the screen
    global wall_text, wall_end
 
    WIN.blit(BACKGROUND, (0 - cameraOffset[0], 0 - cameraOffset[1]))

    score_disp = text_font.render("Score: "+str(score), 0, (255,255,255))
    wall_amount = notification_big.render("Walls: "+str(len(objects)), 0, (255,255,255))
    press_space_text = notification_big.render("Movement Paused", 0, (255,255,255))
        
    handle_apple()
    playerPos = ((player.x - PLAYER_W//2) - cameraOffset[0], (player.y-PLAYER_H//2) - cameraOffset[1])
    pygame.draw.rect(WIN, (100, 10, 255), (*playerPos, player.width, player.height))
                
    for i in objects:
        numberx = i.width // 20
        numbery = i.height // 20
        try:
            pygame.draw.rect(WIN, (0,0,0), (i.x - cameraOffset[0] - i.width// numberx, i.y - cameraOffset[1] - i.height//numbery, i.width, i.height))
        except:
            numberx = i.width 
            numbery = i.height
    
    for i in wallobjects:
        numberx = i.width // 20
        numbery = i.height // 20
        try:
            pygame.draw.rect(WIN, (0,0,0), (i.x - cameraOffset[0] - i.width// numberx, i.y - cameraOffset[1] - i.height//numbery, i.width, i.height))
        except:
            numberx = i.width 
            numbery = i.height
            
    if wall_text != None and pygame.time.get_ticks() < wall_end:
        WIN.blit(wall_text, (SCREEN_W-120, 15))

    if wall_pop_text != None and pygame.time.get_ticks() < wall_end_pop:
        WIN.blit(wall_pop_text, (SCREEN_W-140, 15))

    if easy and move_dir == "":
        WIN.blit(press_space_text, (SCREEN_W//2-200, SCREEN_H//2+player.height+5))
    
    WIN.blit(score_disp, (10, 10))
    WIN.blit(wall_amount, (10, SCREEN_H-30))
                 
    pygame.display.update()



def main():
    global cameraOffset, move_dir
    running, dead = True, False
    while running:
        clock.tick(FPS)
        if collision(player.x, player.y):
            remove_wall()
            dead = True
        if dead:
            display_death_screen()
        if not dead:
            draw_screen(player)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    running = False
                if event.key == pygame.K_RETURN and dead:
                    dead = False
        keys_pressed = pygame.key.get_pressed()
        handle_movement(keys_pressed, player)
        
        

    pygame.quit()

if __name__ == "__main__":
    main()


簡化邏輯:

left  = pressed[pygame.K_a] or pressed[pygame.K_LEFT]
right = pressed[pygame.K_d] or pressed[pygame.K_RIGHT]
up    = pressed[pygame.K_w] or pressed[pygame.K_UP]
down  = pressed[pygame.K_s] or pressed[pygame.K_DOWN]
    
player.x += (right - left) * SPEED
player.y += (down - up) * SPEED

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM