news 2026/5/21 23:45:46

从零开发游戏需要学习的c#模块,第十八章(2D 碰撞检测与金币收集)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从零开发游戏需要学习的c#模块,第十八章(2D 碰撞检测与金币收集)

这节课我们将要学习

  1. 在地图上随机生成金币(黄色方块代替)

  2. 玩家碰到金币后,金币消失,分数增加

  3. 屏幕左上角显示实时分数

将game1替换为

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;

namespace MY_FIRST_GAME
{
public class Game1 : Game
{
private GraphicsDeviceManager _graphics;
private SpriteBatch _spriteBatch;

// 玩家
private Texture2D playerTexture;
private Vector2 playerPosition;
private float playerSpeed = 200f;

// ★ 金币
private Texture2D coinTexture;
private List<Vector2> coins;
private Random rng;
private int score;

// 字体(显示分数用)
private SpriteFont font;

public Game1()
{
_graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
IsMouseVisible = true;
}

protected override void Initialize()
{
_graphics.PreferredBackBufferWidth = 800;
_graphics.PreferredBackBufferHeight = 600;
_graphics.ApplyChanges();

playerPosition = new Vector2(400, 300);
rng = new Random();
coins = new List<Vector2>();
score = 0;

// 生成 5 个金币
SpawnCoins(5);

base.Initialize();
}

protected override void LoadContent()
{
_spriteBatch = new SpriteBatch(GraphicsDevice);

// 加载玩家图片
using var stream = System.IO.File.OpenRead("Content/player.png");
playerTexture = Texture2D.FromStream(GraphicsDevice, stream);

// ★ 创建金币纹理(黄色 32x32 方块)
coinTexture = new Texture2D(GraphicsDevice, 32, 32);
Color[] data = new Color[32 * 32];
for (int i = 0; i < data.Length; i++)
data[i] = Color.Gold;
coinTexture.SetData(data);

// ★ 加载字体(需要先创建字体文件,见下方说明)
// font = Content.Load<SpriteFont>("font");
}

// ★ 生成金币
private void SpawnCoins(int count)
{
for (int i = 0; i < count; i++)
{
float x = rng.Next(50, 750);
float y = rng.Next(50, 550);
coins.Add(new Vector2(x, y));
}
}

protected override void Update(GameTime gameTime)
{
KeyboardState keyboard = Keyboard.GetState();
float speed = playerSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds;
float deltaTime = (float)gameTime.ElapsedGameTime.TotalSeconds;

// 移动
if (keyboard.IsKeyDown(Keys.W) || keyboard.IsKeyDown(Keys.Up))
playerPosition.Y -= speed;
if (keyboard.IsKeyDown(Keys.S) || keyboard.IsKeyDown(Keys.Down))
playerPosition.Y += speed;
if (keyboard.IsKeyDown(Keys.A) || keyboard.IsKeyDown(Keys.Left))
playerPosition.X -= speed;
if (keyboard.IsKeyDown(Keys.D) || keyboard.IsKeyDown(Keys.Right))
playerPosition.X += speed;

// 限制玩家不超出窗口
playerPosition.X = Math.Clamp(playerPosition.X, 32, 768);
playerPosition.Y = Math.Clamp(playerPosition.Y, 32, 568);

// ★ 检测金币碰撞
CheckCoinCollision();

// ★ 金币捡完了重新生成
if (coins.Count == 0)
SpawnCoins(5);

if (keyboard.IsKeyDown(Keys.Escape))
Exit();

base.Update(gameTime);
}

// ★ 碰撞检测
private void CheckCoinCollision()
{
Rectangle playerRect = new Rectangle(
(int)playerPosition.X - 32,
(int)playerPosition.Y - 32,
64, 64
);

for (int i = coins.Count - 1; i >= 0; i--)
{
Rectangle coinRect = new Rectangle((int)coins[i].X, (int)coins[i].Y, 32, 32);

if (playerRect.Intersects(coinRect))
{
coins.RemoveAt(i); // 移除金币
score += 10; // 加分
}
}
}

protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);

_spriteBatch.Begin();

// 画所有金币
foreach (Vector2 coinPos in coins)
{
_spriteBatch.Draw(coinTexture, coinPos, Color.White);
}

// 画玩家(以图片中心为锚点)
_spriteBatch.Draw(
playerTexture,
playerPosition,
null,
Color.White,
0f,
new Vector2(playerTexture.Width / 2, playerTexture.Height / 2),
1f,
SpriteEffects.None,
0f
);

// ★ 画分数(暂时用窗口标题栏显示)
Window.Title = $"分数:{score} | 剩余金币:{coins.Count}";

_spriteBatch.End();

base.Draw(gameTime);
}
}
}

