Seite 1 von 1

Kreiskollision

Verfasst: 12.05.2008 09:14
von Andreas_S
Ich hab da eine Simulation für eine Kreiskollision geschrieben, ist zwar noch von der Übersicht verbesserbar, aber sonst sieht sie, denk ich, ganz realistisch aus...

Code: Alles auswählen

EnableExplicit


#Deg2Rad	= #PI/180
#Rad2Deg	= 180/#PI

#Screen_Width	= 1280		; <--- Ändern
#Screen_Height	=  800		; <--- Ändern
#Screen_Depth	=   32		; <--- Ändern
#Screen_Title	= "Kreiskollision"

Enumeration
	#Sprite_Circle_Static
	#Sprite_Circle_Ball
	
	#Sprite_Mouse
EndEnumeration

#Sprite_Circle_Static_Width	= 500
#Sprite_Circle_Static_Height	= 500

#Sprite_Circle_Ball_Width	=  50
#Sprite_Circle_Ball_Height	=  50

#Sprite_Mouse_Width		= 10
#Sprite_Mouse_Height	= 10


Structure Circle
	x0.d
	y0.d
	r.d
	
	vx0.d
	vy0.d
	
	x.d
	y.d
	xM.d
	yM.d
	
	vx.d
	vy.d
	
	ax.d
	ay.d
EndStructure


Procedure pythagorasK(h1.d, h2)
	ProcedureReturn Sqr(h1 * h1 + h2 * h2)
EndProcedure

Procedure high(num1.d, num2.d)
	If num1 > num2
		ProcedureReturn num1
	Else
		ProcedureReturn num2
	EndIf
EndProcedure
Procedure low(num1.d, num2.d)
	If num1 < num2
		ProcedureReturn num1
	Else
		ProcedureReturn num2
	EndIf
EndProcedure

Procedure normal(x1, y1, x2, y2, toX.d, width, rgb=0)
	Protected dx, dy, k.d, alfa.d, xx.d, yy.d
	
	dx = x2 - x1
	dy = y2 - y1
	
	k = dy / -dx
	
	alfa = ATan(k)
	
	xx = Sin(alfa) * width/2
	yy = Cos(alfa) * width/2
	
	Line(x1 + (toX - xx), y1 - (yy + k * toX), 2*xx, 2*yy, rgb)
EndProcedure


Define Circle_Static.Circle
	Circle_Static\r	= #Sprite_Circle_Static_Width/2
	Circle_Static\x0	= #Screen_Width/2 - Circle_Static\r
	Circle_Static\x	= Circle_Static\x0
	Circle_Static\xM	= Circle_Static\x + Circle_Static\r
	Circle_Static\y0	= #Screen_Height/2 - Circle_Static\r
	Circle_Static\y	= Circle_Static\y0
	Circle_Static\yM	= Circle_Static\y + Circle_Static\r

Define Circle_Ball.Circle
	Circle_Ball\r		= #Sprite_Circle_Ball_Width/2
	Circle_Ball\x0		= #Screen_Width - 2 * Circle_Ball\r
	Circle_Ball\x		= Circle_Ball\x0
	Circle_Ball\xM		= Circle_Ball\x + Circle_Ball\r
	Circle_Ball\y0		= 105
	Circle_Ball\y		= Circle_Ball\y0
	Circle_Ball\yM		= Circle_Ball\y + Circle_Ball\r
	
	Circle_Ball\vx0	= -70
	Circle_Ball\vx		= Circle_Ball\vx0
	
	;Circle_Ball\ay		= 40


Define dx.l, dy.l
Define distance.d
Define k.d
Define alfa.d

Define dbx.l, dby.l
Define kb.d
Define alfab.d

Define dmx.l, dmy.l
Define distancem.d
Define km.d
Define alfam.d

Define time.d, time_start, time_yet
Define reached.b

Define sum.d, calcX.d, calcY.d, factor.d, a.d, b.d

