How to create inheritance?

Started by zelda64bit, August 08, 2021, 15:10:47

Previous topic - Next topic

zelda64bit

I give an example and explain what I want to achieve.


SuperStrict
AutoMidHandle(True) 'centra origen en el medio

Type Tjugador
Field x:Int
Field y:Int
Field rotacion:Int
Field imagen:TImage = LoadImage("00.png")

Function Create:Tjugador()
Local jugador:Tjugador = New Tjugador
SeedRnd(MilliSecs()) 
jugador.x = Rand(32, 608)
jugador.y = Rand(100, 450)
Return jugador
EndFunction

Method pintar()
rotacion:+ 1
SetScale(0.5,0.5)
SetRotation(rotacion)
DrawImage(imagen,x,y)
EndMethod

EndType

Global objetos:Int

Graphics(640,480)


Global lista_jugador:TList = CreateList()

While Not KeyDown(key_escape)
SetScale(2,2)
SetRotation(0)
DrawText("frames: "+GraphicsHertz(),100,32)
DrawText("objetos: "+objetos,320,32)

If(GraphicsHertz() > 58) Then
Local jugador:Tjugador = Tjugador.Create()
ListAddLast(lista_jugador,jugador)
objetos:+1
EndIf

For Local j:Tjugador = EachIn lista_jugador
j.pintar()
Next

Flip()
Cls()
EndWhile



In the example I create an object and add it to a list, then I loop through the list and show it. If I have to do this on all the objects I create it can get heavy having to create a list for each object and loop through each object. As you could do all this in a parent class and that by inheriting from this class, you would inherit all its properties and no longer have to create more lists and loops to display objects. I don't know if I've explained myself well.

Derron

I do not really understand what you exactly plan to achieve.


TGameObject
> Method Update()
> Method Draw()

TShip extends TGameObject

TPlanet extends TGameObject


List:TList
List.addLast(new TPlanet)
List.addLast(new TShip)

'all
For local o:TGameObject = EachIn list
  o.Update
Next

'ignore all but the ships (or extending from ship)
For local s:TShip = EachIn list
  s.Update()
Next



Maybe this already helps you with the issue you think you have with inheritance:
https://blitzmax.org/docs/en/tutorials/oop_tutorial/#inheritance


bye
Ron

zelda64bit

When you create an object you have to add it to a list and then loop through that list. What I want to do is do this same thing in a class and then have others inherit from that class so I don't have to do that thing of creating a list and going through it. It is what unity does internally, that when you create an object you can show it without adding it to a list to show it or delete it.

Derron

#3
somewhere you have to call specific functions ... OR ... you provide an "event" in which the systems hook in on first use (eg adding the first game object)

Code (Blitzmax) Select

Type TGameObject
  global elements:TList = new TList

  Method New()
     elements.AddLast(self)
  End Method

  Method Update()
    print "Update Base"
  End Method

  Method Render()
    print "Render Base"
  End Method

  Function UpdateAll()
    For local o:TGameObject = EachIn elements
      o.Update()
    Next
  End Function

  Function RenderAll()
    For local o:TGameObject = EachIn elements
      o.Render()
    Next
  End Function
End Type


Type TShip extends TGameObject
  'the override is NOT needed but helps as NG then fails to compile
  'if you removed or renamed the "Render" method in TGameObject and
  'so making the override no longer an override
  Method Render() override
    print "Render Ship"
  End Method
End Type

'create a new ship
local myShip:TShip = new TShip
'attention this does NOT delete the old ship but
'adds a new one now!
myShip = new TShip

'adds even more ships
For local i:int = 0 until 10
  new Tship
Next


'loop...
TGameObject.UpdateAll()
TGameObject.RenderAll()



Another approach - and I think the better one is to NOT use the "new()" as this hides the "addition".


Code (Blitzmax) Select

Type TGameObject
  global elements:TList = new TList

  Method Update()
    print "Update Base"
  End Method

  Method Render()
    print "Render Base"
  End Method

  Function UpdateAll()
    For local o:TGameObject = EachIn elements
      o.Update()
    Next
  End Function

  Function RenderAll()
    For local o:TGameObject = EachIn elements
      o.Render()
    Next
  End Function

  Function Register(o:TGameObject, skipCheck:int = False)
    if skipCheck or not elements.contains(o)
      elements.AddLast(o)
    endif
  End Function

  Function Unregister(o:TGameObject)
    elements.Remove(o)
  End Function
