pygame显示器上的Rect碰撞;碰撞后按第二个键,导致Rect跳转

2024-04-24 06:58:03 发布

您现在位置:Python中文网/ 问答频道 /正文

我很难让碰撞100%正常工作。如果我一次只按一个键,碰撞似乎可以正常工作,但如果我按一个键并继续按,同时碰撞,然后按另一个键,碰撞似乎可以同时解释两个键。从研究来看,似乎我需要做单独的轴计算,但我不知道具体如何做,使用我的算法碰撞。如果可能的话,我希望这是程序性的。如果有人能修改我的代码,用一个有效的程序解决方案,我将不胜感激。谢谢。你知道吗

import pygame as pg
import sys
from math import fabs

pg.init()

width = 600
height = 600

gameDisplay = pg.display.set_mode((width, height))
pg.display.set_caption('Block')


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

clock = pg.time.Clock()
closed = False
FPS = 60
Player_Speed = 200
x, y = 270, 0
vx = 0
vy = 0
collision = False

def Collision(hero, enemy):
    global vx, vy, x, y, collision
    deltay = fabs(block.centery - ENEMY.centery)
    deltax = fabs(block.centerx - ENEMY.centerx)
    if deltay < ENEMY.height and deltax < ENEMY.width:
        collision = True
        if vx > 0:
            vx = 0
            x = ENEMY[0] - block[2] 
        if vx < 0:
            vx = 0
            x = ENEMY[0] + 30
        if vy > 0:
            vy = 0
            y = ENEMY[1] - block[3] 
        if vy < 0:
            vy = 0
            y = ENEMY[1] + 30
    else:
        collision = False


def xy_Text(x, y):
    font = pg.font.SysFont("Courier", 16, True)
    text = font.render("X: " + str(round(x)), True, (0,150,0))
    text1 = font.render("Y: " + str(round(y)), True, (0,150,0))
    gameDisplay.blit(text, (0,0))
    gameDisplay.blit(text1, (0,14))

while not closed:
    for event in pg.event.get():
        if event.type == pg.QUIT:
            closed = True

        dt = clock.tick(FPS)/1000
        vx, vy = 0, 0

        keys = pg.key.get_pressed()

        if keys[pg.K_ESCAPE]:
            closed = True
        if keys[pg.K_LEFT] or keys[pg.K_a]:
            vx = -Player_Speed
        if keys[pg.K_RIGHT] or keys[pg.K_d]:
            vx = Player_Speed
        if keys[pg.K_UP] or keys[pg.K_w]:
            vy = -Player_Speed
        if keys[pg.K_DOWN] or keys[pg.K_s]:
            vy = Player_Speed
        if vx != 0 and vy != 0:
            vx *= 0.7071
            vy *= 0.7071


    gameDisplay.fill(white)
    ENEMY = pg.draw.rect(gameDisplay, red, (270, 270, 30, 30))
    block = pg.draw.rect(gameDisplay, (0, 150, 0), (x, y, 30, 30))
    xy_Text(x, y)
    x += vx * dt
    y += vy * dt
    Collision(block, ENEMY)
    pg.display.update()
    clock.tick(FPS)

pg.quit()
sys.exit()

Tags: ortrueifkeysblockpgplayerspeed
2条回答

如果要处理与墙的碰撞,请先沿x轴或y轴移动,如果发生碰撞,请将播放器放回原处,然后对另一个轴执行相同的操作。如果您使用pygame.Rect,您可以使用它们的leftrighttopbottom属性轻松地将播放器设置回块的相应一侧。你知道吗

因此,请检查玩家是否与块发生碰撞,如果他/她向右移动(vx > 0),然后将hero.right设置为block.left,并对其他方向执行相同的操作。如果玩家rect被更新,你还必须返回新的x和y坐标。你知道吗

我建议将块(rects)放入blocks列表中,您可以将其传递给wall collision函数,然后只使用for循环。你知道吗

from math import fabs
import pygame as pg


pg.init()

width = 600
height = 600

gameDisplay = pg.display.set_mode((width, height))

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

clock = pg.time.Clock()
closed = False
FPS = 60
Player_Speed = 200
x, y = 270, 0
vx = 0
vy = 0
# Define the font in the global scope.
FONT = pg.font.SysFont("Courier", 16, True)


# Better don't use global variables.
def handle_horizontal_collisions(hero, blocks, x, vx):
    """Sets the player back to the left or right side."""
    for block in blocks:
        if hero.colliderect(block):
            if vx > 0:
                hero.right = block.left
            elif vx < 0:
                hero.left = block.right
            return hero.x  # Need to update the actual `x` position.
    return x


def handle_vertical_collisions(hero, blocks, y, vy):
    """Sets the player back to the top or bottom side."""
    for block in blocks:
        if hero.colliderect(block):
            if vy > 0:
                hero.bottom = block.top
            elif vy < 0:
                hero.top = block.bottom
            return hero.y  # Need to update the actual `y` position.
    return y


def xy_Text(x, y):
    text = FONT.render("X: " + str(round(x)), True, (0,150,0))
    text1 = FONT.render("Y: " + str(round(y)), True, (0,150,0))
    gameDisplay.blit(text, (0,0))
    gameDisplay.blit(text1, (0,14))


# Use pygame.Rects for the player and blocks.
player = pg.Rect(x, y, 30, 30)
# Put the blocks into a list.
blocks = []
for rect in (pg.Rect(200, 200, 60, 30), pg.Rect(230, 230, 60, 30)):
    blocks.append(rect)

dt = 0

