• Advertisement
Sign in to follow this  

Crazy booleans..

This topic is 3292 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've come across an extremely annoying problem, I have this booleans to record if a particular key is being currently pressed. Later on a class with these booleans is checked and if one of one of them holds true then a particular actions is taken, the code however seems to ignore these booleans and simply take actions wether they are true or false. Something to notice, if I initialized the booleans to true or false it didnt matter however if I included a "!" in the condition to revert whatever its current state was it did not get run. The problem I don't think is in the key check(The setting of the booleans), I placed a breakpoint in that part of the code and it doesnt run until a key is pressed(But the actions are carried out from the very beginning). Is there any reason why this could be happening? I included all the code where the booleans is used just in case. game is a class that contains a pointer to the input class.
#ifndef INPUT_H
#define INPUT_H

The input class(with the booleans).
class Input
{
private:
	bool move_forward;
	bool move_backward;
	bool turn_right;
	bool turn_left;
	bool shooting;
public:
	Input();

	//Move Forward
	void set_move_forward(bool);
	bool get_move_forward();
};

#endif





This is the input class constructor
#include "input.h"

Input::Input()
:
move_forward(false),
move_backward(false),
turn_right(false),
turn_left(false),
shooting(false)
{}

//Move Forward
void Input::set_move_forward(bool new_move_forward)
{
	move_forward = new_move_forward;
}
bool Input::get_move_forward()
{
	return move_forward;
}





Here is the code with the ignored booleans, the 'ifs' are carried out seemingly without caring about the condition. Something that caught my attention was that(Before I removed the code for all keys except 'move_forward') the only one that didnt run was the 'shooting' 'if' however the code didnt seem to differ in standard from the others and even if I clicked the respective key it still didnt run... If I changed the condition to be one of the other keys it did run.
//Update
void Ship::update(Game &game)
{
	if(game.get_input().get_move_forward())
	{
		move();
	}
/*	if(game.get_input().turn_left)
	{
		rotate(3);
		set_velocity(0);
	}
	if(game.get_input().shooting)
	{
		game.create_missile(get_position(), get_rotation());
	}*/

	if(get_hit_animation())
	{
		play_hit(game);
	}
}





The key checking
LRESULT CALLBACK Application::WndProc(HWND hWnd, UINT message,
											   WPARAM wParam, LPARAM lParam)
{
    switch(message)
	{
        case WM_DESTROY:
			{
                PostQuitMessage(0);
                return 0;
            } break;

		case WM_KEYDOWN:
			{
				switch(wParam)
				{
				case VK_UP:
					{
						input_data.set_move_forward(true);
					} break;


				case VK_ESCAPE:
					{
						DestroyWindow(hWnd);
					} break;
				}

			} break;

		case WM_KEYUP:
			{
				switch(wParam)
				{

				}

			} break;
	}

    return DefWindowProc (hWnd, message, wParam, lParam);
}





Application contains the input_data, an instance of the input class. Game has both a pointer to an application class instance and its'input class instance.
int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,
                   int nCmdShow)
{
	//Display Window
	Application application(640,480);
	if(!application.display_window(hInstance, nCmdShow))
		return 0;

	//Init D3D
	Direct3D direct3d;
	if(!direct3d.init_d3d(application.get_handle(), application.get_dimensions()))
		return 0;

	//Game Class
	Game game(application, direct3d);
	game.run();

	//Close direct3d
    direct3d.close_directx();

    return 0;
}


[Edited by - Antonym on January 15, 2009 6:59:23 AM]

Share this post


Link to post
Share on other sites
Advertisement
in your key checking function, when you detect the up key you do

input_data.set_move_forward(false);

you give false as argument... you should give true.

Share this post


Link to post
Share on other sites
Sorry I set that to false to test if that was the problem it didn't change anything but I forgot to set it back to true. (Being back at true and testing just in case, the problem is still here)

Share this post


Link to post
Share on other sites
if you put a breakpoint on the following line, do you ever reach it?
input_data.set_move_forward(true);

Share this post


Link to post
Share on other sites
Quote:
Original post by OldProgie2
input_data.set_move_forward(false);
^^^^^ ?

I think what he's asking is if the input_data in your Application::WndProc is at all related to the Input member in your Game class instance.

Also, are you returning the Input from the Game object by value in the get_input() function?

I suspect the answer to your problem lies in the code you have not yet posted.

I would also suggest that instead of enumerating what key is pressed by a discrete set of indicator flags, you could enumerate them using an enumerator and potentially reduce some compile time dependencies.

Share this post


Link to post
Share on other sites
When you run the debugger, what does is say the value of the booleans are when you go through the if statements? Are they the right values and it is simply ignoring them? Or are they the right values, going into the if statement, and what you call in the If statement isn't working right?

Basically I'm asking if you are positive you are getting into the if statement(Try putting a break on the call to move() ).

Beyond that, you didn't post your "game" class, so we can't see what it does. Perhaps it is getting into the if statement but the "game.get_input().get_move_forward()" call isn't doing what you thought it would, or it should?

Share this post


Link to post
Share on other sites
The problem must be in the code you have not posted, but here is something you might check for that I am often guilty of myself.

In your if statements that are checking the value of the booleans, are you sure you are using "==" and not just "="? For instance:

if (boolVal = true)
{

}

instead of:

if (boolVal == true)
{

}

That should not cause a compile error, and is a common mistake. That could be what is setting your bool values.

Share this post


Link to post
Share on other sites
Hi,

it looks like you don't reset the variable. When the key is released, you should set move_forward to false.

Hope this might help.

Share this post


Link to post
Share on other sites
Quote:

