Little help - new to objects and lists

BlitzMax Forums/BlitzMax Beginners Area/Little help - new to objects and lists

Dax Trajero(Posted 2008) [#1]
I'm just trying to get my head around objects and lists

As a test I want to write a quick space invaders clone. I call them aliens not invaders by the way...

Each alien has a draw method and an update method and all belong in an alienObjectList

I keep a separate gameObjectList with everything in it (player, aliens, bullets, etc)

As it's my first time with lists, I'm having a little trouble with the logic that updates the each alien's on-screen position. Obviously they move in a group and drop down a line when any reach the edge of the screen

Has anyone got any source code I could look at ?

I'd rather update them as a group instead of update them individually ?


GfK(Posted 2008) [#2]
Typed straight into reply box but you get the idea:
Strict

Global alienList:TList = New TList
Global alien:tAlien
Local n:int

'create some aliens
For n = 1 To 5
  alien = New tAlien
  alien.X = Rand(0,300)
  alien.Y = Rand(0,200)
  alienList.AddLast alien
Next

'update aliens en-masse
For alien = EachIn alienList
  alien.y:+1
Next

Type tAlien
  Field X:Int
  Field Y:Int
End Type



Dax Trajero(Posted 2008) [#3]
thanks Gfk for your swift response

I thought its good practice to have an UPDATE method for each game object. In this case I have a DRAW method and UPDATE method for each individual alien. Are you saying ditch that and update them all in one go ?

My main loop would have to change which is a single for next working through the gameObjectList

draw objects
update objects


Sledge(Posted 2008) [#4]
Space Invaders is a tricky one to start with because only one invader per frame is updated (which is why, in the arcade version, the aliens get faster and faster the less of them there are) -- you're going to have to look up how to simulate B3D's After command with TLinks if you want yours to behave similarly.

If that is the case then having a list specifically for aliens, like in Gfk's code, is a good idea although for neatness I would probably encapsulate it within the alien type. ie...
Type tAlien
  Global list:TList = CreateList()

  Field X:Int
  Field Y:Int
End Type

...which you access with "tAlien.List" from outside the type, but just as "list" from within the class functions and methods.


Dax Trajero(Posted 2008) [#5]
see below


Dax Trajero(Posted 2008) [#6]
thanks sledge

ignoring the fact only one invader is supposed to move per frame, I'm just going to move them all per frame (for now)

1. is it best to perform single update, which deals with all the invaders

or

2. is it best to update each invader on an individual basis - its this method I'm having trouble with

I'd like to use method 2 (especially if I'm going to convert it later to move on invader per frame) but I'm having trouble with the logic.

Has anyone got any source code for the update on each invader ? eg. checking if they've reached the screen boundary, etc...


Sledge(Posted 2008) [#7]
I don't think there's any hard and fast rule. My preference is to have a class fuction, say tAlien.Update(), that calls the required methods of each instance:

Type tAlien
  Global list:TList = CreateList()

  Field X:Int
  Field Y:Int

  Function Update()
    For Local currentAlien:TAlien = EachIn list
      currentAlien.Move()
      currentAlien.Draw()
    Next
  End Function

  Method Move()
    ...
  End Method

  Method Draw()
    ...
  End Method
End Type



Dax Trajero(Posted 2008) [#8]
ok, thanks


Dax Trajero(Posted 2008) [#9]
is there a more elegant way to find out the current list position when you're inside say the currentAlien.Update code?

eg. a crude way...

global currentPOS:int=0
For Local currentAlien:TAlien = EachIn list
currentAlien.Update()
currentAlien.Draw()
currentPOS:+1
Next


Sledge(Posted 2008) [#10]
If you are not going to remove aliens from the list (but deactivate them instead when sploded) then you could add an enumerated index field.


Dax Trajero(Posted 2008) [#11]
Ok, so I've solved my last problem thanks to everyone's help above. Remember it's a space invader clone - I chose something simple to get my head around OO code and lists. The invaders are currently all updated each frame.

So now I'm using a Tlink to move through my gameObjectList. It works no problem like this: (part of my main loop)
Local Link:TLink = AlienObjectList.FirstLink()

While	Link <> Null
				
 Local MyObject:TGameObject = TGameObject(Link.Value())
 MyObject.UpdateSelf()
 Link = Link.NextLink() 

Wend
Flip


So now, I want to update one invader per frame, as per the original space invaders game. When I try my solution everything works eg. one invader per frame, but now they don't move in sequence like they used to. Instead a seemingly random invader moves, then another and so on, completely out of sequence. Can someone explain what I'm doing wrong...
If Link <> Null
				
 Local MyObject:TGameObject = TGameObject(Link.Value())
 MyObject.UpdateSelf()
 Link = Link.NextLink() 

Else
		
 Link = AlienObjectList.FirstLink()
			
EndIf
			
Flip



Mahan(Posted 2008) [#12]
It sounds like you maybe should look over your initialization of the aliens on the screen so that the alien order in your list is somehow related to their position onscreen.

To illustrate I'll show the aliens as numbers on a presumptive "screen" where the "alien number" is the order of the alien in the linked list:


11 10 09 08
07 06 05 04
03 02 01 00



if you write an algorithm that will move one alien each x frames and then move on to the next link.

pseudocode to give an idea:

currAlien = list.first()
frameCount = 0
const FRAMES_PER_MOVE = 15 '(?) change to test a good speed

while not keypressed(esc)
  frameCount = frameCount + 1
  if (frameCount % FRAMES_PER_MOVE) = 0 then
    currAlien.update(currentDirection)
    currAlien = currAlien.next
    if currAlien = NULL then
      currAlien = list.first()
      currentDirection = changeDirectionIfNeeded()
    endif
  endif
  drawAliens(list)
  flip
end while



Dax Trajero(Posted 2008) [#13]
Thanks Mahan - could you see what I was doing wrong with my code ?

Actually, it's probably not a good idea to update one invader per frame - I'm running frame independent timing so I guess I'll have to update one invader every x millisecs ?


Mahan(Posted 2008) [#14]
If you don't mind showing some code, could you maybe copy&paste the part of the code where you instanciate (start up) the Alient objects (ie the vicinity of any "new Alien" statements. Also show the code that gives the Aliens their starting position (x, y coordinates at start).

My guess is that if you fix up the initialization (the setup of coordinates etc.) of the Alien objects and make their position in the list somewhat systematic against the screen coordinates you'll be able to iterate in any pace (every X millisecs for instance, as you said) you like in your list and apply identical updates on each Alien and the updates will be in the order you want them to.

Btw in what order do you want the Aliens to move? If you look at my presumptive "screen" in my first reply: Would you like them to move ordered as i did it (00 first then 01 .... upwards up to 11) or do you have another moving order in mind? If you got an own idea on their movement you could draw it here on the forum in a similar way as I did.

(I'm pretty sure that if you show how you want them to move someone will come up with some code that will set it up for you :-)


Dax Trajero(Posted 2008) [#15]
here you go:

Type TAlien1 Extends TGameObject

Function Create:TAlien1(Image:TImage,xstart:Int,ystart:Int)

Local Alien1:TAlien1=New TAlien1

Alien1.X=xstart
Alien1.Y=ystart
Alien1.frame=1
Alien1.Image=Image

If Alien1.Image=Null
Print "Not able to load image file. Program aborting"
End
EndIf

ListAddLast AlienObjectList, Alien1

End Function

and then there's the allocation of their positions on screen...


Local start=220

For Local x = 1 To 11

TAlien1.Create(LoadAnimImage(URL+"invader1.png",24,16,0,2),start+x*32,350)

Next


Dax Trajero(Posted 2008) [#16]
How does the FLIP command work ? Does my main loop cycle through time and time again, ignoring FLIP until it's time to swap the buffers to the screen ?

Or does program execution halt until its time to swap the buffers to the screen ?

I'm using the FLIP command in it's default form. Framerate is based on whatever the user's screen is running at (in this case 60Hz). I'm using framerate independent timing (delta time)


Dax Trajero(Posted 2008) [#17]
Update: I've found a bug in the .update code which was causing the problem. May thanks Mahan for your patience.


Dax Trajero(Posted 2008) [#18]
got all the movement working, frame by frame in correct order.

Just need to track down some decent examples concerning collision - in this case player's bullet (gameObjectList) to each invader (alienObjectList) so if anyone has any good tutorials, let me know! ;-)


Dax Trajero(Posted 2008) [#19]
I'll draw a close to this particular thread