Objects inside objects:how to get rid of them

Monkey Forums/Monkey Programming/Objects inside objects:how to get rid of them

mteo77(Posted 2013) [#1]
Hello all.
I was playing with some code and encountered a problem.
I have a class that has another class as field.
I can't see to find a way to get rid of the "class field" when i don't want to use the main class anymore.
Example:

global carlist:list<car>=new list<car>

class car
   field size:int
   field name:string
   field speed:float
   field wheels:wheel
   function create()
      local loc:car=new car
      loc.size=100
      loc.name="mycar"
      loc.speed=10.0
      loc.wheels=new wheel
      carlist.addlast loc
   end function
   method drawcar()
      'draw my car here
   end method
end class

class wheel
   field longevity:int
   field price:float
   field colour:string
   method drawwheels()
      'draw wheels here
   end method
end class

main()
   local supercar:car=new car
   supercar.speed=supercar.speed-1
   if supercar.speed = 0
      carlist.remove supercar
   endif
end



Hope i havent made any mistake..was pseudocode so hopefully you will get the idea...
Basically if i delete the main class from the list the class get deleted but not the sub class...how can i do that?
(Sorry if it is a silly question..can't find a way to get rid of it!)


mteo77(Posted 2013) [#2]
I suppose i will have to create a remove function for the sub class object?

if supercar.speed=0
   carlist.remove supercar
   wheellist.remove wheels
endif



mteo77(Posted 2013) [#3]
Tried implementing a remove function for the child class and it works, but i wonder if there is another way to do that sort of "removing".


dawlane(Posted 2013) [#4]
When removing a object from a list. It should remove all of that object data including any fields that use custom data types (that's basically what a class is). The only data member that should not be affected is any declared global or constant as it's seen by all instances of a class. If you want to make sure that such non global objects get removed: set it to a value of Null before you remove the parent class. The GC should get rid of it when it detects that it's not being used.
Don't forget you would have to iterate through that list using the EachIn command to ensure that each object in the list is parsed.

By the way. The code in the main() would never work as you would have to call the create function to add data to the list. Just doing New method would just give you an empty object. And your second post suggests your trying to use two separate lists. Meaning that wheellist is not bound to any car object.

Edit: Some code.



Gerry Quinn(Posted 2013) [#5]
What dawlane says. There's no 'delete' option in Monkey; instead we have garbage collection. In most situations, you just have to let it work.

In this case, if only supercar knows about its own wheels, and if everything else has forgotten about supercar (i.e. the only thing that kept a reference to it was carlist, from which it has now been removed), then supercar should eventually be garbage collected. At that point nothing remembers about supercar's wheels, so they are eligible for garbage collection too.


dawlane(Posted 2013) [#6]
One thing I would like to point out is that the GC can sometimes slow down your code and there has been a time or two I could have killed just to have been able to use a delete and pointers.
Look around the forum for reusing/pooling of objects.


mteo77(Posted 2013) [#7]
Hello.
Thanks for the suggestions.
I will have to go through all my code and see what i am doing wrong, but i think i might have declared something global, or something is being used by all instances.
I think it might be time for me to rewrite all my code from scratch (i think i have added too much during my learning process, and now is just a collection of "half right" garbage!).


Gerry Quinn(Posted 2013) [#8]
Just a question: how do you know there is a problem? Have you a memory leak or something?


dawlane(Posted 2013) [#9]
If mteo77 has managed to get a memory leak then were all buggered. As I haven't seen any big issues with the GC for quite a while. Unless mteo77 is using the v70 experimental and some new bugs (or old problems) have come to light.

@mteo77
A couple of tips.
1) Always use strict mode. Doing this helps to eliminate most code bugs and mistakes.
2) Write small test code modules before integrating it to the main project code and always organise the code in a modular fashion by placing your large class declarations into separate files. Any small class declarations that are in some way essential to only that one class should go there as well. Any other small class declarations that can be used by all other classes should be grouped into their own file.
3) Be mindful when dealing with floats, integer numbers and on the odd occasion custom data types. Assigning a float to a integer data type looses the floats precision (e.g. 0.5 will become just 0). Monkey is smart enough to know what to cast a data type to most of the time, but sometimes you may need to explicitly cast it to ensure that it's enforced.
4) If possible study other people's code for ideas on how they solved their problem.
5) If you using a Windows OS. Buy Jungle IDE as the built in live code debugger save a fair bit of time.

Edit:
There is one way that I can think of where a memory leak as such could happen and that is if you define a member field that is to be used as a reference to another single instance of a object (like one that's in a list of objects). Removing that object instance doe's not automatically remove it's reference within that member field and there for would just reference junk data. In this situation you should set the member field to Null so the GC can get rid of it.

E.g. If you have a homing missile that has a field that is used as a reference to an enemy object instance as for targeting and that enemy is destroyed by another means. Then the missiles reference to that enemy objects instance becomes invalid and points to junk data and would just go round and round the last point the the enemy use to be.


Gerry Quinn(Posted 2013) [#10]
That's what I meant: I wasn't suggesting that the GC itself it bugged, but it's perfectly possible to accidentally hang onto references you don't need in your own code.

I agree it's unlikely, though, hence what I was really asking the OP was: what makes you think you need to delete the wheels?


dawlane(Posted 2013) [#11]
Glad you cleared that up Gerry you had me worried there.;). Though as to the question of the GC having bugs. You never know what can happen when Marks decide to do a bit of a tinkering.

Didn't mteo77 have another post about guide missiles or something somewhere? Maybe that's what he's having problems with? I think I was going to post some code for him to have a play with when I got something workable running.


mteo77(Posted 2013) [#12]
Hello.
Thanks for the suggestions.
I think the problem is i still don't understand classes (oop in general) properly.
Especially when trying to use external modules.
I try to explain the problem i am having (i feel it's related to my scarce knowledge of oop.... when i think i am starting to understand everything slips out of my hands again lol).
When coding little examples everything goes smoothly and fine.
As soon as i try to use external modules i hit obstacles.
In this case i am using Ignition.
All my classes are extended.
I got 3 main classes:player, bullets, enemies.
Player is directly controlled by me so no problem there (no AI or anything).
Bullets are ok as well, they have got 2 movements:homing and straight.
Enemies are difficult...especially the creation of them.
They have 9 different types of movements(and most of those types need 5 variables to be put through during creation..like x,y,targetx,targety,speed).
Also i have recently created another class(the one giving me problems) called "enemywaves"..basically is a class that has got enemies as fields;reason for this is so i can create some enemies and assign them positions based on the kind of wave i want to create.
And the problem is here:when i delete the wave class, the enemies that should go as well keep going.
Just deleting the wave class doesn't work.
I use a global field to hold my images (don't ask me why i did that..i think i was trying to load resources outside OnUpdate, since it was slowing down my android phone too much) and i load them inside OnCreate.
Maybe my car example wasn't that great i admit.
Maybe i should post my enemy class entirely (it's pages long...) so you can all horrify!
I personally think my little program has become too big for me to handle, i should half my expectations a bit (also considering i can dedicate just few hours a day at most, but it seems all i am doing is reading my code and not learning anything).
The problem i am having while studying someone elses code is that since monkey is a oop language, the coding style can be so different that i can't make up whats going on most of the time (i am getting there though).


mteo77(Posted 2013) [#13]


As you can see i added some code to get rid of the single enemy instances, otherwise just deleting the wave from the wavelist wouldn't work.
Also wavelist is called outside as a global (i quite don't understand whats the difference between global outside and inside a function, i think i listened to something in a tutorial but couldn't quite get my head around it).


mteo77(Posted 2013) [#14]
As i understand the enemy class is put through 2 different lists:a layer object list(used by ignition) and my personal enemy list.
So maybe its why just removing the wave from wavelist doesn't get rid of the enemies used as fields?


mteo77(Posted 2013) [#15]
I should probably give us using Ignition for now and learn monkey properly.
I did quite well though almost managed to make an entire game (enemy AI it was what made me realise i needed more knowledge...unless i want enemies that only go left and right like space invaders!).


mteo77(Posted 2013) [#16]
I just re read my posts...eek horrible english there!


dawlane(Posted 2013) [#17]
I haven't got the ignition frame work and really any kind of questions should be aimed at Playniax and your opening post didn't mention that you was using the ignition frame work. I'm actually surprised that Playniax hasn't got a support forum on his site.

I should probably give us using Ignition for now and learn monkey properly.
Yes I think you should. Trying to use some else's code without full understanding how it works and the necessary programming concepts is just asking for disaster. It's even worse if there is a lack of documentation.

I tend to prefer writing my own code from the ground up as I think it is more flexible than using some else's code. And I also reuse many classes that I've written myself and from time to time I'll improve them with tweaks. Not only that it's also much more satisfying knowing that I myself have done the grafted.

To start with write a dozen or so simple games just using Monkey only and then try rewriting them using something like diddy. Then have ago at writing them using the ignition frame work. But then again once you've mastered monkey and written some of your own classes modules you may come to the conclusion that it's not worth the hassle to learn some else's framework.


mteo77(Posted 2013) [#18]
The only reason i started using Ignition earlier was the fact that i have collisions with it, while monkey alone hasn't.
And since every little game need collisions...i thought it will saves me time so i could concentrate on something else.


dawlane(Posted 2013) [#19]
For collisions investigate Box2D. For simple stuff standard rectangle,circle collisions should do.


Gerry Quinn(Posted 2013) [#20]
I think the waves issue is probably straightforward. You have your waves class to organise generation of enemies, but I bet you also add them to some other list (perhaps in the Ignition framework, or perhaps in your own code). Your waves are no longer the only things that remember enemies, so when the waves disappear the enemies persist. Something is drawing them, I'd guess the framework (I don't use it so I can't tell).


mteo77(Posted 2013) [#21]
Had a look...bit too much for me,also i couldn't find any documentation at all apart from comments in the code.
Apart from that Ignition is very easy to use, obviously my problem is class oriented (i can use classes in a basic way ).
You are right about strict mode though...i managed to get rid of PLENTY of problems i encountered just by declaring every variable type and every method type (let's call it a semi strict mode :P).
Before when you said i could try to set the fields to null after removing the "master" class.How do i do that?
To explain it better:
Class wave has got a field called enemy
Enemy class is contained in 2 lists
enemy class has got a field that is shared by all instances and its the image(declared global).

The only thing i do is removing the wave class, but doing that doesn't remove field enemy(the enemy has got a remove method that remove them when they reach the bottom of the screen).

Sorry if i sound thick.


mteo77(Posted 2013) [#22]
Thanks Gerry.
Yes the framework is drawing them through a list (one of the 2 i mentioned before).
I resolved my problem by using the remove method i wrote for my class enemy, so everytime a wave get removed it automatically call the remove method of every enemy contained in the list, and it works perfectly.
I was just wondering if there was another way to do it, but obviously i am expecting too much :P
I really would like to do everything myself, but atm its too much.
Even if i get frustrated by errors, i am enjoying the learning ( i don't plan to write a game nor publish anything, this is a hobby to me like sudoku is to someone else :P); i hope nobody will get annoyed by my requests!
Thanks all.


Gerry Quinn(Posted 2013) [#23]
You seem to be doing quite well! Maybe you will come up with something you want to publish...


mteo77(Posted 2013) [#24]
Thanks for the hint Dawnlane.
As soon as i had a look at box2d i was like "eeek", so i started to code my own collision detection code.
Easier than i thought, went right first try (first time for me, usually i get tons of errors).
I basically draw circles around my object and check for circle collision.
Works out really well (not sure the efficency of it).