0

您可以在 Flash ActionScript 中使用帧来保存欢迎屏幕、游戏内容和游戏结束屏幕;您可以在 Microsoft XNA 中创建游戏状态的枚举,并在 Draw 方法中调用该状态时绘制所有图形和文本。你会如何在 HTML5 和 JavaScript 中做到这一点?我有一种感觉,这可以通过显示和隐藏 div 来完成,但我不完全确定该怎么做。

<asp:DropDownList ID="DDL_SelectGame" runat="server" CssClass="BigText">
    <asp:ListItem>MatchMe (Memory)</asp:ListItem>
    <asp:ListItem>Royal Jewels (Bejeweled)</asp:ListItem>
    <asp:ListItem>Tetris</asp:ListItem>
</asp:DropDownList>
<div id="Welcome" class="Welcome">
    <asp:Button ID="BTN_StartGame" runat="server" CssClass="Button" />
</div>
<div id="Game" class="Game">
</div>
<div id="GameOver" class="GameOver">
    <asp:Button ID="BTN-Replay" CssClass="Button" runat="server" />
</div>

上面的代码是我如何在我的网站 ( http://www.graphics-geek.com ) 上设置游戏页面的示例。

4

1 回答 1

1

这是我计划用于未来游戏开发的状态机。

有了这样的东西,你应该能够实现不同状态的绘制,以及回调中的状态变化。通过显示/隐藏 div,或在画布上绘制不同的缓冲区/图形。

创建状态:

// initially hide the divs using css or js

state.add("welcome",
    function () {
        document.getElementById("Welcome").style.display = "block";
    },
    function () {
        document.getElementById("Welcome").style.display = "none";
    }
);

state.add("level01",
    function () {
        document.getElementById("Game").style.display = "block";
    },
    function () {
        document.getElementById("Game").style.display = "none";
    }
);

state.add("end",
    function () {
        document.getElementById("GameOver").style.display = "block";
    }
);

第二个功能是可选的(实际上两者都是,但这样的状态不会做任何事情)。

切换状态(假设我们添加了 3 个状态:“welcome”、“level01”和“end”):

state.enter("welcome");

//... at some point welcome changes state using following:
state.enter("level01");

//... at the end of level1:
state.enter("end");

代码:

var state = (function () {
    "use strict";
    var currentState = -1,
        stateNames = [],
        stateCallbacks = [];

    return {
        current: function () {
            if (currentState >= 0) {
                return stateNames[currentState];
            }
        },
        add: function (name, onEnter, onExit) {
            var index = stateNames.indexOf(name);
            if (index !== -1) {
                throw "State " + name + " already exist!";
            }
            stateCallbacks.push({
                enterState: onEnter || false,
                exitState: onExit || false
            });
            stateNames.push(name);
        },
        remove: function (name) {
            var index = stateNames.indexOf(name);
            if (index === -1) {
                throw "State " + name + " not found!";
            }
            stateNames.splice(index, 1);
            stateCallbacks.splice(index, 1);
        },
        enter: function (name) {
            var index = stateNames.indexOf(name);
            if (index === -1) {
                throw "State " + name + " not found!";
            }
            if (stateCallbacks[currentState].exitState) {
                stateCallbacks[currentState].exitState();
            }
            currentState = index;
            if (stateCallbacks[index].enterState) {
                stateCallbacks[index].enterState();
            }
        },
        exit: function () {
            if (currentState === -1) {
                throw "Not currently in any state";
            }
            if (stateCallbacks[currentState].exitState) {
                stateCallbacks[currentState].exitState();
            }
            currentState = -1;
        }
    };
}());

附加评论:

包装代码的匿名函数的结构是来自http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html的 javascript 模块模式。这类似于其他语言中的命名空间。

为了可能获得更好的查找性能(在此处实现为 Array.indexOf(name)),您可能希望添加一个带有与索引值关联的字符串键的对象,尤其是对于大量状态(即具有 100 多个级别的游戏,或一个不同的用例,其中状态切换得更频繁)。不过,我没有对此进行基准测试,因此这是高度投机的。理论上,数组搜索比哈希表查找慢 n - 1 倍(对象可能被实现为)。

编辑:

  1. 修复了代码中的错误。state.add 现在检查现有名称。
  2. 添加了免责声明。
  3. 添加了如何在回调中显示/隐藏 div 的示例。
  4. 删除免责声明,用改进版本替换代码。
于 2013-08-14T20:17:53.937 回答