Define mx.l, my.l


InitSprite()
InitKeyboard()
InitMouse()


OpenScreen(#Screen_Width, #Screen_Height, #Screen_Depth, #Screen_Title)
	CreateSprite(#Sprite_Circle_Static, #Sprite_Circle_Static_Width, #Sprite_Circle_Static_Height)
		StartDrawing(SpriteOutput(#Sprite_Circle_Static))
			Circle(#Sprite_Circle_Static_Width/2, #Sprite_Circle_Static_Height/2, #Sprite_Circle_Static_Width/2, RGB(255, 0, 0))
		StopDrawing()
	CreateSprite(#Sprite_Circle_Ball, #Sprite_Circle_Ball_Width, #Sprite_Circle_Ball_Height)
		StartDrawing(SpriteOutput(#Sprite_Circle_Ball))
			Circle(#Sprite_Circle_Ball_Width/2, #Sprite_Circle_Ball_Height/2, #Sprite_Circle_Ball_Width/2, RGB(255, 255, 0))
		StopDrawing()
	
	CreateSprite(#Sprite_Mouse, #Sprite_Mouse_Width, #Sprite_Mouse_Height)
		StartDrawing(SpriteOutput(#Sprite_Mouse))
			Line(0, #Sprite_Mouse_Height/2, #Sprite_Mouse_Width, 0, RGB(255, 255, 255))
			Line(#Sprite_Mouse_Width/2, 0, 0, #Sprite_Mouse_Height, RGB(255, 255, 255))
		StopDrawing()
	
	
	time_start = ElapsedMilliseconds()
	Repeat
		mx = MouseX()
		my = MouseY()
		
		
		Circle_Ball\xM = Circle_Ball\x + Circle_Ball\r
		Circle_Ball\yM = Circle_Ball\y + Circle_Ball\r
		
		
		dmx = mx - Circle_Static\xM
		dmy = my - Circle_Static\yM
		
		km = dmy / dmx
		
		alfam = ATan(km)
		
		If (dmx < 0 And dmy > 0) Or (dmx < 0 And dmy < 1)
			alfam + #PI
		EndIf
		If dmx = 0 And dmy = 0
			alfam = 0
		EndIf
		
		
		dbx = Circle_Ball\vx
		dby = Circle_Ball\vy
		
		kb = dby / dbx
		
		alfab = ATan(kb)
		
		If (dbx < 0 And dby > 0) Or (dbx < 0 And dby < 1)
			alfab - #PI
		EndIf
		If dbx = 0 And dby = 0
			alfab = 0
		EndIf
		
		
		dx = Circle_Ball\xM - Circle_Static\xM
		dy = Circle_Ball\yM - Circle_Static\yM
		
		k = dy / dx
		
		alfa = ATan(k)
		
		If (dx < 0 And dy > 0) Or (dx < 0 And dy < 1)
			alfa + #PI
		EndIf
		If dx = 0 And dy = 0
			alfa = 0
		EndIf
		
		
		distance = pythagorasK(dx, dy)
		
		If distance < Circle_Static\r + Circle_Ball\r
			a = Circle_Static\r + Circle_Ball\r + 1
			
			Circle_Ball\x = Circle_Static\xM + Cos(alfa) * a - Circle_Ball\r
			Circle_Ball\y = Circle_Static\yM + Sin(alfa) * a - Circle_Ball\r
			Circle_Ball\x0 = Circle_Ball\x
			Circle_Ball\y0 = Circle_Ball\y
			
			reached = 1
		EndIf
		
		
		FlipBuffers()
		ClearScreen(RGB(0, 0, 0))
		
		DisplayTransparentSprite(#Sprite_Circle_Static, Circle_Static\x, Circle_Static\y)
		DisplayTransparentSprite(#Sprite_Circle_Ball, Circle_Ball\x, Circle_Ball\y)
		DisplayTransparentSprite(#Sprite_Mouse, mx - #Sprite_Mouse_Width/2, my - #Sprite_Mouse_Height/2)
		
		
		If MouseButton(#PB_MouseButton_Left)
			Circle_Ball\x = mx - Circle_Ball\r
			Circle_Ball\y = my - Circle_Ball\r
			Circle_Ball\x0 = Circle_Ball\x
			Circle_Ball\y0 = Circle_Ball\y
			
			time_start = ElapsedMilliseconds()
			
			Circle_Ball\vx0 = MouseDeltaX() * 10
			Circle_Ball\vy0 = MouseDeltaY() * 10
			Circle_Ball\vx = Circle_Ball\vx0
			Circle_Ball\vy = Circle_Ball\vy0
		Else
			If Not reached
				Circle_Ball\vx = Circle_Ball\vx0 + Circle_Ball\ax * time
				Circle_Ball\vy = Circle_Ball\vy0 + Circle_Ball\ay * time
				
				Circle_Ball\x = Circle_Ball\x0 + Circle_Ball\vx0 * time + (Circle_Ball\ax * time * time)/2
				Circle_Ball\y = Circle_Ball\y0 + Circle_Ball\vy0 * time + (Circle_Ball\ay * time * time)/2
			Else
				sum = Abs(Circle_Ball\vx) + Abs(Circle_Ball\vy)
				a = 2*alfa - alfab
				b = Abs(Circle_Ball\vx) + Abs(Circle_Ball\vy)
				
				calcX = -Cos(a) * b
				calcY = -Sin(a) * b
				
				factor = sum / (Abs(calcX) + Abs(calcY))
				If Abs(calcX) + Abs(calcY) = 0
					factor  = 0
				EndIf
				
				Circle_Ball\vx = calcX * factor
				Circle_Ball\vy = calcY * factor
				
				
				time_start	= ElapsedMilliseconds()
				time			= 0
				
				Circle_Ball\vx0 = Circle_Ball\vx
				Circle_Ball\vy0 = Circle_Ball\vy
				
				a = Circle_Static\r + Circle_Ball\r
				
				Circle_Ball\x0 = Circle_Static\xM + Cos(alfa) * a - Circle_Ball\r
				Circle_Ball\y0 = Circle_Static\yM + Sin(alfa) * a - Circle_Ball\r
				
				Circle_Ball\x = Circle_Ball\x0
				Circle_Ball\y = Circle_Ball\y0
				
				reached = 0
			EndIf
		EndIf
		
		
		If IsScreenActive()
			StartDrawing(ScreenOutput())
				LineXY(Circle_Static\xM, Circle_Static\yM, Circle_Ball\xM, Circle_Ball\yM, RGB(0, 255, 0))
				normal(Circle_Static\xM, Circle_Static\yM, Circle_Ball\xM, Circle_Ball\yM, Cos(alfa) * Circle_Static\r, 400, RGB(255, 255, 255))
				DrawText(0, 0, StrD(distance - 275))
				DrawText(0, 30, Str(Circle_Ball\xM) + " , " + Str(Circle_Ball\yM))
				DrawText(0, 60, StrD(alfa * #rad2deg))
				DrawText(0, 90, StrD(alfab * #rad2deg))
				
				LineXY(Circle_Static\xM, Circle_Static\yM, mx, my, RGB(127, 127, 127))
				normal(Circle_Static\xM, Circle_Static\yM, mx, my, Cos(alfam) * Circle_Static\r, 400, RGB(127, 127, 127))
			StopDrawing()
		EndIf
		
		
		Delay(1)
		
		ExamineKeyboard()
		ExamineMouse()
		
		time_yet = ElapsedMilliseconds()
		time = (time_yet - time_start) / 1000
	Until KeyboardPushed(#PB_Key_Escape)
CloseScreen()

Andreas

Verfasst: 12.05.2008 09:59
von Vermilion
Funktioniert einwandfrei. Ist ganz cool... Inspiriert! :allright: