check move

This commit is contained in:
Ian Jauslin 2021-09-29 03:24:23 -04:00
parent a5caeec29a
commit 159ac83e86

View File

@ -14,7 +14,6 @@ class Cross():
self.pos=Point(x,y) self.pos=Point(x,y)
self.color=kwargs.get("color",(0,0,1)) self.color=kwargs.get("color",(0,0,1))
self.selected=False self.selected=False
self.stuckto=None
# set position # set position
def setpos(self,x,y): def setpos(self,x,y):
@ -46,7 +45,19 @@ class Cross():
# check whether a cross at pos interacts with cross # check whether a cross at pos interacts with cross
def check_interaction(self,pos): def check_interaction(self,pos):
return (pos-self.pos).int()**2>=5 # allow for error
return int(pos.x-self.pos.x+sgn(pos.x-self.pos.x)*1e-11)**2+int(pos.y-self.pos.y+sgn(pos.y-self.pos.y)*1e-11)**2>=5
# check whether a cross at position pos is touching self
def check_touch(self,pos):
rel=pos-self.pos
for i in [-3,-2,-1,1,2,3]:
# allow for error
if abs(rel.x-i)<1e-11 and abs(rel.y)<=4-abs(i)+1e-11 and abs(rel.y)>=3-abs(i)-1e-11:
return True
if abs(rel.y-i)<1e-11 and abs(rel.x)<=4-abs(i)+1e-11 and abs(rel.x)>=3-abs(i)-1e-11:
return True
return False
# find position along a line that comes in contact with the line going through pos in direction v # find position along a line that comes in contact with the line going through pos in direction v
def move_on_line_to_stick(self,pos,v): def move_on_line_to_stick(self,pos,v):
@ -92,7 +103,7 @@ class Cross():
closest=self.move_on_line_to_stick_relative(Point(-x.x,x.y),Point(-v.x,v.y)) closest=self.move_on_line_to_stick_relative(Point(-x.x,x.y),Point(-v.x,v.y))
return Point(-closest.x,closest.y) return Point(-closest.x,closest.y)
# move along edge of cross while remaining stuck # move along edge of cross
def move_along(self,newpos,pos): def move_along(self,newpos,pos):
rel=pos-self.pos rel=pos-self.pos
# check if the particle is stuck in the x direction # check if the particle is stuck in the x direction
@ -220,7 +231,7 @@ class Cross_painter(Widget):
def on_touch_down(self,touch): def on_touch_down(self,touch):
# create new cross # create new cross
if touch.button=="right": if touch.button=="right":
if self.check_add(Point(touch.x/Cross.size,touch.y/Cross.size)): if self.check_interaction_any(Point(touch.x/Cross.size,touch.y/Cross.size),None):
new=Cross(touch.x/Cross.size,touch.y/Cross.size) new=Cross(touch.x/Cross.size,touch.y/Cross.size)
with self.canvas: with self.canvas:
new.draw() new.draw()
@ -258,30 +269,37 @@ class Cross_painter(Widget):
# none found # none found
return None return None
# check whether a position intersects with any of the crosses
def check_interaction_any(self,pos,exception):
for other in self.crosses:
if other!=exception:
if other.check_interaction(pos)==False:
return False
return True
# check that a cross can move to new position # check that a cross can move to new position
def check_move(self,newpos,cross): def check_move(self,newpos,cross):
# whether newpos is acceptable
accept_newpos=True
for other in self.crosses: for other in self.crosses:
# do not compare a cross to itself # do not compare a cross to itself
if other!=cross: if other!=cross:
# move would make cross overlap with other # move would make cross overlap with other
if other.check_interaction(newpos)==False: if other.check_interaction(newpos)==False:
# check if cross is stuck to other accept_newpos=False
if cross.stuckto==other: # check if cross touches other
if other.check_touch(cross.pos):
# move along other while remaining stuck # move along other while remaining stuck
return other.move_along(newpos,cross.pos) candidate=other.move_along(newpos,cross.pos)
else: else:
# stick to the cross candidate=other.move_on_line_to_stick(cross.pos,newpos-cross.pos)
cross.stuckto=other if self.check_interaction_any(candidate,cross):
return other.move_on_line_to_stick(cross.pos,newpos-cross.pos) return candidate
# reset stuckto if move is allowed if accept_newpos:
cross.stuckto=None return newpos
return newpos else:
# cannot move cross at all, try again
# check that a cross can be added at position return self.check_move(candidate,cross)
def check_add(self,pos):
for cross in self.crosses:
if cross.check_interaction(pos)==False:
return False
return True