/ Published in: C++
Expand |
Embed | Plain Text
//cspritebashe.h #ifndef __CSPRITEBASE_H__ #define __CSPRITEBASE_H__ #include "SDL.h" struct CSpriteFrame //структура описывает каждый кадр анимации { //Каждый кадр состоит из: SDL_Surface *image; //поверхности (surface) с изображением int pause; //значения паузы (в миллисекундах) между показами кадров }; //Класс CSpriteBase является базой для спрайта //В нем хранятся все изображения кадров и некоторые другие данные class CSpriteBase //Класс CSpriteBase является базой для спрайта { public: //Ядро класса - функция init //принимает параметр - имя папки с изображениями спрайта и файлом info int init(char* dir); //инициализирует класс и загружает все изображения CSpriteFrame *mAnim; //указатель на структуру CSpriteFrame(массив) int mBuilt; //индикатор того, что класс создан int mNumframes; //количество кадров int mW, mH; //ширина и высотаспрайта }; #endif //__CSPRITEBASE_H__ //cspritebase.cxx #include <stdio.h> #include <stdlib.h> #include "cspritebase.h" #include <string.h> //------------------------------------------------- int CSpriteBase::init(char* dir) { //три массива типа char-временные хранилища для кое-каких данных char buffer[255]; char filename[255]; char name[255]; int pause=0, r=0, g=0, b=0; //4 временных переменных FILE *fp; //указатель типа FILE //поместим в строку имя и путь файла и попытаемся его открыть sprintf(filename,"%s/info",dir); //печатает не на экран, а в переменную if((fp=fopen(filename,"r"))==NULL) { printf("Error opening file %s\n\n",filename); return -1; } //считаем первую строчку в буфер - "FILE: количество кадров" fgets(buffer,255,fp); //Достанем это количество кадров из буфера //поместим количество кадров в член класса mNumframes sscanf(buffer,"FILES: %d",&mNumframes); //выделим память для массива CSpriteFrame mAnim = new CSpriteFrame[mNumframes]; mBuilt = 1; //класс инициализирован //Заведем переменную-счетчик, чтобы считать загруженные картинки int count = 0; //пока не достигнем конца файла (EOF) и пока count < mNumframes while(!feof(fp) && count<mNumframes) { fgets(buffer, 255, fp); //считывать по одной строке из файла if ( buffer[0]!='#' && buffer[0]!='\r' && buffer[0]!='\n' && buffer[0]!='\0' && strlen(buffer)!=0 ) //Если строка - комментарий, то не считаем ее. { //считаем RGB, паузу и имя файла с картинкой кадра sscanf(buffer,"%s %d %d %d %d",name,&pause,&r,&g,&b); sprintf(filename,"%s/%s",dir,name); SDL_Surface *temp; //создадим временную поверхность SDL_Surface if((temp=SDL_LoadBMP(filename))==NULL) //загрузим в нее картинку return -1; //проверим на прозрачность: if(r>=0) //если значение R "-", то прозрачность не ставится. SDL_SetColorKey ( temp, SDL_SRCCOLORKEY, SDL_MapRGB(temp->format,r,g,b) ); /* Присвоим соответствующему элементу массива из CSpriteFrame загруженную картинку с помощью SDL_DisplayFormat. Эта функция возвращает SDL_Surface, но в том же формате, что и экранная поверхность. Это нужно для увеличения скорости отображения, т.к. не тратится время на преобразования форматов каждый раз.*/ mAnim[count].image = SDL_DisplayFormat(temp); //уничтожим временную поверхность, чтобы не создавать утечки памяти SDL_FreeSurface(temp); //присвоим элементу pause массива mAnim значение из файла info mAnim[count].pause = pause; //Ширину и высоту сделаем таких же размеров, как у первого кадра if(!mW) mW = mAnim[count].image->w; if(!mH) mH = mAnim[count].image->h; count++; } } fclose(fp); //закроем файл return 0; //конец CSpriteBase::init } //------------------------------------------------- //csprite.cxx #include <stdio.h> #include "csprite.h" //--------------------------------------------- int CSprite::init(CSpriteBase *base, SDL_Surface *screen) { mSpriteBase = base; if(mSpriteBase->mBuilt) { if(mSpriteBase->mNumframes>1) mAnimating=1; mBackreplacement = SDL_DisplayFormat(mSpriteBase->mAnim[0].image); } mScreen = screen; return 0; } //--------------------------------------------- void CSprite::clearBG() { if(mDrawn==1) { SDL_Rect dest; dest.x = mOldX; dest.y = mOldY; dest.w = mSpriteBase->mW; dest.h = mSpriteBase->mH; SDL_BlitSurface(mBackreplacement, NULL, mScreen, &dest); } } //--------------------------------------------- void CSprite::updateBG() { SDL_Rect srcrect; srcrect.w = mSpriteBase->mW; srcrect.h = mSpriteBase->mH; srcrect.x = mX; srcrect.y = mY; mOldX=mX; mOldY=mY; SDL_BlitSurface(mScreen, &srcrect, mBackreplacement, NULL); } //--------------------------------------------- void CSprite::draw() { if(mAnimating == 1) { if(mLastupdate+mSpriteBase->mAnim[mFrame].pause*mSpeed < SDL_GetTicks()) { mFrame++; if(mFrame>mSpriteBase->mNumframes-1) mFrame=0; mLastupdate = SDL_GetTicks(); } } if(mDrawn==0) mDrawn=1; SDL_Rect dest; dest.x = mX; dest.y = mY; SDL_BlitSurface(mSpriteBase->mAnim[mFrame].image, NULL, mScreen, &dest); } //csprite.h #ifndef __CSPRITE_H__ #define __CSPRITE_H__ #include "SDL.h" #include "cspritebase.h" class CSprite //описывает непосредственно сам спрайт { public: CSprite(){} ~CSprite(){} /*Для иницифлизации класса служит все та же функция init. Эта функция принимант два параметра: указатель на экземпляр класса CSpriteBase (мы передаем именно указатель, чтобы не загромождать память) и указатель на поверхность SDL_Surface*/ int init(CSpriteBase *base, SDL_Surface *screen); //используются для отрисовки спрайта на экране void draw(); void clearBG(); void updateBG(); //изменяет значение переменой mFrame, которая задает следующий кадр анимации void setFrame(int nr) { mFrame = nr; } int getFrame() { return mFrame; } //возвращает текущий отображаемый кадр /*Далее функции setSpeed() и getSpeed(). Они работают с переменной mSpeed, которая задает скорость отображения спрайтов. Эта скорость умножается с паузой, то есть это коэффициент. Если mSpeed равна 2, то скорость будет в 2 раза медленнее, а если зададим значение 0,5 то скорость будет в два раза быстрее. */ void setSpeed(float nr) { mSpeed = nr; } float getSpeed() { return mSpeed; } void toggleAnim() { mAnimating = !mAnimating; } void startAnim() { mAnimating = 1; } void stopAnim() {mAnimating = 0; } void rewind() {mFrame = 0; } void xadd(int nr) { mX+=nr; } void yadd(int nr) { mY+=nr; } void xset(int nr) { mX=nr; } void yset(int nr) { mY=nr; } void set(int xx, int yy) { mX=xx; mY=yy; } private: int mFrame; int mX, mY, mOldX, mOldY; int mAnimating; int mDrawn; float mSpeed; long mLastupdate; CSpriteBase *mSpriteBase; SDL_Surface *mBackreplacement; SDL_Surface *mScreen; }; #endif //__CSPRITE_H__ //ex3.cxx #include <stdio.h> #include <stdlib.h> #include "csprite.h" #include "cspritebase.h" #include "SDL.h" SDL_Surface* ImageLoad(char *file); int InitImages(); void DrawIMG(SDL_Surface *img, int x, int y); void DrawBG(void); void DrawScene(void); SDL_Surface *screen, *back; CSpriteBase frog2base; CSpriteBase frog1base; CSprite frog; CSprite frog1; CSprite frog2; //----------------------------------------- int main(int argc, char *argv[]){ Uint8* keys; if ( SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO) < 0 ){ printf("Unable to init SDL: %s\n", SDL_GetError()); exit(1); } atexit(SDL_Quit); SDL_WM_SetCaption("SDL Gfx Example #3","ex3"); SDL_WM_SetIcon(SDL_LoadBMP("icon.bmp"), NULL); screen=SDL_SetVideoMode(800,600,32,SDL_HWSURFACE|SDL_DOUBLEBUF); //|SDL_FULLSCREEN if ( screen == NULL ){ printf("Unable to set 800x600 video: %s\n", SDL_GetError()); exit(1); } frog2base.init("data/frog2"); frog1base.init("data/frog1"); frog.init(&frog2base,screen); frog.set(250,400); frog.setSpeed(0.8); frog1.init(&frog1base,screen); frog1.set(350,300); frog1.setSpeed(3.5); frog2.init(&frog1base,screen); frog2.set(150,250); frog2.setSpeed(4.5); SDL_ShowCursor(0); InitImages(); DrawBG(); int done=0; while(done == 0){ SDL_Event event; while ( SDL_PollEvent(&event) ){ if ( event.type == SDL_QUIT ){ done = 1; } if ( event.type == SDL_KEYDOWN ){ if ( event.key.keysym.sym == SDLK_ESCAPE ){ done = 1; } if ( event.key.keysym.sym == SDLK_SPACE ){ frog.toggleAnim(); } } } keys = SDL_GetKeyState(NULL); if(keys[SDLK_UP]){ frog.yadd(-2);} if(keys[SDLK_DOWN]){ frog.yadd(2);} if(keys[SDLK_LEFT]){ frog.xadd(-2);} if(keys[SDLK_RIGHT]){ frog.xadd(2);} DrawScene(); } return 0; } //----------------------------------------- SDL_Surface* ImageLoad(char *file){ SDL_Surface *temp1, *temp2; temp1 = SDL_LoadBMP(file); temp2 = SDL_DisplayFormat(temp1); SDL_FreeSurface(temp1); return temp2; } //----------------------------------------- int InitImages(){ back = ImageLoad("data/bg.bmp"); return 0; } //----------------------------------------- void DrawIMG(SDL_Surface *img, int x, int y){ SDL_Rect dest; dest.x = x; dest.y = y; SDL_BlitSurface(img, NULL, screen, &dest); } //----------------------------------------- void DrawBG(){ DrawIMG(back, 0, 0); } //----------------------------------------- void DrawScene(void){ frog.clearBG(); frog1.clearBG(); frog2.clearBG(); frog.updateBG(); frog1.updateBG(); frog2.updateBG(); frog.draw(); frog1.draw(); frog2.draw(); SDL_Flip(screen); } //-----------------------------------------
You need to login to post a comment.
