win8 開發之旅(14) --飛機游戲制作揭秘


先看看這個游戲的類結構的介紹

類結構 

公共類層:

子彈幫助類、 BulletHepler,公共幫助類、 CommonHelper,圖片幫助類、ImageHelper,精靈工廠類、SpriteFactory。

游戲元素層:

 公有元素有精靈類、Sprite,精靈實體類、ModelSprite,英雄實體類、HeroSprite,游戲結束類、GameOver;

旗下又包括了Bullet層,Daoju層,Effect層,Enemy層。

Bullet層有一個基類BulletSprite,子彈精靈類。其他是具體的實現類EnemyBulletSprite、敵人子彈類,HeroCircleBulletSprite、英雄圓形子彈類,HeroNomalBulletSprite、英雄普通子彈類,LightningBulletSprite、閃電子彈類。

Daoju層有一個基類Support,道具類。其他是具體的實現類AddLife、加血的道具,CircleBullet、球形子彈道具,Clear、清空道具,LightningBullet、閃電子彈道具,PelletBullent、球形子彈道具,

Bomb層有一個類Bomb,爆炸效果類。

Enemy層有一個基類BaseEnemy、敵人基類,其他是具體實現類FristBoss、大佬怪類,HelicopterEnemy、直升飛機怪物類,NomalEnemy、普通敵人類,UFOEnemy、UFO敵人類。

相應枚舉部分:

EnemyType、敵人枚舉類型,HeroState、英雄狀態和英雄子彈的枚舉,SupportType、道具枚舉,UserKeyDir、用戶方向枚舉。

