• Advertisement
Sign in to follow this  

Need help understanding Particular Function

This topic is 4175 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 am working on a game tutorial. The have implemented a class that will accept user input from both Keyboard and mouse. I am including all the files that are involved, but I have a question regarding the following line in the Main.cpp file:
setup.StateSetup = StateSetup;

StateSetup is defined in the EngineSetup struct as:
]
void (*StateSetup)();

we initialized it in the constructor
]
StateSetup = NULL:

Finally in the Engine.cpp constructor it calls it using the Engine object m_setup:
]
m_setup->StateSetup();

Then in Main.cpp through an EngineSetup object "setup" (this is where I am confused) it assign itself, to it'self?
]
//assigning itself back to itself???? Excuse the newb questions
setup.StateSetup = StateSetup

However, I stumbled on how it works because I left it out and my program couldn't accept input from the keyboard until that was added to the main.cpp file. I don't see how it intializes the input state since i don't see any meat to the function. Only being defined as void (*StateSetup)(); Below is the files of the program that are involved with this question. Can someone tell me how that works? The following files are added: main.cpp //contains WinMain Engine.h //Interface to Engine Engine.cpp // allows the use of one global pointer EngineSetup struct //part of Engine class I left out the Input.h and Input.cpp files because there aren't really part of this problem and the post was already so large. MAIN.CPP
]
//-----------------------------------------------------------------------------
// System Includes
//-----------------------------------------------------------------------------
#include <windows.h>

//-----------------------------------------------------------------------------
// Engine Includes
//-----------------------------------------------------------------------------
#include "..\Engine\Engine.h"

//-----------------------------------------------------------------------------
// Test State Class
//-----------------------------------------------------------------------------
class TestState : public State
{
	//-------------------------------------------------------------------------
	// Update function for the TestState.
	//-------------------------------------------------------------------------
	virtual void Update( float elapsed )
	{
		// check the user wants to exit
		if( g_engine->GetInput()->GetKeyPress( DIK_Q ) )
			PostQuitMessage( 0 );
	};

};
//-----------------------------------------------------------------------------
// Application specific state setup.
//-----------------------------------------------------------------------------
void StateSetup()
{
	g_engine->AddState( new TestState, true );
}

//-----------------------------------------------------------------------------
// Entry point for the application.
//-----------------------------------------------------------------------------
int WINAPI WinMain( HINSTANCE instance, HINSTANCE prev, LPSTR cmdLine, int cmdShow )
{
	// Create the engine setup structure.
	EngineSetup setup;
	setup.instance = instance;
	setup.name = "Input Test";
	setup.StateSetup = StateSetup;
	// Create the engine (using the setup structure), then run it.
	new Engine( &setup );
	g_engine->Run();
	
	return true;
}

ENGINE.H
]
//-----------------------------------------------------------------------------
// The primary engine header file. This file links the entire engine together
// and is the only header file that needs to be included in any project using
// the engine.
//-----------------------------------------------------------------------------
#ifndef ENGINE_H
#define ENGINE_H
//-----------------------------------------------------------------------------
// DirectInput Version Define
//-----------------------------------------------------------------------------
#define DIRECTINPUT_VERSION 0x0800
//-----------------------------------------------------------------------------
// System Includes
//-----------------------------------------------------------------------------
#include <stdio.h>
#include <tchar.h>
#include <windowsx.h>
//-----------------------------------------------------------------------------
// DirectX Includes
//-----------------------------------------------------------------------------
#include <d3dx9.h>
#include <dinput.h>
#include <dplay8.h>
#include <dmusici.h>
//-----------------------------------------------------------------------------
// Macros
//-----------------------------------------------------------------------------
#define SAFE_DELETE( p )       { if( p ) { delete ( p );     ( p ) = NULL; } }
#define SAFE_DELETE_ARRAY( p ) { if( p ) { delete[] ( p );   ( p ) = NULL; } }
#define SAFE_RELEASE( p )      { if( p ) { ( p )->Release(); ( p ) = NULL; } }
//-----------------------------------------------------------------------------
// Engine Includes
//-----------------------------------------------------------------------------
#include "LinkedList.h"
#include "ResourceManagement.h"
#include "Geometry.h"
#include "Input.h"
#include "State.h"

