首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SDL2 OpenGL C++移动用VBO和FBO绘制的雪碧

SDL2 OpenGL C++移动用VBO和FBO绘制的雪碧
EN

Stack Overflow用户
提问于 2016-08-08 22:11:30
回答 2查看 261关注 0票数 0

我使用fbo和vbo来绑定和绘制一个由Sprite.cpp中的两个三角形组成的矩形,下面是init方法

代码语言:javascript
复制
void Sprite::init(float x, float y, float width, float height) {

_x = x;
_y = y;
_width = width;
_height = height;

if (_vboID == 0) {

    glGenBuffers(1, &_vboID);

}



vertexData[0] = x + width;
vertexData[1] = y + height;

vertexData[2] = x;
vertexData[3] = y + height;

vertexData[4] = x;
vertexData[5] = y;

vertexData[6] = x + width;
vertexData[7] = y + height;

vertexData[8] = x;
vertexData[9] = y;

vertexData[10] = x + width;
vertexData[11] = y;


glBindBuffer(GL_ARRAY_BUFFER, _vboID);

glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_DYNAMIC_DRAW);

glBindBuffer(GL_ARRAY_BUFFER, 0);

}

这是抽签法

代码语言:javascript
复制
void Sprite::draw() {

glBindBuffer(GL_ARRAY_BUFFER, _vboID);
glEnableVertexAttribArray(0);


glVertexAttribPointer(0, 2, 0x1406, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, 6);

glDisableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);

}

我显然缺少一些非常明显的概念,因为我似乎找不到任何地方的解决方案,我的问题是,当我按下我的矩形不向下移动。(因为我使用的是WASD运动)下面是输入处理程序的代码

代码语言:javascript
复制
void InputHandler::handleInput(SDL_Event* event, Sprite *toMove) {

switch (event->type) {

case SDL_KEYDOWN:
{
    if (event->key.keysym.sym == SDLK_a) {
        toMove->setMovementBooleans(MovementTuples::LEFT, true);
        std::cout << "Set left ";
    }
    if (event->key.keysym.sym == SDLK_d) {
        toMove->setMovementBooleans(MovementTuples::RIGHT, true);
        std::cout << "Set right ";
    }
    if (event->key.keysym.sym == SDLK_s) {
        toMove->setMovementBooleans(MovementTuples::DOWN, true);
        std::cout << "Set down ";
    }
    if (event->key.keysym.sym == SDLK_w) {
        toMove->setMovementBooleans(MovementTuples::UP, true);
        std::cout << "Set up ";
    }
    break;

}

case SDL_KEYUP:
{
    if (event->key.keysym.sym == SDLK_a) {
        toMove->setMovementBooleans(MovementTuples::LEFT, false);
    }
    if (event->key.keysym.sym == SDLK_d) {
        toMove->setMovementBooleans(MovementTuples::RIGHT, false);
    }
    if (event->key.keysym.sym == SDLK_s) {
        toMove->setMovementBooleans(MovementTuples::DOWN, false);
    }
    if (event->key.keysym.sym == SDLK_w) {
        toMove->setMovementBooleans(MovementTuples::UP, false);
    }
}

}

}

静态访问此方法。以下是在我的sprite cpp中单击s键时移动sprite的代码

代码语言:javascript
复制
void Sprite::update() {

if (movementBooleans[MovementTuples::DOWN]) {
    _x -= .1f;
    init(_x, _y, _width, _height);
    std::cout << "Moved to: (" << _x << ", " << _y  << ")"<<  std::endl;
}

当我点击向下,我的矩形完全消失,_x值保持不变。我测试了输入,它的工作方式与我想要的完全一样,我只是不能让矩形移动。有人能帮我弄清楚怎么移动雪碧吗,谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-08-08 22:52:28

我在用OpenGL。虽然我没有使用SDL,因为我使用的是用户实现的输入处理程序,但概念应该是相同的。

我目前使用的Game有一个Game对象,它是从Engine类对象继承的,其中Engine类是Singleton对象。由于这个游戏引擎的结构,引擎类需要游戏类来实现一个虚拟的keyboardInput函数。这是原型的样子

引擎类

代码语言:javascript
复制
class Engine : public  Singleton {
protected:
    // Protected Members
private:
    // Private Members

public:
    // virtual destructor & public functions
protected:
    // explicit protected Constructor & protected functions
private:
    bool messageHandler( unsigned uMsg, WPARAM wParam, LPARAM lParam );

    virtual void keyboardInput( unsigned vkCode, bool isPressed ) = 0;

    // Other Private Functions

}; // Engine

游戏类

代码语言:javascript
复制
class Game sealed : public Engine {
private:
    // private members here

public:
    // Constructor and virtual Destructor

private:
   virtual void keyBoardInput( unsigned vkCode, bool isPressed ) override;
}; // Game

下面是用于Windows的messageHandler()函数

代码语言:javascript
复制
// ----------------------------------------------------------------------------
// messageHandler()
bool Engine::messageHandler( unsigned uMsg, WPARAM wParam, LPARAM lParam ) {
    switch( uMsg ) {
        case WM_CLOSE: {
            PostQuitMessage( 0 );
            return true;
        }
        case WM_SYSKEYDOWN : {
            if ( ( VK_MENU == wParam ) && ( lParam & 0x1000000 ) ) {
                wParam = VK_RMENU; // Alt Key
            }
            // Fall Through
        }
        case WM_KEYDOWN: {
            if ( ( VK_RETURN == wParam ) && ( lParam & 0x1000000 ) ) {
                wParam = VK_SEPARATOR;

            } else if ( ( VK_CONTROL == wParam ) && ( lParam & 0x1000000 ) ) {
                wParam = VK_RCONTROL;
            }

            if ( 0 == ( lParam & 0x40000000 ) ) { // Supress Key Repeats
                keyboardInput( wParam, true );
            }
            return true;
        }
        case WM_SYSKEYUP: {
            if ( ( VK_MENU == wParam ) && ( lParam & 0x1000000 ) ) {
                wParam = VK_RMENU; // Alt Key
            }
            // Fall Through
        }
        case WM_KEYUP: {
            if ( ( VK_RETURN == wParam ) && ( lParam & 0x1000000 ) ) {
                wParam = VK_SEPARATOR;

            } else if ( ( VK_CONTROL == wParam ) && ( lParam & 0x1000000 ) ) {
                wParam = VK_RCONTROL;
            }

            keyboardInput( wParam, false );

            return true;
        }
        case WM_MOUSEMOVE: {
            // Mouse Motion Detected, Coordinates Are WRT Window Therefore
            // 0,0 Is The Coordinate Of The Top Left Corner Of The Window
            m_mouseState.position = glm::ivec2( LOWORD( lParam ), HIWORD( lParam ) );
            mouseInput();
            return true;
        }
        case WM_LBUTTONDOWN: {
            m_mouseState.isButtonPressed[MOUSE_LEFT_BUTTON] = true;
            mouseInput();
            return true;
        }
        case WM_LBUTTONUP: {
            m_mouseState.isButtonPressed[MOUSE_LEFT_BUTTON] = false;
            mouseInput();
            return true;
        }
        case WM_RBUTTONDOWN: {
            m_mouseState.isButtonPressed[MOUSE_RIGHT_BUTTON] = true;
            mouseInput();
            return true;
        }
        case WM_RBUTTONUP: {
            m_mouseState.isButtonPressed[MOUSE_RIGHT_BUTTON] = false;
            mouseInput();
            return true;
        }
        case WM_MBUTTONDOWN: {
            m_mouseState.isButtonPressed[MOUSE_MIDDLE_BUTTON] = true;
            mouseInput();
            return true;
        }
        case WM_MBUTTONUP: {
            m_mouseState.isButtonPressed[MOUSE_MIDDLE_BUTTON] = false;
            mouseInput();
            return true;
        }
        case WM_MOUSEWHEEL: {
            // Mouse Wheel Moved
            // wParam Contains How Much It Was Moved
            return true;
        }
        default: {
            return false; // Did Not Handle The Message
        }
    }
} // messageHandler

最后,这是keyboardInput()函数

代码语言:javascript
复制
// ----------------------------------------------------------------------------
// keyboardInput()
void Game::keyboardInput( unsigned vkCode, bool isPressed ) {
    std::ostringstream strStream;
    strStream << "Key 0" << std::hex << vkCode << " was " << ( isPressed ? "Pressed" : "Released" );
    Logger::log( strStream );

    if ( VK_ESCAPE == vkCode ) {
        PostQuitMessage( 0 );
    }

    static bool keyPressed[256] = { 0 };
    if ( vkCode < 256 ) {
        keyPressed[vkCode] = isPressed;
    }

    if ( isPressed ) {
        return;
    }

    switch ( vkCode ) {
        case VK_DOWN:
        case 'S' : {
            // do logic here
            break;
        }
        case VK_LEFT:
        case 'A' : {
            // do logic here
            break;
        }
        case VK_RIGHT:
        case 'D' : {
            // do logic here
            break;
        }
        case VK_UP: 
        case 'W' : {
            // do logic here
            break;
        }
    }

} // handleKeyboard

当您仔细查看代码时,我不是在轮询键何时被按下,而是在查询或等待密钥何时释放。这个逻辑的原因是这样的:当你按下一个键时,它可以被反复按下,而不会触及向上状态。这就像在任何文本编辑器中按下相同的键,就会看到屏幕上显示相同的键。避免这种行为;我们做的是相反的逻辑。

我们寻找钥匙何时被释放。密钥只能释放一次,必须再次按下才能再次进入释放状态。这样你就可以让程序的动作发生一次,每次按下键,然后释放。

现在,如果您注意到,我们检查键是否处于按下状态,然后返回;这很重要,因为如果不这样做,程序将自动执行消息处理程序中的操作,因为默认情况下键按状态已经处于释放状态。因此,在调用Game::keyboardInput()Engine::messageHandler()函数时,在呈现框架或更新框架期间发生了什么,如果它检测到按键已将其状态更改为true,则从该函数返回并再次调用,直到释放密钥;一旦释放密钥,状态更改为已释放的状态,然后跳过if语句,直接转到正在处理的键的开关语句。

票数 1
EN

Stack Overflow用户

发布于 2016-08-09 16:05:14

如果你想移动一个OpenGL形状,你真的应该做矩阵转换。

我个人使用GLM为我做所有的繁重工作,所以我所要做的就是在转换完成后将矩阵传递给GLSL。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38839279

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档