Skip to content

Instantly share code, notes, and snippets.

@icebreaker
Created October 19, 2011 06:42
Show Gist options
  • Select an option

  • Save icebreaker/1297627 to your computer and use it in GitHub Desktop.

Select an option

Save icebreaker/1297627 to your computer and use it in GitHub Desktop.
ATL style templating and inheritance with "no virtuals".
*.swp
cppsdl
/*
Sample: ATL style templating and inheritance with "no virtuals"
almost for free :)
Copyright (c) 2011, Mihail Szabolcs
Released into the public domain.
Compile & Run:
make; ./cppsdl
*/
#include <SDL.h>
struct RectS
{
short x, y;
unsigned short w, h;
};
template< typename T >
class WindowI
{
public:
void setTitle(const char *pTitle)
{
static_cast<T *>(this)->onSetTitle(pTitle);
}
bool setVideMode(int pWidth, int pHeight, int pBpp)
{
return static_cast<T *>(this)->onSetVideoMode(pWidth, pHeight, pBpp);
}
int exec(void)
{
T *self = static_cast<T *>(this);
bool done = false;
while(!done)
{
while(self->onPollMessages())
{
if(self->onProcessMessages())
{
done = true;
break;
}
}
self->onUpdate();
self->onDraw();
self->onSwapBuffers();
//
// sleep 10 ms
//
// Notes:
// in a production app, especially when "rendering"
// we should calculate the "delta" and sleep the
// necessary amount in order to synch up with our
// 'fixed' time-step (i.e => FPS, 1000 sec/30 fps = 33.33 ms) or such :)
//
self->onSleep(10);
}
return EXIT_SUCCESS;
}
void clear(unsigned short pR, unsigned short pG, unsigned short pB, unsigned short pA)
{
static_cast<T *>(this)->onClear(pR, pG, pB, pA);
}
void fill(RectS *pRect, unsigned short pR, unsigned short pG, unsigned short pB, unsigned short pA)
{
static_cast<T *>(this)->onFill(pRect, pR, pG, pB, pA);
}
protected:
bool onPollMessages(void)
{
return true;
}
bool onProcessMessages(void)
{
return true;
}
void onSetTitle(const char *pTitle)
{
// empty
}
bool onSetVideoMode(int pWidth, int pHeight, int pBpp)
{
return false;
}
void onUpdate(void)
{
// empty
}
void onDraw(void)
{
// empty
}
void onSwapBuffers(void)
{
// empty
}
void onSleep(unsigned int pMs)
{
// empty
}
void onClear(unsigned short pR, unsigned short pG, unsigned short pB, unsigned short pA)
{
// empty
}
void onFill(RectS *pRect, unsigned short pR, unsigned short pG, unsigned short pB, unsigned short pA)
{
// empty
}
};
template< typename T >
class SDLWindowC: public WindowI< SDLWindowC<T> >
{
friend class WindowI< SDLWindowC<T> >;
protected:
SDLWindowC(void) : mScreen(NULL)
{
SDL_Init(SDL_INIT_VIDEO);
}
~SDLWindowC(void)
{
SDL_Quit();
}
bool onSetVideoMode(int pWidth, int pHeight, int pBpp)
{
mScreen = SDL_SetVideoMode(pWidth, pHeight, pBpp, SDL_SWSURFACE);
return (mScreen != NULL);
}
bool onPollMessages(void)
{
return SDL_PollEvent(&mEvent) == 1;
}
bool onProcessMessages(void)
{
return mEvent.type == SDL_QUIT;
}
void onSetTitle(const char *pTitle)
{
SDL_WM_SetCaption(pTitle, pTitle);
}
void onSwapBuffers(void)
{
SDL_Flip(mScreen);
}
void onSleep(unsigned int pMs)
{
SDL_Delay(pMs);
}
void onClear(unsigned short pR, unsigned short pG, unsigned short pB, unsigned short pA)
{
SDL_FillRect(mScreen, &mScreen->clip_rect, SDL_MapRGBA(mScreen->format, pR, pG, pB, pA));
}
void onDraw(void)
{
return static_cast<T *>(this)->onDraw();
}
void onUpdate(void)
{
return static_cast<T *>(this)->onUpdate();
}
void onFill(RectS *pRect, unsigned short pR, unsigned short pG, unsigned short pB, unsigned short pA)
{
// FIXME: memcpy
SDL_Rect rect;
rect.x = pRect->x;
rect.y = pRect->y;
rect.w = pRect->w;
rect.h = pRect->h;
SDL_FillRect(mScreen, &rect, SDL_MapRGBA(mScreen->format, pR, pG, pB, pA));
}
private:
SDL_Surface *mScreen;
SDL_Event mEvent;
};
class DemoC : public SDLWindowC<DemoC>
{
friend class SDLWindowC<DemoC>;
public:
DemoC(void)
{
mRect.x = 100;
mRect.y = 100;
mRect.w = 100;
mRect.h = 200;
mRnd = 0;
}
protected:
void onDraw(void)
{
clear(120, 55, 23, 255);
fill(&mRect, 200, 120, 200, 255);
}
void onUpdate(void)
{
if(++mRnd > 50)
{
mRect.x = rand() % 200;
mRect.y = rand() % 200;
mRnd = 0;
}
}
private:
RectS mRect;
unsigned int mRnd;
};
int main(int argc, char *argv[])
{
DemoC demo;
if(demo.setVideMode(800, 600, 32))
{
demo.setTitle("SDL Demo");
return demo.exec();
}
return 0;
}
SDL=`sdl-config --cflags --libs`
all:
g++ cppsdl.cpp -Wall -o cppsdl $(SDL)
clean:
rm -f cppsdl
distclean: clean
realclean: clean
.PHONY: all clean distclean realclean
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment