•      Sign In
• Create Account

Restricting movement to a box

Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

7 replies to this topic

#1psy_commando  Members   -  Reputation: 127

Like
0Likes
Like

Posted 24 June 2012 - 10:15 PM

Hi, I'm working a 3d rail shooter, and I ran in a problem.

I'd like to restrict an aircraft's vertical and horizontal movement to an invisible plane of h height and w width around a middle point, but I'm not sure what's the best approach. I tried a simple check if the coordinate of the craft are within the bounds, but it doesn't work if the aircraft goes too fast. Any suggestions ?

Sponsor:

#2LorenzoGatti  Crossbones+   -  Reputation: 2006

Like
0Likes
Like

Posted 25 June 2012 - 03:28 AM

What do you mean by a "check"? You need to actually push back to the desired bounds an object that tries to escape, usually by altering computed positions (say previous position + velocity*time increment) to obtain valid values before they are treated as part of the game state (used for rendering, collisions, further updates, etc.) and cause trouble.

If your clipping doesn't work you must be either correcting positions improperly (leaving them outside bounds), or skipping corrections because you are making wrong assumptions, or using invalid positions before correcting them. Can you post a code example?
Produci, consuma, crepa

#3Bacterius  Crossbones+   -  Reputation: 5639

Like
0Likes
Like

Posted 25 June 2012 - 04:49 AM

Setting hard limits to a plane's position is generally not a good idea as it will look like your plane "bumps" into solid air. A better way is to apply a force to the plane pushing it back where it came from when it strays too far away from where it should be (similar to a magnet pushing away a metal ball rolling towards it). It will feel more natural. Another solution (used by many games) is to have the game display a warning message along the lines of "return to the battleground or you will be killed" if the plane goes outside the box, giving players a strong incentive to remain inside it. But this only works if the player has a point of reference to the space in which he is supposed to be, otherwise he will be confused.

Does that makes sense?

Edited by Bacterius, 25 June 2012 - 04:50 AM.

"The best comment is a deleted comment."

#4psy_commando  Members   -  Reputation: 127

Like
0Likes
Like

Posted 25 June 2012 - 10:37 AM

What do you mean by a "check"? You need to actually push back to the desired bounds an object that tries to escape, usually by altering computed positions (say previous position + velocity*time increment) to obtain valid values before they are treated as part of the game state (used for rendering, collisions, further updates, etc.) and cause trouble.

If your clipping doesn't work you must be either correcting positions improperly (leaving them outside bounds), or skipping corrections because you are making wrong assumptions, or using invalid positions before correcting them. Can you post a code example?

Alright, well I'm not correcting so that might be the problem, I simply remove the part of the velocity taking it outside when it reach a bound.
Here's the code, its pretty messy this far :

m_fPitchAxis and m_fYawAxis are misnamed inputs from the mouse, their value range from -1.0f to 1.0f
m_vReferencePoint is the center of the plane, and the origin of the local space below.

		 Vector vCamRight = CrossProduct( Vector(0,0,1), m_vCameraForward );
m_vCurrentVelocity = vec3_origin; //Reset velocity to 0

if( m_fPitchAxis != 0.0f && GetAbsVelocity().Length() < GetMaxSpeed() )
{
m_fVerticalSpeed += GetVerticalAccel();
}
if( m_fYawAxis != 0.0f && GetAbsVelocity().Length() < GetMaxSpeed() )
{
m_fHorizontalSpeed += GetHorizontalAccel();
}
if( m_fPitchAxis == 0.0f && m_fVerticalSpeed > 0.0f )
{
m_fVerticalSpeed -= GetVerticalAccel() * 2.0f;
}
if( m_fYawAxis == 0.0f && m_fHorizontalSpeed > 0.0f )
{
m_fHorizontalSpeed -= GetHorizontalAccel() * 2.0f;
}

Vector vLocalPosition = GetAbsOrigin() - m_vReferencePoint;
Vector diffZ( 0, 0, m_fYawAxis >= 0 ? sfr_fighter_max_move_height.GetFloat() : -sfr_fighter_max_move_height.GetFloat() ),
diffX( m_fPitchAxis >= 0 ? sfr_fighter_max_move_width.GetFloat() : -sfr_fighter_max_move_width.GetFloat(), 0, 0 );
diffZ -= vLocalPosition;
diffX -= vLocalPosition;

diffZ.x = 0;
diffZ.y = 0;
diffX.y = 0;
diffX.z = 0;

if( ( diffX.Length() - abs(m_fYawAxis) * m_fHorizontalSpeed * gpGlobals->frametime * 2.0f ) > 0 )
m_vCurrentVelocity += m_fYawAxis * vCamRight * m_fHorizontalSpeed  * gpGlobals->frametime;

if( ( diffZ.Length() - abs(m_fPitchAxis) * m_fVerticalSpeed * gpGlobals->frametime * 2.0f ) > 0 )
m_vCurrentVelocity += m_fPitchAxis *  Vector(0,0,1) * m_fVerticalSpeed * gpGlobals->frametime;


Setting hard limits to a plane's position is generally not a good idea as it will look like your plane "bumps" into solid air. A better way is to apply a force to the plane pushing it back where it came from when it strays too far away from where it should be (similar to a magnet pushing away a metal ball rolling towards it). It will feel more natural. Another solution (used by many games) is to have the game display a warning message along the lines of "return to the battleground or you will be killed" if the plane goes outside the box, giving players a strong incentive to remain inside it. But this only works if the player has a point of reference to the space in which he is supposed to be, otherwise he will be confused.

Does that makes sense?

Well it makes sense, but There's not much room to allow the player to wander off, he'd hit the sky render target brush, which would look pretty odd.

