Detect overlapping circles

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
Hellbent
Posts: 2114
Joined: 23 Sep 2017, 13:34

Re: Detect overlapping circles

29 Sep 2021, 05:26

You also have a few unnecessary steps in your code.

Take this for example.

Code: Select all

n := "1|2|3|4|5|6|7|8|9|10"

loop, parse, n, |


You could just loop 10 times like you did one step earlier.

Code: Select all

loop 10
	{
		random r, 4, 12
		s%A_index% := floor((_H/100) * r)
	}	
These two variables would have the same value in your example.

Code: Select all

z := A_index
f := A_loopfield
The Ayes function should be more like this. (per your example)

Code: Select all

Ayes( a , i )
{
	
	return ( i <= a.Length() ) ? ( "True" ) : ( "False" )  ;*EDIT*:: Changed "<" to "<="
	
	
/*
	;AKA
	if( i < a.Length() )
		return true
	else 	
		return false
*/		
}
You should really consider using objects and arrays to hold your orb data.

Code: Select all


;All the orbs
Orbs := []

;Adding a new orb
Orbs[1] := { X: 10 , Y: 10 , W: 100 , H: 100 }

;Or
Orbs[2] := {}
Orbs[2].X := 10
Orbs[2].Y := 10
Orbs[2].W := 100
Orbs[2].H := 100



Here is how you can set up your collision detection.

Code: Select all

;Looping to detect collisions (Pseudo code)

Loop, % Orbs.Length() - 1 											;Loop over all but the last orb ( no need to check if the last one is hitting anything )
{
	Index := A_Index 											;Set the current outer loop count to a variable that will carry it into the inner loop
	Loop, % Orbs.Length() - Index									;Loop over only items that are ahead of the current item.
	{
		if( CollisionCheck( Orbs[ Index ] , Orbs[ A_Index + Index ] ) )		;Collision check.
		{
			Msgbox, Collision Detected							;Collision resolution.
		}
	}
}

Here is what the code from above does if you had 5 orbs.

Code: Select all

first loop (outer loop)
orb = 1
orb 1 looks at "orb 2|orb 3|orb 4|orb 5"  (inner loop)

second loop (outer loop)
orb = 2
orb 2 looks at "orb 3|orb 4|orb 5"  (inner loop)

third loop (outer loop)
orb = 3
orb 3 looks at "orb 4|orb 5"  (inner loop)

forth loop (outer loop)
orb = 4
orb 4 looks at "orb 5"  (inner loop)

orb 5 has nothing to look at.
Last edited by Hellbent on 29 Sep 2021, 17:57, edited 1 time in total.
User avatar
Hellbent
Posts: 2114
Joined: 23 Sep 2017, 13:34

Re: Detect overlapping circles

29 Sep 2021, 13:50

Here is an example of setting your orbs to their starting positions, you can add 10 to 250 orbs and none will overlap (*if they were circles)
Temp (1).gif
Temp (1).gif (135.45 KiB) Viewed 541 times

Code: Select all

;*****************************************************************************************************************************************
;*****************************************************************************************************************************************
#SingleInstance, Force
SetBatchLines, -1
;*****************************************************************************************************************************************
;*****************************************************************************************************************************************
LoopCount := 250
Gui, 1:+AlwaysOnTop
Gui, 1:Color, 22262a
Gui, 1:Add, Slider, xm w200 ToolTip Range10-%LoopCount% hwndSlider1, 100
Gui, 1:Add, Button, xm gStart
Gui, 1:Show,w500 h400,Demo
;*****************************************************************************************************************************************
;*****************************************************************************************************************************************

Orbs := []
Loop, % LoopCount	{
	Gui, 1:Add, Progress, x0 y0 w0 h0 BackgroundRed hwndhwnd
	Orbs[ A_Index ] := { Hwnd: hwnd , X: 0 , Y: 0 , R: Random( 2 , 10 ) , CX: "" , CY: "" }
}

