CopyEntity

Blitz3D Forums/Blitz3D Programming/CopyEntity

Hello again, chaps!

I'm having trouble with CopyEntity, it seems.

I've made an array of types, the first field of which is supposed to be a pointer to a sprite. I have 2 functions -

1) which sets up each group of sprites
2) one which renders each group of sprites

The set-up function executes right every time (as far as I can tell), but when the render function tries to execute for the third time, it decides the entity it's trying to access doesn't exist. This, specifically, is the sprite image pointer.

All the other information contained within the type list is correct, as far as I can tell...

Is there any way to check the success or otherwise of the CopyEntity command? Or perhaps a way to lift the limit on the amount of entities I can create?

Thanks!

We really need to see some code.

You are only calling your setup function only once, right? i.e. outside the main loop.

Yup - only called once. It must be failing in there, though...

isn't there a CopySprite command?


isn't there a CopySprite command?


Nope.


I'm assuming that you first create the sprite entity then hide it and every instance of the sprite is simply a copyentity.

Are you freeing any sprites during the main loop and if so how are you doing it?

Some code would be good.

Stevie

Code, baby.


Or perhaps a way to lift the limit on the amount of entities I can create?



How many sprites are you trying to create? I seem to remember there being a sprite limit, though not what it is exactly. Anyway one would hope that if sprite creation failed for some reason the pointer returned would be zero though I do not think it is that graceful.

In fact I have just tried it and you would probably get a memory access violation at renderworld (here somewhere between 16000 and 17000 sprites!), so I do not think that is your problem.

Just for in case it's not the problem DJWoodgate just described:
When you use CopyEntity, it will return a handle. When the handle is zero, the entity wasn't created for some reason. Tho, this never happened to me.

Copyentity creates an instance of the original. Now when you remove the original, but keep the instance, there will be a new original. Although I am not sure if this is a ghost copy, somewhere stored intenally, or if it's gonna be one of the instances. If it's one of the instances, there may arise some problems when you continously delete the "new original" entity.

BTW: Whenever you free an entity in your code, you should set it's handle to zero. So you will be able at any time to check for the existance of an entity without to risk a MAV.

The code is below.

I'm not freeing any sprites yet - just trying to allocate about 50 of them, so far. The code below has some lines edited out because I was trying to work out what was happening with it, but I've drawn a blank so far.

Any ideas?

Graphics3D 800,600,16
SetBuffer BackBuffer()

Global Car1 = LoadSprite("Sprites\Army Truck Vert.bmp",52)
Global Car2 = LoadSprite("Sprites\Austin Vert.bmp",52)
Global Car3 = LoadSprite("Sprites\Buick Vert.bmp",52)
Global Car4 = LoadSprite("Sprites\Caddy Vert.bmp",52)
Global Car5 = LoadSprite("Sprites\Hot Dog Vert.bmp",52)
Global Car6 = LoadSprite("Sprites\Merc Vert.bmp",52)
Global Car7 = LoadSprite("Sprites\Muscle Car Vert.bmp",52)
Global Car8 = LoadSprite("Sprites\Police Car Vert.bmp",52)
Global Car9 = LoadSprite("Sprites\Sports Car Vert.bmp",52)
Global Car10= LoadSprite("Sprites\Viper Vert.bmp",52)

ScaleSprite Car1,1,2.3 
ScaleSprite Car2,1,2.3 
ScaleSprite Car3,1,2.3 
ScaleSprite Car4,1,2.3 
ScaleSprite Car5,1,2.3 
ScaleSprite Car6,1,2.3 
ScaleSprite Car7,1,2.3 
ScaleSprite Car8,1,2.3 
ScaleSprite Car9,1,2.3 
ScaleSprite Car10,1,2.3 

HideEntity Car1
HideEntity Car2
HideEntity Car3
HideEntity Car4
HideEntity Car5
HideEntity Car6
HideEntity Car7
HideEntity Car8
HideEntity Car9
HideEntity Car10

