本文介绍了pygame列表冲突的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用pygame在python中用玩家和墙壁创建的地图即时通讯

I have a map im creating in python using pygame with a player and walls:

import pygame


x = 25
y = 19

collision = [
    [0,0,0,37],#vertical
    [4,23,4,27],
    [12,18,12,25],
    [13,0,13,1],
    [13,4,13,7],
    [13,10,13,11],
    [15,13,15,18],
    [15,23,15,37],
    [19,0,19,13],
    [29,25,29,26],
    [29,29,29,37],
    [35,0,35,9],
    [35,12,35,17],
    [35,21,35,26],
    [35,29,35,37],
    [36,17,36,21],
    [44,0,44,6],
    [44,10,44,17],
    [54,0,54,17],
    [0,0,19,0],#horizontal
    [35,0,46,0],
    [52,0,54,0],
    [13,5,19,5],
    [19,6,24,6],
    [30,6,35,6],
    [0,13,10,13],
    [15,13,21,13],
    [25,13,44,13],
    [35,17,36,17],
    [44,17,54,17],
    [35,21,36,21],
    [4,23,12,23],
    [0,25,4,25],
    [19,25,36,25],
    [4,27,12,27],
    [0,37,35,37],
    [14,12,14,12],#dots
    [11,14,11,14]
]

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

pygame.init()

screen = pygame.display.set_mode((200,200))
pygame.display.set_caption('Collision')
screen.fill(white)

for list in collision:#draw map
    pygame.draw.line(screen,black,(list[0],list[1]),(list[2],list[3]),1)

pygame.draw.line(screen,red,(x,y),(x,y),1)#draw player

pygame.display.update()

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

        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_w:
                for list in collision:
                    #---START OF EQUATION---#
                    if(list[0]<=list[2] and not(y-1==list[1] and x>=list[0] and x<=list[2])) or (list[0]>list[2] and not(y-1==list[1] and x>=list[2] and x<=list[0])):#updated
                    #---END OF EQUATION---#
                        pygame.draw.line(screen,white,(x,y),(x,y),1)
                        y-=1
                        pygame.draw.line(screen,red,(x,y),(x,y),1)
                        break
            elif event.key == pygame.K_s:
                for list in collision:
                    if(list[0]<=list[2] and not(y+1==list[1] and x>=list[0] and x<=list[2])) or (list[0]>list[2] and not(y+1==list[1] and x>=list[2] and x<=list[0])):#updated
                        pygame.draw.line(screen,white,(x,y),(x,y),1)
                        y+=1
                        pygame.draw.line(screen,red,(x,y),(x,y),1)
                        break
            elif event.key == pygame.K_a:
                for list in collision:
                    if(list[1]<=list[3] and not(x-1==list[0] and y>=list[1] and y<=list[3])) or (list[1]>list[3] and not(x-1==list[0] and y>=list[3] and y<=list[1])):#updated
                        pygame.draw.line(screen,white,(x,y),(x,y),1)
                        x-=1
                        pygame.draw.line(screen,red,(x,y),(x,y),1)
                        break
            elif event.key == pygame.K_d:
                for list in collision:
                    if(list[1]<=list[3] and not(x+1==list[0] and y>=list[1] and y<=list[3])) or (list[1]>list[3] and not(x+1==list[0] and y>=list[3] and y<=list[1])):#updated
                        pygame.draw.line(screen,white,(x,y),(x,y),1)
                        x+=1
                        pygame.draw.line(screen,red,(x,y),(x,y),1)
                        break
            pygame.display.update()

方程式,以更轻松"的格式读取:

The equation, in an 'easier' to read format:

if (
    list[0]<=list[2]
    and not(

        y-1==list[1]
        and

        x>=list[0]
        and
        x<=list[2])

    )

    or

    (

    list[0]>list[2]
    and not(

        y-1==list[1]
        and

        x>=list[2]
        and
        x<=list[0]

        )

    )

向下检测到按键的地方是即时通讯出现问题的地方.我已经对该方法进行了多次测试,但始终会导致错误的功能.

Down where keypresses are being detected is where im having an issue. I have tested this method several times, but it always results in the wrong functionality.

