Multiple object listMonkey Forums/Monkey Beginners/Multiple object list
| Hi team,|
I have a list full of various object types and I'd like to filter out certain objects only for a collision check, but I can't understand why the code below doesn't work and only checks against one Orange.
If item <> Apple Then ...
which works but is only good if I want to check for collision with any object.
If item = Orange Then ...
only seems to check against one of my oranges (bottom right) in the list the others are ignored.
Thanks in advance for any help anyone can give.
Strict Import mojo Global FruitList:List<TFruit> = New List<TFruit> Global Apple:TApple Global Banana:TBanana Global Orange:TOrange Function Main:Int() New TGame() return 0 End Function Class TGame extends App Method OnCreate:Int() SetUpdateRate (60) For Local i:Int = 1 To 3 Banana = New TBanana Next For Local i:Int = 1 To 3 Orange = New TOrange Next Apple = New TApple Return 0 End Method Method OnUpdate:Int() TFruit.UpdateAll() Return 0 End Method Method OnRender:Int() Cls TFruit.DrawAll() Return 0 End Method End Class Class TFruit Field x:Float Field y:Float Field r:Int Function DrawAll:Void() Local item:TFruit For item = Eachin FruitList item.draw() Next End Function Function UpdateAll:Void() Local item:TFruit For item = Eachin FruitList item.update() Next End Function Method New() FruitList.AddLast(Self) End Method Method draw:Void() Abstract Method update:Void() Abstract End Class Class TApple Extends TFruit Field collision:Bool Method New() x = Rnd(640) y = Rnd(480) r = 16 End Method Method draw:Void() SetColor(0,255,0) DrawCircle(x,y,r) SetColor(255,255,255) If collision = True Then DrawText("collision",10,10) endif End Method Method update:Void() If KeyDown (KEY_LEFT) Then x = x - 5 If KeyDown (KEY_RIGHT) Then x = x + 5 If KeyDown (KEY_UP) Then y = y - 5 If KeyDown (KEY_DOWN) Then y = y + 5 Local item:TFruit collision = False For item = Eachin FruitList If item = Orange Then '<--------------- why can't I just say I want only to check against oranges? If x - item.x < 2*r And y - item.y < 2*r And item.x - x < 2*r And item.y - y < 2*r Then collision = True Endif Endif Next End Method End Class Class TBanana Extends TFruit Method New() x = Rnd(640) y = Rnd(480) r = 16 End Method Method draw:Void() SetColor(255,255,0) DrawCircle(x,y,r) SetColor(255,255,255) End Method Method update:Void() End Method End Class Class TOrange Extends TFruit Method New() x = Rnd(640) y = Rnd(480) r = 16 End Method Method draw:Void() SetColor(255,128,0) DrawCircle(x,y,r) SetColor(255,255,255) End Method Method update:Void() End Method End Class
| Those globals are each holding a single instance.|
What you want to do is check the type. You can cast it to Orange and see if it works:
if Orange(item) ' it's an orange else 'it's not endif
| Thanks Raph, |
Your explanation of the problem makes it clear why it wasn't working, but I don't understand your solution. After a bit of thinking and understanding the problem, I've added another field to the base class and given each sub class an id which I can check against. Not sure if this is good practice but it works.
If anyone knows of a better way to do this please give suggestions.
New working code:
| I had a typo. But here's an explanation... |
Your list is made of TFruit. You have subclasses that are TApple, TOrange, whatever.
When you pull an item from the list, say into a local variable fruitinstance, it's a TFruit. That's what you defined fruitinstance as, that's what the list is.
But you can attempt to cast it to TApple or TOrange -- if the cast succeeds, you know it is that type. If it does not, you know it isn't. So, if you have a fruitinstance that is a TFruit, it could be any of the fruit. If it's actually TApple and try
if TApple(fruitinstance) return true else return false endif
as a TApple, this will return true. If it were a TOrange it would return false because the cast would fail.
Casting in Monkey is basically like this:
fuji:TApple = TApple(fruitinstance)
| PS, an id works, and I have used it myself lots. But unless you have other reasons to have an id (I use it for tool display, that sort of thing) it's a little bit of memory overhead. |
| Thanks Raph, |
I managed to get your explanation to work. I'm still very new to programming and have never heard of casting, but it does seem a cleaner way to achieve what I wanted instead of creating a new field.
| final code:|
| You can think of casting as "changing something of one type into another." You can't cast an object into a type that is actually different, though, so it's really more like "adjusting the label on things." :) |
| I personally don't like an automatic all inclusive list in a class. It limits the things you can do with the class objects. so I don't use lists that way at all.|
also objects make it easier to figure out collision:
| Thanks Jesse,|
I don't have the experience yet to fully see why or why not one way is better than the other, but thanks for showing me an alternative. I'll have a play around with your code and do some hard thinking! There are various little tweaks in there that are very interesting.
Either which way, I have two solutions now so thank you both for your time.