Animation script: declaring a default state?
by Infinitum3D · in Torque Game Engine · 03/26/2009 (6:37 am) · 11 replies
I want my door to start in a default setting Closed, so that onCollision the script will check, see if its Open or Closed and play the appropriate .dsq
I don't know how or where to declare something like $Door.defaultState = "closed"
Here's my script.
$DoorAnim::DoorOpening = 1;
$DoorAnim::DoorClosing = 2;
datablock StaticShapeData(Door)
{
category = "Doors";
shapeFile = "~/data/shapes/doors/door.dts";
};
//--collision detection
function Door::onCollision(%this, %obj, %col)
{
if(%col.getClassName() $="Player")
{
%client=%col.client;
echo("player collides with door");
%obj.playDoorAnimation();
}
}
function Door::playDoorAnimation(%this, %anim)
{
echo("should play doorOpening animation");
if(%this.getState() !$="Closed")
%this.setActionThread("DoorOpening");
else(%this.getState() !$="Open")
echo("should play doorClosing animation");
%this.setActionThread("DoorClosing");
}
So how/where do I tell Torque that the default state is closed?
Also, if anything else is wrong, please point it out to me.
Thanks!
Tony
I don't know how or where to declare something like $Door.defaultState = "closed"
Here's my script.
$DoorAnim::DoorOpening = 1;
$DoorAnim::DoorClosing = 2;
datablock StaticShapeData(Door)
{
category = "Doors";
shapeFile = "~/data/shapes/doors/door.dts";
};
//--collision detection
function Door::onCollision(%this, %obj, %col)
{
if(%col.getClassName() $="Player")
{
%client=%col.client;
echo("player collides with door");
%obj.playDoorAnimation();
}
}
function Door::playDoorAnimation(%this, %anim)
{
echo("should play doorOpening animation");
if(%this.getState() !$="Closed")
%this.setActionThread("DoorOpening");
else(%this.getState() !$="Open")
echo("should play doorClosing animation");
%this.setActionThread("DoorClosing");
}
So how/where do I tell Torque that the default state is closed?
Also, if anything else is wrong, please point it out to me.
Thanks!
Tony
#2
function Door::onAdd(%obj, %this)
{
%obj.setState = "Closed";
}
function Door::getStateName()
etc etc etc...
Can that work in script, or do I have to C++ it?
Tony
03/27/2009 (6:56 am)
What if I script a function Door::onAdd()function Door::onAdd(%obj, %this)
{
%obj.setState = "Closed";
}
function Door::getStateName()
etc etc etc...
Can that work in script, or do I have to C++ it?
Tony
#3
I know the feeling. I really have learned a lot about scripting during this exercise in futility :)
I WILL succeed though. I'm getting close, I just know it.
I've stripped my functions down to try to isolate the 'door_opening.dsq' using function Armor::onCollision
When I get that to work, I'll add 'door_closing.dsq' and then, once that's working, I'll replace the onCollsion with a raycast/proximity and keypress.
This has become more lke a .blog or .plan than a forum thread, though, so if anyone is reading this, just post a simple hello, or "good luck", or even "you dumbass why are you wasting your time???"
Anyone? Just so I don't feel so alone *snif*
Tony
03/27/2009 (11:58 am)
Thomas Edison once said, when asked if he was making progress on the electric lightbulb, "Progress? Why yes! I know a dozen ways that DON'T work!"I know the feeling. I really have learned a lot about scripting during this exercise in futility :)
I WILL succeed though. I'm getting close, I just know it.
I've stripped my functions down to try to isolate the 'door_opening.dsq' using function Armor::onCollision
When I get that to work, I'll add 'door_closing.dsq' and then, once that's working, I'll replace the onCollsion with a raycast/proximity and keypress.
This has become more lke a .blog or .plan than a forum thread, though, so if anyone is reading this, just post a simple hello, or "good luck", or even "you dumbass why are you wasting your time???"
Anyone? Just so I don't feel so alone *snif*
Tony
#4
Anyway, so the first thing I see looking at your code is that you seem to be confusing datablocks and objects.
Datablocks are basically templates for objects. They define things like what DTS file to use for any objects based on the datablock. The information contained within a datablock is common to all objects created with that datablock. So if you create a Door datablock, the idea is you can create multiple door objects based on that datablock, and each one will use the same DTS file as defined within the datablock.
Each actual door in your game is a separate object -- in this case, a ShapeBase-derived object (such as a StaticShape), rather than a TSStatic shape. I didn't see any code above where you create an actual door object. This is the code that defines what datablock the object should use, where it's positioned, and so on. The code would look something like this:
Each one of your door objects can be open or closed at any one time, so this type of information would be stored within each individual object. So with the code example above, you could put a variable like "state" underneath where the datablock, position, and rotation are defined, and give it an initial value of "closed". You would then refer to this variable by using doorObject.state.
Animations should be called on the objects themselves, rather than on the datablocks. So in the Door::playDoorAnimation() method, you're calling the animation by using %this.setActionThread(), which is calling the animation on %this -- the datablock, not the object. Routines like setActionThread or playThread should be called on the %obj instead. But to do this, you'll need to make a couple of minor changes.
In your code above, in the Door::onCollision() method, you call %obj.playDoorAnimation(). This will then look for the playDoorAnimation method for the object, rather than the datablock. You want it for the datablock, as you have defined it. So instead, you would want to call %this.playDoorAnimation(%obj);. This will call the datablock's playDoorAnimation method, and tell it to use the %obj.
Now, in the Door::playDoorAnimation routine, you want to include the %obj in the method's definition. So you should change it to: function Door::playDoorAnimation(%this, %obj). You can leave out the %anim, since you're not using it.
Later in that method, instead of calling %this.setActionThread, you would call %obj.setActionThread (or %obj.playThread). And then you could use an if statement that says if(%obj.state !$= "Closed"), and so on.
Make sense?
03/30/2009 (9:25 am)
Damn web site ate my nice long response, so I'll try to reproduce it again. By the way, never, ever post long responses by entering text directly into a web browser. Always use a text editor, or copy it before hitting the "post" button. Man I hate that.Anyway, so the first thing I see looking at your code is that you seem to be confusing datablocks and objects.
Datablocks are basically templates for objects. They define things like what DTS file to use for any objects based on the datablock. The information contained within a datablock is common to all objects created with that datablock. So if you create a Door datablock, the idea is you can create multiple door objects based on that datablock, and each one will use the same DTS file as defined within the datablock.
Each actual door in your game is a separate object -- in this case, a ShapeBase-derived object (such as a StaticShape), rather than a TSStatic shape. I didn't see any code above where you create an actual door object. This is the code that defines what datablock the object should use, where it's positioned, and so on. The code would look something like this:
new StaticShape(doorObject) {
datablock = "Door";
position = "0 0 0";
rotation = "1 0 0 0";
etc.
}Each one of your door objects can be open or closed at any one time, so this type of information would be stored within each individual object. So with the code example above, you could put a variable like "state" underneath where the datablock, position, and rotation are defined, and give it an initial value of "closed". You would then refer to this variable by using doorObject.state.
Animations should be called on the objects themselves, rather than on the datablocks. So in the Door::playDoorAnimation() method, you're calling the animation by using %this.setActionThread(), which is calling the animation on %this -- the datablock, not the object. Routines like setActionThread or playThread should be called on the %obj instead. But to do this, you'll need to make a couple of minor changes.
In your code above, in the Door::onCollision() method, you call %obj.playDoorAnimation(). This will then look for the playDoorAnimation method for the object, rather than the datablock. You want it for the datablock, as you have defined it. So instead, you would want to call %this.playDoorAnimation(%obj);. This will call the datablock's playDoorAnimation method, and tell it to use the %obj.
Now, in the Door::playDoorAnimation routine, you want to include the %obj in the method's definition. So you should change it to: function Door::playDoorAnimation(%this, %obj). You can leave out the %anim, since you're not using it.
Later in that method, instead of calling %this.setActionThread, you would call %obj.setActionThread (or %obj.playThread). And then you could use an if statement that says if(%obj.state !$= "Closed"), and so on.
Make sense?
#5
03/30/2009 (9:30 am)
Makes sense to me.
#6
I don't have a Creat datablock because I thought I created the objects in the world editor.
I'll work on it and let you know.
Thanks again!
Tony
03/30/2009 (3:33 pm)
Wow, thanks Rubes! That is very helpful. So you're saying %this refers to the datablock, and %obj refers to the object in-game, right? I think I understand things better now.I don't have a Creat datablock because I thought I created the objects in the world editor.
I'll work on it and let you know.
Thanks again!
Tony
#7
When you create objects in the world editor and save the mission file, those object declarations are stored in the .mis file. So you can go into that file and add any additional object variables that you want, such as the door "state".
04/01/2009 (8:54 am)
Yes, for those routines %this refers to the datablock, and %obj is the specific object of interest that is using that datablock.When you create objects in the world editor and save the mission file, those object declarations are stored in the .mis file. So you can go into that file and add any additional object variables that you want, such as the door "state".
#8
04/01/2009 (10:20 am)
I understand. Now, if I wanted a checkbox in the World Editor Inspector for DoorState, I'd have to do that in C++ first, then add it to the datablock in script, right?
#9
04/01/2009 (12:17 pm)
I'm not sure what you want with a checkbox...from what I gather, the DoorState is a text value ("open" or "closed"), right? What would you be doing by checking the box?
#10
I guess I could just do two separate datablocks, Door1 defaults to open, Door2 defaults to closed. Inside doors would have a different skin compared to outside doors, and outside doors are usually locked, inside doors are usually unlocked...Enough variations to justify two datablocks.
Tony
04/01/2009 (3:11 pm)
Sorry, I guess I wasn't very clear there. The checkbox would be for setting the default state, checked = open, unchecked = closed. Because inside doors are typically left open, but outside doors are typcally closed.I guess I could just do two separate datablocks, Door1 defaults to open, Door2 defaults to closed. Inside doors would have a different skin compared to outside doors, and outside doors are usually locked, inside doors are usually unlocked...Enough variations to justify two datablocks.
Tony
Torque Owner Infinitum3D
My echo displays correctly.
I thought of another way that I could do this...
I could add the collision detection to the player.cs like this:
function Armor::onCollision(%this, %obj,%col)
{
if(%col.getClassName() $="Door")
{
if(%obj.getState() $"Closed")
%obj.playDoorAnimation();
}
}
Either way I get the error. I'm basing all this on player.cs Armor functions which check the "state" of the player ...
if(%obj.getState() $="Dead")
Is "Dead" declared in the source player.cc file maybe? I've got check that. Do I have to declare my door state "Open" in the souce somewhere?
Any ideas?
UPDATE: PLAYER.CC line 1292
Player::getStateName()
Can I script this?
function Door:setStateName()
etc, etc,...
Tony