【问题标题】:Passing in an SDL_Event* into a method将 SDL_Event* 传递给方法
【发布时间】:2021-04-25 13:49:01
【问题描述】:

我想对 SDL2 中的文本输入进行计时,使其不会以每秒 1000 次按键的速度发送垃圾邮件,而不是像 ~33kps 这样的标准。

ma​​in.cpp

#include <iostream>
#include <SDL2/SDL.h>


#include "main.h"

void Main::Init()
{
    std::cout << "Main Init called\n";

    SDL_Init(SDL_INIT_VIDEO);

    Get_Instance().window = SDL_CreateWindow("Program", 0, 30, 1280, 720, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE );
    Get_Instance().renderer = SDL_CreateRenderer(Get_Instance().window, -1, SDL_RENDERER_ACCELERATED  );

    Get_Instance().running = true;

}



void Main::Free()
{

    SDL_DestroyRenderer(Get_Instance().renderer);
    SDL_DestroyWindow(Get_Instance().window);


    SDL_Quit();

    std::cout << "Main Free called\n";

}



void Main::Mainloop()
{

    Get_Instance(); ///To initialize constructor

    if (Get_Instance().mainloopInstanceBlocker == 'C')
    {
        Get_Instance().mainloopInstanceBlocker = 'B';   ///Begins at I (initialized), then C (constructed) then B (began)
                                        ///It works as it begins as constructed, then does the main loop, after set to B, won't enter again.


        Get_Instance().Init();

        SDL_Event event;
        SDL_StartTextInput();



        while (Get_Instance().running)
        {

            ///Poll events
            SDL_PollEvent(&event);


            ///To quit program
            if ( event.type == SDL_QUIT ){
                Get_Instance().running = false;
                break;
            }



            ///Clear display to color
            SDL_SetRenderDrawColor(Get_Instance().renderer, 0,255,0,255);
            SDL_RenderClear(Get_Instance().renderer);



            Get_Instance().m_Main_Loop.Mainloop( Get_Instance().window, Get_Instance().renderer, &event );


            SDL_RenderPresent(Get_Instance().renderer);
        }



        SDL_StopTextInput();


        Get_Instance().Free();


    }
}




int main(int argc, char* argv[])
{

    Main::Mainloop();

    return 0;
}

ma​​in.h

#ifndef MAIN_H
#define MAIN_H

#include "main_loop.h"



class Main
{
public:
    Main(const Main&) = delete;
    Main(Main&&) = delete;
    Main& operator=(const Main&) = delete;
    Main& operator=(Main&&) = delete;


    static void Mainloop();




private:
    Main()
    {
        std::cout << "Main constructor called\n";
        mainloopInstanceBlocker = 'C';
    }

    static Main& Get_Instance()
    {
        static Main instance;
        return instance;
    }


    static void Init();
    static void Free();



    Main_Loop m_Main_Loop;

    SDL_Window* window = nullptr;
    SDL_Renderer* renderer = nullptr;

    bool running = false;
    char mainloopInstanceBlocker = 'I';



};








#endif // MAIN_H

ma​​in_loop.h

#ifndef MAIN_LOOP_H
#define MAIN_LOOP_H


#include <iostream>
#include <string>
#include <SDL2/SDL.h>


class Main_Loop
{
public:
    Main_Loop();
    ~Main_Loop();


    void Mainloop(SDL_Window* window, SDL_Renderer* renderer, SDL_Event* event);




};




#endif // MAIN_LOOP_H

ma​​in_loop.cpp

#include "main_loop.h"




Main_Loop::Main_Loop()
{

}


void Main_Loop::Mainloop(SDL_Window* window, SDL_Renderer* renderer, SDL_Event* event)
{
    if (event->type == SDL_TEXTINPUT)
    {
        std::cout << event->text.text << std::endl;
    }


}





Main_Loop::~Main_Loop()
{

}

【问题讨论】:

  • 抱歉不清楚您打算做什么以及您的问题似乎是什么。您刚刚获取了事件结构的指针 - 使用 &amp;event。 SDL_PollEvent 将事件数据写入指定结构,因此每次调用都可以覆盖之前的内容。
  • 我设法修复了它,只是不要在 while 循环中调用它,而只是实际函数 SDL_PollEvent() 本身。但是,我还有另一个问题,if (event-&gt;type == SDL_TEXTINPUT) 如果您按住一个键输入文本,它会以每秒 1000 个字符的速度输入文本。我怎样才能使它像任何其他文本应用程序一样计时,即,您按住一个键并在大约每秒约 33 个键的小 sn-p 时间后发送垃圾邮件(与退格键相同,删除)@keltar
  • 我需要查看您的代码来回答这个问题。 SDL 使用系统的按键重复,因此它的行为方式应该与其他程序相同。
  • 好的,因为原来的 q 得到了修复,所以我的代码/重新编辑问题@keltar
  • 如果你运行那个代码,你第二次输入一个字母就会发送大约 1000 次垃圾邮件

标签: c++ class parameter-passing sdl-2


【解决方案1】:

你的问题是

        SDL_PollEvent(&event);

SDL_PollEvent 如果队列中没有更多事件,则返回 0,但在这种情况下,它不会将任何内容写入传递的事件结构。由于您不再检查 PollEvent 的返回值,因此您对上次事件留下的陈旧数据进行操作。至少做一些类似的事情

if(!SDL_PollEvent(&event)) event.type = 0;

您的Mainloop 函数有问题 - 这是否意味着每帧可能只有一个事件?如果单帧中发生了多个事件,你会怎么做?我建议将事件处理和渲染分开 - 即制作处理整个事件队列并通过修改数据来对事件做出反应的事件处理函数,以及仅进行渲染的单独渲染函数。

【讨论】:

  • 它只能处理一个事件吗?我正在传递一个指向整个 SDL_Event 结构的指针,以便它可以访问其所有成员?
  • 不,SDL_Event 仅包含单个事件。这就是为什么您使用while(SDL_PollEvent()) 循环来获取事件、处理其内容、获取下一个事件,...
  • 哦,哇,好吧,那肯定会让事情变得更加困难,好吧
  • 这可能是一个过于宽泛的问题,但如果我想将渲染和事件处理分开以允许循环中的多个事件,我将如何构建我的 Mainloop 或类似的结构以使其工作?因为如果对象根据事件移动,然后我必须在单独的部分中渲染它们,你将如何构建它?
  • 有不止一种方法可以做到这一点,但通常 - 在事件处理函数中,您对事件做出反应并更新状态(例如,提高“向前移动”标志),在更新函数中您迭代所有需要更新和设置新位置等的对象(这部分需要在非锁定间隔运行或知道上次更新后经过了多少时间),并且在渲染函数中迭代所有需要绘制和绘制的对象他们。当然,关于如何更新或绘制事物可能会有很多细节,但基本思想仍然相同。
猜你喜欢
  • 2015-11-04
  • 2011-01-01
  • 2014-06-03
  • 2011-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-05
相关资源
最近更新 更多