feat: 初始版本
This commit is contained in:
@@ -0,0 +1,706 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Windows.Forms;
|
||||
using System.IO;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace DesktopRoachRampage
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
Application.Run(new MainForm());
|
||||
}
|
||||
}
|
||||
|
||||
enum CockroachState
|
||||
{
|
||||
Walking,
|
||||
Flying,
|
||||
Dead // 死亡状态
|
||||
}
|
||||
|
||||
class Cockroach
|
||||
{
|
||||
public float X { get; set; }
|
||||
public float Y { get; set; }
|
||||
public float DirectionX { get; set; }
|
||||
public float DirectionY { get; set; }
|
||||
public float CurrentAngle { get; set; }
|
||||
public int CurrentFrame { get; set; }
|
||||
public Random Random { get; set; }
|
||||
public CockroachState State { get; set; }
|
||||
public float FlyHeightOffset { get; set; }
|
||||
public float StateTimer { get; set; }
|
||||
public float DeathTimer { get; set; } // 死亡后消失计时器
|
||||
public float Scale { get; set; } // 缩放比例,死亡时缩小
|
||||
|
||||
public Cockroach(float x, float y, Random rand)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
Random = rand;
|
||||
State = CockroachState.Walking;
|
||||
FlyHeightOffset = 0;
|
||||
StateTimer = 0;
|
||||
DeathTimer = 0;
|
||||
Scale = 1f;
|
||||
|
||||
double angle = rand.NextDouble() * Math.PI * 2;
|
||||
float speed = 2f + (float)rand.NextDouble() * 2f;
|
||||
DirectionX = (float)Math.Cos(angle) * speed;
|
||||
DirectionY = (float)Math.Sin(angle) * speed;
|
||||
|
||||
CurrentAngle = (float)(angle * 180 / Math.PI) + 90f;
|
||||
CurrentFrame = rand.Next(8);
|
||||
}
|
||||
|
||||
// 被打死
|
||||
public void Kill()
|
||||
{
|
||||
if (State == CockroachState.Dead) return;
|
||||
|
||||
State = CockroachState.Dead;
|
||||
DeathTimer = 0;
|
||||
DirectionX = 0;
|
||||
DirectionY = 0;
|
||||
}
|
||||
|
||||
public void Update(Rectangle totalBounds, int petSize)
|
||||
{
|
||||
// 如果已经死亡,处理消失动画
|
||||
if (State == CockroachState.Dead)
|
||||
{
|
||||
DeathTimer++;
|
||||
Scale = Math.Max(0, 1f - DeathTimer / 30f); // 30帧内缩小到消失
|
||||
return;
|
||||
}
|
||||
|
||||
StateTimer++;
|
||||
|
||||
// 更频繁检查状态切换(约5秒),飞行概率更高
|
||||
if (StateTimer > 100)
|
||||
{
|
||||
StateTimer = 0;
|
||||
if (Random.NextDouble() < 0.7) // 70%概率切换
|
||||
{
|
||||
if (State == CockroachState.Walking)
|
||||
{
|
||||
// 开始飞行 - 速度大幅提升
|
||||
State = CockroachState.Flying;
|
||||
float flySpeed = 7f + (float)Random.NextDouble() * 4f; // 飞行速度7-11
|
||||
double flyAngle = Random.NextDouble() * Math.PI * 2;
|
||||
DirectionX = (float)Math.Cos(flyAngle) * flySpeed;
|
||||
DirectionY = (float)Math.Sin(flyAngle) * flySpeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 降落
|
||||
State = CockroachState.Walking;
|
||||
FlyHeightOffset = 0;
|
||||
float walkSpeed = 2f + (float)Random.NextDouble() * 2f;
|
||||
double walkAngle = Random.NextDouble() * Math.PI * 2;
|
||||
DirectionX = (float)Math.Cos(walkAngle) * walkSpeed;
|
||||
DirectionY = (float)Math.Sin(walkAngle) * walkSpeed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 飞行时高度偏移
|
||||
if (State == CockroachState.Flying)
|
||||
{
|
||||
FlyHeightOffset = (float)Math.Sin(StateTimer * 0.1) * 5f - 8f;
|
||||
}
|
||||
|
||||
// 移动
|
||||
X += DirectionX;
|
||||
Y += DirectionY;
|
||||
|
||||
// 边界检测与反弹
|
||||
if (X <= totalBounds.Left || X >= totalBounds.Right - petSize)
|
||||
{
|
||||
DirectionX = -DirectionX + (float)(Random.NextDouble() - 0.5) * 2;
|
||||
float minSpeed = State == CockroachState.Flying ? 6f : 1.5f;
|
||||
if (Math.Abs(DirectionX) < minSpeed) DirectionX = DirectionX > 0 ? minSpeed + 1 : -minSpeed - 1;
|
||||
X = Math.Max(totalBounds.Left, Math.Min(X, totalBounds.Right - petSize));
|
||||
}
|
||||
|
||||
if (Y <= totalBounds.Top || Y >= totalBounds.Bottom - petSize)
|
||||
{
|
||||
DirectionY = -DirectionY + (float)(Random.NextDouble() - 0.5) * 2;
|
||||
float minSpeed = State == CockroachState.Flying ? 6f : 1.5f;
|
||||
if (Math.Abs(DirectionY) < minSpeed) DirectionY = DirectionY > 0 ? minSpeed + 1 : -minSpeed - 1;
|
||||
Y = Math.Max(totalBounds.Top, Math.Min(Y, totalBounds.Bottom - petSize));
|
||||
}
|
||||
|
||||
// 随机改变方向
|
||||
if (Random.Next(100) < 5)
|
||||
{
|
||||
float changeRange = State == CockroachState.Flying ? 6f : 3f;
|
||||
DirectionX += (float)(Random.NextDouble() - 0.5) * changeRange;
|
||||
DirectionY += (float)(Random.NextDouble() - 0.5) * changeRange;
|
||||
float maxSpeed = State == CockroachState.Flying ? 12f : 5f;
|
||||
DirectionX = Math.Max(-maxSpeed, Math.Min(maxSpeed, DirectionX));
|
||||
DirectionY = Math.Max(-maxSpeed, Math.Min(maxSpeed, DirectionY));
|
||||
}
|
||||
|
||||
CurrentFrame = (CurrentFrame + 1) % 8;
|
||||
}
|
||||
|
||||
public void Draw(Graphics g, Image[] walkFrames, Image[] flyFrames, int petSize)
|
||||
{
|
||||
Image[] frames = State == CockroachState.Flying ? flyFrames : walkFrames;
|
||||
if (frames == null || frames.Length == 0) return;
|
||||
|
||||
Image frame = frames[CurrentFrame % frames.Length];
|
||||
if (frame == null) return;
|
||||
|
||||
float targetAngle = (float)(Math.Atan2(DirectionY, DirectionX) * 180 / Math.PI) + 90f;
|
||||
|
||||
float angleDiff = targetAngle - CurrentAngle;
|
||||
if (angleDiff > 180) angleDiff -= 360;
|
||||
if (angleDiff < -180) angleDiff += 360;
|
||||
CurrentAngle += angleDiff * 0.15f;
|
||||
|
||||
Matrix oldMatrix = g.Transform;
|
||||
|
||||
float drawY = Y + FlyHeightOffset;
|
||||
float drawSize = petSize * Scale;
|
||||
|
||||
// 绘制缩放和旋转
|
||||
g.TranslateTransform(X + drawSize / 2, drawY + drawSize / 2);
|
||||
g.RotateTransform(CurrentAngle);
|
||||
g.ScaleTransform(Scale, Scale);
|
||||
g.TranslateTransform(-drawSize / 2, -drawSize / 2);
|
||||
|
||||
g.DrawImage(frame, 0, 0, drawSize, drawSize);
|
||||
|
||||
g.Transform = oldMatrix;
|
||||
}
|
||||
}
|
||||
|
||||
// 点击特效类
|
||||
class ClickEffect
|
||||
{
|
||||
public float X { get; set; }
|
||||
public float Y { get; set; }
|
||||
public float Timer { get; set; }
|
||||
public const float MaxTime = 15f; // 持续15帧
|
||||
|
||||
public ClickEffect(float x, float y)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
Timer = 0;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
Timer++;
|
||||
}
|
||||
|
||||
public void Draw(Graphics g)
|
||||
{
|
||||
float progress = Timer / MaxTime;
|
||||
float size = 20 + progress * 30; // 从20扩散到50
|
||||
float alpha = 1f - progress; // 逐渐透明
|
||||
|
||||
using (Pen pen = new Pen(Color.FromArgb((int)(alpha * 200), 255, 100, 100), 3))
|
||||
{
|
||||
g.DrawEllipse(pen, X - size / 2, Y - size / 2, size, size);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsDead()
|
||||
{
|
||||
return Timer >= MaxTime;
|
||||
}
|
||||
}
|
||||
|
||||
class MainForm : Form
|
||||
{
|
||||
private List<Cockroach> cockroaches;
|
||||
private Image[] walkFrames;
|
||||
private Image[] flyFrames;
|
||||
private Timer mainTimer;
|
||||
private Timer breedTimer;
|
||||
private Random random;
|
||||
private const int PetSize = 64;
|
||||
private bool dragging = false;
|
||||
private int dragIndex = -1;
|
||||
private Point dragOffset;
|
||||
private const int MaxCockroaches = 50;
|
||||
private Rectangle totalScreenBounds;
|
||||
private Bitmap bufferBitmap;
|
||||
private Graphics bufferGraphics;
|
||||
|
||||
// 打蟑螂相关
|
||||
private int score = 0; // 分数
|
||||
private int lastScore = 0; // 上次的分数
|
||||
private float scoreIdleTimer = 0; // 分数没变化的时间
|
||||
private bool showScore = true; // 是否显示分数
|
||||
private List<ClickEffect> clickEffects; // 点击特效
|
||||
private Font scoreFont;
|
||||
|
||||
public MainForm()
|
||||
{
|
||||
random = new Random();
|
||||
cockroaches = new List<Cockroach>();
|
||||
clickEffects = new List<ClickEffect>();
|
||||
|
||||
// 启用双缓冲优化
|
||||
this.SetStyle(ControlStyles.DoubleBuffer |
|
||||
ControlStyles.UserPaint |
|
||||
ControlStyles.AllPaintingInWmPaint |
|
||||
ControlStyles.OptimizedDoubleBuffer, true);
|
||||
this.UpdateStyles();
|
||||
|
||||
CalculateTotalScreenBounds();
|
||||
|
||||
this.FormBorderStyle = FormBorderStyle.None;
|
||||
this.ShowInTaskbar = false;
|
||||
this.TopMost = true;
|
||||
this.TransparencyKey = Color.Magenta;
|
||||
this.BackColor = Color.Magenta;
|
||||
this.Bounds = totalScreenBounds;
|
||||
|
||||
LoadFrames();
|
||||
|
||||
// 创建双缓冲位图
|
||||
CreateBufferBitmap();
|
||||
|
||||
// 创建分数字体
|
||||
scoreFont = new Font("Arial", 14f, FontStyle.Bold);
|
||||
|
||||
SpawnCockroachOnPrimary();
|
||||
|
||||
mainTimer = new Timer();
|
||||
mainTimer.Interval = 50;
|
||||
mainTimer.Tick += MainTimer_Tick;
|
||||
mainTimer.Start();
|
||||
|
||||
breedTimer = new Timer();
|
||||
breedTimer.Interval = 8000;
|
||||
breedTimer.Tick += BreedTimer_Tick;
|
||||
breedTimer.Start();
|
||||
|
||||
ContextMenuStrip menu = new ContextMenuStrip();
|
||||
menu.Items.Add("清除所有蟑螂", null, (s, e) => ClearAll());
|
||||
menu.Items.Add("添加一只蟑螂", null, (s, e) => SpawnCockroach());
|
||||
menu.Items.Add("让所有蟑螂起飞!", null, (s, e) => MakeAllFly());
|
||||
menu.Items.Add("让所有蟑螂降落!", null, (s, e) => MakeAllLand());
|
||||
menu.Items.Add("随机分布到所有屏幕", null, (s, e) => RedistributeAll());
|
||||
menu.Items.Add("-", null, null);
|
||||
menu.Items.Add("重置分数", null, (s, e) => ResetScore());
|
||||
menu.Items.Add("-", null, null);
|
||||
menu.Items.Add("Exit / 退出", null, (s, e) => Application.Exit());
|
||||
this.ContextMenuStrip = menu;
|
||||
|
||||
this.MouseDown += MainForm_MouseDown;
|
||||
this.MouseMove += MainForm_MouseMove;
|
||||
this.MouseUp += MainForm_MouseUp;
|
||||
|
||||
SystemEvents.DisplaySettingsChanged += SystemEvents_DisplaySettingsChanged;
|
||||
}
|
||||
|
||||
private void ResetScore()
|
||||
{
|
||||
score = 0;
|
||||
lastScore = 0;
|
||||
showScore = true;
|
||||
scoreIdleTimer = 0;
|
||||
this.Invalidate();
|
||||
}
|
||||
|
||||
private void CreateBufferBitmap()
|
||||
{
|
||||
if (bufferBitmap != null)
|
||||
{
|
||||
bufferBitmap.Dispose();
|
||||
bufferGraphics.Dispose();
|
||||
}
|
||||
|
||||
bufferBitmap = new Bitmap(totalScreenBounds.Width, totalScreenBounds.Height, PixelFormat.Format32bppArgb);
|
||||
bufferGraphics = Graphics.FromImage(bufferBitmap);
|
||||
bufferGraphics.InterpolationMode = InterpolationMode.NearestNeighbor;
|
||||
bufferGraphics.SmoothingMode = SmoothingMode.None;
|
||||
}
|
||||
|
||||
private void CalculateTotalScreenBounds()
|
||||
{
|
||||
totalScreenBounds = Rectangle.Empty;
|
||||
foreach (Screen screen in Screen.AllScreens)
|
||||
{
|
||||
totalScreenBounds = Rectangle.Union(totalScreenBounds, screen.Bounds);
|
||||
}
|
||||
}
|
||||
|
||||
private void SystemEvents_DisplaySettingsChanged(object sender, EventArgs e)
|
||||
{
|
||||
CalculateTotalScreenBounds();
|
||||
this.Bounds = totalScreenBounds;
|
||||
CreateBufferBitmap();
|
||||
this.Invalidate();
|
||||
}
|
||||
|
||||
private void SpawnCockroachOnPrimary()
|
||||
{
|
||||
if (cockroaches.Count >= MaxCockroaches) return;
|
||||
|
||||
Rectangle primary = Screen.PrimaryScreen.WorkingArea;
|
||||
float x = primary.Left + random.Next(100, primary.Width - 100 - PetSize);
|
||||
float y = primary.Top + random.Next(100, primary.Height - 100 - PetSize);
|
||||
|
||||
cockroaches.Add(new Cockroach(x, y, random));
|
||||
|
||||
UpdateTitle();
|
||||
}
|
||||
|
||||
private void SpawnCockroach()
|
||||
{
|
||||
if (cockroaches.Count >= MaxCockroaches) return;
|
||||
|
||||
Screen[] screens = Screen.AllScreens;
|
||||
Screen randomScreen = screens[random.Next(screens.Length)];
|
||||
Rectangle workingArea = randomScreen.WorkingArea;
|
||||
|
||||
float x = workingArea.Left + random.Next(50, workingArea.Width - 50 - PetSize);
|
||||
float y = workingArea.Top + random.Next(50, workingArea.Height - 50 - PetSize);
|
||||
|
||||
cockroaches.Add(new Cockroach(x, y, random));
|
||||
|
||||
UpdateTitle();
|
||||
}
|
||||
|
||||
private void MakeAllFly()
|
||||
{
|
||||
foreach (var roach in cockroaches)
|
||||
{
|
||||
if (roach.State != CockroachState.Dead)
|
||||
{
|
||||
roach.State = CockroachState.Flying;
|
||||
roach.StateTimer = 0;
|
||||
float flySpeed = 7f + (float)random.NextDouble() * 4f;
|
||||
double flyAngle = random.NextDouble() * Math.PI * 2;
|
||||
roach.DirectionX = (float)Math.Cos(flyAngle) * flySpeed;
|
||||
roach.DirectionY = (float)Math.Sin(flyAngle) * flySpeed;
|
||||
}
|
||||
}
|
||||
this.Invalidate();
|
||||
}
|
||||
|
||||
private void MakeAllLand()
|
||||
{
|
||||
foreach (var roach in cockroaches)
|
||||
{
|
||||
if (roach.State != CockroachState.Dead)
|
||||
{
|
||||
roach.State = CockroachState.Walking;
|
||||
roach.FlyHeightOffset = 0;
|
||||
roach.StateTimer = 0;
|
||||
float walkSpeed = 2f + (float)random.NextDouble() * 2f;
|
||||
double walkAngle = random.NextDouble() * Math.PI * 2;
|
||||
roach.DirectionX = (float)Math.Cos(walkAngle) * walkSpeed;
|
||||
roach.DirectionY = (float)Math.Sin(walkAngle) * walkSpeed;
|
||||
}
|
||||
}
|
||||
this.Invalidate();
|
||||
}
|
||||
|
||||
private void RedistributeAll()
|
||||
{
|
||||
Screen[] screens = Screen.AllScreens;
|
||||
foreach (var roach in cockroaches)
|
||||
{
|
||||
if (roach.State != CockroachState.Dead)
|
||||
{
|
||||
Screen randomScreen = screens[random.Next(screens.Length)];
|
||||
Rectangle workingArea = randomScreen.WorkingArea;
|
||||
|
||||
roach.X = workingArea.Left + random.Next(50, workingArea.Width - 50 - PetSize);
|
||||
roach.Y = workingArea.Top + random.Next(50, workingArea.Height - 50 - PetSize);
|
||||
}
|
||||
}
|
||||
this.Invalidate();
|
||||
}
|
||||
|
||||
private void UpdateTitle()
|
||||
{
|
||||
int flyCount = 0;
|
||||
int walkCount = 0;
|
||||
int deadCount = 0;
|
||||
foreach (var roach in cockroaches)
|
||||
{
|
||||
if (roach.State == CockroachState.Flying)
|
||||
flyCount++;
|
||||
else if (roach.State == CockroachState.Walking)
|
||||
walkCount++;
|
||||
else
|
||||
deadCount++;
|
||||
}
|
||||
this.Text = string.Format("Desktop Roach Rampage - {0} roaches alive (flying:{1} walking:{2}) - killed: {3}",
|
||||
cockroaches.Count - deadCount, flyCount, walkCount, score);
|
||||
}
|
||||
|
||||
private void BreedTimer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
// 检查是否所有蟑螂都被消灭了
|
||||
int aliveCount = cockroaches.FindAll(r => r.State != CockroachState.Dead).Count;
|
||||
|
||||
if (aliveCount == 0)
|
||||
{
|
||||
// 蟑螂全被消灭了,自动生成一只
|
||||
SpawnCockroachOnPrimary();
|
||||
return;
|
||||
}
|
||||
|
||||
int currentCount = cockroaches.Count;
|
||||
for (int i = 0; i < currentCount && cockroaches.Count < MaxCockroaches; i++)
|
||||
{
|
||||
// 飞行中的蟑螂繁殖概率更高
|
||||
double breedChance = cockroaches[i].State == CockroachState.Flying ? 0.6 : 0.4;
|
||||
if (cockroaches[i].State != CockroachState.Dead && random.NextDouble() < breedChance)
|
||||
{
|
||||
Cockroach parent = cockroaches[i];
|
||||
float offsetX = (float)(random.NextDouble() - 0.5) * 80;
|
||||
float offsetY = (float)(random.NextDouble() - 0.5) * 80;
|
||||
|
||||
float newX = parent.X + offsetX;
|
||||
float newY = parent.Y + offsetY;
|
||||
|
||||
newX = Math.Max(totalScreenBounds.Left, Math.Min(newX, totalScreenBounds.Right - PetSize));
|
||||
newY = Math.Max(totalScreenBounds.Top, Math.Min(newY, totalScreenBounds.Bottom - PetSize));
|
||||
|
||||
cockroaches.Add(new Cockroach(newX, newY, random));
|
||||
}
|
||||
}
|
||||
|
||||
UpdateTitle();
|
||||
this.Invalidate();
|
||||
}
|
||||
|
||||
private void ClearAll()
|
||||
{
|
||||
cockroaches.Clear();
|
||||
SpawnCockroachOnPrimary();
|
||||
this.Invalidate();
|
||||
}
|
||||
|
||||
private void MainForm_MouseDown(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (e.Button == MouseButtons.Left)
|
||||
{
|
||||
Point mousePos = this.PointToClient(e.Location);
|
||||
|
||||
// 从后往前检测(点到最上面的蟑螂)
|
||||
bool hit = false;
|
||||
for (int i = cockroaches.Count - 1; i >= 0; i--)
|
||||
{
|
||||
Cockroach roach = cockroaches[i];
|
||||
if (roach.State == CockroachState.Dead) continue;
|
||||
|
||||
float drawY = roach.Y + roach.FlyHeightOffset;
|
||||
RectangleF rect = new RectangleF(roach.X - this.Left, drawY - this.Top, PetSize, PetSize);
|
||||
if (rect.Contains(mousePos))
|
||||
{
|
||||
// 打到蟑螂了!
|
||||
roach.Kill();
|
||||
score++;
|
||||
hit = true;
|
||||
showScore = true; // 立即显示分数
|
||||
scoreIdleTimer = 0;
|
||||
|
||||
// 添加点击特效
|
||||
float effectX = mousePos.X + this.Left;
|
||||
float effectY = mousePos.Y + this.Top;
|
||||
clickEffects.Add(new ClickEffect(effectX, effectY));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没打到,也添加一个空的点击特效
|
||||
if (!hit)
|
||||
{
|
||||
float effectX = mousePos.X + this.Left;
|
||||
float effectY = mousePos.Y + this.Top;
|
||||
clickEffects.Add(new ClickEffect(effectX, effectY));
|
||||
}
|
||||
|
||||
// 检查是否拖动(只有没打到蟑螂时才拖动)
|
||||
if (!hit)
|
||||
{
|
||||
for (int i = cockroaches.Count - 1; i >= 0; i--)
|
||||
{
|
||||
Cockroach roach = cockroaches[i];
|
||||
if (roach.State == CockroachState.Dead) continue;
|
||||
|
||||
float drawY = roach.Y + roach.FlyHeightOffset;
|
||||
RectangleF rect = new RectangleF(roach.X - this.Left, drawY - this.Top, PetSize, PetSize);
|
||||
if (rect.Contains(mousePos))
|
||||
{
|
||||
dragging = true;
|
||||
dragIndex = i;
|
||||
dragOffset = new Point(mousePos.X - (int)(roach.X - this.Left), mousePos.Y - (int)(drawY - this.Top));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void MainForm_MouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (dragging && dragIndex >= 0 && dragIndex < cockroaches.Count)
|
||||
{
|
||||
Point mousePos = this.PointToClient(e.Location);
|
||||
Cockroach roach = cockroaches[dragIndex];
|
||||
roach.X = mousePos.X - dragOffset.X + this.Left;
|
||||
roach.Y = mousePos.Y - dragOffset.Y + this.Top - roach.FlyHeightOffset;
|
||||
this.Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private void MainForm_MouseUp(object sender, MouseEventArgs e)
|
||||
{
|
||||
dragging = false;
|
||||
dragIndex = -1;
|
||||
}
|
||||
|
||||
private void LoadFrames()
|
||||
{
|
||||
string basePath = AppDomain.CurrentDomain.BaseDirectory;
|
||||
string imagePath = Path.Combine(basePath, "images");
|
||||
|
||||
if (!Directory.Exists(imagePath))
|
||||
{
|
||||
imagePath = Path.Combine(basePath, "..", "images");
|
||||
}
|
||||
|
||||
walkFrames = new Image[8];
|
||||
flyFrames = new Image[8];
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
string walkFrameFile = Path.Combine(imagePath, string.Format("walk_{0:D2}.png", i));
|
||||
if (File.Exists(walkFrameFile))
|
||||
walkFrames[i] = Image.FromFile(walkFrameFile);
|
||||
|
||||
string flyFrameFile = Path.Combine(imagePath, string.Format("fly_{0:D2}.png", i));
|
||||
if (File.Exists(flyFrameFile))
|
||||
flyFrames[i] = Image.FromFile(flyFrameFile);
|
||||
}
|
||||
}
|
||||
|
||||
private void MainTimer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
// 更新蟑螂
|
||||
foreach (var roach in cockroaches)
|
||||
{
|
||||
roach.Update(totalScreenBounds, PetSize);
|
||||
}
|
||||
|
||||
// 移除完全消失的死蟑螂
|
||||
cockroaches.RemoveAll(r => r.State == CockroachState.Dead && r.Scale <= 0);
|
||||
|
||||
// 更新点击特效
|
||||
for (int i = clickEffects.Count - 1; i >= 0; i--)
|
||||
{
|
||||
clickEffects[i].Update();
|
||||
if (clickEffects[i].IsDead())
|
||||
{
|
||||
clickEffects.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
// 分数显示逻辑:分数变化时显示,2秒不变化则隐藏
|
||||
if (score != lastScore)
|
||||
{
|
||||
lastScore = score;
|
||||
scoreIdleTimer = 0;
|
||||
showScore = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
scoreIdleTimer++;
|
||||
// 50ms每帧,40帧 = 2秒
|
||||
if (scoreIdleTimer >= 40)
|
||||
{
|
||||
showScore = false;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateTitle();
|
||||
this.Invalidate();
|
||||
}
|
||||
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
{
|
||||
// 使用双缓冲绘制
|
||||
Graphics g = bufferGraphics;
|
||||
|
||||
g.Clear(Color.Magenta);
|
||||
|
||||
g.TranslateTransform(-this.Left, -this.Top);
|
||||
|
||||
// 绘制蟑螂
|
||||
foreach (var roach in cockroaches)
|
||||
{
|
||||
roach.Draw(g, walkFrames, flyFrames, PetSize);
|
||||
}
|
||||
|
||||
// 绘制点击特效
|
||||
foreach (var effect in clickEffects)
|
||||
{
|
||||
effect.Draw(g);
|
||||
}
|
||||
|
||||
// 绘制分数(在主屏幕左上角)
|
||||
if (showScore)
|
||||
{
|
||||
g.ResetTransform();
|
||||
g.TranslateTransform(Screen.PrimaryScreen.Bounds.Left - this.Left,
|
||||
Screen.PrimaryScreen.Bounds.Top - this.Top);
|
||||
|
||||
string scoreText = string.Format("Killed: {0}", score);
|
||||
g.DrawString(scoreText, scoreFont, Brushes.Red, 10, 10);
|
||||
|
||||
// 绘制剩余数量
|
||||
int alive = cockroaches.FindAll(r => r.State != CockroachState.Dead).Count;
|
||||
string countText = string.Format("Alive: {0}", alive);
|
||||
g.DrawString(countText, scoreFont, Brushes.DarkOrange, 10, 35);
|
||||
|
||||
g.ResetTransform();
|
||||
}
|
||||
|
||||
// 一次性绘制到屏幕
|
||||
e.Graphics.DrawImage(bufferBitmap, 0, 0);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
SystemEvents.DisplaySettingsChanged -= SystemEvents_DisplaySettingsChanged;
|
||||
if (mainTimer != null) mainTimer.Dispose();
|
||||
if (breedTimer != null) breedTimer.Dispose();
|
||||
if (bufferBitmap != null) bufferBitmap.Dispose();
|
||||
if (bufferGraphics != null) bufferGraphics.Dispose();
|
||||
if (scoreFont != null) scoreFont.Dispose();
|
||||
if (walkFrames != null)
|
||||
foreach (var frame in walkFrames)
|
||||
if (frame != null) frame.Dispose();
|
||||
if (flyFrames != null)
|
||||
foreach (var frame in flyFrames)
|
||||
if (frame != null) frame.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user