while not closed:
    for event in pg.event.get():
        if event.type == pg.QUIT:
            closed = True
        # clock.tick should not be called in the event loop.

    vx, vy = 0, 0
    # key.get_pressed should also not be in the event loop.
    keys = pg.key.get_pressed()

    if keys[pg.K_ESCAPE]:
        closed = True
    if keys[pg.K_LEFT] or keys[pg.K_a]:
        vx = -Player_Speed
    if keys[pg.K_RIGHT] or keys[pg.K_d]:
        vx = Player_Speed
    if keys[pg.K_UP] or keys[pg.K_w]:
        vy = -Player_Speed
    if keys[pg.K_DOWN] or keys[pg.K_s]:
        vy = Player_Speed
    if vx != 0 and vy != 0:
        vx *= 0.7071
        vy *= 0.7071

    # Game logic.
    x += vx * dt
    player.x = x
    x = handle_horizontal_collisions(player, blocks, x, vx)

    y += vy * dt
    player.y = y
    y = handle_vertical_collisions(player, blocks, y, vy)

    # Rendering.
    gameDisplay.fill(white)
    for block in blocks:
        pg.draw.rect(gameDisplay, red, block)
    pg.draw.rect(gameDisplay, (0, 150, 0), player)

    xy_Text(x, y)
    pg.display.update()
    dt = clock.tick(FPS)/1000

pg.quit()

经过多次修改后,碰撞工作

我搬家了

x += vx * dt
y += vy * dt

发生碰撞。你知道吗

我在代码中改变了组织,我总是使用Rect()来保持玩家和敌人的位置和大小

我还添加了第二个敌人来测试如何检查与许多元素的碰撞。你知道吗

import pygame as pg
import sys
from math import fabs

# - functions  - (lower_case_names)

def check_collision(player, enemy1, enemy2):
    global player_vx, player_vy

    #  - X  -

    player.x += player_vx * dt

    # enemy 1

    deltay = fabs(player.centery - enemy1.centery)
    deltax = fabs(player.centerx - enemy1.centerx)

    if deltay < enemy1.height and deltax < enemy1.width:
        if player_vx > 0:
            player_vx = 0
            player.x = enemy1.x - player.w
        elif player_vx < 0:
            player_vx = 0
            player.x = enemy1.x + player.w

    # enemy 2

    deltay = fabs(player.centery - enemy2.centery)
    deltax = fabs(player.centerx - enemy2.centerx)

    if deltay < enemy2.height and deltax < enemy2.width:
        if player_vx > 0:
            player_vx = 0
            player.x = enemy2.x - player.w
        elif player_vx < 0:
            player_vx = 0
            player.x = enemy2.x + player.w

    #  - Y  -

    player.y += player_vy * dt

    # enemy 1

    deltay = fabs(player.centery - enemy1.centery)
    deltax = fabs(player.centerx - enemy1.centerx)

    if deltay < enemy1.height and deltax < enemy1.width:
        if player_vy > 0:
            player_vy = 0
            player.y = enemy1.y - player.h
        elif player_vy < 0:
            player_vy = 0
            player.y = enemy1.y + player.w

    # enemy 2

    deltay = fabs(player.centery - enemy2.centery)
    deltax = fabs(player.centerx - enemy2.centerx)

    if deltay < enemy2.height and deltax < enemy2.width:
        if player_vy > 0:
            player_vy = 0
            player.y = enemy2.y - player.h
        elif player_vy < 0:
            player_vy = 0
            player.y = enemy2.y + player.w


def xy_text(screen, x, y):
    font = pg.font.SysFont("Courier", 16, True)

    text = font.render("X: " + str(round(x)), True, (0,150,0))
    screen.blit(text, (0,0))

    text = font.render("Y: " + str(round(y)), True, (0,150,0))
    screen.blit(text, (0,14))

#  - constants  - (UPPER_CASE_NAMES)

WIDTH = 600
HEIGHT = 600

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

FPS = 60

#  - main  - (lower_case_names)

player_speed = 200
player_vx = 0
player_vy = 0

player = pg.Rect(270, 0, 30, 30)
enemy1 = pg.Rect(270, 270, 30, 30)
enemy2 = pg.Rect(240, 300, 30, 30)

# - init -
pg.init()

game_display = pg.display.set_mode((WIDTH, HEIGHT))
pg.display.set_caption('Block')

# - mainloop -

clock = pg.time.Clock()

closed = False
while not closed:

    dt = clock.tick(FPS)/1000

    # - events -

    for event in pg.event.get():
        if event.type == pg.QUIT:
            closed = True

    keys = pg.key.get_pressed()

    player_vx = 0
    player_vy = 0

    if keys[pg.K_ESCAPE]:
        closed = True
    if keys[pg.K_LEFT] or keys[pg.K_a]:
        player_vx = -player_speed
    if keys[pg.K_RIGHT] or keys[pg.K_d]:
        player_vx = player_speed
    if keys[pg.K_UP] or keys[pg.K_w]:
        player_vy = -player_speed
    if keys[pg.K_DOWN] or keys[pg.K_s]:
        player_vy = player_speed
    if player_vx != 0 and player_vy != 0:
        player_vx *= 0.7071
        player_vy *= 0.7071

    # - updates -

    check_collision(player, enemy1, enemy2)

    # - draws -

    game_display.fill(WHITE)
    pg.draw.rect(game_display, RED, enemy1)
    pg.draw.rect(game_display, RED, enemy2)
    pg.draw.rect(game_display, (0, 150, 0), player)
    xy_text(game_display, player.x, player.y)
    pg.display.update()
    clock.tick(FPS)

# - end -

pg.quit()
sys.exit()

相关问题 更多 >