D 将枚举分配给其他枚举值

D 将枚举分配给其他枚举值,d,D,我用D和SDL创建了一个简单的游戏。我试图在SDL周围创建一个包装器,这样我就不会直接使用它了。现在我正试图创建我自己的输入类,尽可能远离SDL的输入。但是,为键盘键分配正确的枚举值时遇到一些问题 到目前为止,我已经尝试过,为键盘键分配SDL的枚举,因为这似乎是最简单的,但似乎不起作用,没有任何东西打印到控制台 --SDLInput-- --DPInput-- --DPApp-- //..main在此调用run()我根本不知道SDL,但我发现这段代码可能存在一些问题: 1)在SDLInput中的

我用D和SDL创建了一个简单的游戏。我试图在SDL周围创建一个包装器,这样我就不会直接使用它了。现在我正试图创建我自己的输入类,尽可能远离SDL的输入。但是,为键盘键分配正确的枚举值时遇到一些问题

到目前为止,我已经尝试过,为键盘键分配SDL的枚举,因为这似乎是最简单的,但似乎不起作用,没有任何东西打印到控制台

--SDLInput--

--DPInput--

--DPApp--


//..main在此调用run()

我根本不知道SDL,但我发现这段代码可能存在一些问题:

1)
SDLInput
中的
事件在哪里更新?您似乎假设
SDL\u事件总是自动包含最新的“状态”?我觉得不会的

请注意,
SDL_Event
可能是一个结构(?)并执行
this.Event=app.Event
将在该点复制事件,现在在两个不同的位置有两个不同的事件对象,更新一个不会更新另一个。(但是,如果
SDL_Event
是一个类,则
此.Event
将引用与
app.Event
相同的对象)

2)虽然很难判断,但由于代码不完整,我确实认为这段代码对事件的工作方式感到困惑。从我所看到的这个设计,意味着每帧只能处理一个事件,任何额外的事件都会被删除

想象一个用户同时按下两个按钮。这将生成两个键关闭事件,可能在一个帧中,但您有一个事件对象,我认为您将用任何传入事件覆盖该对象,然后读取该对象。您可能会在过程中丢失事件。此外,仅通过查看最后一个事件无法知道是否按下了某个特定的键。如果按下两个键,而您只查看最后一个事件,您不可能知道第一个键是否已按下,则该信息将永远丢失

传统的方法是让事件调度器调用一些函数并传递一个事件对象,其中包含一些关于事件的额外信息,然后保留您自己的输入状态。这可能发生在
update()
-函数之外,并且可能在
update()
之前发生多次。例如,您可以有如下内容:

// Pseudo code
bool keys[256];

void keyDown(Event e){
    keys[e.keyCode] = true;
}

void keyUp(Event e){
    keys[e.keyCode] = false;
}

void update(){
    if(keys[KEY_W])
        movePlayerForward();
    if(keys[KEY_SPACE])
        jumpPlayer();
}

void loop(){
    while(true){
        fireAllQueuedEvents(); // Could call keyUp/Down several times
        update();
        render();
    }
}
fireAllQueuedEvents()
可以触发多个事件,并且可以正常工作。在这里,W和空格键可以同时按下,玩家可以跳跃和移动。现在,我不知道如何在SDL中实现这一点,也不知道如何用“SDL方式”处理输入,所以,是的,除非你知道,否则,到!我想

不过,一般来说,在事件处理中,某个地方需要有一个事件队列。我怀疑SDL有一个或依赖于底层OS:es事件队列。在某个时刻,这个队列需要调度等待事件,我怀疑SDL当时有拦截这些事件的功能。这就是您需要挂接系统的地方,您需要在事件发生时对其作出响应,然后更新自己的数据结构,以获得键向上/向下状态等,稍后在
update()
中使用。将事件对象存储在周围并稍后查看它们以检查是否按下了一个键是没有意义的,因为在最坏的情况下,您必须按顺序存储至少十几个事件对象,然后遍历所有事件对象以确定一个键是向上还是向下。事件对象不描述事物的“大状态”,它们只描述一个变化。看起来你只是在检查最新的变化。这不适用于多个键/事件

至于枚举分配:看起来是正确的


(游戏祝你好运:)

别误会我,我并不反对DIY方法,但如果你想让你的项目继续进行,尽量不要在早期阶段重新发明轮子-使用已经为你准备好的工具,由数百名开发人员完成(并测试)


这就是说,我衷心推荐你使用优秀的弃置2-。它已经包含了您上面写的所有内容,以及更多内容(几乎所有的核心SDL库)。

谢谢您的回复。您是对的,this.event不包含当前的最新事件。这是我第一次尝试自己构建一个游戏(我已经在一本书或教程的帮助下完成了其他游戏),因此我预计代码会有很多错误。我编辑了我如何处理事件,现在我将输出到控制台。我将返回并实现您的事件处理结构,它看起来更干净。感谢您的回复。我是D新手,一般来说是一个新的程序员(大约6个月的经验),所以我还有很多东西要学。就我对derelict2的理解而言,它只是加载sdl库。我如何使用derelict2正确地启动我的项目?从derelict2示例开始,你玩得越多,你就越容易按照你想要的方式制作游戏。
import SDLInput;
import derelict.sdl.sdl; //Eventually I'd get rid of this, only here for testing

class DPInput
{
private:
    SDLInput sdlinput;

public:
    enum DPKey
    {
        DPK_SPACE = SDLK_SPACE
    }

    this()
    {
        sdlinput = new SDLInput;
    }

    bool KeyPressed(DPKey key)
    {
        return sdlinput.KeyPressed(key);
    }
}
import SDLApp;
import DPInput;
import DPTime;
import std.stdio;

class DPApp
{
    //...
    void Run()
    {
        Init();
        Loop();
        Cleanup();
    }


    void Loop()
    {
        dptime.InitNextTime();

        while(gameRunning)
        {
            if(sdlapp.PollQuit())
                gameRunning = false;

            UpdateGame();
            Render();

            dptime.DPDelay(dptime.TimeLeft());
            dptime.UpdateNextTime();
        }
    }

    void UpdateGame()
    {
        if(dpinput.KeyPressed(dpinput.DPKey.DPK_SPACE))
            writeln("DPAPP: SPACE PRESSED");
    }

}
// Pseudo code
bool keys[256];

void keyDown(Event e){
    keys[e.keyCode] = true;
}

void keyUp(Event e){
    keys[e.keyCode] = false;
}

void update(){
    if(keys[KEY_W])
        movePlayerForward();
    if(keys[KEY_SPACE])
        jumpPlayer();
}

void loop(){
    while(true){
        fireAllQueuedEvents(); // Could call keyUp/Down several times
        update();
        render();
    }
}