End Type


Type TShip extends TGameObject
  'the override is NOT needed but helps as NG then fails to compile
  'if you removed or renamed the "Render" method in TGameObject and
  'so making the override no longer an override
  Method Render() override
    print "Render Ship"
  End Method
End Type

'create a new ship
local myShip:TShip = new TShip
'attention this does delete the old ship
myShip = new TShip
'manage this ship
TGameObject.Register(myShip)

'adds even more ships
For local i:int = 0 until 10
  TGameObject.Register( new TShip)
Next


'loop...
TGameObject.UpdateAll()
TGameObject.RenderAll()





bye
Ron

Derron

If you often "retrieve" elements anonymously (just storing them in the Gameobject-collection and only pass around the ID - a simple number). It might be a good idea to give each game object an ID ... and simply store the elements in a TIntMap. This way - and with eg an ensured "order" of adding objects, you can pass around the number in multiplayer code, or when storing stuff for a savegame ...


Code (Blitzmax) Select

Type TGameObject
  Field id:int

  global lastID:Int = 0
  global elements:TIntMap = new TIntMap


  Method New()
    lastID :+ 1
    self.id = lastID
  End Method

  Method Update()
    print "Update Base"
  End Method

  Method Render()
    print "Render Base"
  End Method

  Function UpdateAll()
    For local o:TGameObject = EachIn elements.Values()
      o.Update()
    Next
  End Function

  Function RenderAll()
    For local o:TGameObject = EachIn elements.Values()
      o.Render()
    Next
  End Function

  Function Register(o:TGameObject)
    If not o then Return
    'overrides an existing object with the same ID (so eg. if it was added before already)   
    elements.Insert(o.id, o)
  End Function

  Function Unregister(o:TGameObject)
    If not o then Return
    elements.Remove(o.id)
  End Function

  Function Get:TGameObject(id:Int)
    Return elements.ValueForKey(id)
  End Function
End Type



If you need more than the 2147483647 game objects, you would need an "id:long" (and a TLongMap - which you would need to write/adapt on your own - or simply ask me/copy from TVTower/DIG-Framework source).


bye
Ron

zelda64bit

Thank you very much Derron for the examples, I will study them calmly until I can apply them. ;)

By the way, the translator translates quite badly

zelda64bit

I have it almost finished, now I have the object class and the player and enemy class that inherit from object.

The only thing I need is to be able to eliminate objects, for that I use the function remove to eliminate an object and the clear function to eliminate them all.

But there is a problem ... from the player class an instance is created and from the enemy class 10 instances are created, when I try to eliminate all the enemies with clear the 10 enemies and the player are eliminated, but I only want to eliminate the 10 enemies and leave the player alive.

How would it be done?

Derron

simply do not remove player from your list/map ?!

Remove what you want "individually", do not simply clear your list.


bye
Ron

zelda64bit

But isn't there some way to delete many objects of one class, without affecting objects of other classes?

Derron

variant 1:
Remove each one separately.

variant 2:
have lists for each "class" - then you can of course empty them the way you want.
Of course it will be very hard then to "sort" them (when taking other object classes into consideration too - so ships behind a planet, a planet behind ships ...)


If you want to delete objects a thousand times per frame, then you might better think of a different solution to your problem. If you just want the "ability" to remove all "classX" from the elements list you can simply do:

For local my:TMySpecialClass = EachIn myList
...

it will skip everything "incompatible" (not extending or exactly being TMySpecialClass).
Please keep in mind that you should avoid modifying the "myList" when iterating over it - you might run in the "concurrent list modification" issue (iterator might stumble over it).
TIntMap would be better there then -> store the IDs of "to Delete" elements, and then remove by "ID" in a second step.

Else you need to find _fast_ ways to access elements via "index". Brl.ObjectList contains a TList like array. When removing an element do not forget to decrease the "index value" (else you skip stuff then too).


bye
Ron

zelda64bit