When you run the debugger, what does is say the value of the booleans are when you go through the if statements? Are they the right values and it is simply ignoring them? Or are they the right values, going into the if statement, and what you call in the If statement isn't working right?

Basically I'm asking if you are positive you are getting into the if statement(Try putting a break on the call to move() ).

Beyond that, you didn't post your "game" class, so we can't see what it does. Perhaps it is getting into the if statement but the "game.get_input().get_move_forward()" call isn't doing what you thought it would, or it should?

How do you do that?

I am not sure what part of my code to show...

Here's the game class(Only header though, the source file is quite large)

#ifndef GAME_H
#define GAME_H

class Game;

#include <d3d9.h>
#include <d3dx9.h>
#include "Application.h"
#include "Direct3D.h"
#include "Input.h"
#include <vector>

class Game
{
private:
Application *application;
Direct3D *direct3d;
Input *input;

std::vector<Object*> game_objects;
std::vector<Object*> destroy_queue;
std::vector<Object*> add_queue;

DWORD spawn_rate;
DWORD time_since_last_spawn;
DWORD frame_rate;

public:
Game(Application&, Direct3D&);

//Run
void run();
void load_graphics();
void init_game();
void render();
void update();
void main_loop();

//Create
void create_ship(D3DXVECTOR2, float);
void create_missile(D3DXVECTOR2, float);
void create_asteroid(D3DXVECTOR2, float);
void create_effect(D3DXVECTOR2, float, Sprite*, int);

//Application
Application get_application();

//Input
Input get_input();

//Game Objects
std::vector<Object*> get_game_objects();

//Destroy Queue
std::vector<Object*> get_destroy_queue();

//Frame Rate
DWORD get_frame_rate();

//Extra
double random_number(int, int);


};

#endif





The game class constructor

Game::Game(Application &new_application, Direct3D &new_direct3d)
:
application(&new_application),
direct3d(&new_direct3d),
input(&new_application.get_input_data()),
spawn_rate(1700),
time_since_last_spawn(0),
frame_rate(170)
{}




the 'get_input' function

Input Game::get_input()
{
return *input;
}



Share this post


Link to post
Share on other sites
I suspect dragongame is correct in that you do not set it to false once you have consumed the key state.

Maybe try the following :


//Move Forward
void Input::set_move_forward(bool new_move_forward)
{
move_forward = new_move_forward;
}

bool Input::get_move_forward()
{
if(move_forward)
{
move_forward = false;
return true;
}
return false;
}



Personally I don't like multiple return paths but this gets the job done. Of course you would have to do this in all the get key state functions. This may not be the problem but its worth looking into.

Share this post


Link to post
Share on other sites

class Game
{
Input *input; //pointer

Input get_input(); //Returns Value
}


//ship update
if(game.get_input().get_move_forward())
{
move();
}





Are you certain you are returning the Input objects value properly, post get_input(). May not be an issue but its worth a look :)

[Edited by - Guthur on January 15, 2009 1:26:48 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Antonym
the 'get_input' function

Mmm, returns a copy by value. Not likely to cause the symptom you're seeing unless your Input copy constructor does something weird, but it's kinda a waste to be creating and destroying temporary objects all over the place like that.

Share this post


Link to post
Share on other sites
Actually double check that the Input object (input_data) you are setting in the windows message loop is getting copied to the one in your Game object (*input), I suspect it isn't.

Share this post


Link to post
Share on other sites
Quote:
Original post by Antonym
the 'get_input' function
*** Source Snippet Removed ***


This makes a copy of the pointed at Input instance each time (because you return a value, and it can't very well rip the existing value out of its current spot). If you make a change to the copy, the original won't be affected. If you then request another copy of the original, it will not reflect the change, because it's a copy of the original, not a copy of the modified copy.

But this is only a symptom: the real problem appears to be that you are building multiple levels of "OO" wrapping to "encapsulate" concepts like "Game" and "Application", without really understanding why (and possibly not really accomplishing the goal, anyway). Get/set pairs for data members (such as set_move_forward and get_move_forward) are a symptom of not-well-thought-out attempts at encapsulation, driven by (often outdated) guidelines rather than real understanding.

Share this post


Link to post
Share on other sites
How do I work with the members then? Should I make them public? I just started using classes a while ago so I am not really sure if I am doing/how to do things right.

Share this post


Link to post
Share on other sites
Making them all public wouldn't really solve much besides removing the need for the accessor methods.

For the case of the Input object; you have it tightly held in all classes that require access to it, to the point where they are nearly all treating it as their own little object when in fact it should be the same object, there is currently only one source of input afterall.

There is a number of options I can think of but I'm worried about giving you an even worse design strategy :s. Others here could give you a better solution but I will throw in the start of one.



class InputManager
{
friend class Application;
public:
InputManager( );

private:
KeyEventListeners* CreateKeyListener ( WORD KeyValue );
std::vector< KeyEventListener* > KeyListeners;
}


class KeyEventListener
{
public:
KeyEventListener( WORD KeyValue );
bool ConsumeState( );
bool PeekState( );
void KeyPressed( );

private:
bool State;
WORD KeyValue;
}









The application class would hold the InputManager; call the CreateKeyListener to get the required keylisteners and pass the returned listener pointer to the game class or what ever. It would then iterate through any key listeners in the std::vector<KeyEventListeners*> during the message loop to update everything.

I don't like the public KeyPressed function, it means any class can change key state but it could be easily removed, or made private and then make the application class a friend. A nice way might be to use a std::map instead of a vector and have the input manager update the state through a function call with the passed key value.

I'm tired though, and off to bed so I can't really take it any further :|.

[Edited by - Guthur on January 16, 2009 5:55:25 AM]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement