游戏场景控制与事件处理

游戏开发过程中,场景控制和事件处理是至关重要的组成部分。本文将分享一些关于如何在C#中创建和管理游戏场景的经验和代码示例。

场景类CommandScene的实现

CommandScene类继承自Scene类,用于控制场景中的按钮,并将按钮点击事件通知给外部。

CommandScene类包含以下成员:

  • 一个内部事件Executing,用于通知外部哪个按钮被点击。
  • 一个背景图片backgroundShape。
  • 一个按钮列表buttons,存储由CommandScene控制的所有按钮。
  • 一个动画列表animes,存储场景中的动画。

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

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); }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485