Zelle graphics.py中的碰撞

时间:2017-09-27 23:58:17

标签: python python-2.7 collision-detection shapes zelle-graphics

我正在尝试使用Zelle graphics.py让我的圆圈从我的矩形中弹回。一旦圆圈从矩形反弹,我希望它随机移动。到目前为止,这是我的代码,它正在工作! 另外我知道每个圆形图形在技术上都可以使用适合圆圈的最小可能方形的点来进行碰撞,但是我在这方面遇到了麻烦。

from graphics import *
import random

def delay(d):
    for i in range(d):
        for i in range(50):
            pass
#-------------------------------------------------
def main():


    win=GraphWin("Moving Circle",500,400)
    win.setBackground('white')
    pt= Point(100,200)
    cir=Circle(pt,30)
    #changes the color of the circle for each game
    r = random.randrange(256)
    b = random.randrange(256)
    g = random.randrange(256)
    color = color_rgb(r, g, b)
    cir.setFill(color)
    cir.draw(win)
#rectangle
    rec = Rectangle(Point(450,450), Point(275, 425))
    rec.draw(win)
    rec.setFill('black')
#-------------------------------------------------
    pt5 = Point(250,30)
    instruct1=Text(pt5, "click multiple times to start(rectangle can take multiple clicks to move)")
    instruct1.setTextColor('black')
    instruct1.draw(win)


#-------------------------------------------------
    p=cir.getCenter()
    p2=win.getMouse()

    dx=1
    dy=1

    keepGoing=True

    while keepGoing:
        d = 100
        delay(d)
        cir.move(dx,dy)
        p=cir.getCenter()
        p2=win.checkMouse()
        instruct1.setText("")


#rectanlge
        isClicked= win.checkMouse()
        if isClicked:
            rp = isClicked
            rc = rec.getCenter()
            rdx = rp.getX() - rc.getX()
            rdy = rp.getY() - rc.getY()
            rec.move(rdx,rdy)

#circle
        if((p.getX()-30)<=0.0) or ((p.getX()+30)>=500):
            dx= -dx

        if((p.getY()-30)<=0.0) or ((p.getY()+30)>=400):
            dy=-dy
        p3=win.checkMouse()



main()

1 个答案:

答案 0 :(得分:0)

  

我知道每个圆形图形在技术上都可以使用   最小的可能方形,围绕圆圈做冷杉   碰撞

我正在玩另一个想法 - 我们可以考虑围绕矩形的圆圈而不是圆圈周围的方形。对我来说,问题在于我们不仅需要检测碰撞,而且需要了解哪种方式可以远离其他物体。它不仅仅是TrueFalse,而是(dx, dy)类型的结果。

显然,矩形周围的圆形太粗糙,但假设构成矩形的是许多较小的圆圈,我们测量圆心到中心的距离以检测命中:

enter image description here

仅在中央(绿色)矩形圆上点击意味着反转大圆的垂直方向。仅在末端(红色)圆圈上击中意味着反转大圆圈的水平方向。我们可以检测到两种命中并完全颠倒大圆圈。

以下是我对代码的修改 - 我还修复了您的多次点击问题并进行了大量的样式更改:

from random import randrange
from graphics import *

WIDTH, HEIGHT = 500, 400

RADIUS = 30

def delay(d):
    for _ in range(d):
        for _ in range(50):
            pass

def distance(p1, p2):
    return ((p2.getX() - p1.getX()) ** 2 + (p2.getY() - p1.getY()) ** 2) ** 0.5

def intersects(circle, rectangle):

    dx, dy = 1, 1  # no change

    center = circle.getCenter()

    rectangle_radius = (rectangle.p2.getY() - rectangle.p1.getY()) / 2
    rectangle_width = rectangle.p2.getX() - rectangle.p1.getX()

    y = rectangle.getCenter().getY()

    for x in range(int(rectangle_radius * 2), int(rectangle_width - rectangle_radius * 2) + 1, int(rectangle_radius)):
        if distance(center, Point(rectangle.p1.getX() + x, y)) <= rectangle_radius + RADIUS:
            dy = -dy  # reverse vertical
            break

    if distance(center, Point(rectangle.p1.getX() + rectangle_radius, y)) <= rectangle_radius + RADIUS:
            dx = -dx  # reverse horizontal
    elif distance(center, Point(rectangle.p2.getX() - rectangle_radius, y)) <= rectangle_radius + RADIUS:
            dx = -dx  # reverse horizontal

    return (dx, dy)

def main():
    win = GraphWin("Moving Circle", WIDTH, HEIGHT)

    circle = Circle(Point(WIDTH / 5, HEIGHT / 2), RADIUS)

    # change the color of the circle for each game
    color = color_rgb(randrange(256), randrange(256), randrange(256))
    circle.setFill(color)

    circle.draw(win)

    # rectangle
    rectangle = Rectangle(Point(275, 425), Point(450, 450))  # off screen
    rectangle.setFill('black')
    rectangle.draw(win)

    dx, dy = 1, 1

    while True:
        delay(100)
        circle.move(dx, dy)

        # rectangle
        isClicked = win.checkMouse()

        if isClicked:
            point = isClicked
            center = rectangle.getCenter()
            rectangle.move(point.getX() - center.getX(), point.getY() - center.getY())

        # circle
        center = circle.getCenter()

        if (center.getX() - RADIUS) <= 0.0 or (center.getX() + RADIUS) >= WIDTH:
            dx = -dx

        if (center.getY() - RADIUS) <= 0.0 or (center.getY() + RADIUS) >= HEIGHT:
            dy = -dy

        # collision bounce

        x, y = intersects(circle, rectangle)
        dx *= x
        dy *= y

main()

不完美,但可以使用,可能会插入更好的intersects()实施。