平方已经开发了一些 Windows Phone 上的一些游戏,算不上什么技术大牛。在这里分享一下经验,仅为了和各位朋友交流经验。平方会逐步将自己编写的类上传到托管项目中,没有什么好名字,就叫 WPXNA 吧,最后请高手绕道而行吧,以免浪费时间。(为了突出重点和减少篇幅,有些示例代码可能不够严谨。)

按钮

在游戏当中,我们可能需要创建一些图形按钮,平方创建了 Button 类来完成这个任务。

首先,我们需要在按钮中定义了一个 Movie,使用这个 Movie 来控制图形,他可以播放按钮各种状态时的动画。

protected readonly Movie backgroundMovie;

protected string upMovieSequenceName = "up";
protected string downMovieSequenceName = "down";
protected string disableMovieSequenceName = "disable"; internal Button ( string name, string resourceName, string command, Vector2 location, int width, int height, bool isSole, Point upFrameIndex, Point downFrameIndex, Point disableFrameIndex, params MovieSequence[] movieSequences )
: base ( name, resourceName )
{
// ... List<MovieSequence> sequences = new List<MovieSequence> ( );
sequences.Add ( new MovieSequence ( this.upMovieSequenceName, upFrameIndex ) );
sequences.Add ( new MovieSequence ( this.downMovieSequenceName, downFrameIndex ) );
sequences.Add ( new MovieSequence ( this.disableMovieSequenceName, disableFrameIndex ) ); if ( null != movieSequences && movieSequences.Length != )
sequences.AddRange ( movieSequences ); this.backgroundMovie = new Movie ( "background", resourceName, location, width, height, , 1f, this.upMovieSequenceName,
sequences.ToArray ( )
); // ...
} internal override void Init ( Scene scene )
{
base.Init ( scene ); this.backgroundMovie.Init ( scene );
} internal override void InitResource ( ResourceManager resourceManager )
{
base.InitResource ( resourceManager ); this.backgroundMovie.InitResource ( resourceManager );
} public override void Dispose ( )
{
this.backgroundMovie.Dispose ( ); base.Dispose ( );
}

在构造函数中,参数 resourceName 表示按钮图形的资源名称,字段 backgroundMovie 是控制按钮背景的电影,默认电影序列的名称为 up,down,disable,分别对应了按钮松开,按钮按下,按钮不可用。

你可以指定不同电影序列对应的帧,也可以使用默认的值。默认情况下,up 右边的是 down,down 右边是 disable,就像下面的图形:

由于 backgroundMovie 是被 Button 创建的,所以 backgroundMovie 需要被 Button 管理。在方法 Init,InitResource 中,我们会初始化 backgroundMovie,在方法 Dispose 中,我们销毁了 backgroundMovie。

internal event EventHandler<ButtonEventArgs> Pressing;
internal event EventHandler<ButtonEventArgs> Pressed; internal static void Press ( Button button )
{
button.IsPressing = true; button.press ( ); if ( null != button.Pressing )
button.Pressing ( button, new ButtonEventArgs ( button.command ) ); } internal static void Unpress ( Button button )
{ if ( !button.IsPressing )
return; button.IsPressing = false; button.unpress ( ); if ( null != button.Pressed )
button.Pressed ( button, new ButtonEventArgs ( button.command ) ); } internal static bool PressTest ( Button button, IList<Motion> motions )
{ if ( !button.isEnabled || !button.isVisible )
return false; foreach ( Motion motion in motions )
if ( motion.Type == MotionType.Down || motion.Type == MotionType.Press )
{
Point location = new Point ( ( int ) motion.Position.X, ( int ) motion.Position.Y ); if ( button.bound.Contains ( location ) )
{
Press ( button );
return true;
} } Unpress ( button );
return false;
}

方法 Press 将使按钮进入按下状态,并触发 Pressing 事件。方法 Unpress 将使按钮离开按下状态,并触发 Pressed 事件。你并不需要直接调用上面的两个方法,而只需要调用 PressTest,这个方法将检测某一个按钮的按下状态。

internal event EventHandler<ButtonEventArgs> Selected;

internal static void Select ( Button button )
{ if ( !button.isEnabled )
return; button.select ( ); if ( null != button.Selected )
button.Selected ( button, new ButtonEventArgs ( button.command ) ); } internal static bool ClickTest ( Button button, IList<Motion> motions )
{ if ( !button.isEnabled || !button.isVisible )
return false; foreach ( Motion motion in motions )
if ( motion.Type == MotionType.Up )
{
Point location = new Point ( ( int ) motion.Position.X, ( int ) motion.Position.Y ); if ( button.bound.Contains ( location ) )
{
Select ( button );
return true;
} } return false;
}

方法 Select 和 Press 方法类似,并可以通过方法 ClickTest 来测试用户是否选择了按钮。

protected virtual void select ( )
{ this.scene.AudioManager.PlaySound ( "click.s" ); } protected virtual void press ( )
{ if ( this.backgroundMovie.CurrentSequenceName != this.downMovieSequenceName )
Movie.Play ( this.backgroundMovie, this.downMovieSequenceName ); } protected virtual void unpress ( )
{ if ( this.backgroundMovie.CurrentSequenceName != this.upMovieSequenceName )
Movie.Play ( this.backgroundMovie, this.upMovieSequenceName ); } internal virtual void Draw ( SpriteBatch batch )
{ if ( !this.isVisible )
return; Movie.Draw ( this.backgroundMovie, null, batch );
}

Button 的 select 方法中将播放资源名称为 click.s 的声音,press 和 unpress 方法中将播放相关的动画。派生类可以修改这些方法来执行自己的操作。在 Draw 方法中,我们将绘制按钮。

protected string command;

internal bool IsPressing = false;

private bool isEnabled = true;
internal virtual bool IsEnabled
{
get { return this.isEnabled; }
set
{
Movie.Play ( this.backgroundMovie, value ? this.upMovieSequenceName : this.disableMovieSequenceName ); this.isEnabled = value;
}
} protected Vector2 location;
public virtual Vector2 Location
{
get { return this.location; }
set {
this.location = value; this.backgroundMovie.Location = value; this.bound = new Rectangle (
( int ) ( value.X ),
( int ) ( value.Y ),
this.Width,
this.Height
);
}
} internal override bool IsVisible
{
set
{
base.IsVisible = value; this.backgroundMovie.IsVisible = value;
}
}

字段 command 表示按钮的命令,字段 IsPressing 表示的按钮是否被按下,属性 IsEnabled 表示按钮是否可用,属性 Location 表示按钮的位置,属性 IsVisible 表示按钮是否可见。

一个例子

internal sealed class SceneT10
: Scene
{
private readonly Button buttonPlay; internal SceneT10 ( )
: base ( Vector2.Zero, GestureType.None,
new Resource[] {
new Resource ( "play.image", ResourceType.Image, @"image\button1" ),
new Resource ( "click.s", ResourceType.Sound, @"sound\click" ),
},
new Making[] {
new Button ( "b.play", "play.image", "PLAY", new Vector2 ( , ), , , new Point ( , ) )
}
)
{
this.buttonPlay = this.makings[ "b.play" ] as Button;
//this.buttonPlay.IsEnabled = false; this.buttonPlay.Pressing += this.buttonPlayPressing;
this.buttonPlay.Pressed += this.buttonPlayPressed;
} protected override void inputing ( Controller controller )
{
base.inputing ( controller ); Button.PressTest ( this.buttonPlay, controller.Motions );
} protected override void drawing ( GameTime time, SpriteBatch batch )
{
base.drawing ( time, batch ); this.buttonPlay.Draw ( batch );
} private void buttonPlayPressing ( object sender, ButtonEventArgs e )
{ Debug.WriteLine ( "play button pressing" ); }
private void buttonPlayPressed ( object sender, ButtonEventArgs e )
{ Debug.WriteLine ( "play button pressed" ); } public override void Dispose ( )
{
this.buttonPlay.Pressing -= this.buttonPlayPressing;
this.buttonPlay.Pressed -= this.buttonPlayPressed; base.Dispose ( );
} }

在场景 SceneT10 中,我们载入按钮所需要的资源,包括:图像,声音。并定义一个按钮。

在场景 SceneT10 的 inputing 方法中,我们使用 Button 的 PressTest 方法测试用户是否按下了按钮。

在构造函数中,我们会 Button 设置了事件 Pressing 和 Pressed,在 buttonPlayPressing 和 buttonPlayPressed 方法中,我们打印了一些文字。

protected override void OnNavigatedTo ( NavigationEventArgs e )
{
// ... this.appendScene ( new mygame.test.SceneT10 ( ), null, false ); // ...
}

最后,我们在 World 的 OnNavigatedTo 方法中,使用 appendScene 方法添加了场景 SceneT10。

本期视频 http://v.youku.com/v_show/id_XNTc0MDY3ODQw.html
项目地址 http://wp-xna.googlecode.com/

更多内容 WPXNA
平方开发的游戏 http://zoyobar.lofter.com/
QQ 群 213685539

欢迎访问我在其他位置发布的同一文章:http://www.wpgame.info/post/decc4_6eacd9

使用 Button 类在 XNA 中创建图形按钮(九)的更多相关文章

  1. 使用 Spirit 类在 XNA 中创建游戏中的基本单位精灵(十三)

    平方已经开发了一些 Windows Phone 上的一些游戏,算不上什么技术大牛.在这里分享一下经验,仅为了和各位朋友交流经验.平方会逐步将自己编写的类上传到托管项目中,没有什么好名字,就叫 WPXN ...

  2. 使用 CommandScene 类在 XNA 中创建命令场景(十二)

    平方已经开发了一些 Windows Phone 上的一些游戏,算不上什么技术大牛.在这里分享一下经验,仅为了和各位朋友交流经验.平方会逐步将自己编写的类上传到托管项目中,没有什么好名字,就叫 WPXN ...

  3. 使用 Scene 类在 XNA 中创建不同的场景(八)

    平方已经开发了一些 Windows Phone 上的一些游戏,算不上什么技术大牛.在这里分享一下经验,仅为了和各位朋友交流经验.平方会逐步将自己编写的类上传到托管项目中,没有什么好名字,就叫 WPXN ...

  4. 使用 Anime 类在 XNA 中创建小动画(十一)

    平方已经开发了一些 Windows Phone 上的一些游戏,算不上什么技术大牛.在这里分享一下经验,仅为了和各位朋友交流经验.平方会逐步将自己编写的类上传到托管项目中,没有什么好名字,就叫 WPXN ...

  5. 使用 NPC,NPCManager 在 XNA 中创建 NPC

    使用 NPC,NPCManager 在 XNA 中创建 NPC 平方已经开发了一些 Windows Phone 上的一些游戏,算不上什么技术大牛.在这里分享一下经验,仅为了和各位朋友交流经验.平方会逐 ...

  6. 编写Java程序,使用ThreadLocal类,项目中创建账户类 Account,类中包括账户名称name、 ThreadLocal 类的引用变量amount,表示存款

    查看本章节 查看作业目录 需求说明: 某用户共有两张银行卡,账户名称相同,但卡号和余额不同.模拟用户使用这两张银行卡进行消费的过程,并打印出消费明细 实现思路: 项目中创建账户类 Account,类中 ...

  7. 使用 Region,RegionManager 在 XNA 中创建特殊区域(十八)

    平方已经开发了一些 Windows Phone 上的一些游戏,算不上什么技术大牛.在这里分享一下经验,仅为了和各位朋友交流经验.平方会逐步将自己编写的类上传到托管项目中,没有什么好名字,就叫 WPXN ...

  8. 使用 Pinup,PinupManager 在 XNA 中创建贴图(十七)

    平方已经开发了一些 Windows Phone 上的一些游戏,算不上什么技术大牛.在这里分享一下经验,仅为了和各位朋友交流经验.平方会逐步将自己编写的类上传到托管项目中,没有什么好名字,就叫 WPXN ...

  9. 使用 Item,ItemManager 在 XNA 中创建物品和道具(十六)

    平方已经开发了一些 Windows Phone 上的一些游戏,算不上什么技术大牛.在这里分享一下经验,仅为了和各位朋友交流经验.平方会逐步将自己编写的类上传到托管项目中,没有什么好名字,就叫 WPXN ...

随机推荐

  1. TCP的三次握手以及TCP状态转换图详解

    今天来讨论一下TCP的三次握手以及TCP的状态转换图.首先发一个三次握手的流程图如下: 圖 2.4-3.三向交握之封包连接模式A:封包发起当用戶端想要对服务器端发起连接时,就必須要送出一個要求连线的封 ...

  2. vue-cli3脚手架的配置以及使用

    Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统,提供: 通过 @vue/cli 搭建交互式的项目脚手架. 通过 @vue/cli + @vue/cli-service-global  ...

  3. Android RecyclerView使用GridLayoutManager间距设置

    使用RecyclerView设置间距,需要重写RecyclerView.ItemDecoration这个类.有如下的效果图需要实现,间距只有中间的格子和底部的格式之间有.   Paste_Image. ...

  4. getuser

    Help on function getuser in module getpass: getuser()    Get the username from the environment or pa ...

  5. Python+selenium之窗口截图

    自动化用例是由程序去执行,因此有时候打印的错误信息并不明确,如果在脚本执行错误的时候能对当前窗口截图保存,那么通过图片就可以非常直观的看出出错的原因.webdriver提供了截图函数get_scree ...

  6. jsp另外五大内置对象之config

    //配置web.xml <?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi=&q ...

  7. hdu 3466 Proud Merchants 自豪的商人(01背包,微变形)

    题意: 要买一些东西,每件东西有价格和价值,但是买得到的前提是身上的钱要比该东西价格多出一定的量,否则不卖.给出身上的钱和所有东西的3个属性,求最大总价值. 思路: 1)WA思路:与01背包差不多,d ...

  8. centos7中文显示为小方块~~啊啊啊 求大佬们解答

    这个问题困扰我很久了,刚好前几天注册了博客园,就想问问大佬们是怎么解决中文显示小方块的? 我试了很多办法,包括但不限于修改i18n配置文件,locale.conf,添加中文字体库等等等... 但都没有 ...

  9. LeetCode 53题 最大子序和 -- JavaScript

    解题思路分析: 该题是在一个整数数组中找到一个和最大的连续子数组,并返回和值.那么如何找到一个和最大的连续子数组呢?我们知道,这肯定需要遍历数组才行:好,那我们就开始遍历数组.首先,我们初始化最大和 ...

  10. 机器学习十大常用算法(CITE 不会停的蜗牛 ) interesting

    算法如下: 决策树 随机森林算法 逻辑回归 SVM 朴素贝叶斯 K最近邻算法 K均值算法 Adaboost 算法 神经网络 马尔可夫 1. 决策树 根据一些 feature 进行分类,每个节点提一个问 ...