noobs & PointEntity

BlitzMax Modules Forums/MiniB3D/noobs & PointEntity

it's a bit complex to explane it but i'll try.

i've a series of 5 planets placed in line
actually those are defined as object, and are an array.
i've placed the camera a bit distant to see all planets, but i wish that on the mouse click the camera zoom on the picked entity.

to made this i've made a function "CameraMover"
Function CamMover:Int(cam:TCamera, X:Int , Y:Int , Z:Int,target:TEntity, Speed:Int=5) 
	'================== X =========================================================
	Local vX:Int, vY:Int, vZ:Int
	PointEntity(cam, target)
	If EntityX(cam) < X Then
		vX= X - EntityX(Cam) 
		If vX => speed Then
			PositionEntity (cam , EntityX(Cam) + speed , EntityY(Cam) , EntityZ(Cam) )
		End If
	Else	
		vX = EntityX(Cam) - X
		If vX => speed Then
			PositionEntity (cam , EntityX(Cam) - speed , EntityY(Cam) , EntityZ(Cam) )
		End If
	End If
	'================== Y =========================================================
	If EntityY(cam) < Y Then
		vY = Y - EntityY(Cam) 
		If vY => speed Then
			PositionEntity (cam , EntityX(Cam), EntityY(Cam) + speed , EntityZ(Cam) )
		End If
	Else	
		vY = EntityY(Cam) - Y
		If vY => speed Then
			PositionEntity (cam , EntityX(Cam), EntityY(Cam) - speed , EntityZ(Cam) )
		End If
	End If
	'================== Z =========================================================
	If EntityZ(cam) < Z Then
		vZ = Z - EntityZ(Cam) 
		If vZ => speed Then
			PositionEntity(cam , EntityX(Cam), EntityY(Cam) , EntityZ(Cam) + speed )
		End If
	Else	
		vZ = EntityZ(Cam) - Z
		If vZ => speed Then
			PositionEntity (cam , EntityX(Cam), EntityY(Cam) , EntityZ(Cam) - speed)
		End If
	End If
	DebugLog "vx:"+ vX +" vY:"+ vY +" xZ:"+ vZ
	If vX <= speed And vY <= speed And vZ <= speed Then
		Return 1
	Else
		Return 0
	End If
End Function

the function will return 1 when meet the destination.
It will be placed on the main loop, so the user will see the camera movement and will fly through the solar system.

i've to say also that i've declared a properties mesh on the object planets so i can reach it when i need, just like in this case.

Type tPlanet 
	Field ID:Int
	Field Name:String

	Field posX:Int
	Field posY:Int
	Field posZ:Int
	
	Field mass:Int					'planet size
	Field mesh:TEntity
        ...


and then the main code, inside the loop there is a check
if the user click on a planet moveCamera will be = 1 and then ...
If moveCamera = 1 Then
	If camMover(cam , camDest.X, camDest.Y , camDest.Z, Planet[Int(EntityName(entityPickata) )].mesh , 20) = 1 Then MoveCamera = 0
End If


but the problem is with PointEntity 'cause i get a Null object error.
Unhandled Exception:Attempt to access field or method of Null object

i hate this error <_<'

Either your camera or object doesn't exist when you call PointEntity.

camera as been created out of the main cycle and
same is for the planets, I've made it just to avoid that kind of problems :-\

'====================================================== 3D Setup ====	
Graphics3D 1000 , 800 , 32 , 0
'Dither True
AntiAlias True
'====================================================== Light =======
	Local light:TLight = CreateLight(2)
	LightRange light , 200000
	AmbientLight 10,10,10
'====================================================== Camera ======
	Global cam:TCamera = CreateCamera() 
	'CameraFogMode cam,1
	'CameraFogRange cam,0,1000
	'========== CAM =============
	Local camX:Int  =  -1800 	'\___ all'alngolo 45°
	Local camY:Int  =	2500		'/
	Local camZ:Int  =	4150
	Local pitch:Int =	  21
	Local yaw:Int   =	-130
	Local roll:Int  =	   0
	Local zoom:Float  =    1.0
	Local mode:Int  =    1
	Local modeDesc:String = "Perspective"

	Local cam_range:Int = 500000
	
	PositionEntity cam , camX , camY , camZ
	RotateEntity cam , pitch , yaw , roll
	CameraRange cam,1,cam_range
	CameraProjMode cam , mode

	Global moveCamera:Int = 0	  	' this is for the camera movement
	Global camDest:tDest			' this is an object to save the coords for the 
	camDest = New tDest				' camera destination... 


	usrSys.drawSystem(usr.SystemID) 	' this generate the planets, by reading a database

'======================================================= CICLO PRINCIPALE ==============
	
While Not KeyDown(KEY_ESCAPE)		
'	keyReset() 
	
	RenderWorld
	
	Local entityPickata:tEntity = PickedEntity()
	If(entityPickata <> Null) 
		If MouseHit(1) Then
			moveCamera = 1
			camDest.X = EntityX(entityPickata, True)
			camDest.Y = EntityY(entityPickata, True)
			camDest.Z = EntityZ(entityPickata, True)
			camDest.Name = Pianeta[Int(EntityName(entityPickata) )].name
		End If
	End If

	If moveCamera = 1 Then
		If camMover(cam , camDest.X, camDest.Y , camDest.Z, Pianeta[Int(EntityName(entityPickata) )].mesh , 20) = 1 Then MoveCamera = 0
	End If