return
;*****************************************************************************************************************************************
;*****************************************************************************************************************************************
GuiClose:
GuiContextMenu:
*ESC::ExitApp
;*****************************************************************************************************************************************
;*****************************************************************************************************************************************
Start:
	Loop, % LoopCount	{
		if( Orbs[ A_Index ].X = 0 )
			break
		Orbs[ A_Index ].X := 0
		GuiControl, 1:MoveDraw, % Orbs[ A_Index ].Hwnd, % "x0 y0 w0 h0"
	}
	GuiControlGet, out, 1:, % Slider1
	ActiveCount := 0
	Loop, % out	{
		Index := A_Index
		ToolTip, % ++ActiveCount
		Loop, {
			Orbs[ ActiveCount ].X := Random( 50 , 450 )
			Orbs[ ActiveCount ].Y := Random( 100 , 350 )
			Orbs[ ActiveCount ].CX := Orbs[ ActiveCount ].X + Orbs[ ActiveCount ].R
			Orbs[ ActiveCount ].CY := Orbs[ ActiveCount ].Y + Orbs[ ActiveCount ].R
			if( !CollisionCheck( Orbs , ActiveCount ) )
				break
		}
		GuiControl, 1:MoveDraw, % Orbs[ ActiveCount ].Hwnd, % "x" Orbs[ ActiveCount ].X " y" Orbs[ ActiveCount ].Y " w" 2 * Orbs[ ActiveCount ].R " h" 2 * Orbs[ ActiveCount ].R
	}
	sleep, 50
	loop 2
		SoundBeep, 999
	ToolTip
	return
;*****************************************************************************************************************************************
;*****************************************************************************************************************************************
CollisionCheck( obj , LoopCount ){
	Loop, % LoopCount - 1	{
		Index := A_Index
		Loop, % LoopCount - Index	{
			MinDistance := obj[ Index ].R + obj[ A_Index + Index ].R
			if( Distance( obj[ Index ] , obj[ A_Index + Index ] ) < MinDistance )
				return True
		}
	}
	Return False
}
;*****************************************************************************************************************************************
;*****************************************************************************************************************************************
 Distance( input1 , input2 ){
	return Sqrt( ( ( input1.CX - input2.CX ) ** 2 ) + ( ( input1.CY - input2.CY ) ** 2 ) )
}
;*****************************************************************************************************************************************
;*****************************************************************************************************************************************
Random( Min , Max ){
	local out 
	Random, out, Min, Max
	return out
}
;*****************************************************************************************************************************************
;*****************************************************************************************************************************************
User avatar
PuzzledGreatly
Posts: 1303
Joined: 29 Sep 2013, 22:18

Re: Detect overlapping circles

09 Oct 2023, 22:33

Hellbent - I totally missed replying to this at the time - my apologies. I've been restudying this topic and your examples have been a big help. I'm now trying to use moving circles and have one bounce off the other. Thanks again.
User avatar
Hellbent
Posts: 2114
Joined: 23 Sep 2017, 13:34

Re: Detect overlapping circles

10 Oct 2023, 02:08

PuzzledGreatly wrote:
09 Oct 2023, 22:33
Hellbent - I totally missed replying to this at the time - my apologies. I've been restudying this topic and your examples have been a big help. I'm now trying to use moving circles and have one bounce off the other. Thanks again.
I don't have time atm to create any examples but you might find my vector class useful.

Code: Select all

;************
;Vector Class
;**************************************************************************************************************************************************************************
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;**************************************************************************************************************************************************************************
Class Vector	{
	;Written By: HB
	;Date: Sept 23rd, 2022
	;Last Edit: Sept 24th, 2022
	;Purpose: Vector math class 
	;Credit: Rohwedder 
	;Resources: 
		;Line intercept concepts and code: https://www.autohotkey.com/boards/viewtopic.php?f=76&t=37175
		;Create an Arrow: https://www.autohotkey.com/boards/viewtopic.php?f=76&t=92039&p=479129#p478944
		;Getting an angle: https://www.autohotkey.com/boards/viewtopic.php?f=76&t=108760&p=483661#p483678
		;Setting an Angle: https://www.autohotkey.com/boards/viewtopic.php?f=76&t=108760&p=483786#p483811
		;
		
	static RadToDeg := 45 / ATan( 1 ) 
		, DegToRad := ATan( 1 ) / 45 
		
	__New( x := 0 , y := 0 , rotate := 0 ){ 
		if( IsObject( x ) ){
			if( rotate = 3 ){
				This.X := x.X * -1
				,This.Y := x.Y * -1
			}else if( rotate = 2 ){
				This.X := x.Y 
				,This.Y := x.X * -1
			}else if( rotate = 1 ){
				This.X := x.Y * -1
				,This.Y := x.X 
			}else{
				This.X := x.X
				,This.Y := x.Y
			}
		}else{
			if( rotate = 3 ){
				This.X := X * -1
				,This.Y := Y * -1
			}else if( rotate = 2 ){
				This.X := Y 
				,This.Y := X * -1
			}else if( rotate = 1 ){
				This.X := Y * -1
				,This.Y := X 
			}else{
				This.X := X
				,This.Y := Y
			}
		}
	}
	Add( x , y := "" ){
		if( IsObject( x ) ){
			This.X += x.X
			,This.Y += x.Y
		}else if( y = "" ){
			This.X += x 
			,This.Y += x
		}else{
			This.X += x 
			,This.Y += y 
		}
	}
	Sub( x , y := "" ){
		if( IsObject( x ) ){
			This.X -= x.X
			,This.Y -= x.Y
		}else if( y = "" ){
			This.X -= X
			,This.Y -= X
		}else{
			This.X -= X
			,This.Y -= Y
		}
	}
	Div( x , y := "" ){
		if( IsObject( x ) ){
			This.X /= x.X
			,This.Y /= x.Y
		}else if( x && y = "" ){
			This.X /= x 
			,This.Y /= x 
		}else{
			This.X /= X
			,This.Y /= Y
		}
	}
	Mult( x , y := "" ){
		if( IsObject( x ) ){
			This.X *= x.X
			,This.Y *= x.Y
		}else if( x && y = "" ){
			This.X *= x 
			,This.Y *= x 
		}else{
			This.X *= X
			,This.Y *= Y
		}
	}
	Dist( x , y := "" ){
		if( IsObject( x ) )
			return Sqrt( ( ( This.X - x.X ) **2 ) + ( ( This.Y - x.Y ) **2 ) )
		else 
			return Sqrt( ( ( This.X - X ) **2 ) + ( ( This.Y - Y ) **2 ) )
	}
	GetMag(){
		return Sqrt( This.X * This.X + This.Y * This.Y )
	}
	SetMag( magnitude ){
		local m := This.GetMag()
		This.X := This.X * magnitude / m
		,This.Y := This.Y * magnitude / m
	}
	MagSq(){
		return This.GetMag()**2
	}	
	Dot( x , y := "" ){
		if( IsObject( x ) )
			return ( This.X * x.X ) + ( This.Y * x.Y )
		else
			return ( This.X * X ) + ( This.Y * Y )
	}
	Cross( x , y := "" ){
		if( IsObject( x ) )
			return This.X * x.Y - This.Y * x.X
		else
			return This.X * Y - This.Y * X
		
	}
	Norm(){
		local m := This.GetMag()
		This.X /= m
		This.Y /= m
	}
	GetAngle(){ 
		local angle 
		( (  angle := Vector.RadToDeg * DllCall( "msvcrt\atan2" , "Double" , This.Y , "Double" , This.X , "CDECL Double" ) ) < 0 ) ? ( angle += 360 )
		return angle
	}
	SetAngle( newAngle := 0 , NewVector := 0 ){
		local Angle := This.GetAngle()
		, ChangeAngle := newAngle - Angle 
		, Co := Cos( Vector.DegToRad * ChangeAngle )
		, Si := Sin( Vector.DegToRad * ChangeAngle )
		, X := This.X 
		, Y := This.Y
		, X2 := X * Co - Y * Si 
		, Y2 := X * Si + Y * Co 
		
		if( !NewVector )
			This.X := X2 , This.Y := Y2
		else 
			return New Vector( X2 , Y2 )
	}
	RotateAngle( rotationAmount := 90 , NewVector := 0 ){
		local Co := Cos( Vector.DegToRad * rotationAmount )
		, Si := Sin( Vector.DegToRad * rotationAmount )
		, X := This.X 
		, Y := This.Y
		, X2 := X * Co - Y * Si 
		, Y2 := X * Si + Y * Co 
		
		if( !NewVector )
			This.X := X2 , This.Y := Y2
		else 
			return New Vector( X2 , Y2 )
	}
	;********************************************
	;class methods
	TestLineInterceptPoint( interceptPoint , Line1 , Line2 ){ ; Line = { Start: { X: , Y: } , End: { X: , Y: } } , interceptPoint = { X: , Y: }
		local
		for k , v in [ "X" , "Y" ]	
			M%v%_Min := min( Line1.Start[ v ] , Line1.End[ v ] )
			,M%v%_Max := max( Line1.Start[ v ] , Line1.End[ v ] )
			,L%v%_Min := min( Line2.Start[ v ] , Line2.End[ v ] )
			,L%v%_Max := max( Line2.Start[ v ] , Line2.End[ v ] )
		if( !( interceptPoint.X < Mx_Min || interceptPoint.X > Mx_Max || interceptPoint.X < Lx_Min || interceptPoint.X > Lx_Max ) && !( interceptPoint.Y < My_Min || interceptPoint.Y > My_Max || interceptPoint.Y < Ly_Min || interceptPoint.Y > Ly_Max ) )
			return 1
		return 0
	}
	GetLineInterceptPoint( Line1 , Line2 ){ ; Line = { Start: { X: , Y: } , End: { X: , Y: } }
		local A1 := Line1.End.Y - Line1.Start.Y
		,B1 := Line1.Start.X - Line1.End.X
		,C1 := A1 * Line1.Start.X + B1 * Line1.Start.Y
		,A2 := Line2.End.Y - Line2.Start.Y
		,B2 := Line2.Start.X - Line2.End.X
		,C2 := A2 * Line2.Start.X + B2 * Line2.Start.Y
		,Denominator := A1 * B2 - A2 * B1 
		return New Vector( { X: ( ( B2 * C1 - B1 * C2 ) / Denominator )  , Y: ( ( A1 * C2 - A2 * C1 ) / Denominator ) } )
	}
	;********************************************
}
;**************************************************************************************************************************************************************************
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;**************************************************************************************************************************************************************************
And here is a decent intro to using vectors.

https://www.youtube.com/watch?v=kjBOesZCoqc&list=PL0-GT3co4r2y2YErbmuJw2L5tW4Ew2O5B
User avatar
PuzzledGreatly
Posts: 1303
Joined: 29 Sep 2013, 22:18

Re: Detect overlapping circles

10 Oct 2023, 14:32

Wow! Thanks for taking the time to post your brilliant looking class and the Youtube link. I've started looking at the videos - really good. I want to be able to work this out and you've given me a great start.
User avatar
Hellbent
Posts: 2114
Joined: 23 Sep 2017, 13:34

Re: Detect overlapping circles

11 Oct 2023, 03:27

PuzzledGreatly wrote:
10 Oct 2023, 14:32
Wow! Thanks for taking the time to post your brilliant looking class and the Youtube link. I've started looking at the videos - really good. I want to be able to work this out and you've given me a great start.
Another video. The end of the video discusses some optimizations for collision detection.

https://www.youtube.com/watch?v=eED4bSkYCB8

Another.
https://www.youtube.com/watch?v=LPzyNOHY3A4

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: apeironn, Bing [Bot], Pianist and 186 guests