说明:
forms实现地铁跑酷小游戏
效果图:
step0:游戏规则
# 游戏规则文档## 游戏目标
通过操控角色躲避障碍、收集金币,获得高分并生存更长时间。生命值耗尽时游戏结束。---## 基本操作
### 空格键
- 开始游戏(主菜单或游戏结束时)
- 暂停/继续游戏(游戏中)### 方向键
- **↑(上箭头)**:跳跃(仅站立时可触发)
- **↓(下箭头)**:下蹲(仅站立时可触发,持续0.6秒后自动恢复)
- **←(左箭头)**:移动到下方轨道
- **→(右箭头)**:移动到上方轨道---## 游戏机制
### 角色状态
- **站立**:可自由移动或触发跳跃/下蹲
- **跳跃**:垂直速度受重力影响逐渐下落,落地后恢复站立
- **下蹲**:角色高度缩短,期间无法跳跃或再次下蹲### 轨道系统
- 3条水平轨道(垂直位置):- 上方轨道:Y=180- 中间轨道:Y=410- 下方轨道:Y=640
- **瞬时切换**:左右键可在任意状态(空中/地面)切换轨道### 游戏对象
| 对象类型 | 外观 | 效果 | 生成概率 |
|----------------|--------------|-------------------|----------|
| 金币(金色方块)| 金色 | 触碰+10分 | 1/5 |
| 障碍物(深灰方块)| 深灰色 | 触碰-1生命值 | 4/5 |- 生成规则:从屏幕左侧生成并向右移动,移出右侧边界后消失---## 生命系统
- **初始生命值**:2点
- **失败条件**:生命值归零时游戏结束,显示最终得分---## 难度曲线
| 达成分数 | 移动速度 |
|----------|----------|
| 100分 | 12 |
| 300分 | 15 |
| 500分 | 20 |---## 界面说明
### HUD显示
- 实时显示:- 当前分数(右上角)- 剩余生命值(左上角)
- 特殊状态提示:- 暂停时显示"PAUSED"- 游戏结束显示"GAME OVER"及最终得分### 轨道可视化
- 三条水平分隔线(Y坐标):- 240(上/中轨道分界)- 470(中/下轨道分界)- 700(下边界)### 角色外观
- 颜色随生命值变化:- 2点:绿色- 1点:橙色- 0点:红色---## 进阶策略
1. **轨道优先级**:优先收集金币轨道,灵活切换躲避障碍
2. **动作组合**:- 跳跃规避高空障碍- 下蹲躲避低空障碍
3. **速度预判**:随分数提升加速后,需提前0.5-1秒预判对象位置
4. **生命管理**:保持至少1点生命应对突发障碍> 游戏要求玩家在高速移动场景中快速决策,通过精准操作和路线规划挑战生存极限。祝您游戏愉快!
step1:C:\Users\wangrusheng\RiderProjects\WinFormsApp27\WinFormsApp27\Form1.cs
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;namespace WinFormsApp27
{public partial class Form1 : Form{// 游戏常量private const int PlayerSize = 60;private const int Gravity = 4;private const int JumpVelocity = 32;private const int CrouchDuration = 600;private const int MaxHealth = 2;// 游戏状态private Player player;private List<GameObject> objects = new List<GameObject>();private int score = 0;private int gameSpeed = 10;private bool isPaused = false;private bool isGameRunning = false;private bool gameOver = false;// 计时器private System.Windows.Forms.Timer gameTimer;private DateTime lastGenerateTime = DateTime.Now;private int generateInterval = 1000;public Form1(){InitializeComponent();InitializeGame();this.DoubleBuffered = true;this.KeyDown += MainForm_KeyDown;}private void InitializeGame(){player = new Player{Position = 2,State = PlayerState.Stand,Bounds = new Rectangle(1000, 410, PlayerSize, PlayerSize),Health = MaxHealth,VerticalSpeed = 0};gameTimer = new System.Windows.Forms.Timer { Interval = 30 };gameTimer.Tick += GameLoop;}private void GameLoop(object sender, EventArgs e){if (!isPaused && isGameRunning){UpdateGame();GenerateObjects();}Invalidate();}private void UpdateGame(){UpdatePlayer();UpdateObjects();UpdateDifficulty();if (player.Health <= 0){gameOver = true;isGameRunning = false;}}private void UpdatePlayer(){// 处理跳跃if (player.State == PlayerState.Jump){var bounds = player.Bounds;bounds.Y += player.VerticalSpeed;player.Bounds = bounds;player.VerticalSpeed += Gravity;// 落地检测if (player.Bounds.Y > GetLaneY(player.Position)){bounds = player.Bounds;bounds.Y = GetLaneY(player.Position);player.Bounds = bounds;player.State = PlayerState.Stand;player.VerticalSpeed = 0;}}// 处理下蹲if (player.State == PlayerState.Crouch && (DateTime.Now - player.CrouchStartTime).TotalMilliseconds > CrouchDuration){player.State = PlayerState.Stand;var bounds = player.Bounds;bounds.Height = PlayerSize;player.Bounds = bounds;}}private void GenerateObjects(){if ((DateTime.Now - lastGenerateTime).TotalMilliseconds > generateInterval){objects.Add(new GameObject{Type = new Random().Next(0, 5),Bounds = new Rectangle(-40, GetLaneY(new Random().Next(1, 4)), 30, 30)});lastGenerateTime = DateTime.Now;}}private void UpdateObjects(){for (int i = objects.Count - 1; i >= 0; i--){// 移动物体(使用临时变量修改)var obj = objects[i];var bounds = obj.Bounds;bounds.X += gameSpeed;obj.Bounds = bounds;objects[i] = obj;// 碰撞检测if (obj.Bounds.IntersectsWith(player.Bounds)){HandleCollision(obj);objects.RemoveAt(i);}// 移出屏幕if (obj.Bounds.X > this.ClientSize.Width){objects.RemoveAt(i);}}}private void HandleCollision(GameObject obj){if (obj.Type == 0) score += 10;else player.Health--;}private void UpdateDifficulty(){if (score > 500) gameSpeed = 20;else if (score > 300) gameSpeed = 15;else if (score > 100) gameSpeed = 12;}private int GetLaneY(int lane){return lane switch{1 => 180,2 => 410,3 => 640,_ => 410};}protected override void OnPaint(PaintEventArgs e){base.OnPaint(e);var g = e.Graphics;if (isGameRunning){DrawLanes(g);DrawPlayer(g);DrawObjects(g);DrawHUD(g);}else{DrawMenu(g);}}private void DrawLanes(Graphics g){using var pen = new Pen(Brushes.Black, 3);g.DrawLine(pen, 0, 240, ClientSize.Width, 240);g.DrawLine(pen, 0, 470, ClientSize.Width, 470);g.DrawLine(pen, 0, 700, ClientSize.Width, 700);}private void DrawPlayer(Graphics g){var color = player.Health switch{1 => Brushes.Orange,0 => Brushes.Red,_ => Brushes.Green};g.FillRectangle(color, player.Bounds);}private void DrawObjects(Graphics g){foreach (var obj in objects){g.FillRectangle(obj.Type == 0 ? Brushes.Gold : Brushes.DarkGray, obj.Bounds);}}private void DrawHUD(Graphics g){g.DrawString($"Score: {score}", Font, Brushes.Black, 10, 10);g.DrawString($"Health: {player.Health}", Font, Brushes.Red, 10, 30);if (isPaused){g.DrawString("PAUSED", new Font("Arial", 40), Brushes.Gray, ClientSize.Width/2 - 80, ClientSize.Height/2 - 20);}}private void DrawMenu(Graphics g){g.DrawString("PARKOUR GAME", new Font("Arial", 40), Brushes.Black, 300, 200);g.DrawString("Press SPACE to Start", new Font("Arial", 20), Brushes.Gray, 400, 300);if (gameOver){g.DrawString("GAME OVER", new Font("Arial", 40), Brushes.Red, 350, 400);g.DrawString($"Final Score: {score}", new Font("Arial", 20), Brushes.Black, 420, 450);}}private void MainForm_KeyDown(object sender, KeyEventArgs e){if (e.KeyCode == Keys.Space){if (!isGameRunning) StartGame();else isPaused = !isPaused;}if (isGameRunning && !isPaused) HandleGameInput(e.KeyCode);}private void StartGame(){isGameRunning = true;gameOver = false;score = 0;player.Health = MaxHealth;objects.Clear();gameTimer.Start();}private void HandleGameInput(Keys key){switch (key){case Keys.Up:if (player.State == PlayerState.Stand){player.State = PlayerState.Jump;player.VerticalSpeed = -JumpVelocity;}break;case Keys.Down:if (player.State == PlayerState.Stand){player.State = PlayerState.Crouch;var bounds = player.Bounds;bounds.Height = PlayerSize - 30;player.Bounds = bounds;player.CrouchStartTime = DateTime.Now;}break;case Keys.Left:if (player.Position < 3) {player.Position++;var bounds = player.Bounds;bounds.Y = GetLaneY(player.Position);player.Bounds = bounds;}break;case Keys.Right:if (player.Position > 1){player.Position--;var bounds = player.Bounds;bounds.Y = GetLaneY(player.Position);player.Bounds = bounds;}break;}}}public enum PlayerState { Stand, Crouch, Jump }public class Player{public int Position { get; set; }public PlayerState State { get; set; }public Rectangle Bounds { get; set; }public int Health { get; set; }public int VerticalSpeed { get; set; }public DateTime CrouchStartTime { get; set; }}public class GameObject{public int Type { get; set; }public Rectangle Bounds { get; set; }}
}
end