using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Media;
namespace AirplaneCombat
{
public partial class MainForm : Form
{
private Player player;
private List<Enemy> enemies = new List<Enemy>();
private List<Bullet> bullets = new List<Bullet>();
private List<Explosion> explosions = new List<Explosion>();
private int score = 0;
private int level = 1;
private int lives = 3;
private bool gameOver = false;
private bool gameStarted = false;
private Image playerImage;
private Image enemyImage;
private Image bulletImage;
private SoundPlayer shootSound;
private SoundPlayer explosionSound;
private Font gameFont = new Font("Arial", 14, FontStyle.Bold);
private int enemySpawnTimer = 0;
private const int ENEMY_SPAWN_INTERVAL = 60;
private Random random = new Random();
public MainForm()
{
InitializeComponent();
this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
this.Text = "飞机大战";
this.ClientSize = new Size(800, 600);
this.BackColor = Color.FromArgb(30, 30, 70);
LoadResources();
this.KeyDown += MainForm_KeyDown;
this.KeyPreview = true;
player = new Player(new Point(this.ClientSize.Width / 2, this.ClientSize.Height - 100));
gameTimer.Interval = 16;
gameTimer.Tick += GameTimer_Tick;
}
private void LoadResources()
{
playerImage = CreatePlayerImage();
enemyImage = CreateEnemyImage();
bulletImage = CreateBulletImage();
shootSound = new SoundPlayer();
explosionSound = new SoundPlayer();
}
private Image CreatePlayerImage()
{
Bitmap bmp = new Bitmap(50, 40);
using (Graphics g = Graphics.FromImage(bmp))
{
g.Clear(Color.Transparent);
g.FillRectangle(Brushes.DodgerBlue, 15, 0, 20, 30);
g.FillRectangle(Brushes.CornflowerBlue, 0, 10, 50, 10);
g.FillRectangle(Brushes.RoyalBlue, 22, 30, 6, 10);
g.FillEllipse(Brushes.SkyBlue, 20, 5, 10, 10);
}
return bmp;
}
private Image CreateEnemyImage()
{
Bitmap bmp = new Bitmap(40, 40);
using (Graphics g = Graphics.FromImage(bmp))
{
g.Clear(Color.Transparent);
g.FillEllipse(Brushes.IndianRed, 5, 5, 30, 30);
g.FillEllipse(Brushes.DarkRed, 10, 10, 20, 20);
g.DrawLine(new Pen(Color.Black, 2), 20, 0, 20, 40);
g.DrawLine(new Pen(Color.Black, 2), 0, 20, 40, 20);
}
return bmp;
}
private Image CreateBulletImage()
{
Bitmap bmp = new Bitmap(6, 20);
using (Graphics g = Graphics.FromImage(bmp))
{
g.Clear(Color.Transparent);
g.FillRectangle(Brushes.Gold, 0, 0, 6, 15);
g.FillEllipse(Brushes.Orange, 0, 0, 6, 10);
g.FillRectangle(Brushes.Yellow, 1, 15, 4, 5);
}
return bmp;
}
private void MainForm_KeyDown(object sender, KeyEventArgs e)
{
if (!gameStarted && e.KeyCode == Keys.Space)
{
StartGame();
return;
}
if (gameOver && e.KeyCode == Keys.R)
{
ResetGame();
return;
}
if (gameStarted && !gameOver)
{
const int moveSpeed = 8;
if (e.KeyCode == Keys.Left || e.KeyCode == Keys.A)
{
player.Position = new Point(
Math.Max(0, player.Position.X - moveSpeed),
player.Position.Y);
}
else if (e.KeyCode == Keys.Right || e.KeyCode == Keys.D)
{
player.Position = new Point(
Math.Min(this.ClientSize.Width - player.Width, player.Position.X + moveSpeed),
player.Position.Y);
}
else if (e.KeyCode == Keys.Up || e.KeyCode == Keys.W)
{
player.Position = new Point(
player.Position.X,
Math.Max(0, player.Position.Y - moveSpeed));
}
else if (e.KeyCode == Keys.Down || e.KeyCode == Keys.S)
{
player.Position = new Point(
player.Position.X,
Math.Min(this.ClientSize.Height - player.Height, player.Position.Y + moveSpeed));
}
else if (e.KeyCode == Keys.Space)
{
Shoot();
}
}
}
private void StartGame()
{
gameStarted = true;
gameOver = false;
score = 0;
level = 1;
lives = 3;
enemies.Clear();
bullets.Clear();
explosions.Clear();
gameTimer.Start();
}
private void ResetGame()
{
StartGame();
}
private void Shoot()
{
bullets.Add(new Bullet(new Point(
player.Position.X + player.Width / 2 - 3,
player.Position.Y
)));
try { shootSound.Play(); } catch { }
}
private void GameTimer_Tick(object sender, EventArgs e)
{
if (!gameStarted || gameOver) return;
enemySpawnTimer++;
if (enemySpawnTimer >= ENEMY_SPAWN_INTERVAL / level)
{
SpawnEnemy();
enemySpawnTimer = 0;
}
for (int i = bullets.Count - 1; i >= 0; i--)
{
bullets[i].Update();
if (bullets[i].Position.Y < -20)
{
bullets.RemoveAt(i);
}
}
for (int i = enemies.Count - 1; i >= 0; i--)
{
enemies[i].Update();
if (enemies[i].Position.Y > this.ClientSize.Height)
{
enemies.RemoveAt(i);
}
}
for (int i = explosions.Count - 1; i >= 0; i--)
{
explosions[i].Update();
if (explosions[i].IsFinished)
{
explosions.RemoveAt(i);
}
}
for (int i = bullets.Count - 1; i >= 0; i--)
{
Rectangle bulletRect = new Rectangle(bullets[i].Position, new Size(6, 20));
for (int j = enemies.Count - 1; j >= 0; j--)
{
Rectangle enemyRect = new Rectangle(enemies[j].Position, new Size(40, 40));
if (bulletRect.IntersectsWith(enemyRect))
{
explosions.Add(new Explosion(enemies[j].Position));
try { explosionSound.Play(); } catch { }
bullets.RemoveAt(i);
enemies.RemoveAt(j);
score += 10;
level = Math.Max(1, score / 100 + 1);
break;
}
}
}
Rectangle playerRect = new Rectangle(player.Position, new Size(50, 40));
for (int i = enemies.Count - 1; i >= 0; i--)
{
Rectangle enemyRect = new Rectangle(enemies[i].Position, new Size(40, 40));
if (playerRect.IntersectsWith(enemyRect))
{
explosions.Add(new Explosion(player.Position));
explosions.Add(new Explosion(enemies[i].Position));
try { explosionSound.Play(); } catch { }
enemies.RemoveAt(i);
lives--;
if (lives <= 0)
{
gameOver = true;
gameTimer.Stop();
}
else
{
player.Position = new Point(
this.ClientSize.Width / 2,
this.ClientSize.Height - 100
);
}
break;
}
}
this.Invalidate();
}
private void SpawnEnemy()
{
int x = random.Next(0, this.ClientSize.Width - 40);
enemies.Add(new Enemy(new Point(x, -40)));
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g = e.Graphics;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
DrawStars(g);
if (!gameStarted)
{
DrawStartScreen(g);
return;
}
if (gameOver)
{
DrawGameOverScreen(g);
return;
}
g.DrawImage(playerImage, player.Position);
foreach (var bullet in bullets)
{
g.DrawImage(bulletImage, bullet.Position);
}
foreach (var enemy in enemies)
{
g.DrawImage(enemyImage, enemy.Position);
}
foreach (var explosion in explosions)
{
explosion.Draw(g);
}
DrawGameInfo(g);
}
private void DrawStars(Graphics g)
{
for (int i = 0; i < 100; i++)
{
int x = (i * 73) % this.ClientSize.Width;
int y = (i * 47) % this.ClientSize.Height;
int size = (i % 3) + 1;
g.FillEllipse(Brushes.White, x, y, size, size);
}
}
private void DrawGameInfo(Graphics g)
{
string scoreText = $"得分: {score}";
string levelText = $"等级: {level}";
string livesText = $"生命: {lives}";
g.DrawString(scoreText, gameFont, Brushes.White, 10, 10);
g.DrawString(levelText, gameFont, Brushes.White, 10, 40);
g.DrawString(livesText, gameFont, Brushes.White, 10, 70);
}
private void DrawStartScreen(Graphics g)
{
string title = "飞机大战";
string instruction = "按空格键开始游戏";
Font titleFont = new Font("Arial", 36, FontStyle.Bold);
Font instrFont = new Font("Arial", 18, FontStyle.Regular);
SizeF titleSize = g.MeasureString(title, titleFont);
SizeF instrSize = g.MeasureString(instruction, instrFont);
float titleX = (this.ClientSize.Width - titleSize.Width) / 2;
float titleY = this.ClientSize.Height / 3;
float instrX = (this.ClientSize.Width - instrSize.Width) / 2;
float instrY = titleY + titleSize.Height + 40;
g.DrawString(title, titleFont, Brushes.Gold, titleX, titleY);
g.DrawString(instruction, instrFont, Brushes.LightGreen, instrX, instrY);
g.DrawImage(playerImage, (this.ClientSize.Width - 50) / 2, instrY + 60);
}
private void DrawGameOverScreen(Graphics g)
{
string gameOverText = "游戏结束";
string scoreText = $"最终得分: {score}";
string restartText = "按R键重新开始";
Font gameOverFont = new Font("Arial", 36, FontStyle.Bold);
Font scoreFont = new Font("Arial", 24, FontStyle.Regular);
Font restartFont = new Font("Arial", 18, FontStyle.Regular);
SizeF gameOverSize = g.MeasureString(gameOverText, gameOverFont);
SizeF scoreSize = g.MeasureString(scoreText, scoreFont);
SizeF restartSize = g.MeasureString(restartText, restartFont);
float gameOverX = (this.ClientSize.Width - gameOverSize.Width) / 2;
float gameOverY = this.ClientSize.Height / 3;
float scoreX = (this.ClientSize.Width - scoreSize.Width) / 2;
float scoreY = gameOverY + gameOverSize.Height + 30;
float restartX = (this.ClientSize.Width - restartSize.Width) / 2;
float restartY = scoreY + scoreSize.Height + 30;
g.DrawString(gameOverText, gameOverFont, Brushes.Red, gameOverX, gameOverY);
g.DrawString(scoreText, scoreFont, Brushes.Yellow, scoreX, scoreY);
g.DrawString(restartText, restartFont, Brushes.LightGreen, restartX, restartY);
}
}
public class Player
{
public Point Position { get; set; }
public int Width { get; } = 50;
public int Height { get; } = 40;
public Player(Point position)
{
Position = position;
}
}
public class Enemy
{
public Point Position { get; private set; }
private int speed;
public Enemy(Point position)
{
Position = position;
speed = new Random().Next(3, 7);
}
public void Update()
{
Position = new Point(Position.X, Position.Y + speed);
}
}
public class Bullet
{
public Point Position { get; private set; }
private int speed = 10;
public Bullet(Point position)
{
Position = position;
}
public void Update()
{
Position = new Point(Position.X, Position.Y - speed);
}
}
public class Explosion
{
public Point Position { get; private set; }
private int frame = 0;
private const int MAX_FRAMES = 20;
public bool IsFinished => frame >= MAX_FRAMES;
public Explosion(Point position)
{
Position = position;
}
public void Update()
{
frame++;
}
public void Draw(Graphics g)
{
int size = frame * 2;
int alpha = 255 - (frame * 12);
if (alpha < 0) alpha = 0;
Color color = Color.FromArgb(alpha, Color.Orange);
Brush brush = new SolidBrush(color);
int x = Position.X - size / 2 + 20;
int y = Position.Y - size / 2 + 20;
g.FillEllipse(brush, x, y, size, size);
brush.Dispose();
}
}
partial class MainForm
{
private System.ComponentModel.IContainer components = null;
private Timer gameTimer;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.gameTimer = new System.Windows.Forms.Timer(this.components);
this.SuspendLayout();
this.gameTimer.Enabled = true;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 600);
this.Name = "MainForm";
this.Text = "飞机大战";
this.ResumeLayout(false);
}
}
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
}