This code works on all platforms. I have not tested it in V2 for iOS or Android, yet. But I just tested it in Windows 7 Pro, MS VS 2013 and AppGameKit V2.014.
Header (ta_debug_console.h):
// ******************************************************************************
//
// TADebugConsole - Debug output to console class
//
// Version 1.10
//
// Author: Cynthia R. Douglas, Triassic Associates, LLC
//
// License: GPL, see http://www.gnu.org/licenses/gpl.html
//
// This class was originally created by Triassic Associates, LLC
// for use in its own applications.
//
// It is being made available for public use "AS IS".
//
// Please keep this disclaimer.
//
// ******************************************************************************
#ifndef _TA_DEBUG_CONSOLE_
#define _TA_DEBUG_CONSOLE_
// get some standard objects we need
#include <string>
#include <stdarg.h>
// other includes as needed by platform
#ifdef AGKWINDOWS
#include <windows.h>
#endif
#ifdef IDE_ANDROID
#include <android/log.h>
#endif
#if defined(AGKIOS) || defined(IDE_MAC)
#include <asl.h>
#endif
/////////////////////////////////////////
// CLASS NOTES //////////////////////////
/////////////////////////////////////////
/*
To use in Windows:
1. Adjust the display position and size of the console
by changing the parameters in the MoveWindow call
2. If you want to catch statements sent during your app
closing process, you need to make sure not to actually
exit the app. The sample template.h/.cpp show one way.
To use in Android:
1. Connect via USB
2. Run app from Eclipse
3. Monitor 'LogCat' output window
To use in Mac:
1. Run app from Xcode
2. Monitor 'All Output' window
To use in iOS
1. Connect via Apple cable
2. Run app from Xcode
3. Monitor 'All Output' window
*/
/////////////////////////////////////////
// TYPES ////////////////////////////////
/////////////////////////////////////////
typedef enum taDebugConsole_logType
{
TA_DEBUG_CONSOLE_DEBUG = 0,
TA_DEBUG_CONSOLE_INFO = 1,
TA_DEBUG_CONSOLE_WARN = 2,
TA_DEBUG_CONSOLE_ERROR = 3
} taDebugConsole_logType;
/////////////////////////////////////////
// CLASS DEFINITION /////////////////////
/////////////////////////////////////////
class TADebugConsole {
private:
// static attributes for all
static bool did_not_init; // flag to indicate whether initialised
static char app_tag[128]; // app tag for all messages
static char tmp_str[4096]; // temporary string
static char tag_str[256]; // another temp string for tag
static const char* msg_types[4]; // message type strings
// static attributes as needed by platform
#ifdef AGKWINDOWS
static HWND winHandle;
static HANDLE stdHandle;
static DWORD dword;
static char full_str[5120];
#endif
#if defined(AGKIOS) || defined(IDE_MAC)
static aslclient _asl_client;
#endif
public:
// public static methods
/*
Name: init_console
Purpose:
Sets up information and makes connections as necessary.
If not called, all calls to send_to_console are ignored.
Recommendation is to call in the app::Begin method.
Parameters:
apptag - required by all, any text up to 127 characters that helps
you identify messages sent by this class.
asl_fac - required for iOS/Mac and ignored by others.
This is the 'facility' associated with the asl commands.
Can be any text, but recommend using the package name
followed by '.syslog'.
Eg. TADebugConsole::init_console("MyAppDebug","com.yourcompany.yourapp.syslog");
Returns: nothing
*/
static void init_console(const char* apptag,const char* asl_fac=NULL);
/*
Name: close_console
Purpose:
Nothing done if init_console is not called.
Closes connections as needed (required by iOS/Mac, run during app::End method).
Parameters: none
Returns: nothing
*/
static void close_console();
/*
Name: send_to_console
Purpose:
Nothing done if init_console is not called.
Send the passed message with proper type to the debug console.
Parameters:
msgtype - type of message, must be a taDebugConsole_logType value
fmt, ... - inputs like printf for building message.
Eg. TADebugConsole::send_to_console(TA_DEBUG_CONSOLE_INFO,"%s %d","message number",15);
Returns: nothing
*/
static void send_to_console(taDebugConsole_logType msgtype,const char* fmt, ...);
};
#endif
Implementation (ta_debug_console.cpp):
// ******************************************************************************
//
// TADebugConsole - Debug output to console class
//
// Version 1.10
//
// Author: Cynthia R. Douglas, Triassic Associates, LLC
//
// License: GPL, see http://www.gnu.org/licenses/gpl.html
//
// This class was originally created by Triassic Associates, LLC
// for use in its own applications.
//
// It is being made available for public use "AS IS".
//
// Please keep this disclaimer.
//
// ******************************************************************************
#include "ta_debug_console.h"
/////////////////////////////////////////
// CLASS STATIC ATTRIBUTES //////////////
/////////////////////////////////////////
bool TADebugConsole::did_not_init = true;
char TADebugConsole::app_tag[128];
char TADebugConsole::tmp_str[4096];
char TADebugConsole::tag_str[256];
const char* TADebugConsole::msg_types[4] = {"<Debug>","<Info>","<Warn","<Error>"};
// static attributes as needed by platform
#ifdef AGKWINDOWS
HWND TADebugConsole::winHandle;
HANDLE TADebugConsole::stdHandle;
DWORD TADebugConsole::dword;
char TADebugConsole::full_str[5120];
#endif
#if defined(AGKIOS) || defined(IDE_MAC)
aslclient TADebugConsole::_asl_client;
#endif
/////////////////////////////////////////
// CLASS IMPLEMENTATION /////////////////
/////////////////////////////////////////
void TADebugConsole::init_console(const char* apptag,const char* asl_fac/*=NULL*/)
{
// copy the tag
strncpy(app_tag,apptag,127);
// other inits as needed by platform
#ifdef AGKWINDOWS
// some variables
COORD coord;
SMALL_RECT windowSize;
CONSOLE_SCREEN_BUFFER_INFO coninfo;
// attempt to create a console
if (!AllocConsole())
{
// oops, failed
fprintf( stderr, "Impossible to create the ASL client\n" );
exit( EXIT_FAILURE );
}
// set the title
SetConsoleTitle(apptag);
// get the window handle
winHandle = GetConsoleWindow();
// move it (adjust the position and size here)
MoveWindow(winHandle,10,10,700,700,true);
// get the standard output handle
stdHandle = GetStdHandle(STD_OUTPUT_HANDLE);
// get maximum allowed size and the font size
coord = GetLargestConsoleWindowSize(stdHandle);
// set the screen buffer to be big enough to let us scroll text
GetConsoleScreenBufferInfo(stdHandle,&coninfo);
// reset console buffer size to max
coninfo.dwSize.X = coord.X;
coninfo.dwSize.Y = coord.Y;
if (!SetConsoleScreenBufferSize(stdHandle,coninfo.dwSize)) TADebugConsole::send_to_console(TA_DEBUG_CONSOLE_ERROR,"SetConsoleScreenBufferSize: %d",GetLastError());
// calculate size we want
windowSize.Top = 0;
windowSize.Left = 0;
windowSize.Bottom = windowSize.Top + coord.Y - 11;
windowSize.Right = windowSize.Left + (coord.X >= 120 ? 120 : coord.X) - 1;
// try to set the size and location
if (!SetConsoleWindowInfo(stdHandle,true,&windowSize)) TADebugConsole::send_to_console(TA_DEBUG_CONSOLE_ERROR,"SetConsoleWindowInfo: %d",GetLastError());
#endif
#if defined(AGKIOS) || defined(IDE_MAC)
// make the connection immediately, as stderr and don't pre-filter messages
_asl_client = asl_open( "TADebugConsole", asl_fac, ASL_OPT_STDERR | ASL_OPT_NO_DELAY | ASL_OPT_NO_REMOTE);
// check the connection
if( _asl_client == NULL )
{
// oops, failed
fprintf( stderr, "Impossible to create the ASL client\n" );
exit( EXIT_FAILURE );
}
// set the filter to make sure that all of our messages are displayed
asl_set_filter(_asl_client,ASL_FILTER_MASK(ASL_LEVEL_DEBUG)|ASL_FILTER_MASK(ASL_LEVEL_INFO)|ASL_FILTER_MASK(ASL_LEVEL_WARNING)|ASL_FILTER_MASK(ASL_LEVEL_ERR));
#endif
// indicate initted
did_not_init = false;
// send message to show done
TADebugConsole::send_to_console(TA_DEBUG_CONSOLE_INFO,"TADebugConsole::init_console(%s,%s)",app_tag,(asl_fac == NULL ? "NULL" : asl_fac));
}
void TADebugConsole::close_console()
{
// check for initted
if (did_not_init) return;
// this is handled according to platform
#ifdef AGKWINDOWS
// free the console
FreeConsole();
#endif
#if defined(AGKIOS) || defined(IDE_MAC)
// close the connection
asl_close(_asl_client);
#endif
}
void TADebugConsole::send_to_console(taDebugConsole_logType msgtype,const char* fmt, ...)
{
// check for initted
if (did_not_init) return;
// clear our buffer, just to be sure that we have no garbage
memset(tmp_str,0,4096);
// set up to handle the arguments
va_list args;
// Initialize args to retrieve the additional arguments after parameter fmt
va_start(args,fmt);
// parse through the format string and the arguments
// and create the resulting string, stored in tmp_str
vsprintf(tmp_str, fmt, args);
// make sure to clean up internal stuff that was
// handling the arguments
va_end(args);
// make the tag string
sprintf(tag_str,"%s%s",app_tag,msg_types[msgtype]);
// this is now handled according to platform
#ifdef AGKWINDOWS
// clear the string
memset(full_str,0,5120);
// construct the full string
sprintf(full_str,"%s: %s\n",tag_str,tmp_str);
// get the string length
int len = strlen(full_str);
// output to console
WriteConsole(stdHandle,full_str,len,&dword,NULL);
#endif
#ifdef IDE_ANDROID
// call function directly
__android_log_print(ANDROID_LOG_DEBUG+msgtype, tag_str, tmp_str);
#endif
#if defined(AGKIOS) || defined(IDE_MAC)
// decide asl message level
int asl_lev = (msgtype == TA_DEBUG_CONSOLE_DEBUG
? ASL_LEVEL_DEBUG
: (msgtype == TA_DEBUG_CONSOLE_INFO
? ASL_LEVEL_INFO
: ((msgtype == TA_DEBUG_CONSOLE_WARN
? ASL_LEVEL_WARNING : ASL_LEVEL_ERR))));
// send the message
asl_log(_asl_client, NULL, asl_lev, "%s",tmp_str);
#endif
}
Here are the template.h/.cpp files for my demo project (which does involve a lot of other files, but it shows the basic usage for the class above):
#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 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
// 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_MAIN_INIT_ 2
#define _AS_MAIN_PLAY_ 3
#define _AS_MAIN_DONE_ 4
#define _AS_BAD_STATE_ 5
// indicate whether using TADebugConsole
#define _USE_DEBUG_CONSOLE_ true
/////////////////////////////////////////
// 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_err_msg = "";
// set the initial state
makeStateChange(app_state,_AS_DISPLAY_INIT_,"_AS_DISPLAY_INIT_");
// attempt to initialise the display
if (startProcessDisplay(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 occuring first
switch (app_state)
{
case _AS_MAIN_PLAY_:
// handle the main processing loop
if (mainProcessLoop()) makeStateChange(app_state,_AS_MAIN_DONE_,"_AS_MAIN_DONE_");
break;
case _AS_MAIN_DONE_:
// close down
closeThisApp();
// done, we want to make sure we skip the agk::Sync() call
// because the AGK engine may need a cycle or two to properly forget
// everything that was created
return;
case _AS_BAD_STATE_:
// display message and done
inBadState();
break;
case _AS_MAIN_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())
{
// oops, initialisation did not work
hadAnAppError("Failed to initialise properly:",processErrorWas());
} else {
// initialisation finished without error
// start actual game initialisation in the next cycle
makeStateChange(app_state,_AS_MAIN_PLAY_,"_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
makeStateChange(app_state,_AS_MAIN_INIT_,"_AS_MAIN_INIT_");
break;
}
// sync display
agk::Sync();
}
// Called when the app ends
void app::End ( void )
{
// clean up, if not already done
doProcessCleanup();
}
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::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
makeStateChange(app_state,_AS_BAD_STATE_,"_AS_BAD_STATE_");
// show a message
agk::Print(app_err_msg.c_str());
}
void app::inBadState()
{
// check for exit
if (TAPointer::gotPress()) closeThisApp(false);
// show a message
agk::Print(app_err_msg.c_str());
}
On a Windows box, this will open a separate window that strings can be written to. For iOS/Mac, the messages will be displayed in the Xcode message area. For Android, it assumes connection to Eclipse and outputs to its message window.
The code is part of a project that demonstrates state machines, http connections, multi-platform coding and a few other things. Eventually, I will get the whole project finished with associated tutorial explaining it all.
Here are the handle_object.h/.cpp files (where the 'makeStateChange' method lives):
#ifndef _HANDLE_OBJECTS_
#define _HANDLE_OBJECTS_
// Link to AGK libraries
#include "agk.h"
// include our defined structs
#include "struct_defs.h"
// get some standard objects we need
#include <stdarg.h>
/////////////////////////////////////////
// EXPORTED VARIABLES ///////////////////
/////////////////////////////////////////
// a no-color object for common use
extern tColor no_color;
/////////////////////////////////////////
// EXPORTED FUNCTIONS ///////////////////
/////////////////////////////////////////
// functions to do clean and safe deletes of AGK objects
void delete_sprite(TA_UINT id);
void delete_image(TA_UINT id);
void delete_text(TA_UINT id);
// functions to create sprites
bool create_simple_sprite(
TA_UINT& spr_id, // id for created sprite
TA_UINT img_id, // id for image
float spr_wid, // width for sprite
float spr_hih, // height for sprite
float spr_x, // x position for sprite
float spr_y, // y position for sprite
tColor spr_col // sprite color
);
bool create_sprite_with_text(
TA_UINT& spr_id, // id for created sprite
TA_UINT& txt_id, // id for created text
TA_UINT img_id, // id for image
float spr_wid, // width for sprite
float spr_hih, // height for sprite
float spr_x, // x position for sprite
float spr_y, // y position for sprite
tColor spr_col, // sprite color
float txt_siz, // size for text
tColor txt_col, // color for text
const char* text // text to display
);
// some image functions
bool load_image_file(TA_UINT& img_id,const char* img_file);
// status window functions
bool create_status_window(tStatusWindow the_status);
void set_status_text(const char* fmt, ...);
void add_to_status_text(const char* fmt, ...);
void show_hide_status_window(bool is_vis);
void clean_up_status_window();
// some generic functions
float distance_between(tPoint aPt1, tPoint aPt2);
void get_sprite_position(TA_UINT spr_id,tPoint& isAt);
// message output
void showAGKmessage(const char* fmt, ...);
void printAGKmessage(const char* fmt, ...);
// some debug console support
void makeStateChange(TA_USHORT& the_state,TA_USHORT state_numb,const char* state_name=NULL);
#endif
#include "agk.h"
#include "handle_objects.h"
#include "ta_debug_console.h"
// in Ancient Lady's own project, these are all done
// within a static class that actually keeps
// track of everything and cleans it up
// this file is for simplicity
/////////////////////////////////////////
// EXPORTED VARIABLES ///////////////////
/////////////////////////////////////////
// the functions in handle_objects.cpp, that get passed a parameter
// of type tColor, assume that they are to apply
// color to a sprite unless the passed tColor parameter has
// the red color (i_rc) set to -1
// it is easier to create one instance of that structure
// and let everyone use it
// a no-color object for common use
tColor no_color = {-1,-1,-1,255};
/////////////////////////////////////////
// LOCAL VARIABLES //////////////////////
/////////////////////////////////////////
// used for Status Window and other formatting
char tmp_str[4096];
char add_str[4096];
char full_str[8196];
// the only status window allowed
static tStatusWindow theStatWnd;
/////////////////////////////////////////
// EXPORTED FUNCTIONS ///////////////////
/////////////////////////////////////////
// functions to do clean and safe deletes of AGK objects
void delete_sprite(TA_UINT id)
{
// make sure positive value
if (id < 1) return;
// check for object existing
if (!agk::GetSpriteExists(id)) return;
// get rid of the object
agk::DeleteSprite(id);
}
void delete_image(TA_UINT id)
{
// make sure positive value
if (id < 1) return;
// check for object existing
if (!agk::GetImageExists(id)) return;
// get rid of the object
agk::DeleteImage(id);
}
void delete_text(TA_UINT id)
{
// make sure positive value
if (id < 1) return;
// check for object existing
if (!agk::GetTextExists(id)) return;
// get rid of the object
agk::DeleteText(id);
}
// functions to create sprites
bool create_simple_sprite (
TA_UINT& spr_id, // this will be set and returned
TA_UINT img_id, // id for image
float spr_wid, // width for sprite
float spr_hih, // height for sprite
float spr_x, // x position for sprite
float spr_y, // y position for sprite
tColor spr_col // sprite color
)
{
// create the sprite using passed image id
spr_id = agk::CreateSprite(img_id);
// check to see if the sprite was created
if ((spr_id<1)||(!agk::GetSpriteExists(spr_id)))
{
// make sure the returned id is zero
spr_id = 0;
// indicate failure
return true;
}
// if passed red color is zero or greater, set the color
if (spr_col.i_rc>=0) agk::SetSpriteColor(spr_id, spr_col.i_rc, spr_col.i_gc, spr_col.i_bc, spr_col.i_alpha);
// set the sprite size
agk::SetSpriteSize(spr_id,spr_wid, spr_hih);
// position the sprite
agk::SetSpritePosition(spr_id, spr_x, spr_y);
// good
return false;
}
bool create_sprite_with_text(
TA_UINT& spr_id, // id for created sprite
TA_UINT& txt_id, // id for created text
TA_UINT img_id, // id for image
float spr_wid, // width for sprite
float spr_hih, // height for sprite
float spr_x, // x position for sprite
float spr_y, // y position for sprite
tColor spr_col, // sprite color
float txt_siz, // size for text
tColor txt_col, // color for text
const char* text // text to display
)
{
// try to create the sprite first
if (create_simple_sprite(spr_id,img_id,spr_wid,spr_hih,spr_x,spr_y,spr_col)) return false;
// good so far, create a text object
// we use a blank until we have set all
// the display parameters so that the
// size is calculated correctly
txt_id = agk::CreateText("");
// make sure it worked
if ((txt_id<1)||(!agk::GetTextExists(txt_id)))
{
// failed, clean up the sprite
delete_sprite(spr_id);
// reset the ids
spr_id = 0;
txt_id = 0;
// return error
return true;
}
// set the size
agk::SetTextSize(txt_id,txt_siz);
// set its color
agk::SetTextColor(txt_id, txt_col.i_rc, txt_col.i_gc, txt_col.i_bc, txt_col.i_alpha);
// set the alignment
agk::SetTextAlignment(txt_id,1);
// make sure text stays within width of button
agk::SetTextMaxWidth(txt_id, spr_wid-10.0f);
// now set the text
agk::SetTextString(txt_id, text);
// figure out the height and then the location for the text
float th = agk::GetTextTotalHeight(txt_id);
float y = spr_y + (spr_hih/2.0f) - (th / 2.0f);
float x = spr_x + (spr_wid/2.0f);
agk::SetTextPosition(txt_id,x,y);
agk::SetTextVisible(txt_id,1);
// all is good
return false;
}
// image stuff
bool load_image_file(TA_UINT& img_id,const char* img_file)
{
// assume not loaded
img_id = 0;
// check for file existence
if (!agk::GetFileExists(img_file)) return true;
// try to load the image
img_id = agk::LoadImage(img_file);
// good if actually exists
return (agk::GetImageExists(img_id)?false:true);
}
// status window stuff
bool create_status_window(tStatusWindow the_status)
{
float x,y;
// copy the information about the window
theStatWnd = the_status;
// we need to create two sprites
// try to create the first
if (create_simple_sprite(theStatWnd.spr1_id,0,theStatWnd.spr_wid,theStatWnd.spr_hih,
theStatWnd.spr_x,theStatWnd.spr_y,theStatWnd.spr1_col)) return true;
// now make the second, a little smaller
if (create_simple_sprite(theStatWnd.spr2_id,0,theStatWnd.spr_wid-20.0f,theStatWnd.spr_hih-20.0f,
theStatWnd.spr_x+10.0f,theStatWnd.spr_y+10.0f,theStatWnd.spr2_col)) return true;
// good so far, create a text object
theStatWnd.txt_id = agk::CreateText("");
// make sure it worked
if (theStatWnd.txt_id<1) return true;
// corner for text location
x = theStatWnd.spr_x + 30.0f;
y = theStatWnd.spr_y + 30.0f;
// make the text left aligned
agk::SetTextAlignment(theStatWnd.txt_id,0);
// set the size
agk::SetTextSize(theStatWnd.txt_id,theStatWnd.txt_siz);
// set its position
agk::SetTextPosition(theStatWnd.txt_id,x,y);
// set its color
agk::SetTextColor(theStatWnd.txt_id, theStatWnd.txt_col.i_rc, theStatWnd.txt_col.i_gc, theStatWnd.txt_col.i_bc, theStatWnd.txt_col.i_alpha);
// make sure that it wraps
agk::SetTextMaxWidth(theStatWnd.txt_id, (theStatWnd.spr_wid-64.0f));
// all good
return false;
}
void set_status_text(const char* fmt, ...)
{
// clear the target
memset(full_str,0,8196);
// handle the input
va_list args;
// create our own string
va_start(args,fmt);
vsnprintf(full_str, 8196, fmt, args );
va_end(args);
// now set the text string
agk::SetTextString(theStatWnd.txt_id,full_str);
}
void add_to_status_text(const char* fmt, ...)
{
// temporary object
char* agk_ret;
// clear the targets
memset(tmp_str,0,4096);
memset(add_str,0,4096);
memset(full_str,0,8196);
// handle the input
va_list args;
// get the new bits
va_start(args,fmt);
vsnprintf(add_str, 4096, fmt, args);
va_end(args);
// get pointer to current string
agk_ret = agk::GetTextString(theStatWnd.txt_id);
// copy the current text
strncpy(tmp_str,agk_ret,4095);
// clean up the string
delete[] agk_ret;
// set the text
sprintf(full_str,"%s\n%s",tmp_str,add_str);
// now set the text string
agk::SetTextString(theStatWnd.txt_id,full_str);
}
void show_hide_status_window(bool is_vis)
{
// decide on visibility
int vis = (is_vis?1:0);
// set visibility
agk::SetSpriteVisible(theStatWnd.spr1_id,vis);
agk::SetSpriteVisible(theStatWnd.spr2_id,vis);
agk::SetTextVisible(theStatWnd.txt_id,vis);
}
void clean_up_status_window()
{
// delete things
delete_sprite(theStatWnd.spr1_id);
delete_sprite(theStatWnd.spr2_id);
delete_text(theStatWnd.txt_id);
// clear the ids
theStatWnd.spr1_id = 0;
theStatWnd.spr2_id = 0;
theStatWnd.txt_id = 0;
}
// some generic functions
float distance_between(tPoint aPt1, tPoint aPt2)
{
// calculate first distances
float dx = aPt2.fX - aPt1.fX;
float dy = aPt2.fY - aPt1.fY;
// now get the 'real' distance
float d = sqrt((dx*dx) + (dy*dy));
// return the value
return d;
}
void get_sprite_position(TA_UINT spr_id,tPoint& isAt)
{
// get current position
isAt.fX = agk::GetSpriteX(spr_id);
isAt.fY = agk::GetSpriteY(spr_id);
}
void showAGKmessage(const char* fmt, ...)
{
// handle the input
va_list args;
// create our own string
va_start(args,fmt);
vsnprintf(tmp_str, 4096, fmt, args);
va_end(args);
// display the message
agk::Message(tmp_str);
}
void printAGKmessage(const char* fmt, ...)
{
// handle the input
va_list args;
// create our own string
va_start(args,fmt);
vsnprintf(tmp_str, 4096, fmt, args);
va_end(args);
// display the message
agk::Print(tmp_str);
}
void makeStateChange(TA_USHORT& the_state,TA_USHORT state_numb,const char* state_name/*=NULL*/)
{
// change to the new state
the_state = state_numb;
// output new status to the debug console
// if we have been given a name
if (state_name!=NULL) TADebugConsole::send_to_console(TA_DEBUG_CONSOLE_DEBUG,
"Starting %s(%u) state at %0.2f",
state_name,state_numb,agk::Timer());
}
Cheers,
Ancient Lady