Here's what I'd like to do :
http://youtu.be/jDU4WzM3NsM?t=1m27s
A few seconds in the video, when the player reach the top left corner, he can't move outside the limit at all. That what I'm looking for.

#5LorenzoGatti  Crossbones+   -  Reputation: 2006

Like
1Likes
Like

Posted 26 June 2012 - 01:55 AM

In your code, some aspects are gratuitously complicated and error-prone:
• correcting velocities instead of positions
• dealing with signs, sign comparisons, and absolute values instead of respecting the signed values of vector components
• using local coordinates even if they make the task (keeping the airplane inside a world-space box) more difficult
• using vectors instead of scalars (diffX and diffZ)

Your game state should contain the world-space position and velocity of the airplane, say m_Position and m_Velocity.
The update should compute:
• Acceleration from air friction (which doesn't seem to be considered in your code) depending on m_Velocity, and from user inputs (throttle, also apparently missing, pitch and yaw). By the way, what you are currently doing isn't very clear.
• A tentative position
new_Position=m_Position+frametime*(m_Velocity+frametime*0.5*acceleration)
• A valid position (assuming the acceptable region is minX<=x<=maxX, minZ<=z<=maxZ extruded along axis Y)
if (new_Position.x<minX) new_Position.x=minX;
if (new_Position.x>maxX) new_Position.x=maxX;
if (new_Position.z<minZ) new_Position.z=minZ;
if (new_Position.z>maxZ) new_Position.z=maxZ;

(note that this correction amounts to steering or accelerating a bit "less" than the normal response),
• Finally, the state for the new frame:
m_Velocity=(new_Position-m_Position)/frametime;
m_Position=new_Position.
Obviously, eliminating frametime by making it a constant would simplify the computations. A better integration scheme would also be a good idea.
Produci, consuma, crepa

#6psy_commando  Members   -  Reputation: 127

Like
0Likes
Like

Posted 26 June 2012 - 05:51 PM

In your code, some aspects are gratuitously complicated and error-prone:

Yeah, my prog teachers tell me that all the time

• correcting velocities instead of positions
• dealing with signs, sign comparisons, and absolute values instead of respecting the signed values of vector components
• using local coordinates even if they make the task (keeping the airplane inside a world-space box) more difficult
• using vectors instead of scalars (diffX and diffZ)

Noted, thanks. Though I'm not sure what you mean by # 2.

Your game state should contain the world-space position and velocity of the airplane, say m_Position and m_Velocity.
The update should compute:

• Acceleration from air friction (which doesn't seem to be considered in your code) depending on m_Velocity, and from user inputs (throttle, also apparently missing, pitch and yaw). By the way, what you are currently doing isn't very clear.
• A tentative position
new_Position=m_Position+frametime*(m_Velocity+frametime*0.5*acceleration)
• A valid position (assuming the acceptable region is minX<=x<=maxX, minZ<=z<=maxZ extruded along axis Y)
if (new_Position.x<minX) new_Position.x=minX;
if (new_Position.x>maxX) new_Position.x=maxX;
if (new_Position.z<minZ) new_Position.z=minZ;
if (new_Position.z>maxZ) new_Position.z=maxZ;

(note that this correction amounts to steering or accelerating a bit "less" than the normal response),
• Finally, the state for the new frame:
m_Velocity=(new_Position-m_Position)/frametime;
m_Position=new_Position.

Yeah, its a pretty arcadish game I'm doing, so I didn't bother calculating, lift, drag, and all that.
Anyways, I'll try to clarify a little what I'm trying to do here. Basically, I'm trying to do a on-rail shooter like that vid I showed earlier. The code I pasted here is basically just the part that handles up/down and left/right movement around the reference point. The reference point is the current position on the path the aircraft is following. And thats pretty much why there isn't a throttle input or brakes yet,

In the equation for the new position, is acceleration a vector ? And from where does the 0.5 comes from ?

By the way, if you have any advices on following a path while being free to move around it, I could use those.

Obviously, eliminating frametime by making it a constant would simplify the computations. A better integration scheme would also be a good idea.

A better integration scheme ? What do you mean.

Edited by psy_commando, 26 June 2012 - 06:02 PM.

#7LorenzoGatti  Crossbones+   -  Reputation: 2006

Like
1Likes
Like

Posted 27 June 2012 - 02:09 AM

• As you can see in my suggestions, the only comparison you need are between vector components and arbitrary constants and all other operations done to vectors are additions and multiplications by scalars: there is no use for the sign and the absolute value of vector components.
• Acceleration and velocity are vectors, as should be obvious from how they are used.
• Whatever you do to compute the airplane's acceleration, you still use acceleration in the same way to compute velocity and position. Considering air drag and throttle was only a generic suggestion.
• Multiplying the acceleration by 0.5 means using the average velocity between the start and the end of the frame interval. Consult physics textbooks for details.
• This formula defines the "integration scheme" that translates continuous-time kinematic equations to discrete-time simulations, integrating your arbitrary accelerations to get a sequence of positions; I chose a trivial and rather bad one for simplicity, but other formulas containing "actual" or estimated position, velocity and acceleration at various times work better.

Edited by LorenzoGatti, 27 June 2012 - 02:12 AM.

Produci, consuma, crepa

#8psy_commando  Members   -  Reputation: 127

Like
0Likes
Like

Posted 28 June 2012 - 07:08 PM

Thanks, it works.

Sorry, I should have mentioned that before, but I wanted to make it able to rotate on the z axis too. I guess I'll have to compute a matrix for that ?
Fixed, now I just need to slow down the aircraft movement on the corresponding axis when controls are neutral. What's the simplest approach ?

Edited by psy_commando, 28 June 2012 - 10:59 PM.

Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

PARTNERS