Thing learn't in 3DGPAI1: CH5 + Added thoughts
by Amr Bekhit · 06/20/2006 (12:22 pm) · 2 comments
Hoi!
Back again with some more info learnt from this book. I have to admit, at times going through the book can be very tedious due to the large amounts of typing. This chapter has been the longest so far. The other alternative is for me to copy the source code from the CD and use that--but the good thing about typing the code all out is that you examine the code more thoroughly, in my opinion, than just reading what someone else has written.
Another thing too: the author seems to go for the style of laying down the code first, then explaining it later. I'm not really in favour of that method. I prefer the style where explanations come first, then the code is put down to illustrate. For me, I feel that is better as I'll be writing code that I know how it works. Anyone ever read a rather old book called Teach Yourself Game Programming in 21 Days, by the amazing Andre LaMothe? I really enjoyed that book and felt I learnt a lot from it, one of the reasons being it did the explaining before putting down the code.
Anyway, without further ado, chapter 5:
The GameConnection.SetConnectArgs is a way of passing information form client to server when the client connects. I guess what you put there is up to you.
Canvas.SetContent will display the gui object passed as a parameter onto the screen and Canvas.SetCursor will modify the cursor-I assume that the parameter passed by SetCursor is some sort of cursor profile or datablock.
onWake: an event which occurs when the GUI object is displayed.
onSleep: an event which occurs when the GUI object is removed from the display.
Pushdialog and PopDialog: Seems that torque incorporates a dialog stack. If you want to display a new dialog, you use pushDialog. When you do that, you can't interact with any other dialogs pushed before this one, without closing this dialog first by using PopDialog()
Regular Push and Pop command will simply display and hide stuff, but won't implement this modal behaviour as with Push/PopDialog.
When binding a function to an ActionMap, the function should have just one parameter. This parameter is set to 1 when the key is pressed and set to 0 when the key is released.
The Schedule function allows you to have commands run after a particular time interval. The return value of the function is an event ID, which can be used to later cancel the scheduled event using the Cancel command. The thing I didn't quite understand at first is the 2nd parameter in the function, the reference. After searching through the forums, I found a post here: http://www.garagegames.com/mg/forums/result.thread.php?qt=22272 (3rd post), which indicates that the reference parameter is an object. If that object does not exists when the schedule function kicks in, then the schedule won't be called at all and will be cancelled.
Further reading confirms that a call to schedule like this:
Schedule(100,$someobj,"somefunc");
Is the same as this:
$someobj.schedule(100,"somefunc");
So it makes sense that if $someobj is destroyed, the schedule function won't be called.
In the player.cs file, it confused me that some of the defined functions had a MaleAvatar namespace added before them, whereas others had HumanMaleAvatar. Now, the datablock name is HumanMaleAvatar and the datablock className property is set to MaleAvatar. The name MaleAvatar is arbitrary, so I could change it to SomeClass, and then change the namespaces of all the MaleAvatar functions to SomeClass and the game works just fine. The question is, why are some functions defined with the className namespace, and others with the Datablock name namespace? I understand that by defining functions with the datablock name namespace, I am essentially defining member functions for the datablock, but what of functions defined using the className namespace?
Now here's another thing. It seems that it doesn't matter which namespace the functions are part of. As a test, I replaced all the namespaces with HumanMaleAvatar and the game seemed to work fine. Then I replaced them all with MaleAvatar and again the game seemed to work fine...hmm...
Some more experimentation: Removing the onCollision function meant that the player stopped colliding with things like the weapons and ammo. Removing onImpact seemed to only remove the damage caused by falling from high places; seems to deal with collision with terrain and interiors.
I felt the rest of the code, although not explained in depth, was relatively self-explanatory in what it did.
I also modified the code to add a time limit too (as suggested). A schedule was all that was needed, and a dialog box for added fanciness at the end. I also took this oppurtunity to modify the source code of the engine too. While doing the time limit code, I realised the need for a function which returns the integer part of a number. So, I added a mInt function to the source and works a treat!
Battling on to chapter 6...
--Amr
Back again with some more info learnt from this book. I have to admit, at times going through the book can be very tedious due to the large amounts of typing. This chapter has been the longest so far. The other alternative is for me to copy the source code from the CD and use that--but the good thing about typing the code all out is that you examine the code more thoroughly, in my opinion, than just reading what someone else has written.
Another thing too: the author seems to go for the style of laying down the code first, then explaining it later. I'm not really in favour of that method. I prefer the style where explanations come first, then the code is put down to illustrate. For me, I feel that is better as I'll be writing code that I know how it works. Anyone ever read a rather old book called Teach Yourself Game Programming in 21 Days, by the amazing Andre LaMothe? I really enjoyed that book and felt I learnt a lot from it, one of the reasons being it did the explaining before putting down the code.
Anyway, without further ado, chapter 5:
The GameConnection.SetConnectArgs is a way of passing information form client to server when the client connects. I guess what you put there is up to you.
Canvas.SetContent will display the gui object passed as a parameter onto the screen and Canvas.SetCursor will modify the cursor-I assume that the parameter passed by SetCursor is some sort of cursor profile or datablock.
onWake: an event which occurs when the GUI object is displayed.
onSleep: an event which occurs when the GUI object is removed from the display.
Pushdialog and PopDialog: Seems that torque incorporates a dialog stack. If you want to display a new dialog, you use pushDialog. When you do that, you can't interact with any other dialogs pushed before this one, without closing this dialog first by using PopDialog()
Regular Push and Pop command will simply display and hide stuff, but won't implement this modal behaviour as with Push/PopDialog.
When binding a function to an ActionMap, the function should have just one parameter. This parameter is set to 1 when the key is pressed and set to 0 when the key is released.
The Schedule function allows you to have commands run after a particular time interval. The return value of the function is an event ID, which can be used to later cancel the scheduled event using the Cancel command. The thing I didn't quite understand at first is the 2nd parameter in the function, the reference. After searching through the forums, I found a post here: http://www.garagegames.com/mg/forums/result.thread.php?qt=22272 (3rd post), which indicates that the reference parameter is an object. If that object does not exists when the schedule function kicks in, then the schedule won't be called at all and will be cancelled.
Further reading confirms that a call to schedule like this:
Schedule(100,$someobj,"somefunc");
Is the same as this:
$someobj.schedule(100,"somefunc");
So it makes sense that if $someobj is destroyed, the schedule function won't be called.
In the player.cs file, it confused me that some of the defined functions had a MaleAvatar namespace added before them, whereas others had HumanMaleAvatar. Now, the datablock name is HumanMaleAvatar and the datablock className property is set to MaleAvatar. The name MaleAvatar is arbitrary, so I could change it to SomeClass, and then change the namespaces of all the MaleAvatar functions to SomeClass and the game works just fine. The question is, why are some functions defined with the className namespace, and others with the Datablock name namespace? I understand that by defining functions with the datablock name namespace, I am essentially defining member functions for the datablock, but what of functions defined using the className namespace?
Now here's another thing. It seems that it doesn't matter which namespace the functions are part of. As a test, I replaced all the namespaces with HumanMaleAvatar and the game seemed to work fine. Then I replaced them all with MaleAvatar and again the game seemed to work fine...hmm...
Some more experimentation: Removing the onCollision function meant that the player stopped colliding with things like the weapons and ammo. Removing onImpact seemed to only remove the damage caused by falling from high places; seems to deal with collision with terrain and interiors.
I felt the rest of the code, although not explained in depth, was relatively self-explanatory in what it did.
I also modified the code to add a time limit too (as suggested). A schedule was all that was needed, and a dialog box for added fanciness at the end. I also took this oppurtunity to modify the source code of the engine too. While doing the time limit code, I realised the need for a function which returns the integer part of a number. So, I added a mInt function to the source and works a treat!
Battling on to chapter 6...
--Amr
#2
Thanks for the enlightenment!
--Amr
06/22/2006 (4:07 pm)
Ah I think I see now. So I can define a datablock with a name NAME_A. I could define functions related to that datablock with the namespace NAME_A. Any objects I create that uses that datablock would all use the functions defined under NAME_A. Now, in this datablock, I define the className to be NAME_B. I then define some functions specific to this className with the NAME_B namespace. I can then define other NAME_A datablocks but with a different className and using that className as a namespace, define functions specific to datablocks with that className.Thanks for the enlightenment!
--Amr

Torque 3D Owner Sean H.
as you demonstrated, it doesnt matter where you define the functions. in the case of this particular object, the engine doesnt care whether the function was declared for className or the datablock name. it only starts to matter when you have lots of different objects for which you would like to have some functionality passed down through inheritance, and other functionality to be overriden for that particular class. Finney actually explains this at some point in the book. with the way it's currently set up, you could define a new FemaleAvatar class. this new class would inherit the functionality of the base class by using className = HumanMaleAvatar, and would also define it's own custom functionality separate from the MaleAvatar namespace. thus, general functionality required by both would be placed in HumanMaleAvatar class namespace, while functionality more specific to a particular type of object, would be reserved for it's datablock namespace. this is somewhat arbitrary, and only helps to facilitate OO style development and minimize the amount of code you need to type.