Silverlight C# 游戏开发:Flyer03大图裁剪,高效动画的艺术
Flyer02最后,我們得到了一個(gè)屏幕,上面有云彩向上飄去,但是很容易發(fā)現(xiàn)有一個(gè)很明顯的瑕疵,就是云彩不會(huì)限定在一個(gè)畫面中,那么能不能控制在一個(gè)指定的范圍內(nèi)呢。
Sivlerlight中限定一個(gè)UIElement的邊界,可以使用Clip來(lái)實(shí)現(xiàn),在能夠顯示圖片主窗口元素上添加如下代碼:
?
GameMainWindow.Clip = new RectangleGeometry() { Rect = new Rect(0, 0, 400, 400) };?
?
現(xiàn)在再運(yùn)行一下,看到了吧,是否達(dá)到了我們想要的效果了呢?
是不是很有趣,讓我們想想,如果能夠裁剪的方式獲得一個(gè)限定區(qū)域,那么是不是可以將一組圖片的各個(gè)部分拆分出來(lái)呢?就如資源目錄中的filyer.png,能否將每個(gè)部分拆分出來(lái)顯示?Clip完全可以做到,但是并不高效,其原因是,Clip的裁剪并不會(huì)減少整張圖片的大小,這意味著有多少動(dòng)作幀內(nèi)存中就要載入多少?gòu)堈麖垐D片,很顯然,絕不優(yōu)美,相信玩家也不會(huì)為此買內(nèi)存的單,那么是不是就沒(méi)有辦法了呢?能否有一個(gè)好的方法,只加載一個(gè)張圖片然后處理分成多張小圖,對(duì)內(nèi)存的占用就低的多了。
可以通過(guò)WriteableBitmap來(lái)實(shí)現(xiàn)分成小圖,WriteableBitmap是Silverlight提供操作Bitmap數(shù)據(jù)的BitmapSouce,通過(guò)這個(gè)類可以生成多張指定大小的圖片,在內(nèi)存上不需要加載過(guò)多的圖,只需要一張大圖即可,那么我們的編寫思路圖如下:
?
通過(guò)截取整張圖片當(dāng)中的一個(gè)部分,渲染到WriteableBitmap當(dāng)中,然后轉(zhuǎn)換成為Image控件的Souce,最后通過(guò)一個(gè)定時(shí)器完成動(dòng)畫效果
一如既往,我們只使用代碼實(shí)現(xiàn)這個(gè)部分,那么需要?jiǎng)?chuàng)造一個(gè)類,這個(gè)類的名字叫ClassFlyer
代碼如下:
Image _image; ImageSource[,] FlyerFrames = new ImageSource[6, 8]; public ClassFlyer() { _image = new Image(); BitmapImage bitmap = new BitmapImage(new Uri(@"Src/flyer.png", UriKind.Relative)); bitmap.ImageOpened += new EventHandler<RoutedEventArgs>(bitmap_ImageOpened); this.Children.Add(_image); }//之所以在這里處理是因?yàn)镾ilverlight的圖片下載是異步的,只有載入完畢后才好處理void bitmap_ImageOpened(object sender, RoutedEventArgs e)
{ _image.Source = sender as BitmapImage;
for (int j = 0; j < 6; j++)
{
for (int i = 0; i < 8; i++) {
WriteableBitmap wb = new WriteableBitmap(64,64);
wb.Render(_image, new TranslateTransform() { X = -64 * i, Y = -64 * j }); wb.Invalidate();
FlyerFrames[j, i] = (ImageSource)wb; } }
}
最終的目的是得到了一個(gè)FlyerFrames的禎組,這組圖片涵蓋了以行為劃分的動(dòng)畫序列,清晰的描述角色們的狀態(tài)
現(xiàn)在看起來(lái)容易多了,實(shí)現(xiàn)動(dòng)畫只是找對(duì)正確的行和列,建議實(shí)現(xiàn)一個(gè)簡(jiǎn)單的枚舉,當(dāng)然了,C#不像C++那般方便的將enum轉(zhuǎn)換成為數(shù)字,所以我的實(shí)現(xiàn)方法是用const
?
public class EmFlyerState { public const int 正常 = 0;public const int 向上 = 1;
public const int 向右 = 2;
public const int 向左 = 3;
public const int 向下 = 4;
public const int 擊中 = 5;
}
現(xiàn)在下面重要的是動(dòng)畫,動(dòng)畫是按照一個(gè)時(shí)間的循環(huán),這種有很多方法來(lái)實(shí)現(xiàn),在這里為了方便理解,用一個(gè)DispatcherTimer
DispatcherTimer dispatcherTimer = new DispatcherTimer();dispatcherTimer.Tick += new EventHandler(TickGameFrameLoop);
dispatcherTimer.Interval = TimeSpan.FromMilliseconds(30); //重復(fù)間隔
dispatcherTimer.Start();
private void TickGameFrameLoop(object sender, EventArgs e)
{
}
也許你覺(jué)得現(xiàn)在有點(diǎn)意思了,但是還無(wú)法實(shí)現(xiàn)控制飛行員動(dòng)作,為了達(dá)到這個(gè)目的需要為MainPage加上按鍵事件,
在MainPage類中加上下述代碼,然后實(shí)現(xiàn)KeyDown和KeyUp的方法,這里做一個(gè)特別的說(shuō)明,為什么還要檢測(cè)KeyUp,這是因?yàn)楫?dāng)玩家松開鍵盤的時(shí)候,可以讓飛行員的角色變?yōu)檎顟B(tài)。
this.KeyDown += new KeyEventHandler(MainPage_KeyDown);this.KeyUp += new KeyEventHandler(MainPage_KeyUp);
在KeyDown和KeyUp事件里,我們可以寫下如下代碼來(lái)控制角色的狀態(tài),假設(shè)我們之前定為ClassFlyer的實(shí)例名為Hero
?
void MainPage_KeyDown(object sender, KeyEventArgs e){
switch (e.Key)
{??????????????????
case Key.Up:
Hero.Flyerstate = EmFlyerState.向上;
break;
case Key.Down:
Hero.Flyerstate = EmFlyerState.向下;
break;
case Key.Left:
Hero.Flyerstate = EmFlyerState.向左;
break;
case Key.Right:
Hero.Flyerstate = EmFlyerState.向右;
break;
}
}
void MainPage_KeyUp(object sender, KeyEventArgs e)
{
Hero.Flyerstate = EmFlyerState.正常;
}
基本上我們已經(jīng)接近于完成,但是還有一些細(xì)節(jié)代碼需要整理,在這里就不一一做講解了,有興趣的請(qǐng)直接看代碼:)
點(diǎn)擊這里進(jìn)行下載:FlyerGame2
?
?
總結(jié)
以上是生活随笔為你收集整理的Silverlight C# 游戏开发:Flyer03大图裁剪,高效动画的艺术的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Oracle Database 10g:
- 下一篇: Effective C++ 11 在op