本节课学习的新内容

1. 碰撞检测:Rectangle.Intersects()
Rectangle playerRect = new Rectangle(玩家左上角X, 玩家左上角Y, 宽度, 高度); Rectangle coinRect = new Rectangle(金币X, 金币Y, 32, 32); if (playerRect.Intersects(coinRect)) { // 碰撞了! }
2. 以图片中心为锚点画图
_spriteBatch.Draw( playerTexture, // 纹理 playerPosition, // 位置 null, // 不裁剪 Color.White, // 颜色 0f, // 不旋转 new Vector2(width/2, height/2), // ★ 锚点设为中心 1f, // 不缩放 SpriteEffects.None, // 不翻转 0f // 深度 );
3.Math.Clamp限制范围
playerPosition.X = Math.Clamp(playerPosition.X, 最小值, 最大值);

好了这节课就此结束,关注我,下期更精彩

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/21 23:43:04

如何利用VITON-HD实现高分辨率虚拟试衣的完整指南

如何利用VITON-HD实现高分辨率虚拟试衣的完整指南 【免费下载链接】VITON-HD Official PyTorch implementation of "VITON-HD: High-Resolution Virtual Try-On via Misalignment-Aware Normalization" (CVPR 2021) 项目地址: https://gitcode.com/gh_mirrors/vi/V…

作者头像 李华
网站建设 2026/5/21 23:41:04

三步快速实现GitHub Desktop中文界面:终极汉化指南

三步快速实现GitHub Desktop中文界面&#xff1a;终极汉化指南 【免费下载链接】GitHubDesktop2Chinese GithubDesktop语言本地化(汉化)工具 【GitHub桌面客户端中文汉化】 项目地址: https://gitcode.com/gh_mirrors/gi/GitHubDesktop2Chinese 还在为GitHub Desktop的英…

作者头像 李华
网站建设 2026/5/21 23:38:08

如何快速获取精准歌词?LDDC 跨平台歌词下载工具完整指南

如何快速获取精准歌词&#xff1f;LDDC 跨平台歌词下载工具完整指南 【免费下载链接】LDDC 简单易用的精准歌词(逐字歌词/卡拉OK歌词)下载匹配工具|A simple and user-friendly tool for downloading and matching precise lyrics (word-by-word lyrics/Karaoke lyrics) 项目…

作者头像 李华
网站建设 2026/5/21 23:36:23

快速解决Unity游戏性能瓶颈:UnityMeshSimplifier网格简化实战指南

快速解决Unity游戏性能瓶颈&#xff1a;UnityMeshSimplifier网格简化实战指南 【免费下载链接】UnityMeshSimplifier Mesh simplification for Unity. 项目地址: https://gitcode.com/gh_mirrors/un/UnityMeshSimplifier 当你的Unity游戏在移动设备上帧率骤降、内存占用…

作者头像 李华
网站建设 2026/5/21 23:36:22

fltk-rs实战指南:如何用Rust快速构建跨平台桌面应用

fltk-rs实战指南&#xff1a;如何用Rust快速构建跨平台桌面应用 【免费下载链接】fltk-rs Rust bindings for the FLTK GUI library. 项目地址: https://gitcode.com/gh_mirrors/fl/fltk-rs fltk-rs 是Rust语言中最轻量级的跨平台GUI库之一&#xff0c;它提供了对FLTK&a…

作者头像 李华
网站建设 2026/5/21 23:35:43

企业落地 AI Agent,第一批最容易跑通的 10 个低风险场景

前面几篇&#xff0c;我们已经把一个核心判断讲清楚了&#xff1a; 2026 年之后&#xff0c;企业做 AI Agent&#xff0c;真正比拼的不是谁模型更会说&#xff0c;而是谁更能交付结果。 但问题来了。 就算大家都认同“要从可交付场景切入”&#xff0c;落到执行层面&#xf…

作者头像 李华