BMax OOP rocks!
Miscellaneous Forums/General Discussion/BMax OOP rocks!
Just wanted to say to BRL that despite my recent sound and graphics troubles, BlitzMax is a joy to use. The OOP makes things so much easier and fun. "Upgrading" Types with new functionality is great fun and seeing new ways to make things more objected oriented is very enjoyable. Also the IDE is better than BlitzPlus and all the new 3D card effects like alphablend, scale, rotation etc are really great. I'm sure I'll end up with a really nice looking game.
Thanks.
Damn you and your OOP Knowledge. Right this summer I will learn to use OOP :)
Write a laymens tutorial and I will be your best friend ;)
I think people overthink OOP ... it's actually easier to use not harder. Things become less algorithmic and more natural.
:)
that's all i'm gonna say...
--Mike
Yeah it's not hard one you practive a bit, then it's a very natural easy way to program. Mind you I did learn OOP 10 years ago in C++ and Delphi, so it wasn't hard to lean it in Max, it's just that Max's simplified form is so easy.
BlitzMax's OOP implementation is the best I've seen because it doesn't over complicate the issue - I'm still not truly convinced about OOP though.
I am now.
You just got to make a style to it. It certainly isn't the obvious methods and functions in types that make oo good... its the little "lifesavers" max oo has.
You pick these up months down the line... but when you do, you'll be wondering "how on earth did I manage without?"
List a few of these for us rob
Type tEditor
global thing
Functions and methods....
End Type
Type tGame
global thing
Functions and methods....
End Type
if game.thing...
if editor.thing....
It can change your whole way of organizing and working with code. You get lost less. You don't start thinking... "what was that variable again?" or "I wonder what this variable was for?"
Plus is very cool to use the same var name, but in a different context. Same for functions and so forth...
yeah I like sprite.Draw() and sprite.Manage() etc Also sprite.Init(). Sometimes I'll extend sprite to do player.draw() and override draw() but other times I won't need to, e.g. Bullet.Draw() as the sprite one is good enough.
The other cool thing is changing how a method works, yet to everything external, nothing is different. So you can upgrade stuff easily without breakikng things.
Also making stuff like TLoadingScreen which has other types as part of it such as TLoadingBar and TClickHereButton etc. Encapsulation is cool as is inheritance and polymorphism, oh and wrapping just when you feel lazy.
I'm also into using lists to store game graphics and sounds instead of arrays so that when I want to assign a graphic or sound to a sprite I can refer to it by name instead of an integer value or constant which may have to change as you grow the game (which is a pain).
However, I wouldn't say any of this is unique to BMax it's all standard OOP stuff it's just nice and easy in Max. At first I was dubious of having the methods and functions inside of the Type instead of just declaring them in the type and implementing them fully further down (to keep big types concise) but I don't mind it now, it's better for small types though.
Cheers rob. It's always good for people who are new to bmx who read this thread and see exactly what is great about the language.
I'm also into using lists to store game graphics and sounds instead of arrays so that when I want to assign a graphic or sound to a sprite I can refer to it by name instead of an integer value or constant which may have to change as you grow the game (which is a pain).
I tried that a while back too, grey. You have to remember there's always a reference to the image left if you're trying to get rid of images from mem. Stumped me for a while that one, but yeah, your way is a very nice, simple, elegant way of doing it. bmx does rock.
I actually found Max's OOP implementation quite clumsy, maybe i'm just spoilt by C#.. meh..
This is all very interesting, I have been doing the Lion share of my development in BB3D. I am a coder on a budget... Bmax does seem appealing, however to save a few sheckles I have been using an old version of (dare I say it ?) VB6 for my .ini Gooeys, I may go the way of Bmax in the near future..... The time required to learning a new product is always another factor. Grey does some quite impressed with Bmax's ability though.
Write a laymens tutorial and I will be your best friend ;)
Here you go:
BlitzMax OOP TutorialLet me know if you think it's too confusing or anything.
Rimmsy: Yeah I'm not trying to remove the images, but if a new level is loaded I can just clear the list and refill it and all the old images will be gone :-)
Cool John. I think that should be put somewhere 'official' as its very easy to understand from my perspective anyway.
So inheritance then? So I could make an objrct that just tells the computer how to draw something. Then later, if I was making a robot object, I could inherit the drawing object and use that?
So if I then had a robot object, a tree object and a floor object all using the same drawing method, i could go back to the original Drawing object, change something in it, and all the other objects would respond to the changes? As the drawing methods they are all using are just an instance of the original?
Have I got that right?
boomboom, yes that's it. Furthermore if you wanted the robot object to draw differently, you could just make a Draw() method in it's type and do something else (this is called overriding). You could even call the original object's draw method as well in your draw() method by doing super.draw().
YAY!
boomboom: I just added inheritance and polymorphism to the tutorial. Hopefully they'll be as easy to understand as well.
You can re-download from the link above, or just click here:
http://www.alsbonsai.com/john/BlitzMax_OOP_Tutorial.pdf (125kb)
Thanks man. So just a question on polymorphism:
So it is basicaly a way to activate the shared method in one of the inherited objects (in this case TEntity)?
So rather than activating each draw method for each object, you can instead activate all the common ones?
What would happen if say; TPlayer and TBuilding had a draw method from TEntity. But TTree had its own Draw overide. If you activated all the TEntity's draw methods, would it still activate the TTrees overide? or would it skip that one as it wouln't be a TEntity?
What would happen if say; TPlayer and TBuilding had a draw method from TEntity. But TTree had its own Draw overide. If you activated all the TEntity's draw methods, would it still activate the TTrees overide? or would it skip that one as it wouln't be a TEntity?
In that case, it would execute the TTree override. If you run the last example in the tutorial, you can see that it calls the appropriate Draw() Method for TPlayer, TBuilding, or whatever (even though it's using a TEntity variable). That is the main purpose of polymorphism - to use a more generalized Type, while retaining the object's correct behaviour.
I should probably try to make this more clear in the tutorial.
I agree with everything Grey said, except about the IDE. I wish it allowed syntax highlighting in the same way as previous BRL IDEs.
I don't even know what syntax highlighting is :-) The IDE is OK but I've used "proper" IDEs like Delphi, Visual Studio etc. Protean was good but it was very slow and annoying for massive projects. I liked the fact it correct the case on your variable names and show you function parameters as you began to type, plus had function folding. Oh and it had project wide Find except that it was broke :-(
I just re-uploaded the tutorial. Hopefully polymorphism is described a little more clearly now.
John. The inheritance and polymorphism is great, well explained, will be v. helpful for beginners I'm sure. One thing, maybe you know the answer to (I can't be bothered to test) is if TEntity doesn't have a certain method but TPlayer has Method Fire, and you have done: p:TEntity = New TPlayer, then you say p.Fire will this fail because the method doesn't exist in TEntity, even though it exists in TPlayer? It probably should fail, because it should follow the same rules as for fields, yes?
As far as I know, that would fail (I haven't tested it yet, either). Because of the dynamic nature of polymorphism, the computer would have no way of knowing that p:TEntity is going to be a TPlayer - so it can't allow access to Fire() in that way.
Instead, you could make another Type (which might be called TActor) which Extends TEntity, which would define a "Method Fire() Abstract" or something. Then you can have "Type THuman Extends TActor" and "Type TRobot Extends TActor" if you want.
You could build a Type structure something like this:
Entity -- Static
| / \
Actor / \
/ \ House Tree
/ \
Robot Human
Then you can do something like this:
For act:TActor = EachIn ActorList
act.UpdateAI() 'This could update AI appropriately, whether the actor is THuman or TRobot
act.Shoot() 'You could also do this
Next
For ent:TEntity = EachIn EntityList
ent.Draw()
Next
It really just depends on how you want to structure your code. I'm sure there's a million different ways to do this.
ah yes nice one :-)
Nice tutorial John :)
Thats how they should should be. Start from vary basic ways and build up step by step. Nice one *thumbs up*
Another update :) - now the tutorial covers constructors and destructors.
I'll probably put it on the BlitzMax tutorials forum when it's complete.
??
Why is there nothing in your post but an ad for Aurora?
Edit: Seing the same thing in many other posts, I can only assume you are spamming the forums.
He's spamming - he did it in my thread too.
I shall speak with his mother.
What would you do if blitzmods started deleting any post you make? Take it laying down would you? Hey?
If they want to silence me they'll have to ban me.
If they want to silence me they'll have to ban me.
Please ban the little kid.
why don't you just leave if you don't want to play nice?
Actually, I noticed that they can delete individual posts now.
In the Nintendo Wii thread, someone said "Wii is gay", to which I replied "Eh? Even Noel and yourself?!". The comments were quickly removed, strangely enough.
I wish they would use that ability more often, instead of deleting poor, defenseless, unsuspecting threads.
If they want to silence me they'll have to ban me.
Well you're surely headed in that direction.
They've always been able to tidy up threads by removing certain posts. Sometimes it leaves the threas a tad disjointed. Aurora was getting on my tits a bit though so I say good call, he was like on a suicide mission.
John J. Gonna read the new bit now... Hey why don't you link to it in your sig?
John J. Good extension. Personally I make a Create Function (within the Type declaraion) that takes parameters, because New can't, right? e.g.
Function Create:TEntity(x,y)
Local e:TEntity = New TEntity
e.x = x
e.y = y
EntityList.AddLast(e)
Return e
End Function
So in the code you can just do TEntity.Create(100,200) all on one line. Also If I had another field in TEntity, say Field foo, that wasn't set with Create() I would do this:
Local e:TEntity = TEntity.Create(100,200)
e.foo = 300
Furthermore, if I extended TEntity to TPlayer which had field Health (as per your example) I would pass health into the Create() like this TPlayer.Create(100,200,300) and TPlayer's Create function would look like this (note the use of a typecast):
Function Create(x,y,health)
Local p:TPlayer = TPlayer(Super.Create(x,y))
p.health = health
End Function
:-)
OMG I am actually starting to understand this... Keep it up!!! :)
Another update: Now the tutorial includes a section on custom Types.
Grey Alien: Yeah, Type Functions is next in the tutorial. However, instead of this:
Function Create:TEntity(x,y)
Local e:TEntity = New TEntity
e.x = x
e.y = y
EntityList.AddLast(e)
Return e
End Function
, I prefer this:
Method New:TEntity()
EntityList.AddLast(Self)
End Method
Function Create:TEntity(x,y)
Local e:TEntity = New TEntity
e.x = x
e.y = y
Return e
End Function
This way, New or Create can be used, and it will still get added to EntityList. Basically, crucial stuff should be added to New() 9stuff that might cause bugs if not done when the object is created), while you can initialize other variables (like x and y) with Create().
good one!
John, there's and error in the second to last paragraph which discusses Delete(). It says "Since BLitzMax uses a garbage collection system ... don't rely on a *CONSTRUCTOR* beging called at any specific time." This should be DESTRUCTOR :-)
...and 'being'. :)
being was my typo ;-p
It says "Since BLitzMax uses a garbage collection system ... don't rely on a *CONSTRUCTOR* beging called at any specific time." This should be DESTRUCTOR :-)
Oops, sorry about that. It's fixed now. :)
Update: Now static methods (a Function within a Type) and static fields (a Global within a Type) are included in the tutorial.
I think it's mostly complete now. Let me know if you find any errors, or think of something important I missed.
Have you done Super yet? Didn't see it when I last looked.
Not yet - I'll try to add that next.
@John J: instead of this...
Method New:TEntity()
EntityList.AddLast(Self)
End Method
Function Create:TEntity(x,y)
Local e:TEntity = New TEntity
e.x = x
e.y = y
Return e
End Functionyou can do this...
Field Link:TLink = EntityList.AddLast(Self)
Function Create:TEntity(x,y)
Local e:TEntity = New TEntity
e.x = x
e.y = y
Return e
End FunctionWhich removes the need for a new method and also gives you a handy tlink for each instance.
Yes, that's true, although the purpose of that section is to teach you how to use constructors, not to produce the most compact code.
I agree cos I don't even understand that TLink code!