8.6 KiB
8.6 KiB
Code Patterns - C++ to C# Conversions
Abstract Base Classes
C++ Pattern
class CGfxMoveBase
{
protected:
CGfxMoveBase(GfxMoveMode mode) : m_Mode(mode) {}
public:
virtual ~CGfxMoveBase() {}
virtual void StartMove(const A3DVECTOR3& vHost, const A3DVECTOR3& vTarget) = 0;
virtual bool TickMove(DWORD dwDeltaTime, ...) = 0;
virtual void SetParam(const GFX_SKILL_PARAM* param) { /* default impl */ }
static CGfxMoveBase* CreateMoveMethod(GfxMoveMode mode);
};
C# Pattern
public abstract class CGfxMoveBase
{
protected CGfxMoveBase(GfxMoveMode mode)
{
m_Mode = mode;
}
// Pure virtual (= 0) → abstract
public abstract void StartMove(Vector3 vHost, Vector3 vTarget);
public abstract bool TickMove(uint dwDeltaTime, ...);
// Virtual with default → virtual
public virtual void SetParam(GFX_SKILL_PARAM param)
{
// default implementation
}
// Static factory method
public static CGfxMoveBase CreateMoveMethod(GfxMoveMode mode)
{
switch (mode)
{
case GfxMoveMode.enumLinearMove: return new CGfxLinearMove(mode);
default: return new CGfxLinearMove(mode);
}
}
}
Inheritance Patterns
C++ Pattern
class CGfxLinearMove : public CGfxMoveBase
{
protected:
float m_fSpeed;
public:
CGfxLinearMove(GfxMoveMode mode) : CGfxMoveBase(mode) {}
virtual void StartMove(const A3DVECTOR3& vHost, const A3DVECTOR3& vTarget);
virtual bool TickMove(DWORD dwDeltaTime, ...);
};
C# Pattern
public class CGfxLinearMove : CGfxMoveBase
{
protected float m_fSpeed;
public CGfxLinearMove(GfxMoveMode mode) : base(mode) { }
public override void StartMove(Vector3 vHost, Vector3 vTarget)
{
// implementation
}
public override bool TickMove(uint dwDeltaTime, ...)
{
// implementation
}
}
Static Factory Methods
C++ Pattern
inline CGfxMoveBase* CGfxMoveBase::CreateMoveMethod(GfxMoveMode mode)
{
switch(mode)
{
case enumLinearMove:
return new CGfxLinearMove(mode);
case enumOnTarget:
return new CGfxOnTargetMove(mode);
default:
assert(false);
return NULL;
}
}
C# Pattern
public static CGfxMoveBase CreateMoveMethod(GfxMoveMode mode)
{
switch (mode)
{
case GfxMoveMode.enumLinearMove:
return new CGfxLinearMove(mode);
case GfxMoveMode.enumOnTarget:
return new CGfxOnTargetMove(mode);
default:
return new CGfxLinearMove(mode); // fallback
}
}
Vector Operations
Normalize Pattern
C++:
A3DVECTOR3 vDir = vTarget - m_vPos;
float fDist = vDir.Normalize(); // In-place normalize, returns magnitude
if (fDist < 1e-4f) return true;
C#:
Vector3 vDir = vTarget - m_vPos;
float fDist = Normalize(ref vDir); // Helper method
if (fDist < 1e-4f) return true;
// Helper implementation:
protected static float Normalize(ref Vector3 v)
{
float mag = v.magnitude;
if (mag < 1e-6f) { v = Vector3.zero; return 0f; }
v /= mag;
return mag;
}
Vector Math
C++:
m_vPos += vFlyDir * fFlyDist;
m_vMoveDir = vFlyDir;
C#:
m_vPos += vFlyDir * fFlyDist;
m_vMoveDir = vFlyDir;
Protected Helper Methods
C++ Pattern
protected:
void CalcRange(const A3DVECTOR3& vDir)
{
m_vYRange = _unit_y;
m_vZRange.Set(vDir.x, 0, vDir.z);
if (m_vZRange.Normalize() < .01f) m_vZRange = _unit_z;
m_vXRange = CrossProduct(m_vYRange, m_vZRange);
// ...
}
A3DVECTOR3 GetRandOff() const
{
if (m_Shape == enumBox)
{
// ...
}
// ...
}
C# Pattern
protected void CalcRange(Vector3 vDir)
{
m_vYRange = Vector3.up;
m_vZRange = new Vector3(vDir.x, 0, vDir.z);
if (Normalize(ref m_vZRange) < 0.01f) m_vZRange = Vector3.forward;
m_vXRange = Vector3.Cross(m_vYRange, m_vZRange);
// ...
}
protected Vector3 GetRandOff()
{
if (m_Shape == EmitShape.enumBox)
{
// ...
}
// ...
}
State Machine Pattern
C++ Pattern
enum
{
enumWait,
enumFlying,
enumHit,
enumFinished
} m_enumState;
void Tick(DWORD dwDeltaTime)
{
if (m_enumState == enumFinished) return;
else if (m_enumState == enumHit)
{
// handle hit state
}
else if (m_enumState == enumWait)
{
if (m_dwCurSpan < m_dwDelayTime) return;
m_enumState = enumFlying;
}
else // enumFlying
{
if (m_pMoveMethod.TickMove(dwDeltaTime, ...))
HitTarget(GetTargetCenter());
}
}
C# Pattern
protected GfxSkillEventState m_enumState;
public virtual void Tick(uint dwDeltaTime)
{
if (m_enumState == GfxSkillEventState.enumFinished) return;
else if (m_enumState == GfxSkillEventState.enumHit)
{
// handle hit state
}
else if (m_enumState == GfxSkillEventState.enumWait)
{
if (m_dwCurSpan < m_dwDelayTime) return;
m_enumState = GfxSkillEventState.enumFlying;
}
else // enumFlying
{
if (m_pMoveMethod.TickMove(dwDeltaTime, ...))
HitTarget(GetTargetCenter());
}
}
Const Correctness → Readonly
C++ Pattern
const A3DVECTOR3& GetPos() const { return m_vPos; }
GfxMoveMode GetMode() const { return m_Mode; }
C# Pattern
public Vector3 GetPos() { return m_vPos; } // No const needed
public GfxMoveMode GetMode() { return m_Mode; } // No const needed
Delegate Pattern (Virtual Methods)
C++ Pattern
class A3DSkillGfxEvent
{
CGfxMoveBase* m_pMoveMethod;
public:
GfxMoveMode GetMode() const { return m_pMoveMethod->GetMode(); }
void SetReverse(bool bReverse) const { m_pMoveMethod->SetReverse(bReverse); }
void SetParam(const GFX_SKILL_PARAM* param) { m_pMoveMethod->SetParam(param); }
};
C# Pattern
public class A3DSkillGfxEvent
{
protected CGfxMoveBase m_pMoveMethod;
public GfxMoveMode GetMode() { return m_pMoveMethod.GetMode(); }
public void SetReverse(bool bReverse) { m_pMoveMethod.SetReverse(bReverse); }
public void SetParam(GFX_SKILL_PARAM param) { m_pMoveMethod.SetParam(param); }
}
Random Number Generation
C++ Pattern
float _SymmetricRandom() { return (rand() / (float)RAND_MAX) * 2.0f - 1.0f; }
float _UnitRandom() { return rand() / (float)RAND_MAX; }
A3DVECTOR3 GetRandOff() const
{
if (m_Shape == enumBox)
{
A3DVECTOR3 xOff, yOff, zOff;
xOff = _SymmetricRandom() * m_vXRange;
yOff = _SymmetricRandom() * m_vYRange;
zOff = _SymmetricRandom() * m_vZRange;
return xOff + yOff + zOff;
}
}
C# Pattern
private static float SymRandom()
{
return UnityEngine.Random.value * 2f - 1f;
}
private static float UnitRandom()
{
return UnityEngine.Random.value;
}
protected Vector3 GetRandOff()
{
if (m_Shape == EmitShape.enumBox)
{
Vector3 xOff = SymRandom() * m_vXRange;
Vector3 yOff = SymRandom() * m_vYRange;
Vector3 zOff = SymRandom() * m_vZRange;
return xOff + yOff + zOff;
}
}
Conditional Compilation → #if UNITY_EDITOR
C++ Pattern
#ifdef _DEBUG
assert(false);
#endif
C# Pattern
#if UNITY_EDITOR
UnityEngine.Debug.Assert(false);
#endif
Memory Management Patterns
C++ Pattern
void ReleaseFlyGfx()
{
if (m_pFlyGfx)
{
if (m_bFadeOut)
AfxGetGFXExMan()->QueueFadeOutGfx(m_pFlyGfx, 1000);
else
{
m_pFlyGfx->Release();
delete m_pFlyGfx;
}
m_pFlyGfx = NULL;
}
}
C# Pattern
protected void ReleaseFlyGfx()
{
if (m_pFlyGfx != null)
{
if (m_bFadeOut)
AfxGetGFXExMan().QueueFadeOutGfx(m_pFlyGfx, 1000);
else
{
m_pFlyGfx.Release();
// C#: Automatic garbage collection, no delete needed
}
m_pFlyGfx = null;
}
}
Common Conversion Checklist
When converting a class:
- Abstract base →
abstract class - Pure virtual methods →
abstractmethods - Virtual with default →
virtualmethods - Non-virtual → regular methods
- Static factory →
staticmethod - Const methods → regular methods (no const)
- Pointers → references (remove
*) - References → value types or
ref/out DWORD→uintA3DVECTOR3→Vector3- Union access →
param.value.fVal - Hungarian notation → preserved