Windows8开发7之SpaceCadet2游戏逻辑和处理触控事件.docx
《Windows8开发7之SpaceCadet2游戏逻辑和处理触控事件.docx》由会员分享,可在线阅读,更多相关《Windows8开发7之SpaceCadet2游戏逻辑和处理触控事件.docx(14页珍藏版)》请在冰豆网上搜索。
![Windows8开发7之SpaceCadet2游戏逻辑和处理触控事件.docx](https://file1.bdocx.com/fileroot1/2022-11/26/ea7c334d-fad1-4e51-a282-5ffaf2542584/ea7c334d-fad1-4e51-a282-5ffaf25425841.gif)
Windows8开发7之SpaceCadet2游戏逻辑和处理触控事件
2、游戏逻辑和处理触控事件
添加按钮事件
跳转开始界面,在游戏开始的时候,会点击开始按钮进入游戏界面,在这里我们可以看看如何对按钮进行响应。
打开开始界面(StartPage.xaml),选择界面中的开始按钮,属性界面里,选择“事件”标签,然后双击其中Click事件:
会看到自动在所属的.cs文件中添加了事件处理:
现在可以前往Vs2012中编辑了:
处理页面逻辑
首先,现在应用进入到的第一个页面是MainPage,需要做一下修改,打开App.cs文件的对应位置:
在这就是跳转到MainPage的代码了,可以修改一下成为StartPage,现在可以运行一下看看效果,不错吧,但是开始按钮点击还没有任何的用处,需要添加一行代码。
打开StartPage.cs,找到刚才生成的事件处理位置:
输入代码:
(Window.Current.ContentasFrame).Navigate(typeof(GamePage));
这段代码的意思是,让当前应用的显示页面跳转到GamePage。
现在可以试一下看看跳转效果。
处理游戏逻辑
在处理游戏逻辑之前,先用Blend对元素做一下修改,因为我们将会在代码中访问它们:
分数:
tb_score
等级:
tb_level
玩家:
tb_player
飞船空间:
shipPlace,所有的飞船将会被该画布包含,下属的元素为测试用的,可以删除掉。
飞船控件的代码
打开Ship.cs文件,做如下修改:
publicsealedpartialclassShip:
UserControl
{
publicShip()
{
this.InitializeComponent();
//飞行完成事件增加
Storyboard_Fly.Completed+=Storyboard_Fly_Completed;
//爆炸完成事件增加
Storyboard_explosion.Completed+=Storyboard_explosion_Completed;
//点击事件Pressed事件增加
this.PointerPressed+=Ship_PointerPressed;
}
voidShip_PointerPressed(objectsender,PointerRoutedEventArgse)
{
//如果被点击
//判断是否在爆炸过程中
if(Storyboard_explosion.GetCurrentState()!
=ClockState.Stopped)
return;
//飞行直接停止
Storyboard_Fly.Pause();
//播放爆炸动画
//使用代码替换掉了飞船图片
image.Source=newBitmapImage(newUri("ms-appx:
///Resouce/explosion.png"));
Storyboard_explosion.Begin();
}
voidStoryboard_Fly_Completed(objectsender,objecte)
{
//飞到底移除飞船
RemoveShip();
}
voidStoryboard_explosion_Completed(objectsender,objecte)
{
//爆炸完移除飞船
RemoveShip();
}
publicvoidFly()
{
//开始飞
Storyboard_Fly.Begin();
}
publicvoidRemoveShip()
{
//从父层元素移除自己
(ParentasPanel).Children.Remove(this);
}
}
在本代码中,创建了一些方法来控制和使用故事板系统,让其在正确的逻辑下进展。
需要特别说明的是Storyboard.Completed事件,该事件是当Storyboard完成的时候触发,游戏中的飞船在飞行完成和爆炸后都应在游戏中移除,所以,我们使用这个事件来完成这个操作。
PointerPressed事件是针对于元素本身而言的,当飞船被点击到的时候会触发,按照游戏逻辑,应暂停飞行立即爆炸,但要先判断是不是已经爆炸。
GamePage
飞船的处理完成后,就是如何在游戏中执行逻辑了,现在打开GamePage.cs,做如下的修改:
publicsealedpartialclassGamePage:
Page
{
//随机数
Randomrandom=newRandom((int)DateTime.Now.Ticks);
publicGamePage()
{
this.InitializeComponent();
DispatcherTimertimer=newDispatcherTimer();
timer.Interval=TimeSpan.FromMilliseconds(400);
timer.Tick+=timer_Tick;
timer.Start();
}
voidtimer_Tick(objectsender,objecte)
{
Shipship=newShip();
shipPlace.Children.Add(ship);
Canvas.SetLeft(ship,shipPlace.ActualWidth);
Canvas.SetTop(ship,random.Next()%shipPlace.ActualHeight);
ship.Fly();
}
protectedoverridevoidOnNavigatedTo(NavigationEventArgse)
{
}
}
这段代码中,使用了DispatcherTimer,DispatcherTimer是一个定时器,用它来完成飞船的生成操作。
timer.Interval=TimeSpan.FromMilliseconds(400);
这是指定每400毫秒触发一次,而触发的事件就是timer_Tick,在该事件中,我们生成了一架飞船,添加到了shipPlace这个Canvas最右边中,并随机设置了Y轴位置。
看起来很简单,一共没有写多少代码,运行一下看看:
好了,如果你觉得生成的速度不佳,可以修改timer的间隔数值,如果你觉得飞机飞得过快或者过慢,可以在Blend里直接调整Storyboard_Fly的时间周长度,更多的细节还需自己的发掘。
不同的飞船
现在飞出的飞船都是一样的,如何让飞出来的飞船不一样呢?
还有分数也应该不一样才对,所以,先定义一个飞船类型类:
publicclassShipType
{
publicShipType(ImageSourcebody,intscore)
{
Body=body;
Score=score;
}
publicImageSourceBody{get;privateset;}
publicintScore{get;privateset;}
}
这里描述了一个飞船类型的主体图像是什么,所得分数是多少。
在Ship类里建立一个List:
staticListshipTypeList=newList()
{
newShipType(newBitmapImage(newUri("ms-appx:
///Resouce/ship.png")),10),
newShipType(newBitmapImage(newUri("ms-appx:
///Resouce/ship1.png")),20),
newShipType(newBitmapImage(newUri("ms-appx:
///Resouce/ship2.png")),30),
newShipType(newBitmapImage(newUri("ms-appx:
///Resouce/ship3.png")),40),
};
Randomrandom=newRandom((int)DateTime.Now.Ticks);
ShipTypeshipType;
其实我们在作的就是使用代码控制Image图像,具体的做法前面有提到过,这里先看代码,在上面的代码中提前定义了一个随机数产生器和被随机的飞船类型,在构造函数中Ship()添加这样一段:
//随机一个飞船类型
shipType=shipTypeList[random.Next()%shipTypeList.Count];
//将图片更换
image.Source=shipType.Body;
运行一下,飞船是不是出的都不太一样了呢?
显示分数
在上面一段中,已经加入了分数的数值,但是没有用上,加上分数处理是非常容易:
首先打开GamePage.cs,在GamePage类定义一个静态变量:
publicstaticintGameScore;
这是标识游戏分数的数值,然后就是在恰当的时机刷新它,我们可以使用前面的timer_Tick中做处理,timer_Tick是一段时间处理一次,那么正好符合要求,找到timer_Tick在下面添加:
tb_score.Text="Score:
"+GameScore;
tb_score是在Blend里设计制作的一个TextBlock,通过其Text属性来改变文字内容,定期刷新它就可以完成分数显示。
GameScore在什么时候改变呢?
现在打开Ship.cs,在被打爆的地方添加代码如下:
//爆炸加分
GamePage.GameScore+=shipType.Score;
现在点击就可以显示不同的分数了。
触摸和手势
我们知道在平板上开发游戏很容易面临一个处理,就是手势操作,在Win8应用里可以处理非常多的手势,例如:
Hold、敲击、双敲击、多点触控等等,
在前面,我们使用了控件的Pointer的相关事件来完成了Pressed处理,Pointer还有其他的事件可以帮助完成对于点击的处理,甚至是多点的触控,虽然使用Pointer可以写出来上面的手势,但是不觉得非常的麻烦吗?
在Win8开发中我们可以使用Manipulation相关的事件直接进行手势编程。
在这里我们将尝试一个轻滑(Panning)手势来说明Manipulation是多么的方便,为了展示这个效果,当Panning手势出现的时候,将控制游戏的停止和继续,也就是说,轻滑一下暂停游戏,再轻滑一下继续游戏。
为了达到暂停和继续的效果,所有飞船都必须拥有暂停的功能,在Ship.cs中加入如下代码:
//是否处于暂停状态,这个标记用作飞船的即可,因此不必每个飞船都增加一个bool
publicstaticboolIsPause;
publicvoidPause()
{
Storyboard_Fly.Pause();
}
publicvoidResume()
{
Storyboard_Fly.Resume();
}
记得在Laser方法中加入是否处于暂停的状态判断:
这是因为,当暂停的时候是不需要处理暂停事件的。
现在打开GamePage.cs在其中加入有关触摸的处理,第一步先在构造函数中加入如下代码:
//开启手势可以取得的行为
this.ManipulationMode=ManipulationModes.TranslateY;
//注册事件
this.ManipulationCompleted+=GamePage_ManipulationCompleted;
或者在GamePage.xaml里加入如下代码是一样的效果:
在这里,我们只需要处理Y轴的滑动即可,所以手势的处理属性设置成为了TranslateY,如果想处理更多的手势,可以这样:
this.ManipulationMode=ManipulationModes.TranslateY|ManipulationModes.TranslateX;
第二步实现GamePage_ManipulationCompleted事件:
voidGamePage_ManipulationCompleted(objectsender,ManipulationCompletedRoutedEventArgse)
{
if(e.Cumulative.Translation.Y>=50)
{
Ship.IsPause=!
Ship.IsPause;
foreach(ShipshipinshipPlace.Children)
{
if(Ship.IsPause)
ship.Pause();
else
ship.Resume();
}
}
}
Manipulation可以很轻松地取得Cumulative之后的数据,这样我们只要判断Y轴是否滑动超过50的距离就算为轻滑,这里可以依据自己的需要进行调整。
Manipulation有很多的事件,我用下图来表示这个手势的处理:
通过上图可以了解手势的初步事件位置,而我们不需要处理开始、开始中、过程中的事件,只需要处理完成就可以了。
最后,还需要在Timer循环里加入一个对是否暂停的判断:
好了,运行一下看看吧。