by date
Journal of a young adventurer 06/Jan/08
Journal of a young adventurer 06/Jan/08
| Name: | Nerrad Weil | |
|---|---|---|
| Date Posted: | Jan 06, 2008 | |
| Rating: | 4.0 out of 5 | |
| Public: | YES | |
| Comments: | YES | |
| RSS Feed: | or Subscribe with . | |
| Profile Page: | View profile page for Nerrad Weil |
Blog post
I bought TGE + AFX few months back together with 2 torque reference books. but only recently i have time to fool around with TGE.
my TGE project goal is to create a multiplayer online dancing game, something similar to Audition Online, but much smaller scale, but even that it's quite a undertaking for me. i guess this would be a long and tough journey, but i hope unleast it won't be a lonely journey. i would like to use this space to note down the changes i have made to TGE and hope that some TGE veterans could give some guidance to me.
#1 problem
my project required "multi threaded" animations, e.g. a dance sequence consists of a set of head, body and legs animations. i find that Player::setActionThread() alone is very difficult to achieve the desired result and i have no confidence to hack player class without broken things
#1 problem's solution
my solution is ShapeBase::playThread() function, shapebase's animation functions are more primitive and easier to hack. i also noted that sequence priority play a big role here, for my case legs should has highest priority and head should has the least priority.
#2 problem
shapebase can't play the same animation consecutively
#2 problem's solution
after spamming breakpoints, i discovered this problem was caused by animation sequence didn't rewind properly at end and the sequence did't marked as Thread::Stop. therefore ShapeBase::advanceThreads() always prohibit the same animation sequence being played consecutively.
to solve this problem i added
after ShapeBase::advanceThreads() marked the thread as atEnd and updated the thread's state.
to ensure the thread was rewind properly at the end, add these lines to ShapeBase::updateThread() under Thread::Play case, where st.atEnd != true
#3 problem
shapebase doesn't support animation transition but this is a must have feature for my project
#3 problem's solution
the solution is simple, expose the TSShapeinstance::transitionToSequence to script. one thing to take note is the transitionToSequence() must called after timeScale being set properly. for my case, i do it in this order
#4 problem
after all these changes, now the avatar lost full body animation such as root and walk animation, this due to shapebase's animations have higher piority than player's animation
#4 problem's solution
to solve this problem we need to "disable" shapebase's animation thread when player's animations are needed. for my case, i added in a bool variable called disabled into TSThread class in tsShapeInstance.h
and then in S32 TSThread::operator<(const TSThread & th2) const add in these lines
and also expose a method in shapebase class to script, to do that add in these few lines into shapeBase.cc
btw, TSShapeInstance::animate(S32 dl) is a great place to study the threads' order, just put some breakpoints after sortThreads(mThreadList);
one last point is don't forget to modify your ShapeBase::packUpdate() and ShapeBase::unpackUpdate() methods. for my case, they become these at the end
my TGE project goal is to create a multiplayer online dancing game, something similar to Audition Online, but much smaller scale, but even that it's quite a undertaking for me. i guess this would be a long and tough journey, but i hope unleast it won't be a lonely journey. i would like to use this space to note down the changes i have made to TGE and hope that some TGE veterans could give some guidance to me.
#1 problem
my project required "multi threaded" animations, e.g. a dance sequence consists of a set of head, body and legs animations. i find that Player::setActionThread() alone is very difficult to achieve the desired result and i have no confidence to hack player class without broken things
#1 problem's solution
my solution is ShapeBase::playThread() function, shapebase's animation functions are more primitive and easier to hack. i also noted that sequence priority play a big role here, for my case legs should has highest priority and head should has the least priority.
#2 problem
shapebase can't play the same animation consecutively
#2 problem's solution
after spamming breakpoints, i discovered this problem was caused by animation sequence didn't rewind properly at end and the sequence did't marked as Thread::Stop. therefore ShapeBase::advanceThreads() always prohibit the same animation sequence being played consecutively.
to solve this problem i added
if (!mShapeInstance->getShape()->sequences[st.sequence].isCyclic() && !st.atEnd &&
(st.forward? mShapeInstance->getPos(st.thread) >= 1.0:
mShapeInstance->getPos(st.thread) <= 0)) {
st.atEnd = true;
updateThread(st);
st.state = Thread::Stop; // new line
if (!isGhost()) {
char slot[16];
dSprintf(slot,sizeof(slot),"%d",i);
Con::executef(mDataBlock,3,"onEndSequence",scriptThis(),slot);
}
}
after ShapeBase::advanceThreads() marked the thread as atEnd and updated the thread's state.
to ensure the thread was rewind properly at the end, add these lines to ShapeBase::updateThread() under Thread::Play case, where st.atEnd != true
TSShape::Sequence seq = mShapeInstance->getShape()->sequences[st.sequence];
if (!seq.isCyclic() && !st.transit &&
(st.forward? mShapeInstance->getPos(st.thread) >= 1.0 : mShapeInstance->getPos(st.thread) <= 0)) {
mShapeInstance->setPos(st.thread,st.forward? 0: 1);
}
#3 problem
shapebase doesn't support animation transition but this is a must have feature for my project
#3 problem's solution
the solution is simple, expose the TSShapeinstance::transitionToSequence to script. one thing to take note is the transitionToSequence() must called after timeScale being set properly. for my case, i do it in this order
updateThread(st);
mShapeInstance->transitionToSequence(st.thread,seq,0, duration, continuePlay); // must call after setTimeScale(), updateThread() contains setTimeScale()
#4 problem
after all these changes, now the avatar lost full body animation such as root and walk animation, this due to shapebase's animations have higher piority than player's animation
#4 problem's solution
to solve this problem we need to "disable" shapebase's animation thread when player's animations are needed. for my case, i added in a bool variable called disabled into TSThread class in tsShapeInstance.h
and then in S32 TSThread::operator<(const TSThread & th2) const add in these lines
if (disabled && !th2.disabled)
return 1;
if (th2.disabled && !disabled)
return -1;
and also expose a method in shapebase class to script, to do that add in these few lines into shapeBase.cc
bool ShapeBase::disableThread(U32 slot,bool disable)
{
if (mShapeInstance) {
Thread& st = mScriptThread[slot];
if (st.thread)
{
TSThread * th = st.thread;
if (th->isDisable() == disable) return disable;
setMaskBits(ThreadMaskN << slot);
return th->disableThread(disable);
}
}
return false;
}
ConsoleMethod( ShapeBase, disableThread, bool, 4, 4, "(int slot, bool disable)")
{
int slot = dAtoi(argv[2]);
if (slot >= 0 && slot < ShapeBase::MaxScriptThreads) {
if (object->disableThread(slot,dAtob(argv[3])))
return true;
}
return false;
}
btw, TSShapeInstance::animate(S32 dl) is a great place to study the threads' order, just put some breakpoints after sortThreads(mThreadList);
one last point is don't forget to modify your ShapeBase::packUpdate() and ShapeBase::unpackUpdate() methods. for my case, they become these at the end
// packData
if (stream->writeFlag(mask & ThreadMask)) {
for (int i = 0; i < MaxScriptThreads; i++) {
Thread& st = mScriptThread[i];
if (stream->writeFlag(st.sequence != -1 && (mask & (ThreadMaskN << i)))) {
stream->writeInt(st.sequence,ThreadSequenceBits);
stream->writeInt(st.state,2);
stream->writeFlag(st.forward);
stream->writeFlag(st.atEnd);
stream->writeInt (st.speed*1000, 11);
stream->writeFlag(st.transit);
stream->writeInt(st.duration*100, 10);
stream->writeFlag(st.simulPlay);
stream->writeFlag(st.thread ? st.thread->isDisable() : false);
}
}
// unpackData
if (stream->readFlag()) {
for (S32 i = 0; i < MaxScriptThreads; i++) {
if (stream->readFlag()) {
Thread& st = mScriptThread[i];
U32 seq = stream->readInt(ThreadSequenceBits);
st.state = stream->readInt(2);
st.forward = stream->readFlag();
st.atEnd = stream->readFlag();
st.speed = stream->readInt(11)*0.001f;
st.transit = stream->readFlag();
st.duration = stream->readInt(10)*0.01f;
st.simulPlay = stream->readFlag();
bool disable = stream->readFlag();
if (st.sequence != seq)
{
if (st.transit)
setThreadTransitSequence(i,seq,st.duration,st.simulPlay,false);
else
setThreadSequence(i,seq,false);
}
else
updateThread(st);
disableThread(i, disable);
}
}
Recent Blog Posts
| List: | 04/21/08 - Enabling animation transition in ShapeBase object 01/06/08 - Journal of a young adventurer 06/Jan/08 |
|---|
Submit your own resources!| Ramen-sama (Jan 06, 2008 at 17:59 GMT) |
| Karen Ho (Jan 07, 2008 at 01:43 GMT) |
Edited on Jan 07, 2008 01:44 GMT
| Rex (Jan 07, 2008 at 15:48 GMT) |
shapebase doesn't support animation transition but this is a must have feature for my project
Thanks a ton! for exposing this!. Wondered why when I tried to override the transition, I got bad animation....
| Nerrad Weil (Jan 08, 2008 at 14:40 GMT) |
| David Horn (Feb 14, 2008 at 21:02 GMT) |
I only ask because I'm making a game in which I need to have the player model remain in the last position of the playthread animation. In otherwords, if a player jumps or dances to the right during the animation, have him or her remain to the right instead of snapping back to the original position from which they started the animation.
if that makes sense :)
You must be a member and be logged in to either append comments or rate this resource.


4.0 out of 5


