代码之家  ›  专栏  ›  技术社区  ›  Lau Real

pygame下一个曲面未按预期路径移动

  •  0
  • Lau Real  · 技术社区  · 7 年前

    我是pygame的新手,我正在尝试练习“植物和僵尸”的技能,但在运行代码时出现了一个问题:下一个项目符号不会移动到屏幕边缘,它在上一个项目符号与僵尸碰撞的点结束。我找不出问题出在哪里,希望有人能帮我解决。快跑 main.py ,单击顶部菜单(武器),右键单击草的任何一点,你就会知道问题所在。

    项目目录 : Project 助手.py

    import os
    from PIL import Image
    import pygame
    current_dir = os.getcwd()
    
    
    def get_path(image_name):
        return os.path.join(current_dir, "resource", image_name)
    
    
    def get_image_size(image_name):
        with Image.open(get_path(image_name)) as im:
            return im.size
    
    
    def load_image_source(image_name, with_bullet=False):
        if with_bullet:
            bullet_name = "bullet_"+image_name.replace("shooter_", "")
            return pygame.image.load(get_path(image_name)), pygame.image.load(get_path(bullet_name))
        else:
            return pygame.image.load(get_path(image_name))
    
    
    def load_all_shooters():
        weapon = {"selected": [], "unselected": []}
        shooter_dir = os.path.join(current_dir, "resource")
        for shooter in os.listdir(shooter_dir):
            if "shooter" in shooter:
                if "selected" in shooter:
                    weapon["selected"].append(shooter)
                else:
                    weapon["unselected"].append(shooter)
        weapon["selected"] = sorted(weapon["selected"])
        weapon["unselected"] = sorted(weapon["unselected"])
        return weapon
    
    
    def get_nearest_position(source_list, target_number):
        return min(source_list, key=lambda x: abs(x - target_number))
    

    配置.py :

    LINES = 5
    ZOMBIE_SPEED_X = 1
    ZOMBIE_REFRESH_TIME = 3000
    BULLET_REFRESH_TIME = 1000
    BULLET_SPEED = 3
    SHOOTER_SIZE = (50, 50)
    

    主.py :

    import pygame
    import sys
    import random
    
    from ZombiesVSPlants.common.helper import get_nearest_position, load_image_source, load_all_shooters, get_image_size, get_path, get_path
    from ZombiesVSPlants.config.config import BULLET_SPEED, BULLET_REFRESH_TIME, ZOMBIE_REFRESH_TIME, SHOOTER_SIZE, ZOMBIE_SPEED_X, LINES
    
    pygame.init()
    
    
    # top weapon menu
    menu_height = 60
    
    # get background grass and other resource path and size...
    background_grass_path = get_path("background_grass.png")
    zombie_path = get_path("enemy_zombie.png", )
    single_line_height = get_image_size("background_grass.png")[1]
    zombie_size = get_image_size("enemy_zombie.png")
    
    # screen size
    screen_height = LINES*single_line_height+menu_height
    screen_width = 800
    
    
    # background colour, zombie speed
    background_color = 255, 255, 255
    ZOMBIE_SPEED = [-ZOMBIE_SPEED_X, 0]
    
    # others
    LINES_LIST = [i for i in range(1, LINES+1)]
    zombie_start_x = screen_width-zombie_size[0]
    zombie_start_y = (single_line_height-zombie_size[1])/2
    shooter_centered_position__list_y = [line*single_line_height+zombie_start_y+menu_height for line in range(5)]
    # resource boom
    boom = load_image_source("boom.png")
    # dragging and other global variables
    dragging = False
    mouse_follow = None
    mouse_follow_rect = None
    added_shooters = []
    shooter_bullets = []
    bullets_rect = []
    collide_zombies = []
    collide_bullets = []
    # screen size
    screen = pygame.display.set_mode((screen_width, screen_height))
    # load top weapon surface
    res = load_all_shooters()
    menu_start_position = 5, 5
    menu_shooters = [load_image_source(unselected_shooter, with_bullet=True) for unselected_shooter in res["unselected"]]
    menu_shooters_selected = [load_image_source(selected_shooter) for selected_shooter in res["selected"]]
    menu_shooters_rect = [pygame.Rect(menu_start_position[0]+55*i, menu_start_position[1], SHOOTER_SIZE[0], SHOOTER_SIZE[1]) for i in range(len(menu_shooters))]
    
    # background grass surface
    grass = load_image_source(background_grass_path)
    grass_rect = [pygame.Rect(0, i * single_line_height+menu_height, screen_width, single_line_height) for i in range(LINES)]
    # the very first zombie surface
    zombie = load_image_source(zombie_path)
    zombies_rect = [pygame.Rect(zombie_start_x, zombie_start_y+menu_height, zombie_size[0], zombie_size[1])]
    # ZOMBIE_REFRESH_TIME
    NEW_ZOMBIE_EVENT = pygame.USEREVENT+1
    pygame.time.set_timer(NEW_ZOMBIE_EVENT, ZOMBIE_REFRESH_TIME)
    # BULLET_REFRESH_TIME
    NEW_BULLET_EVENT = pygame.USEREVENT+2
    pygame.time.set_timer(NEW_BULLET_EVENT, BULLET_REFRESH_TIME)
    
    
    while 1:
        screen.fill(background_color)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            # left click on a top menu(weapon), dragging is enabled
            if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                for i in range(len(menu_shooters)):
                    if menu_shooters_rect[i].collidepoint(event.pos):
                        dragging = not dragging
                        mouse_follow = menu_shooters[i]
            # right click when dragging, new weapon will be set on a point
            if event.type == pygame.MOUSEBUTTONDOWN and event.button == 3:
                x = event.pos[0]
                if event.pos[1] > menu_height and dragging:
                    dragging = not dragging
                    y = get_nearest_position(shooter_centered_position__list_y, event.pos[1])
                    added_shooters.append([mouse_follow[0], x, y])
                    shooter_bullets.append([x, y, mouse_follow[1]])
            # spawn new bullet
            if event.type == NEW_BULLET_EVENT:
                for j in range(len(shooter_bullets)):
                    bullets_rect.append([shooter_bullets[j][2], pygame.Rect(shooter_bullets[j][0], shooter_bullets[j][1], 15, 15)])
            # spawn new zombie
            if event.type == NEW_ZOMBIE_EVENT:
                # random in roads that new zombies will appear
                new_zombies_count = random.randint(1, LINES)
                new_zombies_lines = random.sample(LINES_LIST, new_zombies_count)
                # add to zombies list
                for line in new_zombies_lines:
                    new_zombie_rect = pygame.Rect(zombie_start_x, line * single_line_height + zombie_start_y + menu_height, zombie_size[0], zombie_size[1])
                    zombies_rect.append(new_zombie_rect)
        # blit top weapons menu
        for i in range(len(menu_shooters)):
            menu_rect = menu_shooters_rect[i]
            screen.blit(menu_shooters[i][0], menu_rect)
    
        # blit selected weapon if mouse hover on a weapon menu
        for i in range(len(menu_shooters)):
            if menu_shooters_rect[i].collidepoint(pygame.mouse.get_pos()):
                screen.blit(menu_shooters_selected[i], menu_shooters_rect[i])
    
        # blit background grass
        for r in grass_rect:
            screen.blit(grass, r)
        # blit all the weapons on the grass
        for new in added_shooters:
            shooter_rect = pygame.Rect(new[1], new[2], 50, 50)
            screen.blit(new[0], shooter_rect)
        # blit bullets
        for j in range(len(bullets_rect)):
            bullets_rect[j][1].x += 1
            screen.blit(bullets_rect[j][0], bullets_rect[j][1])
        # blit zombies
        for i in range(len(zombies_rect)):
            zombies_rect[i].x -= ZOMBIE_SPEED_X
            screen.blit(zombie, zombies_rect[i])
        # blit weapon follows mouse move position
        if dragging and mouse_follow[0]:
            pos_follow_mouse = pygame.mouse.get_pos()
            mouse_follow_rect = pygame.Rect(pos_follow_mouse[0], pos_follow_mouse[1], 50, 50)
            screen.blit(mouse_follow[0], mouse_follow_rect)
    
        # collide between zombie and bullet
        for i in range(len(bullets_rect)):
            for j in range(len(zombies_rect)):
                if bullets_rect[i][1].colliderect(zombies_rect[j]):
                    print("collide!")
                    screen.blit(boom, zombies_rect[j])
                    collide_bullets.append(bullets_rect[i])
                    collide_zombies.append(zombies_rect[j])
        bullets_rect = [i for i in bullets_rect if i not in collide_bullets]
        zombies_rect = [j for j in zombies_rect if j not in collide_zombies]
    
        pygame.display.flip()
    
    1 回复  |  直到 7 年前
        1
  •  0
  •   Lau Real    7 年前

    for 循环并移除另一个循环中的碰撞矩形 对于

    # draw bullets
    for b in bullets_rect:
        b_r = b[1]
        b_r.x += BULLET_SPEED
        screen.blit(b[0], b_r)
    # draw zombies
    for z in zombies_rect:
        z.x += -ZOMBIE_SPEED_X
        screen.blit(zombie, z)
    # when collide, use list.remove to remove collided rect
    for i, j in itertools.product(bullets_rect, zombies_rect):
        b_r = i[1]
        z_r = j
        if z_r.contains(b_r):
            # when collide, remove the collided rect
            screen.blit(boom, z_r)
            bullets_rect.remove(i)
            zombies_rect.remove(j)
    

    仅供参考。

    推荐文章