//-----------------------------------------------------------------------------
// Engine Setup Structure
//-----------------------------------------------------------------------------
struct EngineSetup
{
	HINSTANCE instance; // Application instance handle.
	char *name; // Name of the application.
	void (*StateSetup)(); // State setup function.

	//-------------------------------------------------------------------------
	// The engine setup structure constructor.
	//-------------------------------------------------------------------------
	EngineSetup()
	{
		instance = NULL;
		name = "Application";
		StateSetup = NULL;
	}
};
//-----------------------------------------------------------------------------
// Engine Class
//-----------------------------------------------------------------------------
class Engine
{
public:
	Engine( EngineSetup *setup = NULL );
	virtual ~Engine();

	void Run();

	HWND GetWindow();
	void SetDeactiveFlag( bool deactive );

	void AddState( State *state, bool change = true );
	void RemoveState( State *state );
	void ChangeState( unsigned long id );
	State *GetCurrentState();

	Input *GetInput();

private:
	bool m_loaded; // Indicates if the engine is loading.
	HWND m_window; // Main window handle.
	bool m_deactive; // Indicates if the application is active or not.

	EngineSetup *m_setup; // Copy of the engine setup structure.

	LinkedList< State > *m_states; // Linked list of states.
	State *m_currentState; // Pointer to the current state.
	bool m_stateChanged; // Indicates if the state changed in the current frame.

	Input *m_input; // Input object.
};
//-----------------------------------------------------------------------------
// Externals
//-----------------------------------------------------------------------------
extern Engine *g_engine;

#endif

ENGINE.CPP
//-----------------------------------------------------------------------------
// Engine.h implementation.
// Refer to the Engine.h interface for more details.
//-----------------------------------------------------------------------------
#include "Engine.h"

//-----------------------------------------------------------------------------
// Globals
//-----------------------------------------------------------------------------
Engine *g_engine = NULL;

//-----------------------------------------------------------------------------
// Handles Windows messages.
//-----------------------------------------------------------------------------
LRESULT CALLBACK WindowProc( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam )
{
	switch( msg )
	{
		case WM_ACTIVATEAPP:
			g_engine->SetDeactiveFlag( !wparam );
			return 0;

		case WM_DESTROY:
			PostQuitMessage( 0 );
			return 0;

		default:
			return DefWindowProc( wnd, msg, wparam, lparam );
	}
}
//-----------------------------------------------------------------------------
// The engine class constructor.
//-----------------------------------------------------------------------------
Engine::Engine( EngineSetup *setup )
{
	// Indicate that the engine is not yet loaded.
	m_loaded = false;

	// If no setup structure was passed in, then create a default one.
	// Otehrwise, make a copy of the passed in structure.
	m_setup = new EngineSetup;
	if( setup != NULL )
		memcpy( m_setup, setup, sizeof( EngineSetup ) );

	// Store a pointer to the engine in a global variable for easy access.
	g_engine = this;

	// Prepare and register the window class.
	WNDCLASSEX wcex;
	wcex.cbSize        = sizeof( WNDCLASSEX );
	wcex.style         = CS_CLASSDC;
	wcex.lpfnWndProc   = WindowProc;
	wcex.cbClsExtra    = 0;
	wcex.cbWndExtra    = 0;
	wcex.hInstance     = m_setup->instance;
	wcex.hIcon         = LoadIcon( NULL, IDI_APPLICATION );
	wcex.hCursor       = LoadCursor( NULL, IDC_ARROW );
	wcex.hbrBackground = NULL;
	wcex.lpszMenuName  = NULL;
	wcex.lpszClassName = "WindowClass";
	wcex.hIconSm       = LoadIcon( NULL, IDI_APPLICATION );
	RegisterClassEx( &wcex );

	// Initialise the COM using multithreaded concurrency.
	CoInitializeEx( NULL, COINIT_MULTITHREADED );

	// Create the window and retrieve a handle to it.
	// Note: Later the window will be created using a windowed/fullscreen flag.
	m_window = CreateWindow( "WindowClass", m_setup->name, WS_OVERLAPPED, 0, 0, 800, 600, NULL, NULL, m_setup->instance, NULL );

	// Create the linked lists of states.
	m_states = new LinkedList< State >;
	m_currentState = NULL;

	// Create the input object.
	m_input = new Input( m_window );

	// Seed the random number generator with the current time.
	srand( timeGetTime() );

	// Allow the application to perform any state setup now.
	if( m_setup->StateSetup != NULL )
		m_setup->StateSetup();

	// The engine is fully loaded and ready to go.
	m_loaded = true;
}
//-----------------------------------------------------------------------------
// The engine class destructor.
//-----------------------------------------------------------------------------
Engine::~Engine()
{
	// Ensure the engine is loaded.
	if( m_loaded == true )
	{
		// Destroy the states linked lists.
		if( m_currentState != NULL )
			m_currentState->Close();
		SAFE_DELETE( m_states );

		// Destroy everything.
		SAFE_DELETE( m_input );
	}

	// Uninitialise the COM.
	CoUninitialize();

	// Unregister the window class.
	UnregisterClass( "WindowClass", m_setup->instance );

	// Destroy the engine setup structure.
	SAFE_DELETE( m_setup );
}

//-----------------------------------------------------------------------------
// Enters the engine into the main processing loop.
//-----------------------------------------------------------------------------
void Engine::Run()
{
	// Ensure the engine is loaded.
	if( m_loaded == true )
	{
		// Show the window.
		ShowWindow( m_window, SW_NORMAL );

		// Used to retrieve details about the viewer from the application.
		ViewerSetup viewer;

		// Enter the message loop.
		MSG msg;
		ZeroMemory( &msg, sizeof( MSG ) );
		while( msg.message != WM_QUIT )
		{
			if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
			{
				TranslateMessage( &msg );
				DispatchMessage( &msg );
			}
			else if( !m_deactive )
			{
				// Calculate the elapsed time.
				unsigned long currentTime = timeGetTime();
				static unsigned long lastTime = currentTime;
				float elapsed = ( currentTime - lastTime ) / 1000.0f;
				lastTime = currentTime;

				// Update the input object, reading the keyboard and mouse.
				m_input->Update();

				// Check if the user wants to make a forced exit.
				if( m_input->GetKeyPress( DIK_F1 ) )
					PostQuitMessage( 0 );

				// Request the viewer from the current state, if there is one.
				if( m_currentState != NULL )
					m_currentState->RequestViewer( &viewer );

				// Update the current state (if there is one), taking state
				// changes into account.
				m_stateChanged = false;
				if( m_currentState != NULL )
					m_currentState->Update( elapsed );
				if( m_stateChanged == true )
					continue;
			}
		}
	}

	// Destroy the engine.
	SAFE_DELETE( g_engine );
}

//-----------------------------------------------------------------------------
// Returns the window handle.
//-----------------------------------------------------------------------------
HWND Engine::GetWindow()
{
	return m_window;
}
//-----------------------------------------------------------------------------
// Sets the deactive flag.
//-----------------------------------------------------------------------------
void Engine::SetDeactiveFlag( bool deactive )
{
	m_deactive = deactive;
}

//-----------------------------------------------------------------------------
// Adds a state to the engine.
//-----------------------------------------------------------------------------
void Engine::AddState( State *state, bool change )
{
	m_states->Add( state );

	if( change == false )
		return;

	if( m_currentState != NULL )
		m_currentState->Close();

	m_currentState = m_states->GetLast();
	m_currentState->Load();
}

