【问题标题】:how do I make triangle collisions with pygame?如何使用 pygame 进行三角形碰撞?
【发布时间】:2017-06-01 15:13:07
【问题描述】:

我正在尝试在 pygame 中制作平台游戏,但遇到了一个问题。我可以很容易地对矩形和正方形进行碰撞,但我不能对直角三角形进行碰撞。甚至可以使用pygame做到这一点吗?我曾考虑只移除一个角落来做到这一点,但我不知道如何做到这一点,并且在任何地方都找不到任何有用的信息。一个人建议使用较小的矩形碰撞来使三角形碰撞,但这并没有产生预期的效果。下面的代码是别人做的,但和我的基本一样,唯一的区别是我的有动画等,我改变了跳跃物理等中的一些数字

#! /usr/bin/python

import pygame
from pygame import *

WIN_WIDTH = 800
WIN_HEIGHT = 640
HALF_WIDTH = int(WIN_WIDTH / 2)
HALF_HEIGHT = int(WIN_HEIGHT / 2)

DISPLAY = (WIN_WIDTH, WIN_HEIGHT)
DEPTH = 32
FLAGS = 0
CAMERA_SLACK = 30

def main():
    global cameraX, cameraY
    pygame.init()
    screen = pygame.display.set_mode(DISPLAY, FLAGS, DEPTH)
    pygame.display.set_caption("Use arrows to move!")
    timer = pygame.time.Clock()

    up = down = left = right = running = False
    bg = Surface((32,72))
    bg.convert()
    bg.fill(Color("#000000"))
    entities = pygame.sprite.Group()
    player = Player(32, 32)
    platforms = []

    x = y = 0
    level = [
        "PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                    PPPPPPPPPPP           P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P    PPPPPPPP                              P",
        "P                                          P",
        "P                          PPPPPPP         P",
        "P                 PPPPPP                   P",
        "P                                          P",
        "P         PPPPPPP                          P",
        "P                                          P",
        "P                     PPPPPP               P",
        "P                                          P",
        "P   PPPPPPPPPPP                            P",
        "P                                          P",
        "P                 PPPPPPPPPPP              P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP",]
    # build the level
    for row in level:
        for col in row:
            if col == "P":
                p = Platform(x, y)
                platforms.append(p)
                entities.add(p)
            if col == "E":
                e = ExitBlock(x, y)
                platforms.append(e)
                entities.add(e)
            x += 32
        y += 32
        x = 0

    total_level_width  = len(level[0])*32
    total_level_height = len(level)*32
    camera = Camera(complex_camera, total_level_width, total_level_height)
    entities.add(player)

    while 1:
        timer.tick(60)

        for e in pygame.event.get():
            if e.type == QUIT: raise SystemExit, "QUIT"
            if e.type == KEYDOWN and e.key == K_ESCAPE:
                raise SystemExit, "ESCAPE"
            if e.type == KEYDOWN and e.key == K_UP:
                up = True
            if e.type == KEYDOWN and e.key == K_DOWN:
                down = True
            if e.type == KEYDOWN and e.key == K_LEFT:
                left = True
            if e.type == KEYDOWN and e.key == K_RIGHT:
                right = True
            if e.type == KEYDOWN and e.key == K_SPACE:
                running = True

            if e.type == KEYUP and e.key == K_UP:
                up = False
            if e.type == KEYUP and e.key == K_DOWN:
                down = False
            if e.type == KEYUP and e.key == K_RIGHT:
                right = False
            if e.type == KEYUP and e.key == K_LEFT:
                left = False

        # draw background
        for y in range(32):
            for x in range(32):
                screen.blit(bg, (x * 32, y * 32))

        camera.update(player)

        # update player, draw everything else
        player.update(up, down, left, right, running, platforms)
        for e in entities:
            screen.blit(e.image, camera.apply(e))

        pygame.display.update()

class Camera(object):
    def __init__(self, camera_func, width, height):
        self.camera_func = camera_func
        self.state = Rect(0, 0, width, height)

    def apply(self, target):
        return target.rect.move(self.state.topleft)

    def update(self, target):
        self.state = self.camera_func(self.state, target.rect)

def simple_camera(camera, target_rect):
    l, t, _, _ = target_rect
    _, _, w, h = camera
    return Rect(-l+HALF_WIDTH, -t+HALF_HEIGHT, w, h)

def complex_camera(camera, target_rect):
    l, t, _, _ = target_rect
    _, _, w, h = camera
    l, t, _, _ = -l+HALF_WIDTH, -t+HALF_HEIGHT, w, h

    l = min(0, l)                           # stop scrolling at the left edge
    l = max(-(camera.width-WIN_WIDTH), l)   # stop scrolling at the right edge
    t = max(-(camera.height-WIN_HEIGHT), t) # stop scrolling at the bottom
    t = min(0, t)                           # stop scrolling at the top
    return Rect(l, t, w, h)

