Types added to a TList not unique?

BlitzMax Forums/BlitzMax Programming/Types added to a TList not unique?

pappavis(Posted 2006) [#1]
Something is truly puzzling me. It seems to me that Types added to a TList is not unique.

I am trying to figure out OOP programming in Blitmax.

I have an idea to (eventually) make a Ikari Warriors-style game--> Your player walks vetical scrolling, with enemys hiding behind trees, or in ditches.
My specific trouble is in the detection of player/enemy objects. What happens (in most games) is that when your player object comes nears a enemy, it will shoot at your player object.
Now this is where the trouble exists: my player object get shot at, by objects which shouldnt be shooting at it! Enemies should shoot at my player when its <= 120 pixels from it. Problem is, enemys which are 500 pixels away will also shoot. Huh?!?

What i do do is:
1. Create a Tlist object TMainAll.
2. Add 2 individual Types of clsEnemySoldier extends clsgameObject to TMainAll.
3. Add playerObject which extends clsgameObject to TMainAll.
4. While waiting for ESC key, call Update() on each object in the TMainAll.

This seems nothing strange, eh?

Looking at the clsEnemySoldier' Update() method:


Type clsMain
  Global TMainAll:TList = New Tlist
  Method Main()
    Graphics(800, 600, 16, 0);
    While Not Keyhit(key_ESCAPE)
      Cls();
      For Local objEverything:clsGameObject = EachIn Self.TMainAll
         objEverything.Update()
      Next
      Flip();
    Wend
  EndMethod

  Method InitGame()
    Local objEnemy1:clsEnemySoldier = clsEnemySoldier.Create() '// static method
    objEnemy1.image = LoadImage("enemy1.gif");
    objEnemy1.X = 380;
    objEnemy1.Y = 530;
    Self.TMainAll.AddLast(objEnemy1);

    Local objEnemy2:clsEnemySoldier = clsEnemySoldier.Create() '// static method
    objEnemy2.image = LoadImage("enemy1.gif");
    objEnemy2.X = 380;
    objEnemy2.Y = 530;
    Self.TMainAll.AddLast(objEnemy2);

    Local objPlayer:clsPlayer = clsPlayer.Create() '// static method
    objPlayer.image = LoadImage("player1.gif");
    objPlayer.X = 380;
    objPlayer.Y = 530;
    Self.TMainAll.AddLast(objPlayer);

  EndMethod

End Type


Type clsEnemySoldier
 Method Update
 For Local objTarget1:clsGameObject = EachIn Self.TMainAll
  If(objTarget1 <> Self And objTarget1.TType="Player")
    If(Self.TType = "EnemySoldier" And Self.DistToTarget(objTarget1) <= 120)
      Self.ShootAtTarget(objTarget1)
    EndIf
  EndIf
 Next

   DrawImage(Self.image, Self.x, Self.y);
 Endmethod
EndType

Type clsGameObject
  Field image:Timage;
  Field X:int;
  Field Y:int;

  Method Update:clsGameObject() abstract
EndType



What goes good:
The images of clsEnemySoldier (objEnemy1 and objEnemy2) are drawn correct, at the good X/y position. When my player object goes into <=120 pixels of either, **both** objEnemy's starts the ShootAtTarget() method! huh, wtf?@$?
The expected result is that only ONE of the enemys will start shooting, not both (unless my player is close to both enemies).

it seems to me, that somehow the Tlist cant distinguish which exact object it have, then it just call the Update on any polymorhic object? Or, alternativly, all objects which have an Update() method and of the specific type will be called simultaneously. Huh?? Thats not what i want!
Is it a bug? Have i done something wrong?

What i want is that only 1 object shoot. Not both. I am going crazy witht this! Any help will be appreciated!

Can someone help me with a idea, about where i coudl have gone wrong?

TIA! Alvast bedankt!


tonyg(Posted 2006) [#2]
Difficult to help with the code you have given.
Where is Self.DistToTarget method? What does it do?
I very much doubt this is a bug.


pappavis(Posted 2006) [#3]
The DistToTarget() is smethod which determines the distance in pixels from Self X/y to objTarget1 X/y.


tonyg(Posted 2006) [#4]
... might be important to the problem then. Any chance of seeing that code? Any chance of an short example showing the problem?


Byteemoz(Posted 2006) [#5]
That's how I would do it ... maybe it helps.
-- Byteemoz
SuperStrict
SeedRnd MilliSecs()

' create enemies
Global Enemies:TList = CreateList()
For Local a:Int = 1 To 5
	Enemies.AddLast TObject.Create(Rand(50, 750), Rand(50, 550))
Next

' create player
Global Player:TObject = TObject.Create(0, 0)

Graphics 800, 600

Repeat
	Cls
	
	' draw enemies
	SetColor 255, 0, 0
	For Local Enemy:TObject = EachIn Enemies
		DrawOval Enemy.PosX - 3, Enemy.PosY - 3, 7, 7
	Next
	
	' draw player
	SetColor 0, 255, 0
	DrawOval Player.PosX - 3, Player.PosY - 3, 7, 7
	
	' draw shots
	SetColor 0, 0, 255
	For Local Enemy:TObject = EachIn Enemies
		If Enemy.ShootAt Then
			DrawLine Enemy.PosX, Enemy.PosY, Enemy.ShootAt.PosX, Enemy.ShootAt.PosY
		EndIf
	Next
	
	Flip


	
	' move player
	Player.PosX = MouseX()
	Player.PosY = MouseY()

	' update enemies
	SetColor 0, 0, 255
	For Local Enemy:TObject = EachIn Enemies
		If Enemy.DistToTarget(Player) < 100 Then
			Enemy.ShootAt = Player
		Else
			Enemy.ShootAt = Null
		EndIf
	Next
	
Until KeyHit(KEY_ESCAPE) Or AppTerminate()

' generic player/enemy object
Type TObject
	Field PosX:Int, PosY:Int
	Field ShootAt:TObject ' only for the enemy
	
	Method DistToTarget:Int(Target:TObject)
		Return Sqr( (PosX - Target.PosX) ^ 2 + (PosY - Target.PosY) ^ 2) 
	EndMethod
	
	Function Create:TObject(X:Int, Y:Int)
		Local e:TObject = New TObject 
		e.PosX = X ; e.PosY = Y
		Return e
	EndFunction
EndType



pappavis(Posted 2006) [#6]
THANKS for the replys, gonna try the examples, but meanwhile here is my code:
[URL]http://swartskaap.googlepages.com/downloads[/URL] (312Kb file).

I'd realy appreciate the help if someone could look at my code..