Quote: "I thought that this was still not the case and that at least some minor modifications were required for each"
The only time a modification is needed, it can easily be put in place with '#ifdef's.
EDIT: I changed the example here to that which is in my State Machine example.
This started as the basic template.h file provided for one platform and morphed rapidly to accommodate my own needs, including extending the core class used within AGK.
#ifndef _H_TEMPLATE_
#define _H_TEMPLATE_
/////////////////////////////////////////
// CONSTANTS ////////////////////////////
/////////////////////////////////////////
#if defined(AGKWINDOWS) || defined(IDE_MAC)
#define DEVICE_WIDTH 1024
#define DEVICE_HEIGHT 768
#define DEVICE_POS_X 32
#define DEVICE_POS_Y 32
#define FULLSCREEN false
#endif
// this is required by AGK for Mac and Windows
// but we will also use this ourselves
#define WINDOW_TITLE "State Machine Demo"
// Link to AGK libraries
#include "agk.h"
// include our defined types
#include "type_defs.h"
// get some standard objects we need
#include <string>
/////////////////////////////////////////
// CLASS DEFINITION /////////////////////
/////////////////////////////////////////
class app
{
private:
TA_USHORT app_state; // state app is in
bool did_end; // flag for game has ended
std::string app_err_msg; // error message for error state
public:
// main vars
#ifdef IDE_MAC
// the Mac setup uses actual variables to hold
// the device width and height that must be
// part of the app class
unsigned int m_DeviceWidth;
unsigned int m_DeviceHeight;
#endif
public:
#if defined(IDE_ANDROID) || defined(AGKIOS) || defined(IDE_MAC)
// constructor
app() {}
// destructor
~app() {}
#else
// constructor
app() {memset ( this, 0, sizeof(app));}
#endif
// main app functions
void Begin( void );
void Loop( void );
void End( void );
private:
void closeThisApp(bool noforce=true);
void checkForExit();
void hadAnAppError(const char* errmsg,const char* extra=NULL);
void inBadState();
};
extern app App;
#endif
// Allow us to use the LoadImage function name
#ifdef LoadImage
#undef LoadImage
#endif
This is my template.cpp (which is modified as needed for the specific apps):
// Includes, namespace and prototypes
#include "template.h"
// supporting classes/functions
#include "simple_pointer.h"
#include "handle_objects.h"
#include "ta_debug_console.h"
// include for main process
#include "main_process.h"
// Namespace
using namespace AGK;
app App;
/////////////////////////////////////////
// CONSTANTS ////////////////////////////
/////////////////////////////////////////
// application states
#define _AS_DISPLAY_INIT_ 1
#define _AS_GAME_INIT_ 2
#define _AS_GAME_PLAY_ 3
#define _AS_BAD_STATE_ 4
// indicate whether using DebugConsole
#define _USE_DEBUG_CONSOLE_ false
/////////////////////////////////////////
// PROTOTYPES ///////////////////////////
/////////////////////////////////////////
#ifdef IDE_ANDROID
extern void exit(int);
#endif
/////////////////////////////////////////
// CLASS IMPLEMENTATION /////////////////
/////////////////////////////////////////
// Begin app, called once at the start
void app::Begin(void)
{
// initialise the debug console
if (_USE_DEBUG_CONSOLE_) TADebugConsole::init_console("StateMachineDemo","com.triassicassociates.statemachinedemo.syslog");
// assume okay for now
did_end = false;
app_state = _AS_DISPLAY_INIT_;
app_err_msg = "";
// attempt to initialise the display
if (initialiseTheDisplay(WINDOW_TITLE)) hadAnAppError("Failed to initialise properly:",processErrorWas());
}
void app::Loop (void)
{
// check for ended
if (app::did_end) return;
// process based on state
// the states are checked in the order
// of most often occurring first
switch (app_state)
{
case _AS_GAME_PLAY_:
// handle the main processing loop
if (mainProcessLoop())
{
// player pressed 'Exit'
// close down
closeThisApp();
// done, we want to make sure we skip the agk::Sync() call
// because it may need a cycle or two to properly forget
// everything that was created
return;
}
break;
case _AS_BAD_STATE_:
// display message and done
inBadState();
break;
case _AS_GAME_INIT_:
// do game initialisation
// the initialiseTheProcess function does not return
// control back to this main loop until
// the initialisation is either complete or fails
// if it doesn't fail (true=fails), then we change to next state
if (initialiseTheProcess()) hadAnAppError("Failed to initialise properly:",processErrorWas());
else app_state = _AS_GAME_PLAY_;
break;
case _AS_DISPLAY_INIT_:
// we want to make sure that the display syncs right now
// so that our splash screen displays and so that
// our display is correctly 'formatted'
// before we start initialisation
agk::Sync();
agk::Sync();
// start actual game initialisation in the next cycle
app_state = _AS_GAME_INIT_;
// show debug state (ignored if console not initiated)
showStateChange("_AS_GAME_INIT_",_AS_GAME_INIT_);
break;
}
// sync display
agk::Sync();
}
// Called when the app ends
void app::End ( void )
{
// clean up, if not already done
}
void app::closeThisApp(bool noforce/*=true*/)
{
// if in debug mode we want to leave the consoles displayed
if (noforce&&_USE_DEBUG_CONSOLE_)
{
// do a couple of sync calls to clear inputs
agk::Sync();
agk::Sync();
// indicate 'error', but it won't be visible
hadAnAppError("Shutdown functions done.\nWaiting so that events can be\nviewed in DebugConsole.");
return;
}
// indicate done
app::did_end = true;
// completely exit the app
#ifdef AGKWINDOWS
PostQuitMessage(0);
#endif
#ifdef AGKIOS
// forcing a quit in iOS is against recommended guidelines - use HOME button
// the exit button is disabled on AGKIOS builds
// but if you want to do so, this is the code
agk::MasterReset();
exit(0);
#endif
#ifdef IDE_ANDROID
// similar to iOS, an exit button should not be done
// but if you want to do so, this is the code
agk::MasterReset();
exit(0);
#endif
#ifdef IDE_MAC
glfwCloseWindow();
#endif
}
void app::checkForExit()
{
// if pointer pressed, we are done
if (TAPointer::gotPress()) closeThisApp(false);
}
void app::hadAnAppError(const char* errmsg,const char* extra/*=NULL*/)
{
// start the message
app_err_msg = "\n\n\n";
app_err_msg += errmsg;
// check for extra
if (extra != NULL)
{
// add extra bits
app_err_msg += "\n";
app_err_msg += extra;
}
// finish the message
app_err_msg += "\n\n\nTouch anywhere to exit";
// save the state as bad
app_state = _AS_BAD_STATE_;
// show a message
agk::Print(app_err_msg.c_str());
}
void app::inBadState()
{
// check for exit
app::checkForExit();
// show a message
agk::Print(app_err_msg.c_str());
}
Obviously, this example is not buildable by anyone else because it is dependent on a lot of files I created. But it does show how one file is easily used in multiple platforms.
Cheers,
Ancient Lady
AGK Community Tester and AppGameKit Master