Reputation: 1279
I used an fbo and vbo to bind and draw a rectangle comprised of two triangles int my Sprite.cpp, here is my init method
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);
}
and here is the draw method
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);
}
I am clearly missing some very obvious concept because I can't seem to find the solution anywhere, my problem is when I press s my rectangle does not move down. (s because I am using WASD movement) Here is the code for the input handler
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);
}
}
}
}
This method is statically accessed. Here is the code for moving the sprite down when you click the s key in my sprite cpp
void Sprite::update() {
if (movementBooleans[MovementTuples::DOWN]) {
_x -= .1f;
init(_x, _y, _width, _height);
std::cout << "Moved to: (" << _x << ", " << _y << ")"<< std::endl;
}
When I click down, my rectangle completely disappear and the _x value stays the same. I tested the input and it works exactly how I want it to, I just can't seem to get the rectangle to move. Can anyone help me figure out how to move my Sprite, thanks!
Upvotes: 0
Views: 324
Reputation: 19
You really should be doing matrix transforms if you want to move a OpenGL shape around.
I personally use GLM to do all of the heavy lifting for me, so then all I have to do is pass the matrix into GLSL after transforms are done.
Upvotes: 1
Reputation: 7905
I'm using OpenGL. Although I am not using SDL since I'm using a user's implemented input handlers the concept should be the same.
The Game Engine that I am currently using has a Game class object that is inherited from an Engine class object where the Engine class is a Singleton object. Due to the structure of this Game Engine; The Engine class requires the Game class to implement a virtual keyboardInput function. Here is what the prototype looks like
Engine Class
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
Game Class
class Game sealed : public Engine {
private:
// private members here
public:
// Constructor and virtual Destructor
private:
virtual void keyBoardInput( unsigned vkCode, bool isPressed ) override;
}; // Game
Here is the messageHandler() function for Windows
// ----------------------------------------------------------------------------
// 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
finally this is the keyboardInput() function
// ----------------------------------------------------------------------------
// 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
When you look closely at the code; I'm not polling to see when the key is pressed but I'm querying or waiting to see when the key was released. The reason for this logic is this; when you press a key down, it can be repeatedly pressed without hitting the up state. This is just like holding down the same key in any text editor where you will see the same key displayed to the screen. To get around this or to avoid this behavior; we do the opposite logic.
We look for when the key was released. The key can only be released once and it has to be pressed again in order to enter into the release state again. This way you have the action of the program happening once for each key press then release.
Now if you noticed we do check to see if the key is in the pressed state and if it is then we return; this is important for if you do not do this your program will automatically do what is within the message handler because the key press state is already in the released state by default. So what happens here is during either then render frame or update frame when the Game::keyboardInput()
and the Engine::messageHandler()
functions are invoked and if it detected that the keypress has changed its state to true it then returns from the function and gets called again continuously until you release the key; once the key is released and the state is changed back to released it then skips over the if statement and goes right to the switch statement for which key you are handling.
Upvotes: 1