cam = CreateCamera() 
MoveEntity cam,0,0,-10 

Type Car
	Field CarHandle
	Field X
	Field Y
	Field Angle
End Type 

Const TotalRoads = 30

Dim Road.Car ( TotalRoads, 30 )
Dim TotalCars ( TotalRoads )	

CurrentRoad = 0

Const CarXSize# = 3
Const CarYSize# = 3
Const CarTypes = 10
Const CityGridLowerX = -50
Const CityGridLowerY = -50
Const CityGridHigherX = 50
Const CityGridHigherY = 50

x# = 0
y# = 0
z# = 5

size# = 1.0 

buildRoadGrid ()
;BuildRoad ( 0, 0, 10 )
;BuildRoad ( 1, 0, 10 )
BuildRoad ( 2, 0, 10 )
BuildRoad ( 3, 0, 10 )
BuildRoad ( 4, 0, 10 )


While Not KeyDown(1) 

	PositionEntity Car1, x#, y#, z#

	Color 255,255,255
	If KeyDown (203) Then X#=X#-0.1
	If KeyDown (205) Then X#=X#+0.1
	If KeyDown (200) Then Y#=Y#+0.1
	If KeyDown (208) Then y#=y#-0.1

	DrawRoad ( 2, 8 )
;	DrawRoad ( 1, 8 )
;	DrawRoad ( 2, 8 )
	DrawRoad ( 3, 8 )
	DrawRoad ( 4, 8 )

	VWait 
	RenderWorld
	Locate 0,0
	Print "x = "+X
	Print "y = "+Y
	Flip 

Wend 

End 

Function BuildRoadGrid ( )
	
	For i = 0 To TotalRoads
		For j = 0 To 30
			Road ( i, j ) = New Car
		Next
	Next
	
End Function

