python-3.x Pygame与列表中的矩形发生冲突,无法正常工作

iih3973s  于 2022-11-26  发布在  Python
关注(0)|答案(1)|浏览(101)

我正在制作python pygame迷宫游戏。移动可以和移动的墙壁一起工作,但不能和玩家一起工作,因为玩家永远不会逃离屏幕。目前我正在X轴上移动,但是出了问题。当玩家和左边的墙壁碰撞时,它通常不会让它向左移动。但是当向右移动时,它会稍微忽略碰撞而向右移动。
可重现示例:

import pygame
import math
pygame.init()
surface = pygame.display.set_mode((1000,600))
clock = pygame.time.Clock()
surfrect = surface.get_rect()
player=pygame.Rect((0,0), (35,35))
player.center=surfrect.w/2,surfrect.h/2
touched = False
levelR=[]
control=pygame.Rect((0,0), (50,50))
controld=[]
yspeed,xspeed=0,0
for i in range(-1,2):
    oxr=surfrect.w/2-75*3/2
    oyr=surfrect.h/2-75*3/2+75*3*i
    yr,xr=oyr,oxr
    gf=[]
    for y in '#-#n#-#n#-#'.split('n'):
        for x in y:
            if x=='#':
                gf.append(pygame.Rect((xr, yr), (75,75)))
            xr+=75
        yr+=75
        xr=oxr
    levelR.append([gf,pygame.Rect((oxr,oyr),(75*3,75*3))])
while True:
    for ev in pygame.event.get():
        if ev.type == pygame.QUIT:
            pygame.quit()
        elif ev.type == pygame.MOUSEBUTTONDOWN:
            touched = True
        elif ev.type == pygame.MOUSEBUTTONUP:
            touched = False
    surface.fill((0,0,0))
    for sd in levelR:pygame.draw.rect(surface,(35,35,35),sd[1])
    pygame.draw.circle(surface, (200,200,200), player.center, player.width/2-player.width/19, player.width)
    for sd in levelR:
        for rect in sd[0]:
            scale=0.6
            recti=pygame.Rect((rect.x,rect.y), (rect.width*scale,rect.height*scale))
            recti.center=rect.center
            pygame.draw.rect(surface,(255,255,255),rect)
            pygame.draw.rect(surface,(0,0,0),recti)
    if touched and not controld:
        controld=pygame.mouse.get_pos()
        control.center=controld
    elif touched and controld:
        radius = 150
        x,y=pygame.mouse.get_pos()
        distance=math.dist((x, y),controld)
        if distance < radius:
            pos=(x, y)
        else:
            dx=x-controld[0]
            dy=y-controld[1]
            ratio=radius/distance
            pos=controld[0]+ratio*dx, controld[1]+ratio*dy
        control.center=pos
        try:xmd=(x-controld[0])/abs(x-controld[0])
        except:xmd=0
        try:ymd=(y-controld[1])/abs(y-controld[1])
        except:ymd=0
        sr=0.02*(150/radius)
        xspeed=xmd*abs(control.centerx-controld[0])*sr
        yspeed=ymd*abs(control.centery-controld[1])*sr
        collisiont=5
        for sd in levelR:
            for block in sd[0]:
                block.x-=xspeed
            sd[1].x-=xspeed
        for rect in [i for sd in levelR for i in sd[0]]:
            if player.colliderect(rect):
                for sd in levelR:
                    for block in sd[0]:
                        block.x+=xspeed
                    sd[1].x+=xspeed
                break
        pygame.draw.circle(surface, (255,255,255), control.center, control.width,control.width)
        pygame.draw.circle(surface, (255,255,255), controld, radius, 5)
    elif not touched and controld:controld=()
    pygame.display.flip() 
    clock.tick(60)

我试着调试碰撞,发现当与墙壁碰撞时向右移动会阻止玩家向右移动,但玩家会稍微向右移动。
我期望当玩家与墙壁碰撞时墙壁不会移动。
碰巧的是,当玩家撞到墙壁时向右移动并没有直接阻止它。

e4yzc0pl

e4yzc0pl1#

由于pygame.Rect应该表示屏幕上的一个区域,因此pygame.Rect对象只能存储整数数据。
Rect对象的坐标都是整数。[...]
Rect 对象的位置变更时,坐标的小数部分会遗失。在您的案例中,这表示向左和向右移动的行为不同,而且block.x += xspeed不是block.x -= xspeed的逆运算。请考虑一下,5 - 0.14,但4 + 0.1仍然是4
可以通过在实际移动对象之前测试对象是否存在碰撞来解决此问题,如果检测到碰撞,则根本不移动对象:

collide = False
for rect in [i for sd in levelR for i in sd[0]]:
    text_rect = rect.copy()
    text_rect.x -= xspeed
    if player.colliderect(text_rect):
        collide = True
        break

if not collide:
    for sd in levelR:
        for block in sd[0]:
            block.x-=xspeed
        sd[1].x-=xspeed

相关问题