每次用户按下w/a/s/d时,我都会在代码列表中循环遍历墙壁",并测试是否能够在没有墙壁的情况下穿过该空间.假设在此处有一堵墙,红点是玩家.如何通过修改方程式来防止玩家向上或向左移动?

I am having my code loop through a list of 'walls' every time the user presses w/a/s/d, and tests if they are capable of going through that space if no wall is present. Lets say that there is a wall like this here with the red dot being the player. How can I prevent the player from moving up or to the left with modification of the equation?

用于测试碰撞的方程式(每个方向都不同,在这种情况下是向上的方向):

Equation thats being used to test for collision (is different for every direction, in this case is for the up direction):

if(list[0]<=list[2] and not(y-1==list[1] and x>=list[0] and x<=list[2])) or (list[0]>list[2] and not(y-1==list[1] and x>=list[2] and x<=list[0]))

推荐答案

问题是因为它检查了第一堵墙,它可能不会发生碰撞,然后才开始移动-但它没有检查其他可能发生碰撞的墙.

Problem is because it checks first wall and it may not collidate and then it makes move - but it didn't check other walls which can collidate.

在移动播放器之前,您必须检查所有墙壁.

You have to check all walls before you can move player.

所有动作几乎相同-您仅使用不同的xy来检查新位置-因此我创建了一个功能来对其进行检查.

All moves are almost the same - you use only different x, y to check new position - so I create one function to check it.

def check_collisions(walls, player_new_x, player_new_y):

    for x1, y1, x2, y2 in walls:
        if x1 <= player_new_x <= x2 and y1 <= player_new_y <= y2:
            print("COLLIDE")
            return True

    return False

完整代码

import pygame

# --- constants --- (UPPER_CASE_NAMES)

WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED   = (255, 0, 0)

FPS = 5

# --- functions --- (lower_case_names)

def check_collisions(walls, player_new_x, player_new_y):

    for x1, y1, x2, y2 in walls:
        if x1 <= player_new_x <= x2 and y1 <= player_new_y <= y2:
            print("COLLIDE")
            return True

    return False

# --- main ---

collision = [
    [0,0,0,37],#vertical
    [4,23,4,27],
    [12,18,12,25],
    [13,0,13,1],
    [13,4,13,7],
    [13,10,13,11],
    [15,13,15,18],
    [15,23,15,37],
    [19,0,19,13],
    [29,25,29,26],
    [29,29,29,37],
    [35,0,35,9],
    [35,12,35,17],
    [35,21,35,26],
    [35,29,35,37],
    [36,17,36,21],
    [44,0,44,6],
    [44,10,44,17],
    [54,0,54,17],
    [0,0,19,0],#horizontal
    [35,0,46,0],
    [52,0,54,0],
    [13,5,19,5],
    [19,6,24,6],
    [30,6,35,6],
    [0,13,10,13],
    [15,13,21,13],
    [25,13,44,13],
    [35,17,36,17],
    [44,17,54,17],
    [35,21,36,21],
    [4,23,12,23],
    [0,25,4,25],
    [19,25,36,25],
    [4,27,12,27],
    [0,37,35,37],
    [14,12,14,12],#dots
    [11,14,11,14]
]

x = 25
y = 19


# - init -

pygame.init()

screen = pygame.display.set_mode((200,200))
screen.fill(WHITE)

# - draws -

for item in collision:
    pygame.draw.line(screen, BLACK, item[:2], item[2:], 1)

pygame.draw.line(screen, RED, (x, y), (x, y), 1)

pygame.display.update()

# - mainloop -

clock = pygame.time.Clock()

