这节课我们将要学习
在地图上随机生成金币(黄色方块代替)
玩家碰到金币后,金币消失,分数增加
屏幕左上角显示实时分数
将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, 最小值, 最大值);好了这节课就此结束,关注我,下期更精彩