first commit
This commit is contained in:
@@ -0,0 +1,202 @@
|
||||
using System.Drawing.Drawing2D;
|
||||
|
||||
namespace TempleRun;
|
||||
|
||||
/// <summary>
|
||||
/// 全局常量与可调参数。想改手感直接改这里。
|
||||
/// 世界坐标约定:X 向右为正,Y 离地向上为正,Z 玩家前方为正。
|
||||
/// 玩家永远停在 Z = 0,世界向 Z 负方向滚动。
|
||||
/// </summary>
|
||||
public static class Cfg
|
||||
{
|
||||
// ---- 相机(透视投影参数)----
|
||||
public const float Focal = 520f; // 焦距:越大视野越窄、远处物体越大
|
||||
public const float CamZ = 235f; // 相机位于玩家后方多远
|
||||
public const float CamHeight = 142f; // 相机离地高度
|
||||
public const float FarZ = 3000f; // 渲染最远距离
|
||||
public const float MinDepth = 45f; // 相机空间最小深度,防止除零
|
||||
|
||||
// ---- 跑道 ----
|
||||
public const int LaneCount = 3;
|
||||
public const float LaneWidth = 112f; // 单条车道宽
|
||||
public const float RoadHalfWidth = LaneWidth * 1.5f;
|
||||
|
||||
// ---- 玩家 ----
|
||||
public const float PlayerHeight = 62f; // 站立高度
|
||||
public const float SlideHeight = 30f; // 滑铲高度
|
||||
public const float PlayerHalfDepth = 22f;
|
||||
public const float JumpSpeed = 430f;
|
||||
public const float Gravity = 950f;
|
||||
public const float LaneLerp = 13f; // 换道插值速度
|
||||
public const float SlideDuration = 0.55f;
|
||||
|
||||
// ---- 速度与难度 ----
|
||||
public const float StartSpeed = 620f;
|
||||
public const float MaxSpeed = 1900f;
|
||||
public const float SpeedAccel = 3.4f; // 每秒自然加速
|
||||
public const float SpeedPerCoin = 5f; // 每金币额外加速
|
||||
public const float SpawnIntervalMin = 0.62f; // 相邻障碍组最小时间间隔(秒)
|
||||
public const float SpawnIntervalMax = 1.15f;
|
||||
|
||||
// ---- 颜色(丛林日落 + 古神庙)----
|
||||
public static readonly Color SkyTop = Color.FromArgb(30, 34, 72);
|
||||
public static readonly Color SkyMid = Color.FromArgb(122, 78, 96);
|
||||
public static readonly Color SkyHorizon = Color.FromArgb(240, 168, 96);
|
||||
public static readonly Color Fog = Color.FromArgb(200, 152, 118);
|
||||
public static readonly Color GroundNear = Color.FromArgb(44, 36, 28);
|
||||
public static readonly Color GroundFar = Color.FromArgb(122, 100, 78);
|
||||
public static readonly Color RoadA = Color.FromArgb(178, 150, 110);
|
||||
public static readonly Color RoadB = Color.FromArgb(156, 130, 94);
|
||||
public static readonly Color Stone = Color.FromArgb(120, 112, 104);
|
||||
public static readonly Color Wood = Color.FromArgb(122, 82, 48);
|
||||
public static readonly Color Vine = Color.FromArgb(74, 116, 62);
|
||||
public static readonly Color Gold = Color.FromArgb(255, 202, 62);
|
||||
public static readonly Color GoldDark = Color.FromArgb(196, 140, 24);
|
||||
public static readonly Color Player = Color.FromArgb(226, 92, 62);
|
||||
|
||||
public static float LaneX(int lane) => (lane - 1) * LaneWidth;
|
||||
|
||||
public static Color Lerp(Color a, Color b, float t)
|
||||
{
|
||||
t = Math.Clamp(t, 0f, 1f);
|
||||
return Color.FromArgb(
|
||||
(int)(a.R + (b.R - a.R) * t),
|
||||
(int)(a.G + (b.G - a.G) * t),
|
||||
(int)(a.B + (b.B - a.B) * t));
|
||||
}
|
||||
}
|
||||
|
||||
public enum RunState { Ready, Playing, Paused, GameOver }
|
||||
|
||||
public enum ObstacleKind
|
||||
{
|
||||
/// <summary>矮障碍:必须跳跃</summary>
|
||||
Low,
|
||||
/// <summary>悬空横梁:必须滑铲</summary>
|
||||
High,
|
||||
/// <summary>整道石墙:必须换道</summary>
|
||||
Full
|
||||
}
|
||||
|
||||
/// <summary>透视相机:把世界坐标投影到屏幕坐标。</summary>
|
||||
public static class Cam
|
||||
{
|
||||
public static float CenterX;
|
||||
public static float HorizonY;
|
||||
public static int Width;
|
||||
public static int Height;
|
||||
|
||||
public static void Setup(int w, int h)
|
||||
{
|
||||
Width = w;
|
||||
Height = h;
|
||||
CenterX = w * 0.5f;
|
||||
HorizonY = h * 0.30f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 投影一个世界点。
|
||||
/// scale 为"每世界单位对应多少像素",用于缩放实体自身尺寸。
|
||||
/// </summary>
|
||||
public static void Project(float x, float y, float z, out float sx, out float sy, out float scale)
|
||||
{
|
||||
float depth = z + Cfg.CamZ;
|
||||
if (depth < Cfg.MinDepth) depth = Cfg.MinDepth;
|
||||
scale = Cfg.Focal / depth;
|
||||
sx = CenterX + x * scale;
|
||||
sy = HorizonY + (Cfg.CamHeight - y) * scale;
|
||||
}
|
||||
|
||||
/// <summary>只投影地面上的点(y = 0)。</summary>
|
||||
public static void ProjectGround(float x, float z, out float sx, out float sy, out float scale)
|
||||
=> Project(x, 0f, z, out sx, out sy, out scale);
|
||||
|
||||
/// <summary>距离雾化系数:0 = 完全清晰,1 = 完全融入雾色。</summary>
|
||||
public static float FogAmount(float z)
|
||||
{
|
||||
float t = Math.Clamp(z / Cfg.FarZ, 0f, 1f);
|
||||
return t * t; // 平方衰减,近处保持通透
|
||||
}
|
||||
}
|
||||
|
||||
public class Obstacle
|
||||
{
|
||||
public float Z;
|
||||
public int Lane;
|
||||
public ObstacleKind Kind;
|
||||
public bool Scored; // 是否已计入"躲避成功"
|
||||
|
||||
public float Width => Kind == ObstacleKind.Full ? 96f : 90f;
|
||||
public float Depth => Kind == ObstacleKind.Full ? 54f : 56f;
|
||||
public float BottomY => Kind == ObstacleKind.High ? 40f : 0f;
|
||||
public float TopY => Kind switch
|
||||
{
|
||||
ObstacleKind.Low => 46f, // 低于跳跃高度,跳过去
|
||||
ObstacleKind.High => 98f, // 悬空横梁,滑铲钻过去
|
||||
_ => 108f // 整道石墙,只能换道
|
||||
};
|
||||
public float CenterX => Cfg.LaneX(Lane);
|
||||
}
|
||||
|
||||
public class Coin
|
||||
{
|
||||
public float Z;
|
||||
public int Lane;
|
||||
public float Y = 36f;
|
||||
public bool Taken;
|
||||
public float Phase;
|
||||
public float CenterX => Cfg.LaneX(Lane);
|
||||
}
|
||||
|
||||
public class Particle
|
||||
{
|
||||
public float X, Y, Z;
|
||||
public float Vx, Vy, Vz;
|
||||
public float Life;
|
||||
public float MaxLife;
|
||||
public float Size;
|
||||
public float GravityScale = 1f;
|
||||
public Color Color;
|
||||
}
|
||||
|
||||
/// <summary>路边装饰物:石柱、火把、树、雕像碎块。</summary>
|
||||
public class SideProp
|
||||
{
|
||||
public float Z;
|
||||
public int Side; // -1 左,+1 右
|
||||
public int Type; // 0=石柱 1=火把 2=枯树 3=碎石
|
||||
public float Height;
|
||||
public float Phase;
|
||||
|
||||
public float CenterX => Side * (Cfg.RoadHalfWidth + 205f + (Type == 3 ? 40f : 0f));
|
||||
}
|
||||
|
||||
public class Player
|
||||
{
|
||||
public float X; // 当前横向世界坐标(插值中)
|
||||
public int TargetLane = 1; // 目标车道 0/1/2
|
||||
public float Y; // 离地高度
|
||||
public float Vy;
|
||||
public bool OnGround = true;
|
||||
public bool Sliding;
|
||||
public float SlideTimer;
|
||||
public float RunPhase; // 跑动动画相位
|
||||
public bool Alive = true;
|
||||
public float Tilt; // 换道时的侧倾(视觉)
|
||||
|
||||
public float Height => Sliding ? Cfg.SlideHeight : Cfg.PlayerHeight;
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
TargetLane = 1;
|
||||
X = Cfg.LaneX(1);
|
||||
Y = 0;
|
||||
Vy = 0;
|
||||
OnGround = true;
|
||||
Sliding = false;
|
||||
SlideTimer = 0;
|
||||
RunPhase = 0;
|
||||
Alive = true;
|
||||
Tilt = 0;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user