Eqqman, if you are comfortable in C++, go with it.
It allows the full use of Object Oriented Programming and so much more control.
I now need to find the time to finish up a Tier 2 tutorial that shows off many things good in Tier 2 and how to handle stuff. I think this will become one of my targets for time on weekends.
And, it only takes a few lines in files to be able to use the same code file set for multiple platforms.
template.h:
#ifndef _H_APP
#define _H_APP
/////////////////////////////////////////
// CONSTANTS ////////////////////////////
/////////////////////////////////////////
#if defined(AGKWINDOWS) || defined(IDE_MAC)
#define DEVICE_WIDTH 960
#define DEVICE_HEIGHT 640
#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 "Help YeeYee Get Home!"
// Link to AGK libraries
#include "agk.h"
// include our defined types
#include "ta_types.h"
// the std:: classes
#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
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);
void inBadState();
};
extern app App;
#endif
// Allow us to use the LoadImage function name
#ifdef LoadImage
#undef LoadImage
#endif
template.cpp:
// Includes, namespace and prototypes
#include "template.h"
#include "ta_pointer.h"
#include "ta_oops.h"
#include "ta_display.h"
#include "the_player.h"
#include "the_globals.h"
#include "game_functions.h"
#include "ta_debug_console.h"
using namespace AGK;
app App;
/////////////////////////////////////////
// CONSTANTS ////////////////////////////
/////////////////////////////////////////
// game states
#define _AS_DISPLAY_INIT_ 1
#define _AS_MAIN_INIT_ 2
#define _AS_MAIN_PLAY_ 3
#define _AS_MAIN_DONE_ 4
#define _AS_BAD_STATE_ 5
// 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("HelpYeeYeeGetHome","com.triassicassociates.helpyeeyeegethome.syslog");
// assume okay for now
did_end = false;
app_state = _AS_DISPLAY_INIT_;
app_err_msg = "";
// set the platform data
TADisplay::setPlatformInfo(false,false);
// do startup function
if (initialiseTheApp(WINDOW_TITLE)) hadAnAppError("Failed to initialise properly:");
}
// Main loop, called every frame
void app::Loop ( void )
{
// check for ended
if (app::did_end) return;
// get seconds per frame and frames per second
g_frametime = agk::GetFrameTime();
g_fps = agk::ScreenFPS();
// figure out the factor to multiply speeds by
g_fixspeed = g_frametime / g_targettime;
TADisplay::printAGKmessage("\nFPS:%0.1f",g_fps);
// process based on state
switch (app_state)
{
case _AS_MAIN_PLAY_:
// handle the main processing stuff
switch (mainProcessingLoop())
{
case 0:
// do the physics, done this way so that we can control
// pausing and restarting
the_player::step_physics(g_fixspeed);
break;
case 1:
// player pressed 'Exit'
// set new state
app_state = _AS_MAIN_DONE_;
break;
case 2:
// an error occurred while starting a game
hadAnAppError("Game did not start properly:");
break;
case 3:
// an error occured while initialising options
hadAnAppError("Failed to initialise options:");
break;
}
break;
case _AS_MAIN_DONE_:
// we want to make sure everything is cleared away
endTheGame();
// close down
closeThisApp();
// done, we want to make sure we skip the Sync() call
return;
case _AS_BAD_STATE_:
// display message and done
inBadState();
break;
case _AS_MAIN_INIT_:
// do initialisation
if (initialiseTheGame()) hadAnAppError("Failed to initialise properly:");
else app_state = _AS_MAIN_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_MAIN_INIT_;
break;
}
// sync display
agk::Sync();
}
// Called when the app ends
void app::End ( void )
{
// clean up, close debug output
TADebugConsole::close_console();
}
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)
{
// save the message
app_err_msg = "\n\n\n";
app_err_msg += errmsg;
app_err_msg += "\n\n";
app_err_msg += ta_oops::get_the_oops();
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());
}
The above gives peeks into using a state machine for handling processes.
In Tier 2, while the agk::sync() call might update displays anywhere in the code, there is only one place that it updates user inputs (touches and stuff). And that is in the app::Loop method, and it will only do so once for each call.
Cheers,
Ancient Lady