基于C#制作一個飛機大戰(zhàn)小游戲的全過程
更新時間:2023年02月16日 09:44:35 作者:摔跤貓子
飛機大戰(zhàn)小游戲詳細大家都不陌生,下面這篇文章主要給大家介紹了關(guān)于基于C#制作一個飛機大戰(zhàn)小游戲的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
前言
此文主要基于C#制作一個飛機大戰(zhàn)游戲,重溫經(jīng)典的同時亦可學習。
實現(xiàn)流程
1、創(chuàng)建項目
打開Visual Studio,右側(cè)選擇創(chuàng)建新項目。
搜索框輸入winform,選擇windows窗體應(yīng)用,填寫對應(yīng)的保存路徑點擊下一步,創(chuàng)建成功后如下圖,會有一個默認打開的Form窗體。
2、界面繪制
準備對應(yīng)的素材(飛機、子彈、音效等),通過Icon以及窗體Text屬性修改窗體圖標以及標題顯示;同時配置StartPosition屬性值為CenterScreen,讓窗體默認居中顯示。
雙擊窗體生成窗體加載事件并定義函數(shù)對背景進行初始化。
使用Random產(chǎn)生隨機數(shù),從資源中獲取圖片設(shè)置為窗體背景。
private const int PLANE_OFFSET = 2; //設(shè)置每次定時器觸發(fā)時圖片發(fā)生偏移的速度 private int pix_x = 0; private int pix_y = 0; //背景圖片移動起始的坐標 int shot_y = 10; int blood_y = 50; private Image[] bgrounds; //設(shè)置多張背景圖片,每次運行程序隨機產(chǎn)生背景圖片 int index = 0; //背景圖片索引 Image avatar = Resource.imgHeadSheep; //角色頭像圖片 Image boomImg = Resource.bomb4; //爆炸效果圖片 Image shotImg = Resource.shotgun; Image bloodImg = Resource.bloodbox; bool isDropGun = false; //是否產(chǎn)生shotgun的標志 bool isDropBox = false; //是否產(chǎn)生bloodbox的標志 private void Form1_Load(object sender, EventArgs e)//窗體加載事件 { InitBackground(); //初始化背景 } public GameForm() { InitializeComponent(); this.Size = new Size(420, 630);//讓窗體與圖片一樣大 //this.DoubleBuffered = true; //雙緩沖區(qū) } ///<summary> /// 初始化背景,隨機生成背景圖片 /// </summary> public void InitBackground() { bgrounds = new Image[4]; Random rd = new Random(); index = rd.Next(0, 4);//產(chǎn)生0-3的隨機數(shù),表示不同背景 bgrounds[0] = Resource.background1;//從資源獲取圖片 bgrounds[1] = Resource.background2; bgrounds[2] = Resource.background3; bgrounds[3] = Resource.background4; }
新建一個背景移動函數(shù),通過定時位置讓圖片發(fā)生偏移,防止有空白。
/// <summary> /// 背景移動函數(shù) /// </summary> /// <param name="e">圖形對象</param> public void BackMove(Graphics e)//通過定時位置讓圖片發(fā)生偏移,防止有空白 { e = this.CreateGraphics(); pix_y += PLANE_OFFSET; if (pix_y > 630) { pix_y = 0; } }
通過工具箱拖拽兩個定時器到窗體上并設(shè)置定時器事件,用于定時生成血包以及強化彈藥。
/// <summary> /// 設(shè)置定時器1事件 /// </summary> private void timer1_Tick(object sender, EventArgs e) { this.Invalidate(); //使當前窗口無效,系統(tǒng)自動調(diào)用OnPaint()函數(shù)重繪 } /// <summary> /// 設(shè)置定時器2事件 /// </summary> private void timer2_Tick(object sender, EventArgs e) { Graphics g = this.CreateGraphics(); for (int j = 0; j < Fighter.fighters.Count; j++) { if (Fighter.fighters[j].flag) { g.DrawImage(boomImg, Fighter.fighters[j].GetLoc()); SoundPlayer music = new SoundPlayer(Resource.BOMB21); music.Play(); Fighter.fighters.Remove(Fighter.fighters[j]); } } }
通過Graphics類繪制游戲界面,Graphics類作用為封裝一個GDI+繪圖圖畫,效果如下。
函數(shù) | 作用 |
---|---|
DrawImage | 在指定位置并且按指定大小繪制指定的Image |
DrawRectangle | 繪制由Rectangle結(jié)構(gòu)指定的矩形 |
FillRectangle | 填充由一對坐標、一個寬度和一個高度指定的矩形的內(nèi)部 |
DrawString | 在指定位置并目用指定的 Brush 和 Font 對象繪制指定的文本字符串 |
DrawImage | 在指定位置并且按指定大小繪制指定的Image |
/// <summary> /// 繪制游戲界面 /// </summary> /// <param name="g"></param> private void DrawGame(Graphics g) { this.BackMove(g); g.DrawImage(bgrounds[index], pix_x, pix_y, 420, 630); g.DrawImage(bgrounds[index], pix_x, pix_y - 630, 420, 630); //繪制背景 g.DrawImage(avatar, 10, 10); //繪制角色頭像 g.DrawRectangle(new Pen(Color.Black), new Rectangle(10, 100, 100, 10)); //繪制血條矩形 g.FillRectangle(Brushes.Red, 10, 101, MyPlane.health, 9); //填充血條矩形 g.DrawRectangle(new Pen(Color.Blue), new Rectangle(10, 120, 100, 10)); g.FillRectangle(Brushes.Green, 11, 121, MyPlane.score, 9); g.DrawString("Player:摔跤貓子", new Font("宋體", 9, FontStyle.Bold), Brushes.Yellow, new Point(10, 140)); //顯示玩家 g.DrawString("Score:" + MyPlane.score, new Font("宋體", 9, FontStyle.Bold), Brushes.Yellow, new Point(10, 160)); //顯示分數(shù) }
3、我方飛機
創(chuàng)建一個MyPlane實體類,定義字段如下。
public static int x = 180; public static int y = 530;//坐標 public static int health = 100; //血量 private const int PLANE_OFFSET = 12;//移動速度 public static Image myPlaneImg=Resource.plane;//我方飛機圖片 static List<Keys> keys = new List<Keys>();//鍵盤鍵列表,用于控制飛機移動 static Image gameOver = Resource.gameover; public static bool isGetGun = false;//是否得到shotgun的標志 public static bool isGetBlood = false;//是否得到bloodbox的標志 public static bool isGameOver = false; //游戲是否結(jié)束的標志 public static int score = 0; //得分
調(diào)用Graphics類的DrawImage函數(shù)顯示我方飛機。
/// <summary> /// 顯示我方飛機 /// </summary> /// <param name="g"></param> public static void MyPlaneShow(Graphics g) { if (health > 0) { g.DrawImage(myPlaneImg, x, y); } else if (health <= 0 || score <= 0) { isGameOver = true; g.DrawImage(myPlaneImg, 0, -300); g.DrawImage(gameOver, 10, 260); } else if (isGetBlood && health <= 90) { health += 10; } }
通過Keys類定義鍵盤事件函數(shù)。
成員名稱 | 說明 |
---|---|
KeyCode | 從鍵值提取鍵代碼的位屏蔽 |
Modifiers | 從鍵值提取修飾符的位屏蔽 |
None | 沒有按任何鍵 |
LButton | 鼠標左按鈕 |
RButton | 鼠標石按鈕 |
Cancel | Cancel 鍵 |
MButton | 鼠標中按鈕(三個按鈕的鼠標) |
XButton1 | 第一個X鼠標按鈕(五個按鈕的鼠標) |
XButton2 | 第二個 X 鼠標按鈕(五個按鈕的鼠標) |
Back | Backspace 鍵 |
這里先用熟悉的WASD鍵來控制我方飛機移動。
/// <summary> /// 顯示我方飛機 /// </summary> /// <param name="g"></param> public static void MyPlaneShow(Graphics g) { if (health > 0) { g.DrawImage(myPlaneImg, x, y); } else if (health <= 0 || score <= 0) { isGameOver = true; g.DrawImage(myPlaneImg, 0, -300); g.DrawImage(gameOver, 10, 260); } else if (isGetBlood && health <= 90) { health += 10; } } /// <summary> /// 松開鍵盤鍵 /// </summary> /// <param name="key"></param> public static void Keyup(Keys key) { keys.Remove(key); } /// <summary> /// 按下鍵盤鍵 /// </summary> /// <param name="key"></param> public static void Keydown(Keys key) { if (!keys.Contains(key)) { keys.Add(key); } } /// <summary> /// 判斷按鍵是否被按下 /// </summary> /// <param name="key"></param> /// <returns>是則返回true 不是則返回false</returns> public static bool IsKeyDown(Keys key) { return keys.Contains(key); } /// <summary> /// 用鍵盤控制我方飛機移動 /// </summary> public static void MyPlaneMove() { if(isGameOver) { return; } if (IsKeyDown(Keys.A)) { myPlaneImg = Resource.planeLeft; if (x < 5) x = 5; x -= PLANE_OFFSET; } if (IsKeyDown(Keys.D)) { myPlaneImg = Resource.planeRight; if (x > 370) x = 370; x += PLANE_OFFSET; } if (IsKeyDown(Keys.W)) { if (y < 5) y = 5; y -= PLANE_OFFSET; } if (IsKeyDown(Keys.S)) { if (y > 530) y = 530; y += PLANE_OFFSET; } }
4、敵方飛機
創(chuàng)建一個Fighter實體類,定義字段如下。
Image redImg; Image greenImg; Image yellowImg; public Image fighterImg;//敵機圖片 private const int FIGHTER_OFFSET = 4;//敵機圖片移動速度 public int _x = 0; public int _y = 0;//敵機圖片移動起始的坐標 public static List<Fighter> fighters = new List<Fighter>();//敵機對象列表 private int fi;//敵機圖片索引 List<Image> imgList = new List<Image>();//敵機圖片列表 public bool flag = false;//碰撞的標志
通過Random產(chǎn)生隨機數(shù),用于定義隨機出現(xiàn)的敵機x以及y點坐標。
/// <summary> /// 隨機產(chǎn)生敵機 /// </summary> public static void ProduceFighter() { Random rad = new Random(); if (rad.Next(18) == 0) { Fighter f = new Fighter(rad.Next(0, 350), rad.Next(0, 3)); fighters.Add(f); } } public Fighter(int x,int i) { _x = x;//橫坐標 fi = i; redImg = Resource.fighterRed; greenImg = Resource.fighterGreen; yellowImg = Resource.fighterYellow; switch (fi) { case 0: fighterImg = redImg;break; case 1: fighterImg = greenImg;break; case 2: fighterImg = yellowImg;break; default: break; } imgList.Add(redImg); imgList.Add(greenImg); imgList.Add(yellowImg); }
通過Graphics繪制敵機圖片。
/// <summary> /// 出現(xiàn)敵機 /// </summary> public void FighterShow(Graphics g) { g.DrawImage(fighterImg,_x,_y); } public void fMove() { _y += FIGHTER_OFFSET; } /// <summary> /// 敵機移動函數(shù) /// </summary> public static void FighterMove(Graphics g)//通過定時位置讓圖片發(fā)生偏移 { for (int i = 0; i < fighters.Count; i++) { fighters[i].FighterShow(g); fighters[i].fMove(); if (fighters[i]._y > 650) { fighters.Remove(fighters[i]); } } }
5、子彈及碰撞檢測
創(chuàng)建一個MyBullet實體類,定義字段如下。
private int x;//子彈橫坐標 private int y;//子彈縱坐標 private const int BULLET_OFFSET = 18;//移動速度 public int Angle;//子彈角度 private Image bulImg;//定義子彈圖片 private const double PI = Math.PI; public static List<MyBullet> mybulList = new List<MyBullet>();//子彈對象集合 static Bitmap bm = new Bitmap(Resource.bomb4);//爆炸圖片 public bool isHit = false;//碰撞的標志
通過按鍵盤J鍵來產(chǎn)生我方子彈
/// <summary> /// 通過按鍵盤J鍵來產(chǎn)生我方子彈 /// </summary> public static void ProduceMybul() { if (!MyPlane.isGameOver && MyPlane.IsKeyDown(Keys.J)) { mybulList.Add(new MyBullet(MyPlane.x + 13, MyPlane.y - 10, 0)); if (MyPlane.isGetGun) { mybulList.Add(new MyBullet(MyPlane.x + 13, MyPlane.y - 8, 60)); mybulList.Add(new MyBullet(MyPlane.x + 7, MyPlane.y - 8, 30)); mybulList.Add(new MyBullet(MyPlane.x + 30, MyPlane.y - 12, 120)); mybulList.Add(new MyBullet(MyPlane.x, MyPlane.y - 7, 150)); } } }
定義敵機碰撞檢測方法
/// <summary> /// 敵機碰撞檢測方法 /// </summary> public static void IsHitEnemy(Graphics g) { Rectangle myPlaneRect = new Rectangle(MyPlane.x, MyPlane.y, MyPlane.myPlaneImg.Width, MyPlane.myPlaneImg.Height); //包住myplane的Rectangle //g.DrawRectangle(new Pen(Color.Red), myPlaneRect); for(int i = 0; i < mybulList.Count; i++) for (int j = 0; j < Fighter.fighters.Count; j++) { Rectangle mybulRect = new Rectangle(mybulList[i].x, mybulList[i].y, 8, 10); Rectangle fighterRect = new Rectangle(Fighter.fighters[j]._x, Fighter.fighters[j]._y, 65, 45); //g.DrawRectangle(new Pen(Color.Black), fighterRect); if (mybulRect.IntersectsWith(fighterRect)) //我方子彈擊中敵機,敵機爆炸 { mybulList.Remove(mybulList[i]); Fighter.fighters[j].flag = true; if (MyPlane.score < 100) { MyPlane.score += 1; } } else if (myPlaneRect.IntersectsWith(fighterRect)) //我方飛機撞上敵機,敵機爆炸 { Fighter.fighters[j].flag = true; if (MyPlane.score < 100) { MyPlane.score += 1; } } } }
總結(jié)
到此這篇關(guān)于基于C#制作一個飛機大戰(zhàn)小游戲的文章就介紹到這了,更多相關(guān)C#制作飛機大戰(zhàn)小游戲內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:
相關(guān)文章
C#寫入對象或集合類型數(shù)據(jù)到xml文件的方法
這篇文章主要介紹了C#寫入對象或集合類型數(shù)據(jù)到xml文件的方法,涉及C#針對XML文件的相關(guān)操作技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-07-07DataGridView自定義單元格表示值、Error圖標顯示的方法介紹
這篇文章介紹了DataGridView自定義單元格表示值、Error圖標顯示的方法,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-02-02