Using the value of an object in a list

BlitzMax Forums/BlitzMax Beginners Area/Using the value of an object in a list

I am making a simple strategy game of sorts, but I'm a little confused. I've gone the OOP path, and I have a type called TMiner, and a type called TBase, whose objects are stored in the list EntityList. When a TMiner is created I want that units x and y (fields of TMiner) coords to start at the TBase x and y (fields of TBase) coords. Trouble is, there is more than one base and I am not sure how to do in code: A miner has been created at base x therefor its position is the same as base x.
I need to do something like this: x=EntityList(12).x (12 being the position in the list that base might be.)
It's kind of hard to explain.

po,

I'll cover 3 OOP concepts and see if this is what you are trying to do:

OOP Concepts
Types
Instantiation
Constructors

You have Types Tminer and Tbase

When you instantiate (create an Object) from the miner Type, you want the x,y coordinates to be the same as the Base where he was created.

one way to do this is to create a special constructor function. With this function you can pass arguments to it (base coordinates) and also include setup info that all miners use (in my example-strength)

Type TMiner
   Field x:int
   Field y:int
   Field Strength:int

  ' constructor
  	Function Create:Tminer(basexpos , baseypos)
   		Local temp:Tminer = New Tminer
      	temp.x = basexpos
      	temp.y = baseypos
       temp.Strength = 100 ' default strength
      Return temp
  	End Function
  
End Type



call it by:
local newminer:Tminer = Tminer.create(mybase.x , mybase.y)


you can add it to your entitylist however you want (i.e listaddlast)

Here's some of my code. Your code works, bradford6, but my problem is that I don't really know the x and y coords of base x yet, so I can't create miners. Because there won't be just one base, I need to figure out a way to select the base you want to use to create your miner. I'm starting to think the only way I can do this is using arrays of types, but this isn't as good in realtime than lists. With arrays I can identify an element by its index, which could be the coords of my mouse for example. I don't see a way of doing this with lists, though.

Type TEntity

	Global EntityList:TList=New TList
	
	Method Draw() Abstract
	
	Method New()
		EntityList.AddLast(Self)
	End Method

End Type

Type TMiner Extends TEntity

	Field x#,y#
	Field capacity:Int
	Field basex:Int,basey:Int
	
	Method Draw()
	
		SetColor(0,255,255)
		DrawOval(10,10,x#,y#)
	
	End Method	
	
	Method New()
		x#=TBase.x;y#=TBase.y	'this doesn't work
		basex=x#;basey=y#	'the same as above	
	End Method
	
	Function Create:TMiner(capacity:Int)
		Local m:TMiner=New TMiner			
			m.capacity=capacity						
		Return m	
	End Function

End Type

Type TBase Extends TEntity

	Field x:Int,y:Int		

	Method Draw()
	
		SetColor(0,0,255)
		DrawRect(100,100,x,y)
	
	End Method	
	
	Function Create:TBase(x:Int,y:Int)
		Local b:TBase=New TBase			
			b.x=x;b.y=y							
		Return b	
	End Function

End Type


x = TBase(EntityList.ValueAtIndex(12)).x

or rather
Local Base:TBase = TBase(EntityList.ValueAtIndex(12))
x=Base.x
y=Base.y


po,

in your code example above:
x#=TBase.x;y#=TBase.y 'this doesn't work

there is not such thing as TBase.x (think of the Type Tbase as template, you have not created an instance yet)


anyway, you could use a TMAP to hold Miner/Base pairs for you:

Global entitylist:TList = CreateList()
Global MinerBase:Tmap = CreateMap()

Type TMiner
   Field x,y

  ' constructor
  	Function Create:Tminer(base:Tbase)
   		Local temp:Tminer = New Tminer
      	temp.x = base.x
      	temp.y = base.y
		ListAddLast(entitylist,temp)
		MapInsert(MinerBase,temp,base) ' key=miner  value = base
		
      Return temp
  	End Function
  

	Method GetBase:Tbase()
	    Local foo:Object = MapValueForKey(MinerBase , Self )
		Return Tbase(foo)
	End Method
	
	
End Type


Type Tbase
	Field x:Int
	Field y:Int
	Field name:String
End Type


Local mybase:Tbase = New Tbase
mybase.x = 10
mybase.y = 20
mybase.name = "FreeBase"

Local exampleminer:Tminer = Tminer.create(mybase)

For t:Tminer = EachIn entitylist
	Print t.x
	Print t.y
	Print t.getbase().name
	'Print gotbase.name
Next




Works for me bradford6...
Type TBase
	Field X:Int = 100
EndType

Local List:TList = New TList
List.AddLast(New TBase)

Print TBase(List.ValueAtIndex(0)).x

*EDIT* sorry my mistake mate, thought you was talking about my post... :/

REDi,
no problem, I edited my post to make it more clear what i was referring to.

I like your solution. very nice. I went a little overboard, I hope I did not just confuse the issue.

po,
is that what you needed?

Yes, thanks, but I have a bit of a different problem. For example, say I want the user to click on a base, which they can then create miner units from that base. Problem is, how do I identify that particular base? What if there are 10 bases, how do I pick out of EntityList the right one?

The first thing you'll need to know is if a base has been clicked, to do this you need to cycle through the entity list and check if the mouse is above each base, when you get a positive result you'll know exactly which base it was.

A little example of how you might do it...
If MouseHit(1)														' if mouse was pressed
	Local This:TBase
	For This = EachIn EntityList									' cycle through each base
		If MouseInRect(This.X, This.Y, This.Width, This.Height)		' and check if mouse is above it
			This.CreateMiner()										' yes this base was clicked! lets create a miner :)
		EndIf
	Next
EndIf

Function MouseInRect(X%,Y%,W%,H%)
	Local MX%=MouseX(), MY%=MouseY()
	If MX=>X And MY=>Y And MX=<X+W And MY=<Y+H Then Return True
EndFunction


Ah, that makes sense. Thanks!