Compare and sort have baffled me already...
BlitzMax Forums/BlitzMax Beginners Area/Compare and sort have baffled me already...
| ||
Okay, so I'm getting to grips with my first Bmax code, and after struggling with the examples on the forum I finally understand what all the fuss is about OO coding. However I've got completely stuck now. I decided to write a simple robotron style shooter, and things were progressing nicely. In the following code "being" is my basetype for all things in the game (player, shot and grunt at the moment), So I'd though It'd be nice and easy to override compare method to use the .y variable to z sort all the images However as soon as I dare override the compare method my delete being code (in workall() setup by killbeing()) completely fails and deletes all manner of random beings. I though it was due to the list sorting messing up my killlist links, but removing the actual sort command made no difference. It seems the very existance of a new compare method causes my code to fail, without compare ever being called and I can't figure out why. So I'm obviously unsure of exactly how compare is used. can you guys point me in the right way. Download the source here: http://www.zen65317.zen.co.uk/simon/MST3K.zip and here's a listing of the being code ' make a base type for all creatures Type being ' constants for creatures in game Const CRhero=1 ' CReature hero Const CRgrunt=2 ' Basic badguy Const CRtank=3 Const SHbasic=50 ' basic lazer Global list:TList ' nblist is a list of pointers to every being to be worked on Global killlist:TList ' Anything on this list will get removed from beings Field x#,y#,z# Field xspd#,yspd# Field spd# ' general speed stuff moves Field image Field scalex#,scaley#,alpha#,rot# ' scale, alpha, rotation Field blend 'blendtype (ie. ALPHABLEND) Field r,g,b ' tint information Field lastshot,shotdelay ' frames since lastshot and min frames between shots Field kind ' Type of being see BNGxxx consts Function Draw() If list=Null Then Return For Local b:being=EachIn list SetBlend(b.blend) ; SetScale(b.scalex,b.scaley) SetColor(b.r,b.g,b.b) ; DrawImage b.image,b.x,b.y Next End Function Function workall() If list=Null Then Return ' code move everything For Local b:being=EachIn list b.work() ' increment the universal timers b.lastshot=b.lastshot+1 Next ' got their positions? cool now draw em SortList(list,True) ' collide ' react If killlist<>Null For Local b:being=EachIn killlist list.remove(b) Next ClearList(killlist) EndIf End Function Method work() Abstract ' overide compare to for use with sortlist Method Compare:Int(o:Object) Return Sgn(y-being(o).y) End Method ' set up master list and default details Method initbeing(kind,x,y,image,scx#,scy#) If list=Null Then list=New TList Self.image=image self.x=x ; self.y=y self.scalex=scx ; self.scaley=scy self.blend=MASKBLEND self.r=255 ; self.g=255 ; self.b=255 self.shotdelay=2 ListAddLast list,Self End Method Method killbeing() If killlist=Null Then killlist=New TList ListAddLast killlist,Self End Method End Type |
| ||
Test to see if this works. It's how I would use the compare method, but it should work with sign too, like you did it, it seems right.' page 26 Method Compare(O:Object)'Override Original Local B:Being = Being(O) If B <> Null If B.Y > Y Return 1 Else Return -1 EndIf EndMethodA few code Tips: ( incase you didn't know ) 1. In methods you don't need to use self, that is assumed, only required if you need to put that object to another function. 2. b.lastshot=b.lastshot+1 can be written b.lastshot:+1 3. Instead if New TList you can use the command CreateList() 4. Also Sort can be called from the List, List.Sort() 5. Instead if ListAddLast myList,Object you can use myList.AddLast( Object ) 6. I recommend writing your draw function as a method like this: Method Draw() SetBlend(blend) ; SetScale(scalex,scaley) SetColor(r, g, b) ; DrawImage image,x,y EndmethodThat's just tips, do what you feel is right for you. |
| ||
Another tip, all those constants in the beginning of they type are a bad idea. It's like you're defining types of the type, in which case you should use types extending the being type. |
| ||
Thanks for the tips. I'm very familiar with blitz2D/3D, but methods and functions in types are very new ground for me, so any advice is welcome. The constants I used are a hangover from when I started the code B2D style. Somewhere along the line I decided to throw myself into extended types, which now means I don't need any such nonsense. It will take some adjusting. As I said, OO is entirely new territory for me. I tried your alternate compare Wave, but now the delete list fails to get rid of anything, so the bullets now hang about in the memory instead. I'll take another look at it in the morning. The thing that's really confusing me is how compare can affect my delete code without ever being called. Is there some other basic commands that rely upon the compare function? |
| ||
Is there some other basic commands that rely upon the compare function? I don't think so. I really have no idea what's your problem is. |
| ||
Okay, this is getting silly. Ran it again this morning without changing any code and now a single bullet is capable of deleting every player and grunt. These are the bugs that really annoy me. Random effects without changing code. I could write a workaround (remove comapre and have a master draw list type to z sort), but I'd really like to know what on earth I've done here. EDIT: oops, Forgot I had changed something before bedtime. On further study, alternative code for the compare method either means nothing or everything is deleted. removing the compare method entirely means the create/delete part of the code works exactly as intended. |
| ||
Update: Rather than have a master killlist to remove everything after draw, collision detection ect, I decided to do away with the list in case I had created some problem by using it, or wasn't passing the correct methods. Nothing changed, it acted exactly as before. Still, at least that's one possible cause eliminated. |
| ||
Okay, been trying to figure this out over the last few days with little success. The only thing I've discovered is that when it deletes a shot, it also deletes any being on the same x or y. Still unsure though, how compare alters the type without ever being called. Pretty sick of the problem to be honest, I guess I'll try for a few more days then just give up on it. Then I guess I'll try a totally side on game that won't require sorting for my next project. Once I have a better understanding of Blitzmax, I may finally discover what I've done wrong here. |
| ||
I ran into something like this the other day when I modified the compare method for sorting and completely nuked the behavior of FindLink which is used for among other things TList:Remove... |
| ||
Ah, thanks. This'll be why listremove(blah,x) and blah.remove both fail in the same way. Sounds like a bug (though I admit there could well be something I'm not grasping about how compare is supposed to work.) Has there been any news on on this from Mark? Or would you folks recommend I just go ahead and write a workaround (remove compare and just repopulate a draw list each frame using the classic B2D style sorts?) |
| ||
Hi, Yep, TList.Remove uses Object.Compare, which is why you're getting weird results. In fact, the version you posted doesn't delete anything because Compare never returns 0! Should it behave like this or just use '='? I'm not sure yet, but this side of things does need some work. Anyways, the best solution is probably to store the TLink returned by TList.AddLast, and use Remove() directly on that, eg: Field link:TLink . . . link=globallist.AddLast( self ) 'add self to globallist . . . link.Remove 'remove self from globallist This will be fastest, and allows you to keep using Compare for sorting if you want. |
| ||
Aha, so I'm not going mad, there are other parts of the code that rely on compare. Thanks for confirming that. Also to be fair I'd altered the code all sorts of ways, but never actually updated in the example above, so I wasn't exactly making it easy for people to help me. I'll try your changes when I get home. Thanks for the response. |
| ||
Yeah, it works a treat. Thanks a lot for the help. |