Function BuildRoad ( RoadNumber, RoadAngle#, CarTotal )

	CurrentX = Rand ( CityGridLowerX, CityGridHigherX )
	CurrentY = Rand ( CityGridLowerY, CityGridHigherY )

; Remove this bit!
	If CurrentX > 14
		CurrentX = 14
	EndIf
	If CurrentX < -14
		CurrentX = -14
	EndIf
	If CurrentY > 9
		CurrentY = 9
	EndIf
	If CurrentY < -9
		CurrentY = -9
	EndIf
;Remove this bit!

	XInc = 0	
	YInc = 0

	Random = Rand ( 0, 3 )
	
	Select True
		Case Random = 0
			XInc = -1
			YInc = 0
		Case Random = 1
			XInc = 1
			YInc = 0
		Case Random = 2
			YInc = -1
			XInc = 0
		Case Random = 3
			YInc = 1
			XInc = 0
	End Select 

	For i=0 To CarTotal
		Random = Rand (0, CarTypes)

;		Road ( RoadNumber, i ) = New Car
		Road ( RoadNumber, i )\CarHandle = 0
				
;		Print "Random = "+Random+" Road = "+RoadNumber+" Car = "+i
;		WaitKey
		
		Select True
			Case Random = 0
				Road ( RoadNumber, i )\CarHandle = CopyEntity ( Car1 )
			Case Random = 1
				Road ( RoadNumber, i )\CarHandle = CopyEntity ( Car2 )
			Case Random = 2
				Road ( RoadNumber, i )\CarHandle = CopyEntity ( Car3 )
			Case Random = 3
				Road ( RoadNumber, i )\CarHandle = CopyEntity ( Car4 )
			Case Random = 4
				Road ( RoadNumber, i )\CarHandle = CopyEntity ( Car5 )
			Case Random = 5
				Road ( RoadNumber, i )\CarHandle = CopyEntity ( Car6 )
			Case Random = 6
				Road ( RoadNumber, i )\CarHandle = CopyEntity ( Car7 )
			Case Random = 7
				Road ( RoadNumber, i )\CarHandle = CopyEntity ( Car8 )
			Case Random = 8
				Road ( RoadNumber, i )\CarHandle = CopyEntity ( Car9 )
			Case Random = 9
				Road ( RoadNumber, i )\CarHandle = CopyEntity ( Car10 )
		End Select		
		
;		If Road ( RoadNumber, i )\CarHandle = 0
;			Stop 
;		EndIf
				
		Road( RoadNumber, i )\X = CurrentX
		Road( RoadNumber, i )\Y = CurrentY
		
		Select True
			Case XInc = 1
				Road( RoadNumber, i )\Angle = ( 90 + RoadAngle# ) Mod 360
			Case XInc = -1
				Road( RoadNumber, i )\Angle = ( 270 + RoadAngle# ) Mod 360
			Case YInc = 1
				Road( RoadNumber, i )\Angle = ( 0 + RoadAngle# ) Mod 360
			Case YInc = -1
				Road( RoadNumber, i )\Angle = ( 180 + RoadAngle# ) Mod 360
		End Select
	
		CurrentX = CurrentX + ( ( XInc * Rand ( 1, 2 ) ) * CarXSize )
		CurrentY = CurrentY + ( ( YInc * Rand ( 1, 2 ) ) * CarYSize )
		
;		Print Road ( RoadNumber, i )\Angle
;		Print "X = "+CurrentX+" Y = "+CurrentY
;		WaitKey
	
	Next
	
End Function

Function DrawRoad ( RoadNumber, CarTotal )

	For i = 0 To CarTotal

;		RenderWorld
	
;		Locate 0,0
;		Print "RoadNumber = "+RoadNumber
;		Print "Car Number = "+i
;		Print "X = "+Road ( RoadNumber, i )\X+" Y = "+Road ( RoadNumber, i )\Y
	
		PositionEntity Road ( RoadNumber, i )\CarHandle, Road ( RoadNumber, i )\X, Road ( RoadNumber, i)\Y, 5
;		PositionEntity Car1, Road ( RoadNumber, i )\X, Road ( RoadNumber, i)\Y, 5

;		RotateSprite Road ( RoadNumber, i )\CarHandle, Road ( RoadNumber, i )\Angle
		RotateSprite Car1, Road ( RoadNumber, i )\Angle

;		PositionEntity road ( RoadNumber, i )\CarHandle, 0, 0, 5
		RenderWorld
;		Flip
;		WaitKey

	Next		
			
End Function


[code] or [codebox]

voila! :)

Random = Rand (0, CarTypes)


Here is the offending line. You're rolling a random number from 0 to 10 (an eleven-sided die!) When you call BuildRoad( 4, 0, 10 ), the random number generated is 10, which you have no Case for; thus, Road ( RoadNumber, i )\CarHandle remains 0 and you throw an "Entity Does Not Exist" error when you try to position it in DrawRoad().

The line should read Rand(0, CarTypes-1).

Array elements start at 0, so if you're using a constant to keep track of the number of something, you need to iterate from 0..COUNT-1 instead of 0..COUNT. You'll need to go through the rest of your code and fix things to reflect this fact. Here are examples of some of the changes you'll need to make:

Const TotalRoads = 30 ; this stays the same - it's more intuitive to keep track of the number of elements instead of the index of the last element

Dim Road.Car ( TotalRoads-1, 30-1 )
Dim TotalCars ( TotalRoads-1 )


	For i = 0 To TotalRoads-1
		For j = 0 To 30-1


One last thing: your Select...Case usage is non-standard - but it still works! You're doing this

Select True
	Case n = 0
	Case n = 1


but most people do this

Select n
	Case 0
	Case 1


Since both ways seem to work, this is only a style issue.

You may want to turn your Car1, Car2, etc. variables into an array like so:

Dim CarSpriteBlueprint(CarTypes-1)
CarSpriteBlueprint(0) = LoadSprite("Sprites\Army Truck Vert.bmp",52)
CarSpriteBlueprint(1) = LoadSprite("Sprites\Austin Vert.bmp",52)
CarSpriteBlueprint(2) = LoadSprite("Sprites\Buick Vert.bmp",52)
CarSpriteBlueprint(3) = LoadSprite("Sprites\Caddy Vert.bmp",52)
CarSpriteBlueprint(4) = LoadSprite("Sprites\Hot Dog Vert.bmp",52)
CarSpriteBlueprint(5) = LoadSprite("Sprites\Merc Vert.bmp",52)
CarSpriteBlueprint(6) = LoadSprite("Sprites\Muscle Car Vert.bmp",52)
CarSpriteBlueprint(7) = LoadSprite("Sprites\Police Car Vert.bmp",52)
CarSpriteBlueprint(8) = LoadSprite("Sprites\Sports Car Vert.bmp",52)
CarSpriteBlueprint(9) = LoadSprite("Sprites\Viper Vert.bmp",52)
For i = 0 To CarTypes-1
	ScaleSprite CarSpriteBlueprint(i),1,2.3
	HideEntity CarSpriteBlueprint(i)
Next


Then you can replace this:

		Random = Rand (0, CarTypes-1)
		Select True
			Case Random = 0
				Road ( RoadNumber, i )\CarHandle = CopyEntity ( Car1 )
			Case Random = 1
				Road ( RoadNumber, i )\CarHandle = CopyEntity ( Car2 )
			Case Random = 2
				Road ( RoadNumber, i )\CarHandle = CopyEntity ( Car3 )
			Case Random = 3
				Road ( RoadNumber, i )\CarHandle = CopyEntity ( Car4 )
			Case Random = 4
				Road ( RoadNumber, i )\CarHandle = CopyEntity ( Car5 )
			Case Random = 5
				Road ( RoadNumber, i )\CarHandle = CopyEntity ( Car6 )
			Case Random = 6
				Road ( RoadNumber, i )\CarHandle = CopyEntity ( Car7 )
			Case Random = 7
				Road ( RoadNumber, i )\CarHandle = CopyEntity ( Car8 )
			Case Random = 8
				Road ( RoadNumber, i )\CarHandle = CopyEntity ( Car9 )
			Case Random = 9
				Road ( RoadNumber, i )\CarHandle = CopyEntity ( Car10 )
		End Select


with this:

		Road ( RoadNumber, i )\CarHandle = CopyEntity ( CarSpriteBlueprint(Rand (0, CarTypes-1)) )


Excellent! That seems to have worked!

Thanks a lot! :)

Glad to be of help. :)

So - now I've got it working, having made all the changes you suggested, the routine for rendering the roads seems *crushingly* slow. Are sprites really slow in Blitz?

*confused* (again!)

Oh.

You only need to render once per frame. Remove the call to RenderWorld() in DrawRoad(). You only need to call it in your main game loop.

Sprites are too slow to use for particle effects because they don't share "surfaces," but you should be fine using them for actors (i.e. cars.)

Done that already - that was only there for debugging purposes. The main loop now looks like this:

While Not KeyDown(1) 

	If KeyDown (203) Then X#=X#-0.5
	If KeyDown (205) Then X#=X#+0.5
	If KeyDown (200) Then Y#=Y#+0.5
	If KeyDown (208) Then y#=y#-0.5
	If KeyDown (16)  Then z#=z#+0.5
	If KeyDown (17)  Then z#=z#-0.5
	PositionEntity cam,X#,Y#,Z# 

	For i = 0 To TotalRoads-1
		DrawRoad ( i, TotalCars-1 )
		RenderWorld
		Flip
	Next

Wend 


and the draw road function now looks like this:
Function DrawRoad ( RoadNumber, CarTotal )

	For i = 0 To CarTotal

		PositionEntity Road ( RoadNumber, i )\CarHandle, Road ( RoadNumber, i )\X, Road ( RoadNumber, i)\Y, 5
		RotateSprite Road ( RoadNumber, i )\CarHandle, Road ( RoadNumber, i )\Angle

	Next		

End Function


all looks OK to me?

Oops! Just noticed why! Doh! :)