在游戏开发过程中,场景控制和事件处理是至关重要的组成部分。本文将分享一些关于如何在C#中创建和管理游戏场景的经验和代码示例。
CommandScene类继承自Scene类,用于控制场景中的按钮,并将按钮点击事件通知给外部。
CommandScene类包含以下成员:
CommandScene包含多种资源,如字体、背景图片和按钮点击声音。构造函数初始化这些资源,并设置按钮的Selected事件。
internal CommandScene(Vector2 location, GestureType gestureType, string backgroundResourcePath, IList resources, IList makings, bool isBroken)
: base(location, gestureType, ResourceManager.Combine(new Resource[] {
new Resource("peg", ResourceType.Font, @"font\peg"),
new Resource("background", ResourceType.Image, string.Format(@"image\{0}", backgroundResourcePath)),
new Resource("click.s", ResourceType.Sound, @"sound\click"),
}, resources),
combine(new Making[] {
new Shape("background.s", "background")
}, makings),
isBroken)
{
this.backgroundShape = this.makings["background.s"] as Shape;
foreach (Making making in this.makings.Values)
{
if (making is Button)
{
Button button = making as Button;
button.Selected += this.buttonSelected;
this.buttons.Add(button);
}
else if (making is Anime)
{
this.animes.Add(making as Anime);
}
}
}
Dispose方法用于清理资源,移除按钮的Selected事件,并清空按钮和动画列表。
public override void Dispose() {
foreach (Button button in this.buttons)
button.Selected -= this.buttonSelected;
this.buttons.Clear();
this.animes.Clear();
base.Dispose();
}
每个按钮的Selected事件会触发buttonSelected方法,在该方法中调用Execute方法。Execute方法会触发CommandScene的Executing事件,参数command是按钮的命令字段,以便外部可以知道哪个按钮被点击。如果按钮的IsSole属性为true,则只有该按钮的点击有效。
private void buttonSelected(object sender, ButtonEventArgs e) {
this.Execute(e.Command);
}
internal void Execute(string command) {
if (null != this.Executing)
this.Executing(this, new SceneEventArgs(command));
}
inputing方法调用PressTest和ClickTest方法,用于检测按钮的点击事件。
protected override void inputing(Controller controller) {
foreach (Button button in this.buttons)
Button.PressTest(button, controller.Motions);
foreach (Button button in this.buttons)
if (Button.ClickTest(button, controller.Motions) && button.IsSole)
break;
}
drawing方法用于绘制按钮、动画和场景背景。updating方法用于更新场景中的动画。
protected override void drawing(GameTime time, SpriteBatch batch) {
Shape.Draw(this.backgroundShape, time, batch);
foreach (Anime anime in this.animes)
Anime.Draw(anime, time, batch);
foreach (Button button in this.buttons)
button.Draw(batch);
}
protected override void updating(GameTime time) {
foreach (Anime anime in this.animes)
anime.Update(time);
}
SceneT13是一个简单的场景,包含两个按钮。
internal sealed class SceneT13 : CommandScene {
internal SceneT13()
: base(Vector2.Zero, GestureType.None, "background1", new Resource[] {
new Resource("play.image", ResourceType.Image, @"image\button1"),
new Resource("stop.image", ResourceType.Image, @"image\button2"),
}, new Making[] {
new Button("b.play", "play.image", "PLAY", new Vector2(100, 100), 100, 50, new Point(1, 1)),
new Button("s.play", "stop.image", "STOP", new Vector2(100, 300), 100, 50, new Point(1, 1))
})
{ }
}
protected override void OnNavigatedTo(NavigationEventArgs e) {
// ...
this.appendScene(new Scene[] {
new mygame.test.SceneT13()
});
base.OnNavigatedTo(e);
}
private void appendScene(Scene scene, Type afterSceneType, bool isInitialized) {
if (null == scene)
return;
this.sceneAppending(scene);
// ...
}
internal void RemoveScene(Scene scene) {
if (null == scene || !this.scenes.Contains(scene))
return;
this.sceneRemoving(scene);
// ...
}
private void sceneAppending(Scene scene) {
if (scene is mygame.test.SceneT13)
(scene as mygame.test.SceneT13).Executing += this.sceneT13Executing;
}
private void sceneRemoving(Scene scene) {
if (scene is mygame.test.SceneT13)
(scene as mygame.test.SceneT13).Executing -= this.sceneT13Executing;
}
private void sceneT13Executing(object sender, SceneEventArgs e) {
Debug.WriteLine("SceneT13: " + e.Command);
}