簡體   English   中英

Zelle graphics.py中的碰撞

[英]Collisions in Zelle graphics.py

我正在嘗試使用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()

我知道每個圓形圖形在技術上都可以使用可能會繞圓形旋轉的最小正方形的點進行碰撞

我正在考慮一種替代方法-我們可以考慮在矩形周圍使用一個圓圈,而不是在該圓圈周圍使用一個正方形。 對我來說,問題在於我們不僅需要檢測碰撞,而且還能以某種方式遠離其他物體。 這不只是TrueFalse ,而是一個(dx, dy)類型的結果。

顯然,矩形周圍的一個圓太粗糙了,但是假設它是由許多較小的圓組成的矩形,我們測量圓的中心到中心的距離以檢測到命中:

在此處輸入圖片說明

僅擊中中心(綠色)矩形圓圈就意味着反轉大圓圈的垂直方向。 在最后一個圓(紅色)上命中表示反轉大圓的水平方向。 而且我們可以檢測到兩種命中並完全扭轉大圓圈。

考慮到以上幾點,這是我對代碼的重做-我還解決了多次單擊的問題,並進行了許多樣式更改:

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()實現。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM