我该怎么做才能让我的方块落在我的另一个方块上并留在上面

How do I make it so my square can land on my other square and stay on it

我是新来的python和pygame,我想学collisionm但是我只会检测collision

如何添加碰撞,让我站在我的大方块上,而我的小方块移动。我不知道如何让它站在另一个广场上而不是被扔出去。在我的脚本底部,我添加了碰撞检测,但无法弄清楚如何让它真正站在我的大块上而不被扔到两侧、顶部和底部。

pygame.init()


win = pygame.display.set_mode((500,500))
pygame.display.set_caption("THIS GAME IS KINDA ASS")


# first squrae
x = 50
y = 50
height= 50
width = 50
speed = 5
isJump = False
JumpCount = 10

# square 2
cordx = 100
cordy = 200
cordheight = 100
cordwidth = 100
    # First Square





# main loop
runningame = True
while runningame:
    pygame.time.delay(50)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            runningame = False
    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT]:
        x -= speed
    if keys[pygame.K_RIGHT]:
        x += speed
    if not(isJump):
        if keys[pygame.K_UP]:
            y -= speed
        if keys[pygame.K_DOWN]:
            y += speed
        if keys[pygame.K_SPACE]:
            isJump = True
    else:
        if JumpCount >= -10:
            y -= (JumpCount *abs(JumpCount))
            JumpCount -= 1
        else:
            isJump = False
            JumpCount = 10



    win.fill((0,0,0))
# I added a varabial to my player square  
    Player = pygame.draw.rect(win, (115, 235, 174), (x,y, height,width))

    # second square
   # this is the big box and its the enemy square that I want my script to stand on
    Enemy = pygame.draw.rect(win, (202, 185 , 241), (cordx, cordy, cordheight,cordwidth))


    if Player.colliderect(Enemy):
        pygame.draw.rect(win, (140, 101, 211), (50,50,50,50))


    pygame.display.update()

pygame.quit()

所以你有 Player.colliderect(Enemy) 所以你知道它什么时候发生碰撞,你只需要弄清楚从哪里开始并相应地移动玩家。

一个不完美的简单方法是确定玩家移动的方向,如果玩家向下移动,则将玩家移动到敌人上方。

在你的代码中,你需要一个方向

direction = "not moving"
...
if keys[pygame.K_LEFT]:
    x -= speed
    direction = "left"
if keys[pygame.K_RIGHT]:
    x += speed
    direction = "right"
...
else:
    if JumpCount >= -10:
        y -= (JumpCount *abs(JumpCount))
        JumpCount -= 1
        if (JumpCount *abs(JumpCount)) > 0:
            direction = "down"
        else:
            direction = "up"
...
if Player.colliderect(Enemy):
    if direction == "down":
        y -= player.bottom - enemy.top #get the amount that that the player is overlapping the enemy and take it off y so it no longer overlapping
    elif direction == "up":
        y += player.top - enemy.bottom
    #do the same for left and right

另一种方法是制作玩家和敌人Rects并用它们来代替xy

所以

# first squrae
x = 50
y = 50
height= 50
width = 50
player = pygame.Rect(x,y,width,height)
speed = 5
isJump = False
JumpCount = 10

# square 2
cordx = 100
cordy = 200
cordheight = 100
cordwidth = 100
enemy = pygame.Rect(cordc,cordy,cordwidth,cordheight)

然后你可以用

画出它们
win.fill((0,0,0))
# I added a varabial to my player square  
pygame.draw.rect(win, (115, 235, 174),player)

# second square
# this is the big box and its the enemy square that I want my script to stand on
pygame.draw.rect(win, (202, 185 , 241), enemy)

并用

更新位置
if keys[pygame.K_LEFT]:
    player.x -= speed
if keys[pygame.K_RIGHT]:
    player.x += speed

和碰撞

