zengine/src/ZE_ZEngine.cpp

688 lines
14 KiB
C++
Raw Normal View History

2002-11-21 05:40:49 +00:00
/*******************************************************************************
2002-12-29 06:50:19 +00:00
This file is Part of the ZEngine Library for 2D game development.
Copyright (C) 2002, 2003 James Turk
2002-11-21 05:40:49 +00:00
2002-12-29 06:50:19 +00:00
Licensed under a BSD-style license.
2002-11-21 05:40:49 +00:00
The maintainer of this library is James Turk (james@conceptofzero.net)
2002-12-29 06:50:19 +00:00
and the home of this Library is http://www.zengine.sourceforge.net
2002-11-21 05:40:49 +00:00
*******************************************************************************/
/*!
\par File Header:
File: ZE_ZEngine.cpp <br>
Description: Implementation source file for ZEngine library main singleton class. <br>
Author(s): James Turk <br>
2003-01-18 21:53:14 +00:00
$Id: ZE_ZEngine.cpp,v 1.16 2003/01/18 21:53:14 cozman Exp $<br>
2002-11-21 05:40:49 +00:00
\file ZE_ZEngine.cpp
\brief Central source file for ZEngine.
2003-01-13 06:31:08 +00:00
Actual implementation of ZEngine singleton class, the core of ZEngine.
2002-11-21 05:40:49 +00:00
**/
#include "ZE_ZEngine.h"
namespace ZE
{
ZEngine *ZEngine::sInstance=NULL;
ZEngine::ZEngine()
{
mWidth = 640;
mHeight = 480;
mBPP = 16;
mFullscreen = true;
#ifdef USE_SDL_MIXER
mRate = 22050;
mStereo = false;
#endif
2002-12-27 03:15:33 +00:00
mNeedReload = false;
2002-11-21 05:40:49 +00:00
mScreen = NULL;
mActive = mQuit = false;
2002-12-03 06:19:43 +00:00
mKeyIsPressed = NULL;
2002-11-21 05:40:49 +00:00
mMouseX = mMouseY = 0;
mMouseB = 0;
2002-12-03 06:19:43 +00:00
for(int k = 0; k < SDLK_LAST; k++)
mKeyPress[k] = false;
2002-11-21 05:40:49 +00:00
mUnpauseOnActive = mPaused = false;
2003-01-04 05:16:01 +00:00
mDesiredFramerate = 0;
mNextUpdate = mLastPause = mPausedTime = mLastTime = 0;
2002-11-21 05:40:49 +00:00
mSecPerFrame = 0.0;
2003-01-13 06:31:08 +00:00
mLogAllErrors = true;
mErrlog = stderr;
2002-11-21 05:40:49 +00:00
}
ZEngine* ZEngine::GetInstance()
{
if(!sInstance)
sInstance = new ZEngine;
return sInstance;
}
void ZEngine::ReleaseInstance()
{
if(sInstance)
{
2002-11-28 23:15:52 +00:00
sInstance->CloseDisplay();
2002-11-21 05:40:49 +00:00
delete sInstance;
}
sInstance = NULL;
}
string ZEngine::GetVersion()
{
return VERSION;
}
void ZEngine::SetupDisplay(int width, int height, int bpp, bool fullscreen)
{
mWidth = width;
mHeight = height;
mBPP = bpp;
mFullscreen = fullscreen;
}
#ifdef USE_SDL_MIXER
void ZEngine::SetupSound(int rate, bool stereo)
{
mRate = rate;
mStereo = stereo;
}
#endif
bool ZEngine::CreateDisplay(string title, string icon)
2002-11-21 05:40:49 +00:00
{
Uint32 flags=0;
SDL_Surface *iconImg;
#ifdef USE_OPENGL
int rgb_size[3];
#endif //USE_OPENGL
2002-11-21 05:40:49 +00:00
if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_AUDIO) < 0)
{
2003-01-13 06:31:08 +00:00
ReportError(ZERR_SDL_INIT,SDL_GetError());
return false;
2002-11-21 05:40:49 +00:00
}
#ifdef USE_SDL_MIXER
if(Mix_OpenAudio(mRate, AUDIO_S16SYS, mStereo?2:1, 4096) < 0) //Open Audio (Stereo?2:1 is conditional for number of channels)
{
2003-01-13 06:31:08 +00:00
ReportError(ZERR_MIX_INIT,SDL_GetError());
return false;
}
#endif //USE_SDL_MIXER
2002-11-21 05:40:49 +00:00
#ifdef USE_OPENGL
2002-11-28 23:15:52 +00:00
switch (mBPP)
{
case 8:
rgb_size[0] = 3;
rgb_size[1] = 3;
rgb_size[2] = 2;
break;
case 15:
case 16:
rgb_size[0] = 5;
rgb_size[1] = 5;
rgb_size[2] = 5;
break;
default:
rgb_size[0] = 8;
rgb_size[1] = 8;
rgb_size[2] = 8;
break;
}
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, rgb_size[0]);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, rgb_size[1]);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, rgb_size[2]);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, mBPP);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 0);
SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, 0);
SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, 0);
SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, 0);
SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, 0);
2002-11-28 23:15:52 +00:00
flags = SDL_OPENGL;
#endif //USE_OPENGL
2002-11-21 05:40:49 +00:00
//Window Manager settings//
2002-12-03 06:19:43 +00:00
SDL_EnableKeyRepeat(30,30);
2002-11-21 05:40:49 +00:00
if(!icon.length())
SDL_WM_SetCaption(title.c_str(),NULL);
else
{
SDL_WM_SetCaption(title.c_str(),icon.c_str());
iconImg = LoadImage(icon);
SDL_WM_SetIcon(iconImg,NULL);
2002-11-21 05:40:49 +00:00
FreeImage(iconImg);
}
2002-11-28 23:15:52 +00:00
//create SDL screen and update settings based on returned screen//
2002-11-21 05:40:49 +00:00
if(mFullscreen)
flags |= SDL_FULLSCREEN;
mScreen = SDL_SetVideoMode(mWidth, mHeight, mBPP, flags);
if(!mScreen) //try 0 for BPP if supplied bpp failed
2002-11-21 05:40:49 +00:00
{
2003-01-13 06:31:08 +00:00
ReportError(ZERR_VIDMODE,SDL_GetError());
mScreen = SDL_SetVideoMode(mWidth, mHeight, 0, flags);
2003-01-12 17:27:05 +00:00
if(!mScreen) //if safe screen setup fails
{
#ifdef USE_SDL_MIXER
2003-01-12 17:27:05 +00:00
Mix_CloseAudio();
#endif
2003-01-12 17:27:05 +00:00
SDL_Quit();
2003-01-13 06:31:08 +00:00
ReportError(ZERR_VIDMODE,FormatStr("Desktop Depth failed: %s",SDL_GetError()));
2003-01-12 17:27:05 +00:00
return false;
}
2002-11-21 05:40:49 +00:00
}
mWidth = mScreen->w;
mHeight = mScreen->h;
mBPP = mScreen->format->BitsPerPixel;
#ifdef USE_OPENGL
SetGL2D();
#endif //USE_OPENGL
2002-12-03 06:19:43 +00:00
mKeyIsPressed = SDL_GetKeyState(NULL);
2002-11-21 05:40:49 +00:00
#ifdef USE_SDL_TTF
if(TTF_Init() < 0)
{
2003-01-13 06:31:08 +00:00
ReportError(ZERR_TTF_INIT,TTF_GetError());
return false;
}
#endif //USE_SDL_TTF
2002-11-21 05:40:49 +00:00
mLastTime = mPausedTime = SDL_GetTicks();
mActive = true;
return true;
2002-11-21 05:40:49 +00:00
}
2002-11-28 23:15:52 +00:00
void ZEngine::CloseDisplay()
2002-11-21 05:40:49 +00:00
{
#ifdef USE_SDL_TTF
TTF_Quit();
#endif
#ifdef USE_SDL_MIXER
Mix_CloseAudio();
#endif
#ifdef USE_PHYSFS
PHYSFS_deinit();
#endif
SDL_Quit();
2003-01-13 06:31:08 +00:00
if(mErrlog != stderr && mErrlog != stdin)
fclose(mErrlog);
2002-11-21 05:40:49 +00:00
}
2002-11-28 23:15:52 +00:00
SDL_Surface *ZEngine::Display()
2002-11-21 05:40:49 +00:00
{
return mScreen;
}
2002-12-12 02:50:35 +00:00
void ZEngine::Update()
2002-11-21 05:40:49 +00:00
{
2002-11-28 23:15:52 +00:00
SDL_GL_SwapBuffers();
2002-11-21 05:40:49 +00:00
mSecPerFrame = (GetTime()-mLastTime)/1000.0;
mLastTime = GetTime();
2003-01-04 05:16:01 +00:00
if(mDesiredFramerate)
{
if(mLastTime < mNextUpdate)
SDL_Delay(mNextUpdate-mLastTime);
mNextUpdate = GetTime()+(1000/mDesiredFramerate);
}
2002-11-21 05:40:49 +00:00
}
void ZEngine::Clear(float red, float green, float blue, float alpha)
2002-11-21 05:40:49 +00:00
{
glClearColor(red,green,blue,alpha);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
2002-11-21 05:40:49 +00:00
}
void ZEngine::SetGL2D()
2002-11-21 05:40:49 +00:00
{
glPushAttrib(GL_ENABLE_BIT);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glEnable(GL_TEXTURE_2D);
/* This allows alpha blending of 2D textures with the scene*/
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glViewport(0, 0, mWidth, mHeight);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0.0, (GLdouble)mWidth, (GLdouble)mHeight, 0.0, 0.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
2002-11-21 05:40:49 +00:00
}
2002-11-28 23:15:52 +00:00
void ZEngine::Delay(Uint32 milliseconds)
2002-11-21 05:40:49 +00:00
{
SDL_Delay(milliseconds);
}
Uint32 ZEngine::GetTime()
{
if(mPaused)
return SDL_GetTicks() - (mPausedTime + (SDL_GetTicks() - mLastPause));
else
return SDL_GetTicks() - mPausedTime;
}
void ZEngine::PauseTimer()
{
if(!mPaused)
{
mLastPause = SDL_GetTicks();
mPaused = true;
}
}
void ZEngine::UnpauseTimer()
{
if(mPaused)
{
mPausedTime += (SDL_GetTicks() - mLastPause);
mPaused = false;
}
}
double ZEngine::GetFrameTime()
{
return mSecPerFrame;
}
2003-01-04 05:16:01 +00:00
double ZEngine::GetFramerate()
{
return 1/mSecPerFrame;
}
void ZEngine::SetDesiredFramerate(Uint8 rate)
{
mDesiredFramerate = rate;
}
Uint8 ZEngine::GetDesiredFramerate()
{
return mDesiredFramerate;
}
2002-11-21 05:40:49 +00:00
bool ZEngine::IsPaused()
{
return mPaused;
}
bool ZEngine::IsActive()
{
return mActive;
}
void ZEngine::RequestQuit()
{
mQuit = true; //simply request a quit, nothing more
}
bool ZEngine::QuitRequested()
{
return mQuit;
}
2002-12-27 03:15:33 +00:00
void ZEngine::SetReloadNeed(bool state)
{
mNeedReload = state;
}
bool ZEngine::ImagesNeedReload()
{
return mNeedReload;
}
2002-12-03 06:19:43 +00:00
void ZEngine::SetKeyRepeatRate(int rate)
{
SDL_EnableKeyRepeat(rate,rate);
}
2002-11-21 05:40:49 +00:00
bool ZEngine::KeyIsPressed(SDLKey key)
{
2002-12-03 06:19:43 +00:00
return mKeyIsPressed[key] == 1;
}
bool ZEngine::KeyPress(SDLKey key)
{
bool temp = mKeyPress[key];
2002-12-05 00:10:42 +00:00
mKeyPress[key] = false;
2002-12-03 06:19:43 +00:00
return temp;
2002-11-21 05:40:49 +00:00
}
void ZEngine::HideCursor()
{
SDL_ShowCursor(SDL_DISABLE);
}
void ZEngine::ShowCursor()
{
SDL_ShowCursor(SDL_ENABLE);
}
2002-11-28 23:15:52 +00:00
int ZEngine::MouseX()
2002-11-21 05:40:49 +00:00
{
return mMouseX;
}
2002-11-28 23:15:52 +00:00
int ZEngine::MouseY()
2002-11-21 05:40:49 +00:00
{
return mMouseY;
}
bool ZEngine::LButtonPressed()
{
return (mMouseB & SDL_BUTTON_LMASK) > 0;
}
bool ZEngine::RButtonPressed()
{
return (mMouseB & SDL_BUTTON_RMASK) > 0;
}
bool ZEngine::MouseInRect(SDL_Rect *rect)
{
return (mMouseX >= rect->x && mMouseX <= rect->x+rect->w &&
mMouseY >= rect->y && mMouseY <= rect->y+rect->h);
}
void ZEngine::CheckEvents()
{
SDL_Event event;
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_VIDEOEXPOSE:
case SDL_ACTIVEEVENT:
if(event.active.state & SDL_APPACTIVE || event.active.state & SDL_APPINPUTFOCUS)
{
if( (event.type == SDL_ACTIVEEVENT && event.active.gain == 1) || event.type == SDL_VIDEOEXPOSE)
{
mActive = true;
if(mUnpauseOnActive)
UnpauseTimer();
2002-12-27 03:15:33 +00:00
if(mFullscreen)
mNeedReload = true;
2002-11-21 05:40:49 +00:00
}
else
{
mActive = mUnpauseOnActive = false;
if(!mPaused)
{
mUnpauseOnActive = true;
PauseTimer();
}
else
mUnpauseOnActive = false;
}
}
break;
2002-12-03 06:19:43 +00:00
case SDL_KEYDOWN:
mKeyPress[event.key.keysym.sym] = true;
break;
case SDL_KEYUP:
mKeyPress[event.key.keysym.sym] = false;
break;
2002-11-21 05:40:49 +00:00
case SDL_QUIT:
mQuit = true;
break;
default:
break;
}
}
2002-12-03 06:19:43 +00:00
mKeyIsPressed = SDL_GetKeyState(NULL); //recommended but not needed (says Sam)
2002-11-21 05:40:49 +00:00
2002-12-03 06:19:43 +00:00
//Alt-X or Alt-F4
if((mKeyIsPressed[SDLK_x] || mKeyIsPressed[SDLK_F4]) &&
(mKeyIsPressed[SDLK_LALT] || mKeyIsPressed[SDLK_RALT]))
2002-11-21 05:40:49 +00:00
mQuit = true;
mMouseB = SDL_GetMouseState(&mMouseX,&mMouseY);
}
#ifdef USE_PHYSFS
void ZEngine::InitPhysFS(string argv)
{
string::size_type pos;
PHYSFS_init(argv.c_str());
pos = argv.rfind(PHYSFS_getDirSeparator());
if(pos != string::npos)
AddPhysFSDir(argv.substr(0,pos));
}
void ZEngine::AddPhysFSDir(string dir)
{
PHYSFS_addToSearchPath(dir.c_str(),0);
}
#endif //USE_PHYSFS
2003-01-13 06:31:08 +00:00
void ZEngine::SetErrorLog(bool logAll, string logFile)
{
mLogAllErrors = logAll;
if(logFile.length())
{
if(logFile == "stderr")
mErrlog = stderr;
else if(logFile == "stdout")
mErrlog = stdout;
else
mErrlog = fopen(logFile.c_str(),"w");
}
}
void ZEngine::ReportError(ZErrorCode code, string desc, string file, unsigned int line)
{
mCurError.Create(code,desc,file,line);
if(mLogAllErrors)
{
LogError(mCurError);
fflush(mErrlog);
}
else
mErrorQueue.push(mCurError);
}
ZErrorCode ZEngine::GetLastError()
{
2003-01-18 21:53:14 +00:00
ZErrorCode code = mCurError.Code();
mCurError.Create(ZERR_NONE);
return code;
2003-01-13 06:31:08 +00:00
}
void ZEngine::WriteLog(string str)
{
fprintf(mErrlog,str.c_str());
}
void ZEngine::LogError(ZError error)
{
fprintf(mErrlog,error.LogString().c_str());
}
void ZEngine::FlushErrors()
{
2003-01-18 21:53:14 +00:00
mCurError.Create(ZERR_NONE);
2003-01-13 06:31:08 +00:00
while(!mErrorQueue.empty())
{
LogError(mErrorQueue.front());
mErrorQueue.pop();
}
}
SDL_Surface* ZEngine::LoadImage(string filename)
2002-11-21 05:40:49 +00:00
{
SDL_Surface *image;
2002-11-21 05:40:49 +00:00
//using physfs//
#ifdef USE_PHYSFS
SDL_RWops *rw;
rw = PHYSFSRWOPS_openRead(filename.c_str());
if(!rw)
2003-01-13 06:31:08 +00:00
{
ReportError(ZERR_LOAD_IMAGE,FormatStr("%s [PhysFS RWops failed: %s]",filename.c_str(),SDL_GetError()));
return NULL;
}
2002-11-21 05:40:49 +00:00
#ifdef USE_SDL_IMAGE
image = IMG_Load_RW(rw,0);
2002-11-21 05:40:49 +00:00
#else
image = SDL_LoadBMP_RW(rw,0);
2002-11-21 05:40:49 +00:00
#endif //USE_SDL_IMAGE
SDL_FreeRW(rw);
//end using physfs//
//Just SDL//
#else
#ifdef USE_SDL_IMAGE
image = IMG_Load(filename.c_str());
2002-11-21 05:40:49 +00:00
#else
image = SDL_LoadBMP(filename.c_str());
2002-11-21 05:40:49 +00:00
#endif //USE_SDL_IMAGE
#endif //USE_PHYSFS
if(!image)
2002-11-21 05:40:49 +00:00
{
2003-01-13 06:31:08 +00:00
ReportError(ZERR_LOAD_IMAGE,filename);
return NULL;
2002-11-21 05:40:49 +00:00
}
else
return image;
2002-11-21 05:40:49 +00:00
}
#ifdef USE_SDL_MIXER
Mix_Chunk* ZEngine::LoadSound(string filename)
2002-11-21 05:40:49 +00:00
{
Mix_Chunk *sound;
2002-11-21 05:40:49 +00:00
#ifdef USE_PHYSFS
SDL_RWops *rw;
rw = PHYSFSRWOPS_openRead(filename.c_str());
sound = Mix_LoadWAV_RW(rw,0);
2002-11-21 05:40:49 +00:00
SDL_FreeRW(rw);
#else
sound = Mix_LoadWAV(filename.c_str());
2002-11-21 05:40:49 +00:00
#endif //USE_PHYSFS
if(!sound)
2002-11-21 05:40:49 +00:00
{
2003-01-13 06:31:08 +00:00
ReportError(ZERR_LOAD_SOUND,filename);
return NULL;
2002-11-21 05:40:49 +00:00
}
else
return sound;
2002-11-21 05:40:49 +00:00
}
Mix_Music* ZEngine::LoadMusic(string filename)
2002-11-21 05:40:49 +00:00
{
Mix_Music *music;
2002-11-21 05:40:49 +00:00
//Currently SDL_Mixer doesn't support Music from a RW
//#ifdef USE_PHYSFS
// SDL_RWops *rw;
// rw = PHYSFSRWOPS_openRead(filename.c_str());
// mus.music = Mix_LoadMUS_RW(filename.c_str(),0);
// SDL_FreeRW(rw);
//#else
music = Mix_LoadMUS(filename.c_str());
2002-11-21 05:40:49 +00:00
//#endif //USE_PHYSFS
if(!music)
2002-11-21 05:40:49 +00:00
{
2003-01-13 06:31:08 +00:00
ReportError(ZERR_LOAD_MUSIC,filename);
return NULL;
2002-11-21 05:40:49 +00:00
}
else
return music;
2002-11-21 05:40:49 +00:00
}
#endif
#ifdef USE_SDL_TTF
TTF_Font* ZEngine::LoadFont(string filename, int size)
2002-11-21 05:40:49 +00:00
{
TTF_Font *font;
2002-11-21 05:40:49 +00:00
//Currently SDL_ttf doesn't support Fonts from a RW
//#ifdef USE_PHYSFS
// SDL_RWops *rw;
// rw = PHYSFSRWOPS_openRead(filename.c_str());
// fnt.font = TTF_OpenFontRW(rw,0);
// SDL_FreeRW(rw);
//#else
font = TTF_OpenFont(filename.c_str(),size);
2002-11-21 05:40:49 +00:00
//#endif //USE_PHYSFS
if(!font)
2002-11-21 05:40:49 +00:00
{
2003-01-13 06:31:08 +00:00
ReportError(ZERR_LOAD_FONT,filename);
return NULL;
2002-11-21 05:40:49 +00:00
}
else
return font;
2002-11-21 05:40:49 +00:00
}
#endif
2002-11-28 23:15:52 +00:00
int ZEngine::Width()
2002-11-21 05:40:49 +00:00
{
return mWidth;
}
2002-11-28 23:15:52 +00:00
int ZEngine::Height()
2002-11-21 05:40:49 +00:00
{
return mHeight;
}
2002-11-28 23:15:52 +00:00
int ZEngine::BPP()
2002-11-21 05:40:49 +00:00
{
return mBPP;
}
bool ZEngine::IsFullscreen()
{
return mFullscreen;
}
}