Wend
End 


ok here is, in short words what the maincode are
the drawSystem have a method that will create the 5 planets

In this code you never call a CameraPick, so EntityPickata is always Null.

Maybe this code helps you (its a bit buggy due to fast production) ;)

Import sidesign.minib3d

Type TPlanet
	Global PlanetList:TList = New TList
	Global ChoosenPlanet:TPlanet = Null
	Global Flyto:Byte = False
	
	Field Mesh:TMesh
	Field Pivot:TPivot
	Field Radius
	
	Method New()
		PlanetList.Addlast(Self)
	End Method
	
	Function Create:TPlanet(X:Int,Y:Int,Z:Int,Radius:Float)
		Local P:TPlanet = New TPlanet
		P.Mesh = CreateSphere()
		P.Pivot = CreatePivot(P.Mesh)
		ScaleEntity P.Mesh,Radius,Radius,Radius
		PositionEntity P.Mesh,X,Y,Z
		EntityColor P.Mesh,Rnd(255),Rnd(255),Rnd(255)
		EntityPickMode P.Mesh,2
		P.Radius = Radius
		Return P
	End Function
	
	Function IsPicked:TPlanet(Camera:TCamera)
		CameraPick Camera,MouseX(),MouseY()
		Local ent:TMesh = TMesh(PickedEntity())
		If ent <> Null Then
			For Local P:TPlanet = EachIn PlanetList
				If P.Mesh = ent Then
					ChoosenPlanet = P
					If Flyto = False Then Flyto = True
				End If
			Next
		End If
	End Function 
	
	Method MoveTo(Cam:TCamera)
		smoothcam(cam,pivot,mesh,400)
		MoveEntity Cam ,.2,0.0,0.0
	End Method
	
	Function Update(Cam:TCamera)
		If ChoosenPlanet <> Null Then
			smoothcam(cam,choosenplanet.pivot,choosenplanet.mesh,400)
			If EntityDistance(Cam,ChoosenPlanet.Mesh) < ChoosenPlanet.Radius*2 Then 
						FlyTo = False
						ChoosenPlanet = Null
			EndIf
			If Flyto = True Then ChoosenPlanet.MoveTo(Cam)
		End If
	End Function
	
End Type

Function smoothcam(cam:TCamera,pivot:TEntity,target:TEntity,camspeed:Float = 5.0)

Local curx#=EntityX(cam)
Local curz#=EntityZ(cam)
Local destx#=EntityX(pivot,True)
Local destz#=EntityZ(pivot,True)

curx#=curx#+((destx#-curx#)/camspeed)
curz#=curz#+((destz#-curz#)/camspeed)
Local cury:Float = EntityY(pivot, True)

PositionEntity cam,curx#,cury#,curz#

PointEntity cam,target
End Function




Graphics3D 800,600,32,2

Local Cam:TCamera = CreateCamera()
CameraRange Cam,1.0,5000
Local Pivot = CreatePivot()
PositionEntity Pivot,0,0,4
EntityParent Pivot,Cam

PositionEntity cam,0,0,-1500

For Local X = -1000 To 1000 Step 300
	TPlanet.Create(X,0,0,Rnd(10,190))
Next

Local mxs#=0
Local mys#=0
Local move#=20.5
MouseXSpeed() ' flush
MouseYSpeed() ' flush


While Not KeyHit(KEY_ESCAPE)

	If MouseDown(2) Then 
			mxs#=mxs#+(MouseXSpeed()/5.0)
			mys#=mys#+(MouseYSpeed()/5.0)
		
			RotateEntity cam , mys# , - mxs# , 0
			
			MoveMouse 400,300
			MouseXSpeed() ' flush
			MouseYSpeed() ' flush
	End If
		
	If KeyDown(KEY_UP)=True Then 
			MoveEntity cam,0,0,move# ' move camera forward
			TPlanet.FlyTo = False
			TPlanet.ChoosenPlanet = Null
	EndIf
	
	If KeyDown(KEY_DOWN)=True Then 
			MoveEntity cam,0,0,-move# ' move camera back
					TPlanet.FlyTo = False
			TPlanet.ChoosenPlanet = Null
	EndIf
	

	If KeyDown(KEY_LEFT)=True Then 
			MoveEntity cam,-move#,0,0 ' move camera left
					TPlanet.FlyTo = False
			TPlanet.ChoosenPlanet = Null
	EndIf
	
	If KeyDown(KEY_RIGHT) = True Then 
			MoveEntity cam , move# , 0 , 0 ' move camera right
					TPlanet.FlyTo = False
			TPlanet.ChoosenPlanet = Null
	EndIf
	
	
	

	If MouseHit(1) Then TPlanet.IsPicked(Cam)
	TPlanet.Update(Cam)
	RenderWorld
	
	Flip
Wend

Function MouseXSpeed()
		Global oldmx
		Local mxs=MouseX()-oldmx
		oldmx=MouseX()
		Return mxs
	End Function
	
	Function MouseYSpeed()
		Global oldmy
		Local mys=MouseY()-oldmy
		oldmy=MouseY()
		Return mys
	End Function
	
	Function MouseZSpeed()	
		Global oldmz
		Local mzs=MouseZ()-oldmz
		oldmz = MouseZ()
		Return mzs
	End Function



oh that's good thx alot :)