Making a Player Fly
by Mark Pumphrey · in Torque Game Engine · 07/15/2005 (3:31 am) · 125 replies
Firstly I would like to state that "Yeah, I have seen the posts about flying but....". They don't work and/or full of bugs. I would like to also state a general request that if you make a post regarding code to edit the original post instead continually trying to 'add' corrections later on making it harder than hell to read. Also, EVERYONE has a copy and paste function of some kind, use it. Saying that "here is some code than will change your life, insert it anywhere" means nothing and helps even less. Ok, enough of that. Has anyone actually made a player fly just like in Tribes?
#42
1. Make a invisible model, this is something the 3D graphic people handles
* make a "PNG" texture that has full alpha.
* mounting stuff
* !The dummy will handle the collision so make sure to get it right here!
2. Make another, animated model... in our case a insect that we will use int the game as our vehicle ;)
3. in the game, declare a flyingvehicle datablock and set shape = dumm model.
4. declare a StaticShape datablock for the animated model.
5. at player creation (in "game.cs") first create the flyingvehicle as your controlled character and then imidiatley mount the animated character on it, the trick is to get the animated character to mount so that the dummy ends up in the middle of the model.
Play and enjoy, a fast animated flying vehicle!
Bonus, the visible model is mounted so you could hot swap the model in the game easily and make easy transformations... kind of kirby style to change your characters apperance =)
05/15/2006 (2:24 am)
Sadly I do not have much time and all parts are not finished yet but this is a fast idea of how we do it, a thing worth noting is that we are not using our resources on the computer so effectivley that you would maybe want to do in a comersial game but it is a fast trick that is easy to do if you are doing a school project like me and is always short on time.1. Make a invisible model, this is something the 3D graphic people handles
* make a "PNG" texture that has full alpha.
* mounting stuff
* !The dummy will handle the collision so make sure to get it right here!
2. Make another, animated model... in our case a insect that we will use int the game as our vehicle ;)
3. in the game, declare a flyingvehicle datablock and set shape = dumm model.
4. declare a StaticShape datablock for the animated model.
5. at player creation (in "game.cs") first create the flyingvehicle as your controlled character and then imidiatley mount the animated character on it, the trick is to get the animated character to mount so that the dummy ends up in the middle of the model.
Play and enjoy, a fast animated flying vehicle!
Bonus, the visible model is mounted so you could hot swap the model in the game easily and make easy transformations... kind of kirby style to change your characters apperance =)
#43
05/15/2006 (4:35 am)
Nice one. all the information required :)
#44
06/26/2006 (9:10 pm)
I thread has been very useful but I have a question about it. How could you change it where when you move forward to plays the run animation then if you stop it goes back to the root?
#45
01/03/2007 (8:50 pm)
Has this been turned in to a resource yet?
#46
01/04/2007 (6:29 am)
I tell ya what, when I come to make the other games I want to make that require flying, I'll try to make a resource out of it. The game I'm working on now doesn't require flying - quite the opposite, I'm trying to figure out how to make Torque NOT fly and bounce around so much
#47
01/05/2007 (5:09 pm)
I've implemented this code in the "starter.fps" template and it works well. However, TGE crashes when the player collides with the computer-controlled orc. Anyone experience the same thing or have any ideas where I should start to look for the the source of the problem?
#48
01/05/2007 (9:12 pm)
I figured out what I did wrong: I used Tom Spilman's fix to smooth flight, but I missed his note about adding lines in Player::readPacketData(). For fellow code box scanners out there, you need to add the following lines to player.cc (add the lines denoted with plus signs):void Player::readPacketData(GameConnection *connection, BitStream *stream)
{
...
stream->read(&mHead.x);
stream->read(&mHead.z);
stream->read(&rot.z);
+ stream->read(&rot.x);
+ stream->read(&rot.y);
rot.x = rot.y = 0;
setPosition(pos,rot);
#49
02/06/2007 (5:00 pm)
For some reason this is causing my rigidshapes (boulders) to go sky rocketing in the air at the load of the map.
#50
09/16/2007 (1:07 pm)
I think I have an idea that could help the "Toggle" function. Make 2 packages, 1 with the walking code, and one with the flying one, then bind a button to activate the package, that's the easiest way I found to do.
#51
11/08/2007 (7:44 pm)
Any news on this resource? Air/Ground toggle? Got the flying to work perfect, But i also need ground aswell :P
#52
12/04/2007 (4:08 pm)
I think they were talking about mFlying booleans know anything?
#53
12/05/2007 (1:48 pm)
Anyone know what the code is for the mFlying boolean?
#54
edit: almost done but I need to study for my math finals :P probably will be able to finish it today or tomorrow assuming nothing goes wrong.
12/06/2007 (7:42 am)
I don't have the time to write the code for it right now but I probably will in the next couple days.edit: almost done but I need to study for my math finals :P probably will be able to finish it today or tomorrow assuming nothing goes wrong.
#55
find
change it to
Next scroll down just a little and find
change it to
Then scroll down a bit more and find
change it to
12/06/2007 (3:46 pm)
So I put it all together. I haven't tested this much, but I do know that flight tends to be a bit jittery. I'm not sure if it was always this way, if not I'll check it out. I didn't go to far to understand everything so I when you go out of flying mode it may stop doing something that the flying needs. Here goes.find
// Acceleration due to gravity VectorF acc(0,0,mGravity * mGravityMod * TickSec);
change it to
VectorF acc;//we have to create acc out here and then declare it inside the statements or else the compiler
//won't think that it exists
if(mFlying){
acc = VectorF(0.0f, 0.0f, 0.0f);
}else{
acc = VectorF(0.0f, 0.0f, mGravity * mGravityMod * TickSec);
}Next scroll down just a little and find
// Acceleration on run surface
if (runSurface) {
mContactTimer = 0;change it to
// Acceleration on run surface
if (runSurface||mFlying) {
if(mFlying)
mContactTimer = 30;
else
mContactTimer = 0;Then scroll down a bit more and find
if (pvl) {
VectorF nn;
mCross(pv,VectorF(0,0,1),&nn);
nn *= 1 / pvl;
VectorF cv = contactNormal;
cv -= nn * mDot(nn,cv);
pv -= cv * mDot(pv,cv);
pvl = pv.len();
}change it to
if (pvl&&!mFlying) {
VectorF nn;
mCross(pv,VectorF(0.0f, 0.0f, 1.0f),&nn);
nn *= 1.0f / pvl;
VectorF cv = contactNormal;
cv -= nn * mDot(nn,cv);
pv -= cv * mDot(pv,cv);
pvl = pv.len();
}
#56
Scroll all the way back up to the top of Player::updateMove() and find
- continued in next post -
12/06/2007 (3:51 pm)
I've been following Matt's initial progression for a bit here. All I have had to do thus far is add an if statement or modify and existing one. It gets a bit tougher, but I tried to make it as nice as possible. For those of you who looked at the code you may have wondered where mFlying came from, I will provide the code that defines that later. Anyways time for the big code block.Scroll all the way back up to the top of Player::updateMove() and find
// Update current orientation
if (mDamageState == Enabled) {
F32 prevZRot = mRot.z;
delta.headVec = mHead;
F32 p = move->pitch;
if (p > M_PI) p -= M_2PI;
mHead.x = mClampF(mHead.x + p,mDataBlock->minLookAngle,
mDataBlock->maxLookAngle);
F32 y = move->yaw;
if (y > M_PI) y -= M_2PI;
GameConnection* con = getControllingClient();
if (move->freeLook && ((isMounted() && getMountNode() == 0) ||
(con && !con->isFirstPerson())))
{
mHead.z = mClampF(mHead.z + y,
-mDataBlock->maxFreelookAngle,
mDataBlock->maxFreelookAngle);
}
else
{
mRot.z += y;
// Rotate the head back to the front, center horizontal
// as well if we're controlling another object.
mHead.z *= 0.5;
if (mControlObject)
mHead.x *= 0.5;
}
// constrain the range of mRot.z
while (mRot.z < 0)
mRot.z += M_2PI;
while (mRot.z > M_2PI)
mRot.z -= M_2PI;
delta.rot = mRot;
delta.rotVec.x = delta.rotVec.y = 0;
delta.rotVec.z = prevZRot - mRot.z;
if (delta.rotVec.z > M_PI)
delta.rotVec.z -= M_2PI;
else if (delta.rotVec.z < -M_PI)
delta.rotVec.z += M_2PI;
delta.head = mHead;
delta.headVec -= mHead;
}
MatrixF zRot;
zRot.set(EulerF(0, 0, mRot.z));
// Desired move direction & speed
VectorF moveVec;
F32 moveSpeed;
if (mState == MoveState && mDamageState == Enabled)
{
zRot.getColumn(0,&moveVec);
moveVec *= move->x;
VectorF tv;
zRot.getColumn(1,&tv);
moveVec += tv * move->y;
// Clamp water movement- continued in next post -
#57
Now replace that code block with
well if I made any mistakes that is probably where they are. It does work though and I was surprised with how clean the code worked out to be.
12/06/2007 (3:54 pm)
- continue -Now replace that code block with
// Update current orientation
if (mDamageState == Enabled) {
Point3F prevRot = mRot;
delta.headVec = mHead;
F32 p = move->pitch;
if (p > M_PI_F)
p -= M_2PI_F;
mHead.x = mClampF(mHead.x + p,mDataBlock->minLookAngle,
mDataBlock->maxLookAngle);
F32 y = move->yaw;
if (y > M_PI_F)
y -= M_2PI_F;
GameConnection* con = getControllingClient();
if (move->freeLook && ((isMounted() && getMountNode() == 0) || (con && !con->isFirstPerson())))
{
mHead.z = mClampF(mHead.z + y,
-mDataBlock->maxFreelookAngle,
mDataBlock->maxFreelookAngle);
}
else
{
mRot.x += p;
mRot.z += y;
// Rotate the head back to the front, center horizontal
// as well if we're controlling another object.
mHead.z *= 0.5f;
if (mControlObject)
mHead.x *= 0.5f;
}
// constrain the range of mRot.z
while (mRot.z < 0.0f)
mRot.z += M_2PI_F;
while (mRot.z > M_2PI_F)
mRot.z -= M_2PI_F;
// constrain the range of mRot.x
if(mRot.x > 1.5706)
mRot.x = 1.5706;
else if(mRot.x < -1.5706)
mRot.x = -1.5706
delta.rot = mRot;
delta.rotVec = prevRot - mRot;
if (delta.rotVec.z > M_PI_F)
delta.rotVec.z -= M_2PI_F;
else if (delta.rotVec.z < -M_PI_F)
delta.rotVec.z += M_2PI_F;
delta.head = mHead;
delta.headVec -= mHead;
}
MatrixF zRot;
zRot.set(EulerF(0.0f, 0.0f, mRot.z));
if(mFlying){
MatrixF xRot;
xRot.set(EulerF(mRot.x, 0, 0));
zRot.mul(zRot, xRot); //well its not zrot anymore but the code is a bit more efficient this way
}
// Desired move direction & speed
VectorF moveVec;
F32 moveSpeed;
if (mState == MoveState && mDamageState == Enabled)
{
zRot.getColumn(0,&moveVec); //note that if you are flying its not zRot it is xzRot
moveVec *= move->x;
VectorF tv;
zRot.getColumn(1,&tv);
moveVec += tv * move->y;
if(mFlying){
zRot.getColumn(2,&tv);
moveVec += tv * move->z;
}
// Clamp water movementwell if I made any mistakes that is probably where they are. It does work though and I was surprised with how clean the code worked out to be.
#58
Now if you are like me and think that the falling animation looks better for flying around then jump over to Player::pickActionAnimation() and scroll down till you find:
change it to
Well that's where Matt left off but I get to keep going, hopefully I remember it all.
So lets go back up near the top to 'Player::Player()' under
put
find
above it put
I'm not sure if that's the "right" place but it works as well as any.
Now we are moving on over to player.h
under
put
a little bit under that find
under it add
Well I think that's all done. I didn't add Tom Spilman's change in this list but you should probably scroll up and add it, and make sure to add the onread packet stuff as well.
12/06/2007 (4:12 pm)
(I'm just going to copy what Matt said here because it works)Now if you are like me and think that the falling animation looks better for flying around then jump over to Player::pickActionAnimation() and scroll down till you find:
if (mContactTimer >= sContactTickTime) {
// Nothing under our feet
action = PlayerData::RootAnim;
}change it to
if (mContactTimer >= sContactTickTime) {
// Nothing under our feet
if(mFlying)
action = PlayerData::FallAnim;
else
action = PlayerData::RootAnim;
}Well that's where Matt left off but I get to keep going, hopefully I remember it all.
So lets go back up near the top to 'Player::Player()' under
mState = MoveState; mFalling = false;
put
mFlying = false;
find
ConsoleMethod( Player, getState, const char*, 2, 2, "Return the current state name.")
{
return object->getStateName();
}above it put
void Player::setFlying(bool Flying){
mFlying = Flying;
}
bool Player::getFlying(){
return mFlying;
}
//----------------------------------------------------------------------------
ConsoleMethod( Player, toggleFlying, bool, 2, 3, "(bool Flying)")
{
bool Flying = (argc > 2)? dAtob(argv[2]): !object->getFlying();
object->setFlying(Flying);
return 1;
}I'm not sure if that's the "right" place but it works as well as any.
Now we are moving on over to player.h
under
ActionState mState; ///< What is the player doing? @see ActionState bool mFalling; ///< Falling in mid-air?
put
bool mFlying; ///< Should we take off towards the sun?
a little bit under that find
static void consoleInit();
under it add
void setFlying(bool Flying); bool getFlying();
Well I think that's all done. I didn't add Tom Spilman's change in this list but you should probably scroll up and add it, and make sure to add the onread packet stuff as well.
#59
toggleFlying;
mFlying = true;
setFlying
mFlying
setFlying = true;
none of those worked.
12/08/2007 (4:04 pm)
Ok I got that code in, but what is the command to toggle it? I tried:toggleFlying;
mFlying = true;
setFlying
mFlying
setFlying = true;
none of those worked.
#60
mFlying = Flying
Player, toggleFlying, bool, 2, 3, "(bool Flying)"
Still none works.
12/09/2007 (8:22 am)
I just tried 2 more:mFlying = Flying
Player, toggleFlying, bool, 2, 3, "(bool Flying)"
Still none works.
Associate Andy Hawkins
DrewFX