本节课学习内容
-
敌人死亡时概率掉落血包或能量球
-
血包恢复血量
-
能量球暂时提升攻击力
-
掉落物有吸引动画(可选)
第一步:创建掉落物类
右键项目 → 添加 → 类 ,文件名 Pickup.cs:
csharp
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace MY_FIRST_GAME
{
public enum PickupType
{
Health, // 血包:恢复25点血量
Power // 能量球:5秒内攻击力翻倍
}
public class Pickup
{
public Vector2 Position;
public PickupType Type;
public bool IsAlive = true;
public float Lifetime = 10f; // 10秒后消失
public int Value;
private Texture2D texture;
private float timer;
private float floatOffset;
private float floatSpeed = 0.5f;
public Pickup(Vector2 position, PickupType type, GraphicsDevice graphicsDevice)
{
Position = position;
Type = type;
int size = 20;
texture = new Texture2D(graphicsDevice, size, size);
Color[] data = new Color[size * size];
switch (type)
{
case PickupType.Health:
Value = 25;
// 红色十字
for (int y = 0; y < size; y++)
for (int x = 0; x < size; x++)
{
bool horizontal = (y >= size * 0.35f && y <= size * 0.65f);
bool vertical = (x >= size * 0.35f && x <= size * 0.65f);
if (horizontal || vertical)
data[y * size + x] = Color.Red;
else
data[y * size + x] = Color.Transparent;
}
break;
case PickupType.Power:
Value = 5; // 持续5秒
// 黄色闪电
for (int y = 0; y < size; y++)
for (int x = 0; x < size; x++)
{
float dx = x - size / 2f;
float dy = y - size / 2f;
if (dx * dx + dy * dy < (size / 2f) * (size / 2f))
data[y * size + x] = Color.Gold;
else
data[y * size + x] = Color.Transparent;
}
break;
}
texture.SetData(data);
}
public void Update(float deltaTime)
{
timer += deltaTime;
floatOffset = (float)System.Math.Sin(timer * 3) * 5; // 上下浮动
if (timer >= Lifetime)
IsAlive = false;
}
public void Draw(SpriteBatch spriteBatch)
{
Vector2 drawPos = Position + new Vector2(0, floatOffset);
spriteBatch.Draw(texture, drawPos, null, Color.White,
0f, new Vector2(texture.Width / 2, texture.Height / 2),
1f, SpriteEffects.None, 0f);
}
public Rectangle GetBounds()
{
return new Rectangle(
(int)(Position.X - texture.Width / 2),
(int)(Position.Y - texture.Height / 2),
texture.Width, texture.Height);
}
}
}
第二步:给 Player 类加 BUFF 系统
在 Player.cs 里添加:
cs
// BUFF 相关
private bool isPoweredUp;
private float powerTimer;
private int originalAttack;
// 在构造函数里保存原始攻击力
// 在 Player 构造函数末尾加:originalAttack = Attack;
// 添加方法
public void ApplyPowerUp(float duration)
{
if (!isPoweredUp)
{
originalAttack = Attack;
isPoweredUp = true;
}
powerTimer = duration;
Attack = originalAttack * 2; // 攻击力翻倍
}
public void UpdateBuffs(float deltaTime)
{
if (isPoweredUp)
{
powerTimer -= deltaTime;
if (powerTimer <= 0)
{
isPoweredUp = false;
Attack = originalAttack; // 恢复
}
}
}
public bool HasPowerUp => isPoweredUp;
public float PowerUpTimeRemaining => powerTimer;
在 Player 的构造函数最后加一行:
csharp
originalAttack = Attack;
第三步:改造 Game1.cs
只列出需要改的地方。
1. 添加字段:
csharp
private List<Pickup> pickups = default!;
2. 在 InitializeGame 里初始化:
csharp
pickups = new List<Pickup>();
3. 在击杀敌人的地方加掉落逻辑:
在 CheckBulletEnemyCollision 击杀分支里:
csharp
if (enemies[j].Hp <= 0)
{
// ...原有代码...
// ★ 掉落判定
float dropChance = (float)rng.NextDouble();
if (dropChance < 0.4f) // 40%概率掉落
{
if (dropChance < 0.25f) // 25%血包
pickups.Add(new Pickup(enemies[j].Position, PickupType.Health, GraphicsDevice));
else // 15%能量球
pickups.Add(new Pickup(enemies[j].Position, PickupType.Power, GraphicsDevice));
}
}
4. 在 Update 的 Game 状态里更新掉落物:
csharp
// 更新掉落物
foreach (Pickup pickup in pickups)
pickup.Update(deltaTime);
pickups.RemoveAll(p => !p.IsAlive);
// 更新玩家 BUFF
player.UpdateBuffs(deltaTime);
// 检测玩家和掉落物碰撞
CheckPickupCollision();
5. 添加碰撞检测方法:
csharp
private void CheckPickupCollision()
{
Rectangle playerRect = player.GetBounds();
for (int i = pickups.Count - 1; i >= 0; i--)
{
if (pickups[i].GetBounds().Intersects(playerRect))
{
Pickup pickup = pickups[i];
pickups.RemoveAt(i);
switch (pickup.Type)
{
case PickupType.Health:
player.Hp = Math.Min(player.Hp + pickup.Value, player.MaxHp);
floatingTexts.Add(new FloatingText(pickup.Position, $"+{pickup.Value} HP", Color.Red));
break;
case PickupType.Power:
player.ApplyPowerUp(pickup.Value);
floatingTexts.Add(new FloatingText(pickup.Position, "攻击力UP!", Color.Gold));
break;
}
}
}
}
6. 在 DrawGameWorld 里画掉落物:
csharp
foreach (Pickup pickup in pickups)
pickup.Draw(_spriteBatch);
7. 在 DrawGameUI 里加 BUFF 提示:
在 UI 最后加:
csharp
if (player.HasPowerUp)
{
_spriteBatch.DrawString(font,
$"⚡ 攻击力UP:{player.PowerUpTimeRemaining:F1}秒",
new Vector2(600, 30), Color.Gold);
}
好了,本节课学习内容到此结束,关注我,下期更精彩!