1

J'essaye de faire rebondir mon cercle de mon rectangle en utilisant Zelle graphics.py. Une fois que le cercle rebondit sur le rectangle, je voulais qu'il continue de bouger au hasard. Voici mon code jusqu'à présent, et ça marche! De plus, je sais que chaque graphique de cercle peut techniquement utiliser les points du plus petit carré possible qui entoure le cercle pour faire la collision, mais j'ai de la difficulté à le faire.Collisions dans 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() 

Répondre

0

Je sais que chaque graphiques cercle techniquement peuvent utiliser les points de la plus petit carré possible qui sapin autour du cercle pour faire la collision

Je joue avec un autre idée - nous pourrions envisager un cercle autour du rectangle au lieu d'un carré autour du cercle. Le problème pour moi est que nous avons non seulement besoin de détecter une collision, mais aussi de savoir comment nous éloigner de l'autre objet. Ce n'est pas seulement True et False mais plutôt un type de résultat (dx, dy).

De toute évidence, un cercle autour du rectangle est trop brut, mais supposons qu'il avait beaucoup de petits cercles qui composent le rectangle et nous mesurons le centre du cercle au centre distance pour détecter un coup:

enter image description here

A frapper juste un cercle rectangle central (vert) signifie inverser la direction verticale du grand cercle. Un coup sur le cercle de fin (rouge) signifie inverser la direction horizontale du grand cercle. Et nous pouvons détecter les deux types de hits et inverser complètement le grand cercle.

Voici mon réusinage de votre code avec ce qui précède à l'esprit - je également fixé vos multiples problème de clic et fait beaucoup de changements de style:

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

Pas parfait, mais quelque chose à jouer avec, peut-être brancher dans une meilleure mise en œuvre intersects().

+0

Merci! C'était très utile! – jen