if player.colliderect(enemy):
    if player.centerx < enemy.left: #if the center of player is left of the enemy
        player.right = enemy.left  

    if player.centerx > enemy.right:
        player.left = enemy.right

    if player.centery < enemy.top:
        player.bottom = enemy.top

    if player.centery > enemy.bottom:
        player.top = enemy.bottom

这两种方法都不是完美的,还有更多方法可以做到,但我想我会推荐第一种方法,因为它更容易理解并且更容易添加到您的代码中。如果您需要更多关于其工作原理或更多方法的解释,请发表评论


import pygame
pygame.init()


win = pygame.display.set_mode((500,500))
pygame.display.set_caption("THIS GAME IS KINDA ASS")

class Player(pygame.sprite.Sprite):
    def __init__(self, x, y, w, h, col):
        pygame.sprite.Sprite.__init__(self)
        self.rect = pygame.Rect(x,y,w,h)
        self.image = pygame.Surface((w,h))
        self.image.fill(col)  
        self.isJump = False
        self.JumpCount = 8

    def update(self):
        if self.isJump:
            if self.JumpCount >= -8:
                self.rect.y -= (self.JumpCount *abs(self.JumpCount))
                self.JumpCount -= 1
            else:
                self.isJump = False
                self.JumpCount = 8          


class Platform(pygame.sprite.Sprite):
    def __init__(self, x, y, w, h, col):
        pygame.sprite.Sprite.__init__(self)
        self.rect = pygame.Rect(x,y,w,h)
        self.image = pygame.Surface((w,h))
        self.image.fill(col)


# first squrae
x = 50
y = 50
height= 50
width = 50
speed = 5

player = Player(x,y,width, height, (115, 235, 174))

# square 2
cordx = 100
cordy = 200
cordheight = 100
cordwidth = 100
enemy1 = Platform(cordx,cordy,cordwidth, cordheight, (202, 185 , 241))

#square 3
enemy2 = Platform(300,90,100,30,(202, 185 , 241))


all_sprites = pygame.sprite.Group()
all_sprites.add(player)
all_sprites.add(enemy1)
all_sprites.add(enemy2)

enemy_sprites = pygame.sprite.Group()
enemy_sprites.add(enemy1, enemy2)

clock = pygame.time.Clock()
# main loop
runningame = True
while runningame:
    clock.tick(50)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            runningame = False

    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT]:
        player.rect.x -= speed
    if keys[pygame.K_RIGHT]:
        player.rect.x += speed
    if not(player.isJump):
        if keys[pygame.K_UP]:
            player.rect.y -= speed
        if keys[pygame.K_DOWN]:
            player.rect.y += speed
        if keys[pygame.K_SPACE]:
            player.isJump = True

    for enemy in enemy_sprites.sprites():
        if player.rect.colliderect(enemy.rect):
            if player.rect.centerx < enemy.rect.left: #if the center of player is left of the enemy
                player.rect.right = enemy.rect.left  

            if player.rect.centerx > enemy.rect.right:
                player.rect.left = enemy.rect.right

            if player.rect.centery < enemy.rect.top:
                player.rect.bottom = enemy.rect.top

            if player.rect.centery > enemy.rect.bottom:
                player.rect.top = enemy.rect.bottom

    all_sprites.update()

    win.fill((0,0,0))

    all_sprites.draw(win)

    pygame.display.update()

pygame.quit()

这是你的程序,但使用了精灵

如您所见,我已将所有与方块相关的代码移至 类。每个精灵都有一个 rect 和一个 image。矩形的使用方式与我上面显示的矩形相同。图像是一个表面,因为 pygame 如何将它放在屏幕上。通过使它的大小相同并用颜色填充它,它与以前完全相同。

我有 2 个精灵组,all_sprites 组包含所有精灵,enemy_sprites 组只有敌人(你可以站立的平台)。我可以通过调用 all_sprites.draw(win).

来绘制所有精灵

对于碰撞,完全相同,除了我想遍历每个敌人(因为我现在有 2 个)。所以我可以调用 enemy_sprites.sprites() 来获取每个精灵。

如果您需要更多解释或示例,请开始聊天。