move a object along a simple line, code example

BlitzMax Forums/BlitzMax Programming/move a object along a simple line, code example

pappavis(Posted 2006) [#1]
I thought this code might be usefull to others..

'// code to draw a line, then allow an object to travel along the line from start to end.
'// code by: Michiel Erasmus on 6-Jul-2006
'// contact: pappavis@..., website: http://netwerke.biz/pappavis
'//USAGE:
'//the clsLijn is an object which calculates coordinates to a target.  Its method getPlottedPath returns
'//a object list of X-Y cooridnates, just look at this example code.
Strict

Global objMain:clsMain= New clsMain;
objMain.AppInstance = objMain;
objMain.Main();


Type clsMain
	Field AppInstance:clsMain;
	Field dx:Int, dy:Int;
	Field player_x:Int = 400, player_y:Int = 500;
	Field enemy_x:Int = 240, enemy_y:Int = 260;
	Field vx:Double, vy:Double;
	Field distance:Int;
	Field intNextUpdate:Int;
	Field intTimerDelay:Int = 610;
	Field blnTerminate:Byte = False;
	
	Method Main()
		Print("------------------------------------------");
		Print("App startED: ");
		Self.InitVariables();
		intNextUpdate = MilliSecs() + intTimerDelay;		

		Local blnEerste:Byte = True;
		Local objPlottedPath:TList;
		Local objLyn1:clsLijn = New clsLijn;
		Local intTeller1:Int = 0;
		Local blnLogStarted:Byte = True; 
		Local intMissileSpeed1:Int = 0;
		objLyn1 = clsLijn.Create(); 
		objLyn1.WriteCoordsToFile = True;
		objPlottedPath = objLyn1.GetPlottedPath(10, 20, enemy_x, enemy_y, intMissileSpeed1); 
		
		While (not blnTerminate and not AppTerminate())
			If(KeyHit(KEY_ESCAPE))
				blnTerminate = Confirm( "Afsluiten?" );
			EndIf
			Cls();
			Local objTest1:clsLijnPos;
			Local currPosX:Int;
			Local currPosY:Int;
			Local intMouseX:Int
			Local intMouseY:Int
			
			If(KeyHit(KEY_SPACE))
				blnEerste = True;
				blnLogStarted = not blnLogStarted;
			EndIf
			If(KeyHit(KEY_Z))
				intMissileSpeed1:-2;
			EndIf
			If(KeyHit(KEY_X))
				intMissileSpeed1:+2;
			EndIf
			
			If(intMissileSpeed1 < 0)	
				intMissileSpeed1 = 0;
			EndIf
			
			If(blnEerste)								
				blnEerste = False;
				objTest1 = clsLijnPos(objPlottedPath.ValueAtIndex(intTeller1));
				currPosX = objTest1.x;
				currPosY = objTest1.y;
			EndIf
			
			If(MilliSecs() > intNextUpdate or intTeller1 < objPlottedPath.Count())
				objLyn1.WriteCoordsToFile = blnLogStarted;
				intNextUpdate = MilliSecs() + intTimerDelay;
				objTest1 = clsLijnPos(objPlottedPath.ValueAtIndex(intTeller1));
				currPosX = objTest1.x;
				currPosY = objTest1.y;
			EndIf
			
			If(intTeller1 > objPlottedPath.Count())
				intTeller1 = 0;
				objPlottedPath = objLyn1.GetPlottedPath(MouseX(), MouseY(), enemy_x, enemy_y, intMissileSpeed1);
			EndIf
            
			If(KeyHit(KEY_LEFT))
				enemy_x:-5;
			EndIf

			If(KeyHit(KEY_RIGHT))
				enemy_x:+5;
			EndIf
			If(KeyHit(KEY_UP))
				enemy_y:-5;
			EndIf

			If(KeyHit(KEY_DOWN))
				enemy_y:+5;
			EndIf
			 
			DrawOval(currPosX, currPosY, 40, 50);   
			DrawOval(enemy_x, enemy_y, 20, 10);   
			DrawText("INSTRUKSIE: Laat die muis op 'n posisie staan.  ESC om af te sluiten.", 5, 10);
			DrawText("Start: MouseX()=" + MouseX() + ", MouseY()=" + MouseY(), 5, 22);
			DrawText("Eind: enemy_x=" + enemy_x + ", enemy_x=" + enemy_y, 5, 34);
			DrawText("Loggen aan (SPASIE aan/uit): " + blnLogStarted, 405, 34);
			DrawText("Projektel spoed : " + intMissileSpeed1 + "  aanpas met Z of X", 5, 46);

			objLyn1.LineImproved(MouseX(), MouseY(), enemy_x, enemy_y);
			Flip(); 
			
			intTeller1:+1;
			'//End;
		Wend

		Print("App EIND ");
		Print("------------------------------------------");
	EndMethod

	Method InitVariables()
		'//Self.AppInstance._AllObjectsList:TList = New TList;
		AppTitle = "Eenvoudig lyn trek met Plot";
		'//Self.ShowTitles = True;
		'//Self.Lives = -1;
		'//Self.SpelGestart = False;
		
		graphics(800, 600, 0, 60);
		
		SetMaskColor 255,0,255
		AutoMidHandle(True);
	EndMethod
		
EndType       



'#Region ' plot 'n pad vir 'n kogel om langs te kan beweeg.



'///<summary>
'/// maak en bewaar coordinate van 'n lyn met 'n startX-Y en 'n eindX-Y.
'///</summary>
Type clsLijn
	Global AppInstance:clsMain;
	Global PlottedPathList:TList;
	Global posX:Double;	
	Global posY:Double;
	Global Counter:Int;
	Global WriteCoordsToFile:Byte;
	Global CoordsFilename:String;	
	
	Function Create:clsLijn()
		Local objLijn:clsLijn = New clsLijn;
		objLijn.posX = 0;
		objLijn.posY = 0;  
		objLijn.PlottedPathList = New TList;
		objLijn.WriteCoordsToFile = False;
		objLijn.CoordsFilename = "";
		
		Return objLijn;
		
	End Function

	'///<summary>
	'///Teken 'n lyn, code van http://www.cs.unc.edu/~mcmillan/comp136/Lecture6/Lines.html
	'///</summary>
	Method LineImproved(x0:Int, y0:Int, x1:Int, y1:Int)
		Local dx:Int, dy:Int, sdx:Int, sdy:Int, px:Int, dxabs:Int, dyabs:Int;
		Local slope:Float, py:Int, b:Int;
		Local dist:Int, plotX:Int, plotY:Int;
	
		Try			
			dx = x1 - x0;		'//aantal pixels op X-axis.
			dy = y1 - y0;		'//aantal pixels op y-axis
			
			If(Abs(dx) > Abs(dy))	'//slope <1
				Local m:Float = Float(dy) / Float(dx); '//sloap.
				Local b:Float = y0 - m * x0;
				
				If(dx < 0)
					dx = -1;
				Else
					dx = 1;
				EndIf
				
				While(x0 <> x1)
					x0 = x0 + dx;
					plotY = Int(m * x0 + b);
					Plot(x0, plotY);
				Wend
			Else
				If(dy <> 0)
					Local m:Float = Float(dx) / Float(dy); '//sloap.
					Local b:Float = x0 - m * y0;

					If(dy < 0)
						dy = -1;
					Else
						dy = 1;
					EndIf
					
					While(y0 <> y1)
						y0 = y0 + dy;
						plotX = Int(m * y0 + b);
						Plot(plotX, y0);
					Wend
				EndIf
			EndIf
		Catch Err1:String
			Print(Err1);
			Throw(Err1);
		EndTry
				
	End Method
	
	'///<summary>
	'///Teken 'n lyn, code van http://www.cs.unc.edu/~mcmillan/comp136/Lecture6/Lines.html
	'///</summary>
	Function GetPlottedPath:TList(x0:Int, y0:Int, x1:Int, y1:Int, MissileSpeed:Int)
		Local dx:Int, dy:Int, sdx:Int, sdy:Int, px:Int, dxabs:Int, dyabs:Int;
		Local slope:Float, py:Int, b:Int;
		Local dist:Int, plotX:Int, plotY:Int;
		Local coordCnt:Int = 0;
		Local intObjectUniqueID:Int = MilliSecs()
		Local strFilename:String = "regte lyn coords" + MilliSecs() + ".xml";
		
		Self.PlottedPathList = New TList;		
	
		Local logOut1:TStream;'// = New TStream;
		Local intSpoedCnt1:Int = 0;

		Try			
			If(MissileSpeed = Null)
				MissileSpeed  = 0;
			EndIf
			If(Self.WriteCoordsToFile)
				logout1 = WriteStream:TStream(strFilename);
				
				If(logout1 <> Null)
					logOut1.WriteLine("<?xml version='1.0' encoding='utf-8'?>");
					logOut1.WriteLine("<root>");
					logOut1.WriteLine("<debuggen id='" + MilliSecs() + "'>");
					logOut1.WriteLine(" <debug opmerking='StartX=" + x0 + ", StartY=" + y0 + "' value='' />");
					logOut1.WriteLine("  <debug opmerking='EindX=" + x1 + ", EindY=" + y1 + "'/>");
					logOut1.WriteLine("  <debug opmerking='GraphicsHeight: " + GraphicsHeight() + ", GraphicsWidth:" + GraphicsWidth() + "' value='' />");
					logOut1.WriteLine("</debuggen>");
				EndIf
			EndIf
			
			dx = x1 - x0;		'//aantal pixels op X-axis.
			dy = y1 - y0;		'//aantal pixels op y-axis
			
			If(Self.WriteCoordsToFile)
				logOut1.WriteLine("  <coordinates>");
			EndIf
			
			If(Abs(dx) > Abs(dy))	'//slope <1
				Local m:Float = Float(dy) / Float(dx); '//sloap.
				Local b:Float = y0 - m * x0;
				
				If(dx < 0)
					dx = -1;
				Else
					dx = 1;
				EndIf
				
				While(x0 <> x1)
					Local paths1:clsLijnPos = New clsLijnPos;
					'//paths1 = clsLijn.Create();
					
					x0 = x0 + dx;
					plotY = Int(m * x0 + b);
					
					paths1.x = x0;
					paths1.y = plotY;
					paths1.IsNegativeSlope = True;
					If(intSpoedCnt1 >= MissileSpeed)
						Self.PlottedPathList.AddLast(paths1);
						intSpoedCnt1 = 0;
					Else
						intSpoedCnt1:+1;
					EndIf
					'//Plot(x0, plotY);
					If(Self.WriteCoordsToFile)
						If(logout1 <> Null)
							logOut1.WriteLine("    <coordinate nummer='" + coordCnt + "' currPosX='" + paths1.x + "' currPosY='" + paths1.y + "'/>");
						EndIf
					EndIf
					
					coordCnt:+1;
				Wend
			Else
				If(dy <> 0)
					Local m:Float = Float(dx) / Float(dy); '//sloap.
					Local b:Float = x0 - m * y0;

					If(dy < 0)
						dy = -1;
					Else
						dy = 1;
					EndIf
					
					While(y0 <> y1)
						Local paths1:clsLijnPos = New clsLijnPos;
						'//paths1 = clsLijn.Create();
						
						y0 = y0 + dy;
						plotX = Int(m * y0 + b);
						
						paths1.x = y0;
						paths1.y = plotX;
						paths1.IsNegativeSlope = False;
						If(intSpoedCnt1 >= MissileSpeed)
							Self.PlottedPathList.AddLast(paths1);
							intSpoedCnt1 = 0;
						Else
							intSpoedCnt1:+1;
						EndIf
						
						'//Plot(plotX, y0);
						If(Self.WriteCoordsToFile)
							If(logout1 <> Null)
								logOut1.WriteLine("    <coordinate nummer='" + coordCnt + "' currPosX='" + paths1.x + "' currPosY='" + paths1.y + "'/>");
							EndIf
						EndIf 
						
						coordCnt:+1;
					Wend
				EndIf
			EndIf
			
			If(Self.WriteCoordsToFile)
				logOut1.WriteLine(" </coordinates>");
			EndIf
			
			If(Self.WriteCoordsToFile)
				If(logout1 <> Null)
					logOut1.WriteLine("    <debuggen id='" + MilliSecs() + "'>");
					logOut1.WriteLine("        <debug opmerking='aantal coordinaten' value='" + Self.PlottedPathList.Count() + "'/>");
					logOut1.WriteLine("        </debuggen>");
					logOut1.WriteLine("</root>");
					logOut1.Close();
				EndIf
			EndIf		
		Catch Err1:String
			Print(Err1);
			'// Throw(Err1);
		EndTry
        
		'//fokken hel, ek geen idee waarom x en y omgeruil is!
		'// na uren gesoek, het ek die kode gebak, blykbaar werk dit perfekt.
		If(Self.PlottedPathList <> Null)
			For Local objLynHerstel:clsLijnPos = EachIn Self.PlottedPathList
				Local tmpX1:Int = objLynHerstel.x;
				Local tmpY1:Int = objLynHerstel.y;
				
				If(not objLynHerstel.IsNegativeSlope)
					objLynHerstel.x = tmpY1;
					objLynHerstel.y = tmpX1;
				EndIf
			Next
		EndIf
		
		Return Self.PlottedPathList;
		
	End Function

	Function DrawTriangle(x:Int,y:Int,length:Int,height:Int)
		Local toppointx:Int = length/2+x'top point y is just y
		Local leftpointy:Int = y+height'left point x is just x
		Local rightpointx:Int = x+length
		Local rightpointy:Int = y+height
		DrawLine toppointx,y,x,leftpointy
		DrawLine x,leftpointy,rightpointx,rightpointy
		DrawLine rightpointx,rightpointy,toppointx,y
	EndFunction	
	
	Function GetAngle:Int(x0:Int, y0:Int, x1:Int, y1:Int)
		Local dx:Int = x1 - x0;		'//aantal pixels op X-axis.
		Local dy:Int = y1 - y0;		'//aantal pixels op y-axis
		Local anglet:Int = ATan2(dy,dx) + 90;
		If(anglet >= -89 and anglet <= -1)
			anglet = anglet + 360;
		EndIf
		
		Return anglet;
		
	End Function
EndType


Type clsLijnPos
	Field x:Int;
	Field y:Int;
	Field IsNegativeSlope:Byte;
	
	Function Create:clsLijnPos()
		Local objLPos1:clsLijnPos = New clsLijnPos;
		objLPos1.x = 0;
		objLPos1.y = 0;
		objLPos1.IsNegativeSlope = False;
		
		Return objLPos1;
	End Function
EndType




'#EndRegion





tonyg(Posted 2006) [#2]
I might be missing something but doesn't this do the same thing...

or here if you want a homing missile?