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

时间:2019-01-28 08:21:34

标签: pygame python-3.6

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

项目目录Project helper.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))

config.py

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

main.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 个答案:

答案 0 :(得分:0)

我现在有了一个折衷的解决方案,当需要移除2个列表中2个矩形之间的碰撞中的表面时,只需在2个单独的for循环中绘制2个列表,然后将碰撞中的矩形移除到另一个{{1 }}循环,演示代码为:

for

仅供参考。