while True:

    moved = False

    # - events -

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

        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_w:
                new_x = x
                new_y = y - 1

                collide = check_collisions(collision, new_x, new_y)

                if not collide:
                    pygame.draw.line(screen, WHITE, (x, y), (x, y), 1)
                    x = new_x
                    y = new_y
                    pygame.draw.line(screen, RED, (x, y), (x, y), 1)

            elif event.key == pygame.K_s:
                new_x = x
                new_y = y + 1

                collide = check_collisions(collision, new_x, new_y)

                if not collide:
                    pygame.draw.line(screen, WHITE, (x, y), (x, y), 1)
                    x = new_x
                    y = new_y
                    pygame.draw.line(screen, RED, (x, y), (x, y), 1)

            elif event.key == pygame.K_a:
                new_x = x - 1
                new_y = y

                collide = check_collisions(collision, new_x, new_y)

                if not collide:
                    pygame.draw.line(screen, WHITE, (x, y), (x, y), 1)
                    x = new_x
                    y = new_y
                    pygame.draw.line(screen, RED, (x, y), (x, y), 1)

            elif event.key == pygame.K_d:
                new_x = x + 1
                new_y = y

                collide = check_collisions(collision, new_x, new_y)

                if not collide:
                    pygame.draw.line(screen, WHITE, (x, y), (x, y), 1)
                    x = new_x
                    y = new_y
                    pygame.draw.line(screen, RED, (x, y), (x, y), 1)

    pygame.display.update()
    clock.tick(FPS) # to display less frame and use less CPU


版本,您可以在其中按住键,它会移动-无需多次按下


version in which you can keep key pressed and it will move - you don't have to press many times

import pygame

# --- constants --- (UPPER_CASE_NAMES)

WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED   = (255, 0, 0)

FPS = 5

# --- functions --- (lower_case_names)

def check_collisions(walls, player_new_x, player_new_y):

    for x1, y1, x2, y2 in walls:
        if x1 <= player_new_x <= x2 and y1 <= player_new_y <= y2:
            print("COLLIDE")
            return True

    return False

# --- main ---

collision = [
    [0,0,0,37],#vertical
    [4,23,4,27],
    [12,18,12,25],
    [13,0,13,1],
    [13,4,13,7],
    [13,10,13,11],
    [15,13,15,18],
    [15,23,15,37],
    [19,0,19,13],
    [29,25,29,26],
    [29,29,29,37],
    [35,0,35,9],
    [35,12,35,17],
    [35,21,35,26],
    [35,29,35,37],
    [36,17,36,21],
    [44,0,44,6],
    [44,10,44,17],
    [54,0,54,17],
    [0,0,19,0],#horizontal
    [35,0,46,0],
    [52,0,54,0],
    [13,5,19,5],
    [19,6,24,6],
    [30,6,35,6],
    [0,13,10,13],
    [15,13,21,13],
    [25,13,44,13],
    [35,17,36,17],
    [44,17,54,17],
    [35,21,36,21],
    [4,23,12,23],
    [0,25,4,25],
    [19,25,36,25],
    [4,27,12,27],
    [0,37,35,37],
    [14,12,14,12],#dots
    [11,14,11,14]
]

x = 25
y = 19


# - init -

pygame.init()

screen = pygame.display.set_mode((200,200))
screen.fill(WHITE)

# - draws -

for item in collision:
    pygame.draw.line(screen, BLACK, item[:2], item[2:], 1)

pygame.draw.line(screen, RED, (x, y), (x, y), 1)

pygame.display.update()

# - mainloop -

clock = pygame.time.Clock()

move_x = 0
move_y = 0

while True:

    # - events -

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

        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_w:
                move_y = -1

            elif event.key == pygame.K_s:
                move_y = 1

            elif event.key == pygame.K_a:
                move_x = -1

            elif event.key == pygame.K_d:
                move_x = 1

        elif event.type == pygame.KEYUP:
            if event.key == pygame.K_w:
                move_y = 0

            elif event.key == pygame.K_s:
                move_y = 0

            elif event.key == pygame.K_a:
                move_x = 0

            elif event.key == pygame.K_d:
                move_x = 0

    # - update -

    if move_x != 0 or move_y != 0:

        new_x = x + move_x
        new_y = y + move_y

        collide = check_collisions(collision, new_x, new_y)

        if not collide:
            pygame.draw.line(screen, WHITE, (x, y), (x, y), 1)
            x = new_x
            y = new_y
            pygame.draw.line(screen, RED, (x, y), (x, y), 1)


    pygame.display.update()
    clock.tick(FPS) # to display less frame and use less CPU

这篇关于pygame列表冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-27 06:29