📄 ski.cpp
字号:
*/
TSkierAttribs& CSkier::Attribs()
{
return iAttribs;
}
/**
* Returns a flag to indicate whether or not the skier is currently jumping
* @retval ETrue the skier is jumping
* @retval EFalse the skier is not jumping
*/
TBool CSkier::Jumping() const
{
return iJumping;
}
/**
* Sets a flag that indicates whether or not the skier is currently jumping
* @param the required jump state for the skier
*/
void CSkier::SetJumping(TBool aJump)
{
iJumping = aJump;
}
/**
* Accesses the magnitude of the maximum velocity
* @return the maximum velocity
*/
TReal CSkier::MaxVel() const
{
return iMaxVel;
}
/**
* Sets the magnitude of the maximum velocity
* @param the maximum velocity
*/
void CSkier::SetMaxVel(TReal aVel)
{
iMaxVel = aVel;
}
/**
* Gets the force that the skier jumps with
* @return the jump force
*/
TInt CSkier::DefJumpForce() const
{
return iDefJumpForce;
}
/**
* Sets the force that the skier jumps with
* @param the jump force
*/
void CSkier::SetDefJumpForce(TInt aForce)
{
iDefJumpForce = aForce;
}
/**
* Gets the friction factor that opposes the skier's motion
* @param aCoeff the friction factor
*/
TReal CSkier::CoeffOfRestitution() const
{
return iCoeff;
}
/**
* Set the friction factor opposing the skier's motion
* @param aCoeff the friction factor
*/
void CSkier::SetCoeffOfRestitution(TReal aCoeff)
{
iCoeff = aCoeff;
}
/**
* Determine the skier's current acceleration from its direction
* @return the skier's acceleration
*/
TSkiVector CSkier::GetAccelFromState() const
{
switch (iAttribs.State())
{
case TSkierAttribs::ESkier0 :
case TSkierAttribs::ESkier180 :
return TSkiVector(0.0f, 0.0f);
case TSkierAttribs::ESkier30 :
return TSkiVector(-KSkiingMaxXAccel, KSkiingMinYAccel);
case TSkierAttribs::ESkier60 :
return TSkiVector(-KSkiingMaxXAccel, KSkiingMaxYAccel);
case TSkierAttribs::ESkier90 :
return TSkiVector(0.0f, 1.0f);
case TSkierAttribs::ESkier120 :
return TSkiVector(KSkiingMaxXAccel, KSkiingMaxYAccel);
case TSkierAttribs::ESkier150 :
return TSkiVector(KSkiingMaxXAccel, KSkiingMinYAccel);
default:
break;
}
return TSkiVector();
}
/**
* Make sure that the skier doesn't exceed the maximum velocity
*/
void CSkier::LimitVelocity()
{
TSkiVector vel = iAttribs.Vel();
if (vel.Magnitude() > iMaxVel)
{
vel.Normalize();
vel.iX *= iMaxVel;
vel.iY *= iMaxVel;
}
//vel.iX *= iCoeff;
//vel.iY *= iCoeff;
// we don't want the skier to go backwards!
if (vel.iY < 0.0f)
{
vel.iY = 0.0f;
}
iAttribs.SetVel(vel);
}
/**
* Update the attributes of the skier eg. increase velocity
* by acceleration
*/
void CSkier::Update()
{
if (iJumping)
{
TInt elev = iAttribs.Elevation();
TInt netForce = iAttribs.JumpForce() - iAttribs.Gravity();
iAttribs.SetJumpForce(netForce);
elev += netForce;
if (elev < 0)
{
// reset
elev = 0;
iJumping = EFalse;
iAttribs.SetJumpForce(iDefJumpForce);
}
iAttribs.SetElevation(elev);
}
// update velocity by acceleration
iAttribs.SetAccel(GetAccelFromState());
TSkiVector vel = iAttribs.Vel() + iAttribs.Accel();
iAttribs.SetVel(vel);
DoFriction();
LimitVelocity();
iAttribs.SetPosn(iAttribs.Posn() + vel);
}
/**
* Limit the motion of the skier with friction
*/
void CSkier::DoFriction()
{
TSkiVector vel = iAttribs.Vel();
TSkiVector accel = iAttribs.Accel();
vel.Normalize();
accel.Normalize();
// find proportion of velocity in direction of accel
TReal dot = vel.DotProduct(accel);
// find part of velocity not in direction of acceleration
vel = iAttribs.Vel();
TSkiVector velProjection(vel.iX * dot, vel.iY * dot);
TSkiVector diff = vel - velProjection;
// account for friction force opposing motion of skier not in direction
// of skies
diff.iX *= iCoeff;
diff.iY *= iCoeff;
vel = velProjection + diff;
iAttribs.SetVel(vel);
}
/**
* Returns the skier to the default state
*/
void CSkier::Reset()
{
iJumping = EFalse;
iAttribs.SetElevation(0);
iAttribs.SetAccel(TSkiVector(0.0f, 0.0f));
iAttribs.SetVel(TSkiVector(0.0f, 0.0f));
}
/**
* Get's the skier's bounding rectangle
* @return the bounding rectangle
*/
TRect CSkier::GetRect() const
{
// get skier position as a TPoint
TSkiVector posVect = iAttribs.Posn();
TPoint skierPosn(static_cast<TInt>(posVect.iX), static_cast<TInt>(posVect.iY));
// from MMapPrimitiveToRectConverter::CreateRect
TSize skierSize = iAttribs.SkierSize();
TRect skierRect(skierPosn, skierSize);
// map position is bottom centre of object
skierRect.Move(-skierSize.iWidth / 2, -skierSize.iHeight);
return skierRect;
}
//
// TSkiVector::
//
/**
* Default c++ constructor
*/
TSkiVector::TSkiVector():
iX(0.0f),
iY(0.0f)
{
}
/**
* c++ constructor
* @param aX the x direction of the vector
* @param aY the y direction of the vector
*/
TSkiVector::TSkiVector(TReal aX, TReal aY):
iX(aX),
iY(aY)
{
}
/**
* operator overload
*/
TSkiVector TSkiVector::operator+(const TSkiVector& aVector) const
{
return TSkiVector(iX + aVector.iX, iY + aVector.iY);
}
/**
* operator overload
*/
TSkiVector TSkiVector::operator-(const TSkiVector& aVector) const
{
return TSkiVector(iX - aVector.iX, iY - aVector.iY);
}
/**
* Find the dot product of this vector and another vector
* @param aVector the vector to dot his vector with
* @return the dot product
*/
TReal TSkiVector::DotProduct(const TSkiVector& aVector) const
{
return (iX * aVector.iX) + (iY * aVector.iY);
}
/**
* Find the magnitude of this vector
* @return the magnitude
*/
TReal TSkiVector::Magnitude() const
{
TReal magSqrd = (iX * iX) + (iY * iY);
TReal mag;
TInt err = Math::Sqrt(mag, magSqrd);
return err == KErrNone ? mag : 0.0f;
}
/**
* Normalize this vector
*/
TInt TSkiVector::Normalize()
{
TReal mag = Magnitude();
if (mag == 0)
{
return KErrDivideByZero;
}
iX /= mag;
iY /= mag;
return KErrNone;
}
//
// TScrollDriver::
//
/**
* C++ constructor
* @param aAttribs screen attributes
* @param aMapLimits the size of the play area
* @param aScrollBox the size of an invisible box in the centre of the screen. The game scrolls when
* the skier moves outside of this box
*/
TScrollDriver::TScrollDriver(TSkiScreenAttribs& aAttribs, TSize aMapLimits, TSize aScrollBox) :
iAttribs(aAttribs),
iLimits(aMapLimits),
iScrollBox(aScrollBox)
{
}
/**
* C++ constructor
* @param aAttribs screen attributes
*/
TScrollDriver::TScrollDriver(TSkiScreenAttribs& aAttribs) :
iAttribs(aAttribs)
{
}
/**
* Updates the screen offset with respect to the new position and the scrollbox size
* @param aPosn the new position
*/
void TScrollDriver::Move(TPoint aPosn)
{
TRect scrRect = iAttribs.Rect();
TRect scrBox = GetScrollBox();
// If the map co-ordinate aPosn is outside of the scroll box, update
// the screen offset. The screen offset is the top left hand corner of the
// screen rectangle. Changing this causes the scrolling.
//
if (!scrBox.Contains(aPosn))
{
TPoint oldOffset = iAttribs.Offset();
TPoint newOffset = oldOffset;
if (aPosn.iX < scrBox.iTl.iX)
{
newOffset.iX += aPosn.iX - scrBox.iTl.iX;
}
else if (aPosn.iX > scrBox.iBr.iX)
{
newOffset.iX += aPosn.iX - scrBox.iBr.iX;
}
if (aPosn.iY < scrBox.iTl.iY)
{
newOffset.iY += aPosn.iY - scrBox.iTl.iY;
}
else if (aPosn.iY > scrBox.iBr.iY)
{
newOffset.iY += aPosn.iY - scrBox.iBr.iY;
}
iAttribs.SetOffset(newOffset);
if (KeptOffsetInMap(newOffset, oldOffset))
{
iAttribs.SetOffset(newOffset);
}
else
{
TPoint oldTopRight(scrRect.iBr.iX, scrRect.iTl.iY);
scrRect = iAttribs.Rect();
TPoint newTopRight(scrRect.iBr.iX, scrRect.iTl.iY);
if (KeptOffsetInMap(newTopRight, oldTopRight))
{
newTopRight.iX -= scrRect.Size().iWidth;
iAttribs.SetOffset(newTopRight);
}
}
}
}
/**
* Returns the scroll box
* @return the scroll box
*/
TRect TScrollDriver::GetScrollBox() const
{
// The screen rectangle is in terms of map co-ordinates, not screen
// co-ordinates. By shrinking and shifting a copy of the screen
// rectangle, we can create the scrollbox in terms of map co-ordinates
TRect scrRect = iAttribs.Rect();
TSize scrRectSize = scrRect.Size();
TInt xShrink = (scrRectSize.iWidth - iScrollBox.iWidth) / 2;
TInt yShrink = (scrRectSize.iHeight - iScrollBox.iHeight) / 2;
scrRect.Shrink(xShrink, yShrink);
scrRect.Move(iOffset); // scrRect is now the scroll box
return scrRect;
}
/**
* Method to ensure that the offset value (the coordinate of the top left of the screen)
* stays in the map
* @param aOffset the offset
* @param the previous position
* @return a boolean flag to indicate if aOffset has been changed
*/
TBool TScrollDriver::KeptOffsetInMap(TPoint& aOffset, TPoint aPrevious)
{
TPoint tempOffset = aOffset;
TRect map(iLimits);
TBool retVal = !map.Contains(aOffset);
if (retVal)
{
// could be just the x or y coordinate responsible for
// entering here, so need to try both combinations of
// possible offset value
tempOffset.iX = aPrevious.iX;
if (!map.Contains(tempOffset))
{
tempOffset = aOffset;
tempOffset.iY = aPrevious.iY;
if (!map.Contains(tempOffset))
tempOffset = aPrevious;
}
}
aOffset = tempOffset;
return retVal;
}
/**
* Gets the size of the map limits
* @return the size of the map
*/
TSize TScrollDriver::Limits() const
{
return iLimits;
}
/**
* Sets the size of the map limits
* @param the new size of the map
*/
void TScrollDriver::SetLimits(TSize aSize)
{
iLimits = aSize;
}
/**
* Gets the size of the scroll box
* @return the size of the scroll box
*/
TSize TScrollDriver::ScrollBox() const
{
return iScrollBox;
}
/**
* Sets the size of the scroll box
* @param the size of the scroll box
*/
void TScrollDriver::SetScrollBox(TSize aSize)
{
iScrollBox = aSize;
}
/**
* Returns the offset of the scrollbox
* @return the offset
*/
TPoint TScrollDriver::Offset() const
{
return iOffset;
}
/**
* Sets the offset of the scrollbox
* @param the offset
*/
void TScrollDriver::SetOffset(TPoint aPosn)
{
iOffset = aPosn;
}
//
// TSkierCollisionResponse::
//
/**
* C++ constructor
* @param aAttribs the skier's attributes
*/
TSkierCollisionResponse::TSkierCollisionResponse(TSkierAttribs& aAttribs) :
iAttribs(aAttribs)
{
}
/**
* Caches the fall position and updates the skier's state
* @param aResartPosn The restart position to be cached
*/
void TSkierCollisionResponse::Fall(const TPoint aRestartPosn)
{
iRestartPosn = aRestartPosn;
iFallTick = iAttribs.FallTickCount();
iAttribs.SetState(TSkierAttribs::ESkierFall);
}
/**
* Decrements a fall counter. When this expires, the skier is updated so that it stands
* @return a boolean flag to indicate whether or not the skier is standing
*/
TBool TSkierCollisionResponse::SkierStanding()
{
if (--iFallTick <= 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -