我正在尝试使用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()
答案 0 :(得分:0)
我知道每个圆形图形在技术上都可以使用 最小的可能方形,围绕圆圈做冷杉 碰撞
我正在玩另一个想法 - 我们可以考虑围绕矩形的圆圈而不是圆圈周围的方形。对我来说,问题在于我们不仅需要检测碰撞,而且需要了解哪种方式可以远离其他物体。它不仅仅是True
和False
,而是(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()
实施。