Home > OS >  Moving balls with minimum distance (Python)
Moving balls with minimum distance (Python)

Time:01-25

I am trying to write a code where I can move two circles around using left mouse button. Most of the code is working, but I am missing one part; There should be a minimum distance of 100 pixels between the circles (not allowed to bring them closer apart than that). I tried using while length > 70 with the function def mouseMoved(self, event) but it did not work. I hope someone can help me on my way.

from tkinter import * 
import math

class Circle:
def __init__(self, x, y, radius):
    self.x = x
    self.y = y
    self.radius = radius

def isInside(self, x, y):
    return distance(self.x, self.y, x, y) <= self.radius
              
class MainGUI:
def __init__(self):   
    window = Tk() 
    window.title("Two Balls") 

    self.canvas = Canvas(width = 400, height = 250)
    self.canvas.pack()
    
    self.c1 = Circle(20, 20, 20)
    self.c2 = Circle(120, 50, 20)
    self.canvas.create_line(self.c1.x, self.c1.y, self.c2.x, self.c2.y, tags = "line")      
    self.getLength()

    self.paint(self.c1, "red", "c1")
    self.paint(self.c2, "red", "c2")
  
    self.canvas.bind("<B1-Motion>", self.mouseMoved)
    
    window.mainloop() 

def getLength(self):
    length = round(math.sqrt((self.c1.x-self.c2.x)**2   (self.c1.y-self.c2.y)**2), 2)
    self.canvas.create_text((self.c1.x self.c2.x)/2, (self.c1.y self.c2.y)/2, text = length, tags = "text") 
    return length
    
def mouseMoved(self, event):
    self.canvas.delete("line") 
    self.canvas.delete("text")

    if self.c2.isInside(event.x, event.y):
        self.c2.x = event.x
        self.c2.y = event.y 
            
    self.canvas.delete("c2")
    self.paint(self.c2, "red", "c2")

    if self.c1.isInside(event.x, event.y):
        self.c1.x = event.x
        self.c1.y = event.y 
    
    self.canvas.delete("c1")
    self.paint(self.c1, "red", "c1")

    self.canvas.create_line(self.c1.x, self.c1.y, self.c2.x, self.c2.y, tags = "line")
    self.getLength()

def paint(self, c, color, tags = "stable"):
    self.canvas.create_oval(c.x - c.radius, c.y - c.radius, c.x   c.radius, c.y   c.radius, fill = color, tags = tags)

def distance(x1, y1, x2, y2):
return ((x1 - x2) * (x1 - x2)   (y1 - y2) * (y1 - y2)) ** 0.5       
MainGUI()

CodePudding user response:

You need to calculate the distance between the two circles after one of them is moved, perform the actual move only if the distance is greater than 100 pixels:

def mouseMoved(self, event):
    f2 = self.c2.isInside(event.x, event.y)
    f1 = self.c1.isInside(event.x, event.y)

    # Is one of the circles is selected?
    if f1 or f2:
        # calculate the distance between the two circles after one of them is moved
        if f1:
            length = distance(event.x, event.y, self.c2.x, self.c2.y)
        else:
            length = distance(event.x, event.y, self.c1.x, self.c1.y)

        # Only perform the move if the distance > 100 pixels
        if length > 100:
            self.canvas.delete("text")
            self.canvas.delete("line")
            if f2:
                self.c2.x = event.x
                self.c2.y = event.y

                self.canvas.delete("c2")
                self.paint(self.c2, "red", "c2")
            else:
                self.c1.x = event.x
                self.c1.y = event.y

                self.canvas.delete("c1")
                self.paint(self.c1, "red", "c1")

            self.canvas.create_line(self.c1.x, self.c1.y, self.c2.x, self.c2.y, tags="line")
            self.getLength(length)

CodePudding user response:

The problem is with the indentation

from tkinter import * 
import math

class Circle:
  def __init__(self, x, y, radius):
      self.x = x
      self.y = y
      self.radius = radius

  def isInside(self, x, y):
      return distance(self.x, self.y, x, y) <= self.radius
              
class MainGUI:
  def __init__(self):   
      window = Tk() 
      window.title("Two Balls") 

      self.canvas = Canvas(width = 400, height = 250)
      self.canvas.pack()
      
      self.c1 = Circle(20, 20, 20)
      self.c2 = Circle(120, 50, 20)
      self.canvas.create_line(self.c1.x, self.c1.y, self.c2.x, self.c2.y, tags = "line")      
      self.getLength()

      self.paint(self.c1, "red", "c1")
      self.paint(self.c2, "red", "c2")
    
      self.canvas.bind("<B1-Motion>", self.mouseMoved)
      
      window.mainloop() 

  def getLength(self):
      length = round(math.sqrt((self.c1.x-self.c2.x)**2   (self.c1.y-self.c2.y)**2), 2)
      self.canvas.create_text((self.c1.x self.c2.x)/2, (self.c1.y self.c2.y)/2, text = length, tags = "text") 
      return length
      
  def mouseMoved(self, event):
      self.canvas.delete("line") 
      self.canvas.delete("text")

      if self.c2.isInside(event.x, event.y):
          self.c2.x = event.x
          self.c2.y = event.y 
              
      self.canvas.delete("c2")
      self.paint(self.c2, "red", "c2")

      if self.c1.isInside(event.x, event.y):
          self.c1.x = event.x
          self.c1.y = event.y 
      
      self.canvas.delete("c1")
      self.paint(self.c1, "red", "c1")

      self.canvas.create_line(self.c1.x, self.c1.y, self.c2.x, self.c2.y, tags = "line")
      self.getLength()

  def paint(self, c, color, tags = "stable"):
      self.canvas.create_oval(c.x - c.radius, c.y - c.radius, c.x   c.radius, c.y   c.radius, fill = color, tags = tags)

  def distance(x1, y1, x2, y2):
    return ((x1 - x2) * (x1 - x2)   (y1 - y2) * (y1 - y2)) ** 0.5       
    MainGUI()
  •  Tags:  
  • Related