Difficult-Rotating and lining up ngons.

BlitzMax Forums/BlitzMax Programming/Difficult-Rotating and lining up ngons.

Ryan Burnside(Posted 2006) [#1]
Ok this is my most difficult task yet.I plan to make a game were bosses and all elements are polygon based. The boss will add more polygons as the game progresses. The most difficult aspect is simply having the ngons line up edge to edge.

I have written a function to create new boss elements called spawn() the problem is that something is wrong with the code, when the boss core is a hexagon the hexagons line up and the other random n-gons are frusteratingly off.
They have the proper centers but the rotation has been corrupted. If the boss shape is anything other than a hexagon the whole system fouls up and the sides are not bisected by the base angles properly. I know this is a daunting task to fix, if you are very good with trig please consider looking this over. I have tried to comment where needed to give you an idea of where i am going.

Ok the blue shape is the boss core and the black ngons are the boss_fragments.


'**************************************************************************************************
' This program was written with BLIde (for great justice!)
' Application: 1/2 of a tube twice daily
' Author: Ryan Burnside
' License: Class C driver's licence
'**************************************************************************************************
 Strict
Graphics 640,480,0
SeedRnd MilliSecs()


Global score%=100000000 ' just a placeholder for now


SetBlend ALPHABLEND
' make some functions
Function poly_radius#(sidelength:Float,num_sides:Int)' finds circumscribed radius of an ngon
		Local r:Float = sidelength /(2*Sin(180.0/num_sides))
		Return r
End Function
Function poly_smallradius#(sidelength#,numsides%)' finds the inscribed radius of an ngon
Local side#=sidelength/2
Local large_angle#=360/numsides
Local small_angle#=large_angle/2.0
Local answer#= side/Tan(small_angle)
Return answer
EndFunction


Function draw_ngon#(x#,y#,numsides%,sidelength#,rotation#)' draws an ngon taking into account rotation
	Local small_angle# =360.0/numsides
	Local radius#=poly_radius(sidelength,numsides)
	
		For Local i=0 To numsides-1
		DrawLine x+Sin(i*small_angle+rotation)*radius,y-Cos(i*small_angle+rotation)*radius,x+Sin((i*small_angle)+small_angle+rotation)*radius,y-Cos((i*small_angle)+small_angle+rotation)*radius
		 
		Next
	
		
End Function 
Function inside_view(x#,y#)' checks to see that an instance is inside the play area
	If x>160 and x<480 and y>0 and y<480
		Return True
	Else
		Return False
	EndIf 
End Function
Function spawn#(parent_x#,parent_y#,parent_numsides#,parent_rotation#,parent_radius#) 'here is the problem code this should simulate random ngons whose edges snugly meet the boss core's edges.
' later this code will be used to make new boss fragments at a set rate and add them on to the boss polygone
'I'm just representing them now by drawing them

' define radi
Local new_side_number%=Rand(0,3)+3 ' make a new random sided ngon
Local new_radius#=poly_smallradius(32.0,new_side_number) 'find the inner radius of that new ngon
Local new_rot_angle#= 360.0/new_side_number ' find the size of the inner angles in the new ngon
Local parent_base_angle#=(360.0/parent_numsides) ' find the parent's inner angle measures
Local parent_final_angle#=parent_base_angle*Rand(parent_numsides)+parent_rotation ' find a random angle that bisects an enge
Local new_x#=parent_x+Cos(parent_final_angle)*(new_radius+parent_radius)' find the new x point of the new ngon
Local new_y#=parent_y-Sin(parent_final_angle)*(new_radius+parent_radius)' find the new y point of the new ngon
Local new_rotation#=parent_final_angle+new_rot_angle 'add the base angle to the new ngon's inner angle measurement
DrawLine parent_x,parent_y, new_x,new_y  ' draw a line so we can visually see the radius
draw_ngon(new_x,new_y,new_side_number,32,new_rotation)' draw the ngon to visuallize what a new ngon to visualize would look like
End Function



'here we will store the types



Type player 
	Global player_list:TList=New TList
	Field x#,y#,timer%=0
	' make a list to hold them
	
		
		Function Create(x,y)
		Local temp_ship:player=New player
		temp_ship.x=x
		temp_ship.y=y
			ListAddLast(player_list,temp_ship)
			
		End Function
		
		Method Draw()
		
	     SetColor 0,0,0 
	     draw_ngon(x,y,3,20,0)
	     
	     SetColor 0,0,0
			DrawOval x-1,y-1,3,3
		SetOrigin( 0,0 )	
		End Method
		
		Method Update()
			' take care of movement
			If KeyDown(KEY_LEFT)
				x:-2
			End If
			
			If KeyDown(KEY_RIGHT)
				x:+2
			End If
			
			If KeyDown(KEY_UP)
				y:-2
			End If
			
			If KeyDown(KEY_DOWN)
				y:+2
			End If
			If KeyDown(KEY_SPACE)and timer=2
			    player_shot.Create(x,y,Rand(29)+RndFloat#()+255)
				
				timer=0
			End If
			snap_view()
			If timer <2
				timer:+1
			End If
			Function snap_view()
			
' snaps objects to the borders of the views
If x<160
	x=160
End If

If y<0
	y=0
End If

If x >480
	x=480
End If

If y >480
	y=480
End If
	
End Function 
			Draw()
		End Method 
		
		Method Destroy()
		ListRemove(player_list,Self)	
		End Method
		
End Type ' this is the player's ship

Type player_shot
	Global player_shot_list:TList=New TList
	Field x#,y#,speed#=6,direction#
	
	Function Create(x#,y#,direction#)
		Local temp:player_shot=New player_shot
		temp.x=x
		temp.y=y
		temp.speed=4
		temp.direction=direction
		ListAddLast(player_shot_list,temp)
	EndFunction
	
	Method Draw()
	SetColor 0,0,0
		draw_ngon(x,y,5,5,direction+18)
		DrawLine x,y,x+Sin(direction+90)*13,y-Cos(direction+90)*13
	End Method
	Method Update()
		x:+Cos(direction)*speed
		y:+Sin(direction)*speed
		
			If inside_view(x,y)=False
				Destroy()
			End If
			
			
			Draw()
	End Method 
	
	Method Destroy()
		ListRemove(player_shot_list,Self)
	End Method
End Type ' this is the player's shot

Type boss_core 
	Global boss_core_list:TList=New TList
	
	Field x#,y#,side_number%,HP%,rotation#,small_radius#,large_radius#
	
	Function Create(x#,y#,HP#,side_number%,rotation#=0)
		Local temp:boss_core=New boss_core
		temp.x=x
		temp.y=y
		temp.HP=HP
		temp.side_number=side_number
		temp.small_radius=poly_smallradius(32,side_number)
		temp.large_radius=poly_radius(32,side_number)
		temp.rotation=rotation
		
		
			ListAddLast(boss_core_list,temp)
	EndFunction
	
	Method Draw()
	SetColor 0,0,0
		draw_ngon(x,y,side_number,32.0,rotation)
		
		spawn#(x,y,side_number,rotation,small_radius)' this normally wouldn;t be here but it's here to show the dynamic spawning.
	End Method 
	Method Update()
		Draw()
	End Method
	Method Destroy()
		ListRemove(boss_core_list,Self)
	End Method
	
     
	
End Type ' this is the center of theboss

Type boss_fragment
	Global boss_fragment_list:TList=New TList
	Field x,y,side_number%,HP%,rotation#,small_radius#,large_radius#
	
	Function Create(x#,y#,HP#,side_number%,rotation#)
		Local temp:boss_fragment=New boss_fragment
		temp.x=x
		temp.y=y
		temp.HP=HP
		temp.side_number=side_number
		temp.small_radius=poly_smallradius(32,side_number)
		temp.large_radius=poly_radius(32,side_number)
		
			ListAddLast(boss_fragment_list,temp)
	EndFunction
	Method Draw()
	SetColor 0,0,0
		draw_ngon(x,y,side_number,32,rotation)
		
	End Method 
	Method Update()
		Draw()
	End Method
	Method Destroy()
		ListRemove(boss_fragment_list,Self)
	End Method 
	
		
End Type  'this is a piece that will be spawned off the core and off each other

player.Create(320,420) ' make the first player
boss_core.Create(320,200,100,6,0.0) ' make the first boss_core
While not KeyDown(KEY_ESCAPE)
 Cls
' draw the background
SetColor 234, 226, 200 ' tyhis is te tan color
DrawRect 0,0,640,480






For Local i:player=EachIn(player.player_list)
	i.Update()
Next 
For Local i:boss_core=EachIn(boss_core.boss_core_list)
	i.Update()
Next 
For Local i:player_shot=EachIn(player_shot.player_shot_list)
	i.Update()
Next
For Local i:boss_fragment=EachIn(boss_fragment.boss_fragment_list)
	i.Update()
Next

SetColor 98,135,152
DrawRect 0,0,160,480
DrawRect 640-160,0,480,640
SetColor 255,255,255
DrawText score,12,12
Flip
Wend  'main game loop

I think everything works it shouldn't require external files.


Regular K(Posted 2006) [#2]
EDIT: your pic didnt show up the first time, my stuff is useless


Ryan Burnside(Posted 2006) [#3]
Well I do appreciate your interest, but the function is already done. These polygons are based on having the same side length. The problem lies in the rotation. and finding the angles that bisect the boss polygon.


TartanTangerine (was Indiepath)(Posted 2006) [#4]
EMail me and I'll tell you how I did it with GEOM.