简体   繁体   English

我怎么做才能让我的方格可以降落在我的另一个方格上并留在上面

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

I am a new python and pygame, and I want to learn collisionm but I only know how to detect collision.我是一个新的python和pygame,我想学习碰撞,但我只知道如何检测碰撞。

How can I add collision that allows me to stand on my big square while my little square moves.我怎样才能添加碰撞,让我站在我的大方格上,而我的小方格移动。 I don't know how to make it stand on the other square instead of getting thrown.我不知道如何让它站在另一个广场上而不是被扔掉。 At the bottom of my script I added collision detection but can't figure out how to make it actually stand on the my big block without it getting thrown to the sides, top and bottom.在我的脚本底部,我添加了碰撞检测,但无法弄清楚如何让它真正站在我的大块上,而不会被扔到侧面、顶部和底部。

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()

So you have Player.colliderect(Enemy) so you know when its colliding, you just need to figure out from where and move the player accordingly.所以你有Player.colliderect(Enemy)所以你知道它什么时候发生碰撞,你只需要弄清楚从哪里开始并相应地移动玩家。

A simple way to do this which is not perfect is to have a direction the player is moving and if the player is moving down, move the player above the enemy.一种不完美的简单方法是确定玩家移动的方向,如果玩家向下移动,则将玩家移动到敌人上方。

In your code, you need a direction在您的代码中,您需要一个方向

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

another way is to make player and enemy Rects and use them to replace x and y另一种方法是制作玩家和敌人Rects并使用它们来替换xy

so所以

# 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)

you can then draw them with然后你可以用

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)

and update the positions with并更新职位

if keys[pygame.K_LEFT]:
    player.x -= speed
if keys[pygame.K_RIGHT]:
    player.x += speed

and for collisions和碰撞

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

both ways work ad neither are perfect, there are also more ways to do it, but i think i would recommend the first method as its easier to understand and easier to add to your code.两种工作方式都不是完美的,还有更多方法可以做到,但我认为我会推荐第一种方法,因为它更容易理解并且更容易添加到您的代码中。 Comment if you need more explanation on how it works or more ways to do it如果您需要更多关于其工作原理或更多方法的说明,请发表评论


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()

Here is your program but using sprites这是您的程序,但使用精灵

As you can see, i have moved any code relating to the squares to their classes.如您所见,我已将任何与方块相关的代码移至它们的类中。 each sprite has a rect and a image .每个精灵都有一个rect和一个image The rect is used the same way as the rect i showed above.矩形的使用方式与我上面显示的矩形相同。 The image is a surface, because that how pygame puts it on the screen.图像是一个表面,因为 pygame 如何将它放在屏幕上。 it the exact same as before by making it the same size and filling it with the colour.通过使其大小相同并填充颜色,它与以前完全相同。

Ive got 2 sprite groups, the all_sprites group which has all of them and the enemy_sprites group, which only has enemies(platforms that you can stand on).我有 2 个精灵组, all_sprites组包含所有精灵组和enemy_sprites组,只有敌人(您可以站立的平台)。 I can draw all sprites by calling all_sprites.draw(win) .我可以通过调用all_sprites.draw(win)来绘制所有精灵。

For collisions, exact same, except i want to loop through each enemy (as i now have 2).对于碰撞,完全相同,除了我想遍历每个敌人(因为我现在有 2 个)。 so i can call enemy_sprites.sprites() to get each sprite.所以我可以调用enemy_sprites.sprites()来获取每个精灵。

If you want more explanation or examples, start a chat.如果您需要更多解释或示例,请开始聊天。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM