/******************************************************************************* This file is Part of the ZEngine Library for SDL Game Development. Copyright (C) 2002 ConceptOfZero.net Licensed under the BSD License, see licensing.txt. The maintainer of this library is James Turk (james@conceptofzero.net) and the home of this Library is http://www.conceptofzero.net/ *******************************************************************************/ /*! \par File Header: File: ZE_ZEngine.cpp
Description: Implementation source file for ZEngine library main singleton class.
Author(s): James Turk
$Id: ZE_ZEngine.cpp,v 1.2 2002/11/28 23:19:55 cozman Exp $
\file ZE_ZEngine.cpp \brief Central source file for ZEngine. Actual implementation of ZEngine singleton class at heart of ZEngine. **/ #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 mScreen = NULL; mActive = mQuit = false; mKeyPressed = NULL; mMouseX = mMouseY = 0; mMouseB = 0; mUnpauseOnActive = mPaused = false; mLastPause = mPausedTime = mLastTime = 0; mSecPerFrame = 0.0; } ZEngine* ZEngine::GetInstance() { if(!sInstance) sInstance = new ZEngine; return sInstance; } void ZEngine::ReleaseInstance() { if(sInstance) { sInstance->CloseDisplay(); 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 void ZEngine::CreateDisplay(string title, string icon) { Uint32 flags; ImageData iconImg; if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_AUDIO) < 0) { LogError(FormatStr("SDL could not be Initialized: %s", SDL_GetError())); //CloseWindow(); } #ifdef USE_SDL_MIXER Mix_OpenAudio(mRate, AUDIO_S16SYS, mStereo?2:1, 4096); //Open Audio Stream (Stereo?2:1 is conditional for number of channels) #endif #ifdef USE_OPENGL_2D int rgb_size[3]; 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, 16 ); SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); flags = SDL_OPENGL; #else //!USE_OPENGL_2D SDL_VideoInfo *videoInfo = const_cast(SDL_GetVideoInfo()); flags = SDL_DOUBLEBUF|SDL_HWPALETTE; //check capabilities and use what we can// if(videoInfo->hw_available) flags |= SDL_HWSURFACE; else flags |= SDL_SWSURFACE; if(videoInfo->blit_hw) flags |= SDL_HWACCEL; #endif //USE_OPENGL_2D //Window Manager settings// 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.image,NULL); FreeImage(iconImg); } //create SDL screen and update settings based on returned screen// if(mFullscreen) flags |= SDL_FULLSCREEN; mScreen = SDL_SetVideoMode(mWidth, mHeight, mBPP, flags); mWidth = mScreen->w; mHeight = mScreen->h; mBPP = mScreen->format->BitsPerPixel; #ifdef USE_OPENGL_2D //OpenGL code from SDL project testgl.c// glViewport(0,0,mWidth,mHeight); glMatrixMode(GL_PROJECTION); glLoadIdentity(); 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(); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); #endif //USE_OPENGL_2D if(!mScreen) { LogError(FormatStr("Unable to set video mode %dx%d (%dBpp): %s",mWidth,mHeight,mBPP,SDL_GetError())); CloseDisplay(); } mKeyPressed = SDL_GetKeyState(NULL); #ifdef USE_SDL_TTF TTF_Init(); #endif mLastTime = mPausedTime = SDL_GetTicks(); mActive = true; } void ZEngine::CloseDisplay() { #ifdef USE_SDL_TTF TTF_Quit(); #endif #ifdef USE_SDL_MIXER Mix_CloseAudio(); #endif #ifdef USE_PHYSFS PHYSFS_deinit(); #endif SDL_Quit(); } SDL_Surface *ZEngine::Display() { return mScreen; } void ZEngine::UpdateScreen() { #ifdef USE_OPENGL_2D SDL_GL_SwapBuffers(); #else //!USE_OPENGL_2D SDL_Flip(mScreen); #endif //USE_OPENGL_2D mSecPerFrame = (GetTime()-mLastTime)/1000.0; mLastTime = GetTime(); } Uint32 ZEngine::MapColor(Uint8 r, Uint8 g, Uint8 b, Uint8 a) { return SDL_MapRGBA(mScreen->format,r,g,b,a); } void ZEngine::Clear(Uint32 color, SDL_Rect *rect) { SDL_FillRect(mScreen,rect,color); } void ZEngine::Delay(Uint32 milliseconds) { 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; } 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; } bool ZEngine::KeyIsPressed(SDLKey key) { return mKeyPressed[key] == 1; } void ZEngine::HideCursor() { SDL_ShowCursor(SDL_DISABLE); } void ZEngine::ShowCursor() { SDL_ShowCursor(SDL_ENABLE); } int ZEngine::MouseX() { return mMouseX; } int ZEngine::MouseY() { 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(); } else { mActive = mUnpauseOnActive = false; if(!mPaused) { mUnpauseOnActive = true; PauseTimer(); } else mUnpauseOnActive = false; } } break; case SDL_QUIT: mQuit = true; break; default: break; } } mKeyPressed = SDL_GetKeyState(NULL); //recommended but not needed (says Sam) if(mKeyPressed[SDLK_F4] && (mKeyPressed[SDLK_LALT] || mKeyPressed[SDLK_RALT])) 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 ImageData ZEngine::LoadImage(string filename) { ImageData img; //using physfs// #ifdef USE_PHYSFS SDL_RWops *rw; rw = PHYSFSRWOPS_openRead(filename.c_str()); if(!rw) LogError(FormatStr("PhysFS RWops failed: %s",SDL_GetError())); #ifdef USE_SDL_IMAGE img.image = IMG_Load_RW(rw,0); #else img.image = SDL_LoadBMP_RW(rw,0); #endif //USE_SDL_IMAGE SDL_FreeRW(rw); //end using physfs// //Just SDL// #else #ifdef USE_SDL_IMAGE img.image = IMG_Load(filename.c_str()); #else img.image = SDL_LoadBMP(filename.c_str()); #endif //USE_SDL_IMAGE #endif //USE_PHYSFS if(!img.image) { img.filename = FormatStr("LoadImage could not load %s.",filename.c_str()); LogError(img.filename); } else img.filename = filename; return img; } void ZEngine::FreeImage(ImageData &image) { if(image.image) { SDL_FreeSurface(image.image); image.image = NULL; image.filename = "free"; } } #ifdef USE_SDL_MIXER SoundData ZEngine::LoadSound(string filename) { SoundData snd; #ifdef USE_PHYSFS SDL_RWops *rw; rw = PHYSFSRWOPS_openRead(filename.c_str()); snd.sound = Mix_LoadWAV_RW(rw,0); SDL_FreeRW(rw); #else snd.sound = Mix_LoadWAV(filename.c_str()); #endif //USE_PHYSFS if(!snd.sound) { snd.filename = FormatStr("LoadSound could not load %s.",filename.c_str()); LogError(snd.filename); } else snd.filename = filename; return snd; } void ZEngine::FreeSound(SoundData &sound) { if(sound.sound) { Mix_FreeChunk(sound.sound); sound.sound = NULL; sound.filename = "free"; } } MusicData ZEngine::LoadMusic(string filename) { MusicData mus; //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 mus.music = Mix_LoadMUS(filename.c_str()); //#endif //USE_PHYSFS if(!mus.music) { mus.filename = FormatStr("LoadMusic could not load %s.",filename.c_str()); LogError(mus.filename); } else mus.filename = filename; return mus; } void ZEngine::FreeMusic(MusicData &music) { if(music.music) { Mix_FreeMusic(music.music); music.music = NULL; music.filename = "free"; } } #endif #ifdef USE_SDL_TTF FontData ZEngine::LoadFont(string filename, int size) { FontData fnt; //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 fnt.font = TTF_OpenFont(filename.c_str(),size); //#endif //USE_PHYSFS if(!fnt.font) { fnt.filename = FormatStr("LoadFont could not load %s.",filename.c_str()); LogError(fnt.filename); } else fnt.filename = filename; return fnt; } void ZEngine::FreeFont(FontData &font) { if(font.font) { TTF_CloseFont(font.font); font.font = NULL; font.filename = "free"; } } #endif int ZEngine::Width() { return mWidth; } int ZEngine::Height() { return mHeight; } int ZEngine::BPP() { return mBPP; } bool ZEngine::IsFullscreen() { return mFullscreen; } }