Posted By

ozkriff on 10/05/08


Tagged


Versions (?)

lesson 3/sdl


 / Published in: C++
 

  1. //cspritebashe.h
  2.  
  3. #ifndef __CSPRITEBASE_H__
  4. #define __CSPRITEBASE_H__
  5.  
  6. #include "SDL.h"
  7.  
  8. struct CSpriteFrame //структура описывает каждый кадр анимации
  9. {
  10. //Каждый кадр состоит из:
  11.  
  12. SDL_Surface *image; //поверхности (surface) с изображением
  13. int pause; //значения паузы (в миллисекундах) между показами кадров
  14. };
  15.  
  16.  
  17. //Класс CSpriteBase является базой для спрайта
  18. //В нем хранятся все изображения кадров и некоторые другие данные
  19.  
  20. class CSpriteBase //Класс CSpriteBase является базой для спрайта
  21. {
  22. public:
  23. //Ядро класса - функция init
  24. //принимает параметр - имя папки с изображениями спрайта и файлом info
  25. int init(char* dir); //инициализирует класс и загружает все изображения
  26.  
  27. CSpriteFrame *mAnim; //указатель на структуру CSpriteFrame(массив)
  28. int mBuilt; //индикатор того, что класс создан
  29. int mNumframes; //количество кадров
  30. int mW, mH; //ширина и высотаспрайта
  31. };
  32.  
  33. #endif //__CSPRITEBASE_H__
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43. //cspritebase.cxx
  44.  
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47.  
  48. #include "cspritebase.h"
  49. #include <string.h>
  50.  
  51. //-------------------------------------------------
  52. int CSpriteBase::init(char* dir)
  53. {
  54.  
  55. //три массива типа char-временные хранилища для кое-каких данных
  56. char buffer[255];
  57. char filename[255];
  58. char name[255];
  59. int pause=0, r=0, g=0, b=0; //4 временных переменных
  60. FILE *fp; //указатель типа FILE
  61.  
  62. //поместим в строку имя и путь файла и попытаемся его открыть
  63. sprintf(filename,"%s/info",dir); //печатает не на экран, а в переменную
  64. if((fp=fopen(filename,"r"))==NULL)
  65. {
  66. printf("Error opening file %s\n\n",filename);
  67. return -1;
  68. }
  69.  
  70. //считаем первую строчку в буфер - "FILE: количество кадров"
  71. fgets(buffer,255,fp); //Достанем это количество кадров из буфера
  72. //поместим количество кадров в член класса mNumframes
  73. sscanf(buffer,"FILES: %d",&mNumframes);
  74. //выделим память для массива CSpriteFrame
  75. mAnim = new CSpriteFrame[mNumframes];
  76.  
  77. mBuilt = 1; //класс инициализирован
  78. //Заведем переменную-счетчик, чтобы считать загруженные картинки
  79. int count = 0;
  80.  
  81. //пока не достигнем конца файла (EOF) и пока count < mNumframes
  82. while(!feof(fp) && count<mNumframes)
  83. {
  84. fgets(buffer, 255, fp); //считывать по одной строке из файла
  85. if
  86. (
  87. buffer[0]!='#' &&
  88. buffer[0]!='\r' &&
  89. buffer[0]!='\n' &&
  90. buffer[0]!='\0' &&
  91. strlen(buffer)!=0
  92. ) //Если строка - комментарий, то не считаем ее.
  93. {
  94. //считаем RGB, паузу и имя файла с картинкой кадра
  95. sscanf(buffer,"%s %d %d %d %d",name,&pause,&r,&g,&b);
  96. sprintf(filename,"%s/%s",dir,name);
  97.  
  98. SDL_Surface *temp; //создадим временную поверхность SDL_Surface
  99. if((temp=SDL_LoadBMP(filename))==NULL) //загрузим в нее картинку
  100. return -1;
  101.  
  102. //проверим на прозрачность:
  103. if(r>=0) //если значение R "-", то прозрачность не ставится.
  104. SDL_SetColorKey
  105. (
  106. temp,
  107. SDL_SRCCOLORKEY,
  108. SDL_MapRGB(temp->format,r,g,b)
  109. );
  110.  
  111. /* Присвоим соответствующему элементу массива из CSpriteFrame
  112. загруженную картинку с помощью SDL_DisplayFormat. Эта функция
  113. возвращает SDL_Surface, но в том же формате, что и экранная
  114. поверхность. Это нужно для увеличения скорости отображения,
  115. т.к. не тратится время на преобразования форматов каждый раз.*/
  116. mAnim[count].image = SDL_DisplayFormat(temp);
  117.  
  118. //уничтожим временную поверхность, чтобы не создавать утечки памяти
  119. SDL_FreeSurface(temp);
  120.  
  121. //присвоим элементу pause массива mAnim значение из файла info
  122. mAnim[count].pause = pause;
  123. //Ширину и высоту сделаем таких же размеров, как у первого кадра
  124. if(!mW)
  125. mW = mAnim[count].image->w;
  126. if(!mH)
  127. mH = mAnim[count].image->h;
  128.  
  129. count++;
  130. }
  131. }
  132.  
  133. fclose(fp); //закроем файл
  134. return 0; //конец CSpriteBase::init
  135.  
  136. }
  137.  
  138. //-------------------------------------------------
  139.  
  140.  
  141.  
  142.  
  143.  
  144.  
  145.  
  146. //csprite.cxx
  147.  
  148.  
  149. #include <stdio.h>
  150.  
  151. #include "csprite.h"
  152.  
  153. //---------------------------------------------
  154. int CSprite::init(CSpriteBase *base, SDL_Surface *screen)
  155. {
  156. mSpriteBase = base;
  157. if(mSpriteBase->mBuilt)
  158. {
  159. if(mSpriteBase->mNumframes>1) mAnimating=1;
  160. mBackreplacement = SDL_DisplayFormat(mSpriteBase->mAnim[0].image);
  161. }
  162. mScreen = screen;
  163. return 0;
  164. }
  165.  
  166. //---------------------------------------------
  167. void CSprite::clearBG()
  168. {
  169. if(mDrawn==1)
  170. {
  171. SDL_Rect dest;
  172. dest.x = mOldX;
  173. dest.y = mOldY;
  174. dest.w = mSpriteBase->mW;
  175. dest.h = mSpriteBase->mH;
  176. SDL_BlitSurface(mBackreplacement, NULL, mScreen, &dest);
  177. }
  178. }
  179.  
  180. //---------------------------------------------
  181. void CSprite::updateBG()
  182. {
  183. SDL_Rect srcrect;
  184. srcrect.w = mSpriteBase->mW;
  185. srcrect.h = mSpriteBase->mH;
  186. srcrect.x = mX;
  187. srcrect.y = mY;
  188. mOldX=mX;
  189. mOldY=mY;
  190. SDL_BlitSurface(mScreen, &srcrect, mBackreplacement, NULL);
  191. }
  192.  
  193. //---------------------------------------------
  194. void CSprite::draw()
  195. {
  196. if(mAnimating == 1)
  197. {
  198. if(mLastupdate+mSpriteBase->mAnim[mFrame].pause*mSpeed < SDL_GetTicks())
  199. {
  200. mFrame++;
  201. if(mFrame>mSpriteBase->mNumframes-1) mFrame=0;
  202. mLastupdate = SDL_GetTicks();
  203. }
  204. }
  205.  
  206. if(mDrawn==0) mDrawn=1;
  207.  
  208. SDL_Rect dest;
  209. dest.x = mX; dest.y = mY;
  210. SDL_BlitSurface(mSpriteBase->mAnim[mFrame].image, NULL, mScreen, &dest);
  211. }
  212.  
  213.  
  214.  
  215.  
  216.  
  217.  
  218. //csprite.h
  219.  
  220. #ifndef __CSPRITE_H__
  221. #define __CSPRITE_H__
  222.  
  223. #include "SDL.h"
  224. #include "cspritebase.h"
  225.  
  226. class CSprite //описывает непосредственно сам спрайт
  227. {
  228. public:
  229. CSprite(){}
  230. ~CSprite(){}
  231.  
  232.  
  233. /*Для иницифлизации класса служит все та же функция init. Эта функция
  234.   принимант два параметра: указатель на экземпляр класса CSpriteBase
  235.   (мы передаем именно указатель, чтобы не загромождать память)
  236.   и указатель на поверхность SDL_Surface*/
  237. int init(CSpriteBase *base, SDL_Surface *screen);
  238.  
  239. //используются для отрисовки спрайта на экране
  240. void draw();
  241. void clearBG();
  242. void updateBG();
  243.  
  244. //изменяет значение переменой mFrame, которая задает следующий кадр анимации
  245. void setFrame(int nr) { mFrame = nr; }
  246. int getFrame() { return mFrame; } //возвращает текущий отображаемый кадр
  247.  
  248. /*Далее функции setSpeed() и getSpeed(). Они работают с переменной mSpeed,
  249.   которая задает скорость отображения спрайтов. Эта скорость умножается
  250.   с паузой, то есть это коэффициент. Если mSpeed равна 2, то скорость
  251.   будет в 2 раза медленнее, а если зададим значение 0,5 то скорость будет
  252.   в два раза быстрее. */
  253. void setSpeed(float nr) { mSpeed = nr; }
  254. float getSpeed() { return mSpeed; }
  255.  
  256. void toggleAnim() { mAnimating = !mAnimating; }
  257. void startAnim() { mAnimating = 1; }
  258. void stopAnim() {mAnimating = 0; }
  259. void rewind() {mFrame = 0; }
  260.  
  261. void xadd(int nr) { mX+=nr; }
  262. void yadd(int nr) { mY+=nr; }
  263. void xset(int nr) { mX=nr; }
  264. void yset(int nr) { mY=nr; }
  265. void set(int xx, int yy) { mX=xx; mY=yy; }
  266.  
  267. private:
  268. int mFrame;
  269. int mX, mY, mOldX, mOldY;
  270. int mAnimating;
  271. int mDrawn;
  272. float mSpeed;
  273. long mLastupdate;
  274. CSpriteBase *mSpriteBase;
  275. SDL_Surface *mBackreplacement;
  276. SDL_Surface *mScreen;
  277. };
  278.  
  279. #endif //__CSPRITE_H__
  280.  
  281.  
  282.  
  283. //ex3.cxx
  284.  
  285. #include <stdio.h>
  286. #include <stdlib.h>
  287.  
  288. #include "csprite.h"
  289. #include "cspritebase.h"
  290.  
  291. #include "SDL.h"
  292.  
  293.  
  294. SDL_Surface* ImageLoad(char *file);
  295. int InitImages();
  296. void DrawIMG(SDL_Surface *img, int x, int y);
  297. void DrawBG(void);
  298. void DrawScene(void);
  299.  
  300. SDL_Surface *screen, *back;
  301. CSpriteBase frog2base;
  302. CSpriteBase frog1base;
  303. CSprite frog;
  304. CSprite frog1;
  305. CSprite frog2;
  306.  
  307.  
  308. //-----------------------------------------
  309. int main(int argc, char *argv[]){
  310.  
  311. Uint8* keys;
  312.  
  313. if ( SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO) < 0 ){
  314. printf("Unable to init SDL: %s\n", SDL_GetError());
  315. exit(1);
  316. }
  317.  
  318. atexit(SDL_Quit);
  319.  
  320. SDL_WM_SetCaption("SDL Gfx Example #3","ex3");
  321. SDL_WM_SetIcon(SDL_LoadBMP("icon.bmp"), NULL);
  322.  
  323. screen=SDL_SetVideoMode(800,600,32,SDL_HWSURFACE|SDL_DOUBLEBUF); //|SDL_FULLSCREEN
  324. if ( screen == NULL ){
  325. printf("Unable to set 800x600 video: %s\n", SDL_GetError());
  326. exit(1);
  327. }
  328.  
  329. frog2base.init("data/frog2");
  330. frog1base.init("data/frog1");
  331.  
  332. frog.init(&frog2base,screen);
  333. frog.set(250,400);
  334. frog.setSpeed(0.8);
  335.  
  336. frog1.init(&frog1base,screen);
  337. frog1.set(350,300);
  338. frog1.setSpeed(3.5);
  339.  
  340. frog2.init(&frog1base,screen);
  341. frog2.set(150,250);
  342. frog2.setSpeed(4.5);
  343.  
  344.  
  345. SDL_ShowCursor(0);
  346.  
  347. InitImages();
  348. DrawBG();
  349.  
  350. int done=0;
  351. while(done == 0){
  352.  
  353. SDL_Event event;
  354.  
  355. while ( SDL_PollEvent(&event) ){
  356. if ( event.type == SDL_QUIT ){ done = 1; }
  357. if ( event.type == SDL_KEYDOWN ){
  358. if ( event.key.keysym.sym == SDLK_ESCAPE ){ done = 1; }
  359. if ( event.key.keysym.sym == SDLK_SPACE ){ frog.toggleAnim(); }
  360. }
  361. }
  362.  
  363. keys = SDL_GetKeyState(NULL);
  364. if(keys[SDLK_UP]){ frog.yadd(-2);}
  365. if(keys[SDLK_DOWN]){ frog.yadd(2);}
  366. if(keys[SDLK_LEFT]){ frog.xadd(-2);}
  367. if(keys[SDLK_RIGHT]){ frog.xadd(2);}
  368.  
  369. DrawScene();
  370. }
  371.  
  372. return 0;
  373.  
  374. }
  375.  
  376. //-----------------------------------------
  377. SDL_Surface* ImageLoad(char *file){
  378.  
  379. SDL_Surface *temp1, *temp2;
  380. temp1 = SDL_LoadBMP(file);
  381. temp2 = SDL_DisplayFormat(temp1);
  382. SDL_FreeSurface(temp1);
  383.  
  384. return temp2;
  385.  
  386. }
  387.  
  388. //-----------------------------------------
  389. int InitImages(){
  390.  
  391. back = ImageLoad("data/bg.bmp");
  392. return 0;
  393.  
  394. }
  395.  
  396. //-----------------------------------------
  397. void DrawIMG(SDL_Surface *img, int x, int y){
  398.  
  399. SDL_Rect dest;
  400. dest.x = x;
  401. dest.y = y;
  402.  
  403. SDL_BlitSurface(img, NULL, screen, &dest);
  404.  
  405. }
  406.  
  407. //-----------------------------------------
  408. void DrawBG(){
  409.  
  410. DrawIMG(back, 0, 0);
  411.  
  412. }
  413.  
  414. //-----------------------------------------
  415. void DrawScene(void){
  416.  
  417. frog.clearBG();
  418. frog1.clearBG();
  419. frog2.clearBG();
  420.  
  421. frog.updateBG();
  422. frog1.updateBG();
  423. frog2.updateBG();
  424.  
  425. frog.draw();
  426. frog1.draw();
  427. frog2.draw();
  428.  
  429. SDL_Flip(screen);
  430.  
  431. }
  432.  
  433. //-----------------------------------------

Report this snippet  

You need to login to post a comment.