//-----------------------------------------------------------------------------
// Removes a state from the engine
//-----------------------------------------------------------------------------
void Engine::RemoveState( State *state )
{
	m_states->Remove( &state );
}
//-----------------------------------------------------------------------------
// Changes processing to the state with the specified ID.
//-----------------------------------------------------------------------------
void Engine::ChangeState( unsigned long id )
{
	// Iterate through the list of states and find the new state to change to.
	m_states->Iterate( true );
	while( m_states->Iterate() != NULL )
	{
		if( m_states->GetCurrent()->GetID() == id )
		{
			// Close the old state.
			if( m_currentState != NULL )
				m_currentState->Close();

			// Set the new current state and load it.
			m_currentState = m_states->GetCurrent();
			m_currentState->Load();

			// Indicate that the state has changed.
			m_stateChanged = true;

			break;
		}
	}
}

//-----------------------------------------------------------------------------
// Returns a pointer to the current state.
//-----------------------------------------------------------------------------
State *Engine::GetCurrentState()
{
	return m_currentState;
}

//-----------------------------------------------------------------------------
// Returns a pointer to the input object.
//-----------------------------------------------------------------------------
Input *Engine::GetInput()
{
	return m_input;
}

Share this post


Link to post
Share on other sites
Advertisement
setup.StateSetup = StateSetup; doesn't even compile for me in msvc 2005.

My guess is maybe your compiler it treating it like setup.StateSetup = StateSetup();, which assigns it to a default constructed StateSetup, which is null.

If thats the case:
setup.StateSetup = StateSetup();
is the same as
setup.StateSetup = 0;

only less readable.

Share this post


Link to post
Share on other sites
You are slightly confused.

You are not assigning it to itself.

Try this instead, perhaps it will shed some light:


// main.cpp, slightly edited


// change StateSetup function to this:
void MyCustomStateSetup()
{
g_engine->AddState( new TestState, true );
}

//-----------------------------------------------------------------------------
// Entry point for the application.
//-----------------------------------------------------------------------------
int WINAPI WinMain( HINSTANCE instance, HINSTANCE prev, LPSTR cmdLine, int cmdShow )
{
// Create the engine setup structure.
EngineSetup setup;
setup.instance = instance;
setup.name = "Input Test";
// point the setup at our custom function
setup.StateSetup = &MyCustomStateSetup;
// Create the engine (using the setup structure), then run it.
new Engine( &setup );
g_engine->Run();

return true;
}




What you are doing is passing a pointer to a function to the state, so it can use it to create the engine.

It isnt assigning itself to itself because ( when you change the function name ) there is no symbol with the name "StateSetup". There is one with the name "EngineSetup::StateSetup".

To self assign ( which would be pointless as you quite rightly mentioned ), you use this:
setup.StateSetup = setup.StateSetup;


Finally, I prefer to use the "&" operator when assigning function pointers, even though its not technically required, to help me when I read the code.

Share this post


Link to post
Share on other sites
@Rip-Off
First off, loved Ireland, my wife and I had one of our best Vacations there - can't wait to go back.

Thanks so much, that makes a good bit more sense. I am not sure why the writer of the tutorial went about it that way, couldn't he have just defined it and called it like:

void StateSetup();

setup->StateSetup;

??

Why do you think someone would want to make it a pointer to a function:
void (*StateSetup)();
??

Share this post


Link to post
Share on other sites
A pointer to a function is a bit like a pointer to a varaible, you want to do something to a "pointee type", but you dont care what "instance of pointee type" you are doing it to. You want to run some function that will do some setup, but not to hardcode *which* function will be run...

If you had a situation where you were running 2 engines, say a networked game with a ServerEngine and a ClientEngine( bad example maybe, im tired). You could write code like this:



void AdditionalClientSetup(){ /* client stuff here */ }
void AdditionalServerSetup(){ /* server stuff here */ }

int main()
{
EngineSetup serverSetup;
serverSetup.additionalSetup = &AdditionalServerSetup;
Engine *server = new Engine( &serverSetup );

EngineSetup clientSetup;
clientSetup.additionalSetup = &AdditionalClientSetup;
Engine *client = new Engine( &clientSetup);


while(true) {
server->runALittle();
client->runALittle();
}
}



Share this post


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

  • Advertisement