Multiple object list
Monkey 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. I've tried: If item <> Apple Then ... which works but is only good if I want to check for collision with any object. however this: 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. Cheers, George |
| ||
| 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. Cheers, George |