代碼我已經發布,可見做這樣一個win8游戲並不難。今天講准備工作,也就是所需要的開發工具。代碼編寫調試:VS2012,美術工具:美圖秀秀(http://xiuxiu.web.meitu.com)。這是最簡陋的開發工具,但已足夠。最好再有Photoshop,NotePad++或UltraEdit等等你喜歡的文本編輯工具。

 

游戲代碼分兩部分,公共部分,元素部分。先說公共部分:包括兩個部分,幫助類部分和工廠類部分。幫助類主要是將一些主要的邏輯的,工具的源代碼封裝在3個不同的幫助類中(子彈幫助類、 BulletHepler,公共幫助類、 CommonHelper,圖片幫助類、ImageHelper)。而工廠類部分主要是用於產生了各種各樣的游戲元素。這樣在游戲元素類的部分只需要調用這個層封裝各種各樣的方法,就能夠完成一個游戲的組裝。

公共層的3個幫助類是:

①游戲的基本幫助類——主要完成一些游戲主要邏輯的判斷

/// <summary>
/// 基本的幫助類
/// 用於幫助游戲的邏輯的處理
/// </summary>
public class CommonHelper
{
/// 檢測兩個精靈是否發生了碰撞
public static bool CheckHit(Sprite.Sprite spriteOne, Sprite.Sprite spriteTwo);

//獲取主頁

public static MainPage GetMain();

/// 添加精靈島canvas中差不多

public static void AddToGetMianCanvas(Sprite.Sprite sprite);

}

這是一個涉及游戲具體邏輯的類,它主要用用於①檢測兩個精靈是否發生了碰撞,②獲取了主頁的相應的信息,③把相應的游戲的每個元素添加到畫布上,用於游戲渲染。 

我們這里是如何完成一個簡單的碰撞的檢測的了,這里等效於判斷兩個元素的坐標的距離是不是小於兩個圓心直接的距離,小於就相交,反之,就不相交。用數學公式來表示:(x1-x2)²+(y1-y2)²<(r2+r1)².相應的源代碼如下:

 

//檢測的條件是(x1-x2)^2+(y1-y2)^2<(r1+r2)^2
if ((Math.Pow((spriteOne.X - spriteTwo.X), 2) + Math.Pow((spriteOne.Y - spriteTwo.Y), 2)) < Math.Pow((spriteOne.Radius + spriteTwo.Radius), 2))
{
return true;
}
//不碰撞就返回了假
return false;

那我們在看看是如何獲取其運行的主頁面的了,這里,本來在silverlight中用App.Current...可獲取,但是,你要知道這在win8 app 中不支持。沒轍,我們這里用了一個全局變量來傳遞mainpage ,相應源代碼如下:

        return (MainPage.main as MainPage);

又怎么吧元素添加到畫布中,我們上個方法中獲取的主頁 中有個公開的畫布的屬性,用add方法添加到畫布中去是不是就可以了。相應的源代碼如下:

 

//添加精靈
GetMain().sprites.Add(sprite);
//添加到子控件中
GetMain().appCanvas.Children.Add(sprite)

②照片的助手類——用於處理相應的圖片的信息。

 

/// <summary>
/// 動畫的幫助類
/// </summary>
public class ImageHelper

{

/// 對圖片進行裁剪的方法  

public static List<WriteableBitmap> GetImageSplit(string imgpath, int count,Action<List<WriteableBitmap>> actions);

}

本來這個方法是基於WriteableBitmap這個類的Render方法進行大圖片裁剪的,但是涉及win8微軟可能從考慮提高顯卡性能的關系,也罷這個類徹底的干掉了。我想到的方法,用

美圖秀秀處理圖片的方法。但是,我還是把源代碼貼在這里,這針對普通的silverlight程序還是起效的。源代碼如下:

 

Image img = new Image();
BitmapImage bitmap = new BitmapImage(new Uri(imgpath));
img.Source = bitmap;
img.ImageOpened += (sender, e) =>
{
for (int i = 0; i < count; i++)
{
int height = bitmap.PixelHeight;
int weight = bitmap.PixelWidth / count;
WriteableBitmap write = BitmapFactory.New(weight,height);
//write.r(img, new TranslateTransform() { X = weight * -1 * i, Y = 0 });
write.Invalidate();
bits.Add(write);
}
CommonHelper.GetMain().appCanvas.Children.Remove(img);
//eventhander(bits, null);

actions(bits);
};
CommonHelper.GetMain().appCanvas.Children.Add(img);

img.Visibility = Visibility.Collapsed;

return bits;

③BulletHelper——游戲子彈處理的邏輯類

public class BulletHepler
{
/// <summary>
/// 當前精靈的實體
/// </summary>
private ModelSprite model;
/// <summary>
/// 構造函數
/// 用於數據的初始化
/// </summary>
/// <param name="sprite"></param>
public BulletHepler(ModelSprite sprite);

/// <summary>
/// 英雄進行開火的方法
/// </summary>
public void HeroWork();

/// <summary>
/// 英雄的子彈開火的方法
/// </summary>
public void NormalEnemyWork();

構造函數傳遞是能發子彈實體的類,如敵人,英雄等等。進行當前信息的初始化。

說一說英雄發子彈的方法,這個進行開火的方法。判斷英雄發子彈不同的類型,①一個是普通的類型,初始化為相應的x軸的速度,y軸的速度,初始化為x,y坐標。這樣子就有普通子彈的類型。將他添加到頁面上。還有②一個圓形子彈,就是循環給初始化普通的子彈添加到泛型數組中。③光球子彈,是以sin,cos形式發出的。源代碼如下:

//普通的子彈
case SpriteBullet.Normal:
//英雄普通的子彈的類
HeroNomalBulletSprite herob = new HeroNomalBulletSprite();
//x坐標等於傳進來的對象x坐標
herob.X = model.X+30;
//y坐標等於傳進來的對象的y坐標

herob.Y = model.Y;
//x上的速度等於0
herob.Vx = 0;
//y上的速度等於-3
herob.Vy = -3;
//添加到頁面上
CommonHelper.AddToGetMianCanvas(herob);

break;
//球形的子彈的類型
case SpriteBullet.Pellet:
//循環的添加
for (int i = -1; i < 2; i++)
{
//英雄的普通子彈的類型
HeroNomalBulletSprite herox = new HeroNomalBulletSprite();
//x坐標等於傳進來的對象的x坐標
herox.X = model.X+30;
//y坐標等於傳進來的對象的y坐標
herox.Y = model.Y;
//其速度等於一個I值
herox.Vx = i;
//其y的速度等於一個-3的值
herox.Vy = -3;
//添加到頁面上
CommonHelper.AddToGetMianCanvas(herox);
}
break;
//圓形子彈的類型
case SpriteBullet.Circle:
//x坐標
double x = 0;
//只要小於二分支π
while (!(x > Math.PI * 2))
{
//英雄的圓圈的對象
HeroCircleBulletSprite herox = new HeroCircleBulletSprite();
//x坐標
herox.X = model.X+30;
//y坐標
herox.Y = model.Y;
//x方向上的速度
herox.Vx = Math.Sin(x) * 3;
//y方向上的速度
herox.Vy = Math.Cos(x) * 3;
//添加到頁面上
CommonHelper.AddToGetMianCanvas(herox);
//x累加
x += 2 * Math.PI / 5;
}
break;
//光子彈的
case SpriteBullet.Lightning:
//光子彈
LightningBulletSprite big = new LightningBulletSprite();
//光子彈的x坐標等於傳進來的對象的x坐標的值
big.X = model.X;
//y坐標的值等於傳進來y的值減高度
big.Y = model.Y - big.SpriteHeight;
//x坐標等於0
big.Vx = 0;
//y坐標等於-3
big.Vy = -3;
//添加到控件上
CommonHelper.AddToGetMianCanvas(big);
break;

而 敵人的子彈開火的方法,與英雄的子彈發出的方法一樣的。此處略去n個字。

3個幫助類,說完了。說一說精靈的工廠類,這個精靈工廠類,與傳統的工廠類是一模一樣。就是傳遞給不同參數,產生了不同精靈的對象。再初始化相應的x,y坐標,x軸速度,y軸速度。代碼如下:

public class SpriteFactory
{

/// <summary>
/// 創建老怪
/// </summary>
/// <param name="enemyType">老怪的類型</param>
/// <returns></returns>
public static BaseEnemy CreateEnemy(EnemyType enemyType)
{
///隨機函數
Random rd = new Random(DateTime.Now.Millisecond);
//基本敵人的對象
BaseEnemy enemy = null;
//創建不同的敵人的對象
switch (enemyType)
{
//直升飛機的敵人
case EnemyType.Helicopter:
enemy = new HelicopterEnemy();
break;
//普通的敵人
case EnemyType.Normal:
enemy = new NomalEnemy();
break;
//ufo敵人
case EnemyType.UFO:
enemy = new UFOEnemy();
break;
}
//敵人的x坐標
enemy.X = (rd.Next(0, 800 - enemy.Radius));
//敵人的y坐標
enemy.Y = -enemy.Radius;
//敵人的x軸上的速度
enemy.Vx = 0;
//敵人的y軸上的速度
enemy.Vy = 3;
//返回建造的enemy的對象
return enemy;
}
//參加相應的道具對象
public static Support CreateSupport(SupportType supportType)
{
//隨機函數
Random rd = new Random(DateTime.Now.Millisecond);
//道具對象
Support support = null;
//創建不同的道具的對象
switch (supportType)
{
//加血的道具
case SupportType.AddLife:
support=new AddLife();
break;
//原性子彈的道具
case SupportType.CircleBullet:
support = new CircleBullet();
break;
//球星子彈的道具
case SupportType.PelletBullet:
support = new PelletBullet();
break;
//廣石化的道具
case SupportType.Lightning:
support = new LightningBullet();
break;
//晴空的道
case SupportType.Clear:
support = new Clear();
break;
}

//x的坐標
support.X = (rd.Next(0, 800 - support.Radius));
//y的坐標
support.Y = -support.Radius;
//x的速度
support.Vx = rd.Next(0, 10);
//y的速度
support.Vy = 3;
//返回道具的對象
return support;
}

//創建了大老怪
public static FristBoss CreateBoss()
{
//隨機函數
Random rd = new Random(DateTime.Now.Millisecond);
//的老怪的對象
FristBoss boss = new FristBoss();
//x的坐標
boss.X = (rd.Next(0, 800 - boss.Radius));
//y的坐標
boss.Y = -boss.Radius;
//返回了大老怪的對象
return boss;
}

}

上述的這些源代碼是只是一個公共層的類概述和源代碼簡介。

說一說游戲元素層,這些層的是產生游戲核心元素——游戲元素的類。

這些游戲的類由於好多源代碼和思路是大同小異的,這里只需要講明白3個類。一個是所有這些類的基類——sprite,一個能活動的游戲元素的基類——Modelsprite,一個子彈的類。

①sprite類——這個類是所有的游戲元素的基類,它定義了這些游戲元素公有的屬性,方法。他的結構如下:

public abstract class Sprite : Canvas
{
/// <summary>
/// x的坐標 進行精靈的x坐標定位
/// </summary>
public double X

/// <summary>
/// y的坐標 進行精靈的y坐標定位
/// </summary>
public double Y

/// <summary>
/// x方向上的速度
/// </summary>
public double Vx { get; set; }
/// <summary>
/// y方向上的速度
/// </summary>
public double Vy { get; set; }
/// <summary>
/// 他所經過的半徑區域
/// </summary>
public int Radius;
/// <summary>
/// 相應精靈的圖片
/// </summary>
public Image SpriteImg;
/// <summary>
/// 精靈的寬度
/// </summary>
private int spriteWidth;
/// <summary>
/// 精靈的高度
/// </summary>
private int spriteHeight;


/// <summary>
/// 構造函數
/// </summary>
public Sprite();

/// <summary>
/// 移去相應的元素
/// </summary>
public virtual void Remove();

/// <summary>
/// 進行了更新的操作
/// </summary>
public abstract void Update();

}

通過這樣結構,我們可以知道他有x,y坐標,vx,vy的屬性 這些都是用於定位於使飛機移動下來所必備的屬性。而Image屬性,是這些類背景圖片又是哪一張。至於Remove操作,是使某個元素消亡以后,他從界面上移去的方法。至於說到所謂的更新操作,這個使飛機位於不同的位置。其中源代碼如下:

public abstract class Sprite : Canvas
{
/// <summary>
/// x的坐標 進行精靈的x定位
/// </summary>
public double X
{

get { return Canvas.GetLeft(this); }
set { Canvas.SetLeft(this, value); }
}
/// <summary>
/// y的坐標 進行精靈的y定位
/// </summary>
public double Y
{
get { return Canvas.GetTop(this); }
set { Canvas.SetTop(this, value); }
}
/// <summary>
/// x方向上的速度
/// </summary>
public double Vx { get; set; }
/// <summary>
/// y方向上的速度
/// </summary>
public double Vy { get; set; }
/// <summary>
/// 他所經過的半徑區域
/// </summary>
public int Radius;
/// <summary>
/// 相應精靈的圖片
/// </summary>
public Image SpriteImg;
/// <summary>
/// 精靈的寬度
/// </summary>
private int spriteWidth;
/// <summary>
/// 精靈的高度
/// </summary>
private int spriteHeight;
/// <summary>
/// 精靈的寬度
/// </summary>
public int SpriteWidth
{
get { return spriteWidth; }
set
{
spriteWidth = value;
SpriteImg.Width = value;
Canvas.SetLeft(SpriteImg,value/2-1);
}
}
/// <summary>
/// 精靈的高度
/// </summary>
public int SpriteHeight
{
get { return spriteHeight; }
set
{
spriteHeight = value;
SpriteImg.Height = value;
Canvas.SetTop(SpriteImg,value/2-1);
}
}
/// <summary>
/// 構造函數
/// </summary>
public Sprite()
{
SpriteImg = new Image();
this.Children.Add(SpriteImg);
}
/// <summary>
/// 移去相應的元素
/// </summary>
public virtual void Remove()
{
//canvas的對象
Canvas canva = CommonHelper.GetMain().appCanvas;
if (canva.Children.Contains(this))
{
//移去對象
(this.Parent as Canvas).Children.Remove(this);

}
//包含相應的對象
if (CommonHelper.GetMain().sprites.Contains(this))
{
//移去對象
CommonHelper.GetMain().sprites.Remove(this);
}
}
/// <summary>
/// 進行了更新的操作
/// </summary>
public abstract void Update();
}

②ModelSprite——基本的神靈的基本類,這是所有的英雄精靈類,各種各樣的敵人精靈類都繼承與他。他的架構如下:

/// <summary>
///基本的精靈的類
/// </summary>
public class ModelSprite : Sprite
{
/// <summary>
/// 最大的生命值
/// </summary>
private int maxlife;
/// <summary>
/// 最大的速度
/// </summary>
public int speed = 5;
/// <summary>
/// 最大的生命值(屬性)
/// </summary>
public int MaxLife
{
//只讀
get { return maxlife; }
//屬性
set
{
maxlife = value;
}
}
/// <summary>
/// 精靈的子彈(屬性)
/// </summary>
public SpriteBullet Bullet { get; set; }
/// <summary>
/// 精靈的更新狀態(屬性)
/// </summary>
public SpriteState State { get; set; }

/// <summary>
/// 進行更新的操作
/// </summary>
public override void Update()
/// <summary>

/// 構造函數 進行了初始化的工作

/// </summary>
public ModelSprite();

}

他包括這個最大生命值,最大運行的速度這些屬性,update方法, 判斷這個精靈生命值是不是小於0,就將他從界面上移去,並且把的坐標改變。

③BulletSprite——子彈的精靈基類,所有子彈繼承與他。這包含了一個DPS——每秒鍾刷新的頻率。   他繼承與精靈類。

后記

程序,樂趣無窮。在一篇文不加點情況下,一篇win8的飛機游戲介紹文章誕生了。

源碼位置:http://51aspx.com/Code/Win8Fly


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM