A tank with 5 turrets (types)

Blitz3D Forums/Blitz3D Programming/A tank with 5 turrets (types)

slenkar(Posted 2004) [#1]
Hi I have a tank with 5 turrets and instead of writing out the info for all turrets within the type Id like to do an array of turret types within the tank type.

How would I do this?


big10p(Posted 2004) [#2]
I'm a bit rusty but you prolly want something like this:

Type turretType
	Field rotation#
	Field elevation#
End Type

Type tankType
	Field turrets.turretType[4]
End Type

tank.tanktype = New tanktype

For n = 0 To 4
	this.turretType = New turretType
	this\rotation = 45
	this\elevation = 10
	tank\turrets[n] = this
Next



slenkar(Posted 2004) [#3]
thanks \
how would i update the turrets during the game?


big10p(Posted 2004) [#4]
Well, following on from the above code, this will update the 4th turret:

tank\turrets[3]\rotation = 90
tank\turrets[3]\elevation = 45



slenkar(Posted 2004) [#5]
thanks that was what I was looking for

I just have a little problem understand this part:

For n = 0 To 4
this.turretType = New turretType
this\rotation = 45
this\elevation = 10
tank\turrets[n] = this
Next



Why does tank/turrets[n] = this?

Is it so the tank type knows which turret type belongs to it?


big10p(Posted 2004) [#6]
Yes. In the tankType definition, 'Field turrets.turretType[4]' simply says that "the field called 'turrets' is an array to hold pointers to 5 turretTypes". Then, in the For/next loop, we actually create the 5 turretType instances and store the pointers to them in the tankType array.


slenkar(Posted 2004) [#7]
thanks, is there any way of doing this but having the turrets the same type as the tank??

This would simplify things greatly.

If the turret was another tanktype


churchaxe(Posted 2004) [#8]
is it possible to get some more flexible design, say, if you sometimes want a tank to have just one turret, in other cases you'd want it to have 15 or so. Do you have to assume the worst case, and how much memory is wasted doing so (I mean for each unused turret element)?


Nacra(Posted 2004) [#9]
Slenkar, I think big10p gave what you requested. The following line shows a pretty easy access to the turrets and their properties.

tank\turrets[3]\rotation = 90

What other style of structure did you have in mind?



Cheers to big10p for an excellent, patient description!


slenkar(Posted 2004) [#10]
I need to use the same type for every object in the game, the method above is good but uses 2 different types,


big10p(Posted 2004) [#11]
mpausi: Yes, it is possible to make things more flexible - a couple of methods spring to mind. Sorry, but I'm in a bit of a rush at the mo but I'll try and get back with some code soon. Of course, anyone else is free to post their own methods in the meantime. :)

Slenkar: Not sure why you would need to contain everything in a single type but I guess you have your reasons. Given that restriction, the only why to achieve this is to 'hardcode' the various fields into a single type, like:

Type tankType
	tankName$
        turret1_rot#
        turret1_ele#
        turret2_rot#
        turret2_ele#
        turret3_rot#
        turret3_ele#
        turret4_rot#
        turret4_ele#
        turret5_rot#
        turret5_ele#
End Type


However, this is alot less flexible than using the array method as you can probably imagine. Actually, there are other ways like using a bank to hold the various turret properties and using peek/poke to read/write them, but this makes things unnecessarily complicated, IMO.

Nacra: You're more than welcome! ;)


John Pickford(Posted 2004) [#12]
If every tank has a max of MAX_TURRETS turrets and turrets are specific to tanks then there is no need for a separate type OR hardcoding each turret as separate pair of fields



then
const MAX_TURRETS=5

type tank

  field tank_name$
  field tank_x#
  field tank_y#
  field tank_z#
  field tank_rotation#
  
  field tank_number_of_turrets

  field turret_elevation#[MAX_TURRETS-1]
  field turret_rotation#[MAX_TURRETS-1]

end type



slenkar(Posted 2004) [#13]
thanks big10p for your help

So, J.P. you are saying put each turret characteristic in its own array?

I worked out how to do it by creating a type instance for each turret so they are destructible


big10p(Posted 2004) [#14]
JP: Yes, that is a more sensible way of keeping everything in a single type. Feel a bit of a plonker having missed that. :P As I said, I'm a bit rusty and see you have subtracted 1 when dimensioning a blitz array with a constant. I wasn't sure if blitz arrays worked this way or not so glad you put me straight on that, too. ;)

mpausi: this is one method of allowing tanks to have different amounts of turrets:

	Type turretType
		Field rotation#
		Field elevation#
		Field nextLink.turretType
	End Type
	
	Type tankType
		Field tankName$
		Field totalTurrets%
		Field turretList.turretType
	End Type
	
	; Create a tank.
	tank.tankType = New tankType
	tank\tankName$ = "Mega Crusher"

	; Add 5 turrets with random rotation and elevation.
	For n = 1 To 5
		add_turret(tank, Rand(360), Rand(45))
	Next

	; Display current tank settings.
	print_tank(tank)
	Print
	Print "Press a key to change rotation & elevation"
	Print "of turret 3 ..."	
	Print
	WaitKey()

	; Now change the rotation and elevation of turret 3.
	this.turretType = get_turret(tank, 3)
	this\rotation = 123
	this\elevation = 456
	
	; Display new tank settings.
	print_tank(tank)	
	WaitKey()

	; Kill the tank.
	free_tank(tank)

	End


;	
; Add a new turret to the specified tank.
;
Function add_turret%(tank.tankType, rotation#=0, elevation#=0)

	; Create a new turret type.
	newTurret.turretType = New turretType
	
	; Set initial turret settings.
	newTurret\rotation = rotation
	newTurret\elevation = elevation
	
	; Add turret to tank's linked list.
	newTurret\nextLink = tank\turretList
	tank\turretList = newTurret
	
	; Increment the total count of turrets belonging to this tank.
	tank\totalTurrets = tank\totalTurrets + 1
	Return tank\totalTurrets
	
End Function


;
; Return a pointer to the specified tank turret. 
;
Function get_turret.turretType(tank.tankType, turretNo%)

	; Return NULL pointer if turretNo is invalid.
	If (turretNo < 1) Or (turretNo > tank\totalTurrets) Then Return Null
	
	; Walk along turret linked list until we reach the requested turret.
	this.turretType = tank\turretList
	For n = tank\totalTurrets-1 To turretNo Step -1
		this = this\nextLink
	Next
	
	; Return pointer to the requested turret type.
	Return this

End Function


;
; free all memory used by a tank type.
;
Function free_tank(tank.tankType)

	; Free all the turrets.
	this.turretType = tank\turretList
	While this <> Null
		nextTurret.turretType = this\nextLink
		Delete this
		this = nextTurret
	Wend

	; Free actual tank.
	Delete tank

End Function


;
; Display settings of specified tank.
;
Function print_tank(tank.tankType)

	Print "Tank Name : " + tank\tankName$
	
	For n = 1 To tank\totalTurrets
		this.turretType = get_turret(tank, n)
		Print "Turret " + n + " : rotation=" + this\rotation + " elevation=" + this\elevation
	Next
	
End Function


Slenkar:

I worked out how to do it by creating a type instance for each turret so they are destructible



I'm a bit confused now - I thought you wanted to keep everything contained within a sigle type?!


slenkar(Posted 2004) [#15]
I did this:
for n=1 to number_of_tanks
t.tank=new tank
t\type =tank
t\hull40
for x=1 to 5
t.tank=new tank
t\type=turret
next
next



churchaxe(Posted 2004) [#16]
thanx alot, big10p, for your efforts. The linked list thing is a big one! But can you also delete one of the turret-instances in the middle of the list. How should the list be updated then?


big10p(Posted 2004) [#17]
lol, I knew you were going to ask for the ability to delete turrets - I toyed with the idea of including it originally. The reason I left it out is because it could lead to confusion, and here's why:

Say you initially create a tank with 5 turrets. They will be numbered sequentially from 1 to 5 so that you can use the get_turret() function to access a specific turret. Fine and dandy but if you then delete turret number 3, say, all the turrets above it 'drop down' the list so: what was turret 4 is now turret 3, and what was turret 5 is now turret 4.

Anyway, as long as you bear this in mind, here's the function to delete a turret:

;	
; Delete a turret from the specified tank.
;
Function delete_turret%(tank.tankType, turretNo%)

	; Return -1 if turretNo is invalid.
	If (turretNo < 1) Or (turretNo > tank\totalTurrets) Then Return -1

	; Walk along turret linked list until we reach the requested turret.
	this.turretType = tank\turretList
	prev.turretType = Null
	For n = tank\totalTurrets-1 To turretNo Step -1
		prev = this
		this = this\nextLink
	Next
	
	; Remove turret from linked list.
	If prev <> Null
		prev\nextLink = this\nextLink
	Else
		tank\turretList = this\nextLink
	EndIf
	
	; Free the turret type.
	Delete this
	
	; Decrease the total count of turrets belonging to this tank.
	tank\totalTurrets = tank\totalTurrets - 1
	Return tank\totalTurrets
	
End Function



churchaxe(Posted 2004) [#18]
wow, I find that extremely useful