class Entity(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)

class Player(Entity):
    def __init__(self, x, y):
        Entity.__init__(self)
        self.xvel = 0
        self.yvel = 0
        self.onGround = False
        self.image = Surface((32,72))
        self.image.fill(Color("#0000FF"))
        self.image.convert()
        self.rect = Rect(x, y, 32, 72)

    def update(self, up, down, left, right, running, platforms):
        if up:
            # only jump if on the ground
            if self.onGround: self.yvel -= 10
        if down:
            pass
        if running:
            self.xvel = 12
        if left:
            self.xvel = -8
        if right:
            self.xvel = 8
        if not self.onGround:
            # only accelerate with gravity if in the air
            self.yvel += 0.3
            # max falling speed
            if self.yvel > 100: self.yvel = 100
        if not(left or right):
            self.xvel = 0
        # increment in x direction
        self.rect.left += self.xvel
        # do x-axis collisions
        self.collide(self.xvel, 0, platforms)
        # increment in y direction
        self.rect.top += self.yvel
        # assuming we're in the air
        self.onGround = False;
        # do y-axis collisions
        self.collide(0, self.yvel, platforms)

    def collide(self, xvel, yvel, platforms):
        for p in platforms:
            if pygame.sprite.collide_rect(self, p):
                if isinstance(p, ExitBlock):
                    pygame.event.post(pygame.event.Event(QUIT))
                if xvel > 0:
                    self.rect.right = p.rect.left
                    print "collide right"
                if xvel < 0:
                    self.rect.left = p.rect.right
                    print "collide left"
                if yvel > 0:
                    self.rect.bottom = p.rect.top
                    self.onGround = True
                    self.yvel = 0
                if yvel < 0:
                    self.rect.top = p.rect.bottom


class Platform(Entity):
    def __init__(self, x, y):
        Entity.__init__(self)
        self.image = Surface((32, 32))
        self.image.convert()
        self.image.fill(Color("#DDDDDD"))
        self.rect = Rect(x, y, 32, 32)

    def update(self):
        pass

class ExitBlock(Platform):
    def __init__(self, x, y):
        Platform.__init__(self, x, y)
        self.image.fill(Color("#0033FF"))

if __name__ == "__main__":
    main()

【问题讨论】:

  • 这个问题其实和pygame没什么太大关系。仅仅因为 pygame 缺少用于三角形碰撞检测的内置函数并不意味着你不能自己编写碰撞检测程序。
  • 好的。我将如何使用我正在使用的代码来做到这一点?
  • 另外,“在 2D 空间中检测三角形碰撞”正在询问如何碰撞 2 个三角形,但我想知道如何碰撞三角形和矩形。人们建议的代码似乎不会做我需要做的事情
  • 每个碰撞相关的算法都可以通过快速的谷歌搜索轻松找到。我们不是来为您编写代码的。 gamedev.stackexchange.com/questions/8326/…

标签: python pygame collision-detection


【解决方案1】:

无法使用 pygame 模块方法实现三角形碰撞。但是搜索 Pylygon 模块。

【讨论】:

    【解决方案2】:

    所以,如果你想进行三角形碰撞,你可以使用这个

    要求你的三角形计算碰撞:

    • 3分的位置
    • 三角形的面积

    如何计算面积

    self.area = abs((self.points[1][0] - self.points[0][0]) * (self.points[2][1] - self.points[0][1]) - (self.points[2][0] - self.points[0][0]) * (self.points[1][1] - self.points[0][1]))
    

    注意:这不是真正的三角形,它只是通过不除以 2 来节省一点时间

    如何进行碰撞

    def collision(self, pos):
        area1 = abs((self.points[0][0] - pos[0]) * (self.points[1][1] - pos[1]) - (self.points[1][0] - pos[0]) * (self.points[0][1] - pos[1]))
        area2 = abs((self.points[1][0] - pos[0]) * (self.points[2][1] - pos[1]) - (self.points[2][0] - pos[0]) * (self.points[1][1] - pos[1]))
        area3 = abs((self.points[2][0] - pos[0]) * (self.points[0][1] - pos[1]) - (self.points[0][0] - pos[0]) * (self.points[2][1] - pos[1]))
        areatotal = (area1 + area2 + area3) / 2
        if areatotal == self.area:
            return True
    

    是的,这是提示,如果您想应用更多种类的东西,请检查:

    http://www.jeffreythompson.org/collision-detection/tri-point.php

    这个也有解释,你可以看看,我不太会解释

    【讨论】:

      猜你喜欢
      • 2016-06-10
      • 1970-01-01
      • 1970-01-01
      • 2012-01-05
      • 2015-08-21
      • 2023-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多