Advertisement
blazinghorizon

Untitled

Dec 15th, 2019
124
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.41 KB | None | 0 0
  1. /**
  2. * spacexplore.c -- прототип игры управления звездолетом
  3. *
  4. * Copyright (c) 2019, Nikita Semenov <ndsemeno@petrsu.ru>
  5. *
  6. * This code is licensed under a MIT-style license.
  7. */
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <time.h>
  13. #include <SDL.h>
  14. #include <SDL_ttf.h>
  15.  
  16. /* Скорости корабля */
  17. #define VXD 6
  18. #define VYD 6
  19.  
  20. typedef struct _gamescreen { // экран
  21. SDL_Surface* sprite;
  22. } gamescreen;
  23.  
  24. typedef struct _gamebackground { // фон
  25. SDL_Surface* sprite;
  26. } gamebackground;
  27.  
  28. typedef struct _spaceship { // корабль
  29. SDL_Surface* sprite;
  30. int x;
  31. int y;
  32. int vx;
  33. int vy;
  34. } spaceship;
  35.  
  36. typedef struct _obstacle { // астероиды
  37. int vx[8];
  38. int vy[8];
  39. int x[8];
  40. int y[8];
  41. int if_exist[8];
  42. int n_existing;
  43. } obstacle;
  44.  
  45. typedef struct _gameresources { // ресурсы
  46. SDL_Surface* asteroid;
  47. SDL_Surface* bitcoin;
  48. int x;
  49. int y;
  50. int if_exist;
  51. int bitcoin_count;
  52. int flag;
  53. } gameresources;
  54.  
  55.  
  56. typedef struct _game { // состояние игры
  57. gamescreen* screen;
  58. spaceship* ship;
  59. gameresources* resources;
  60. gamebackground* background;
  61. obstacle* obstacles;
  62. TTF_Font* font;
  63. int timer;
  64. } game;
  65.  
  66. game* init();
  67.  
  68. void run(game* g);
  69.  
  70. void draw(game* g);
  71.  
  72. void show_counter(game* g, const int counter, const int mode);
  73.  
  74. void show_mission_status(game* g);
  75.  
  76. void spawn_asteroids(game* g);
  77.  
  78.  
  79. int main()
  80. {
  81. game* g = init(); // инициализируем игру
  82.  
  83. run(g); // запускаем цикл обработки
  84.  
  85. return 0;
  86. }
  87.  
  88.  
  89. game* init()
  90. {
  91. /* Создаем структуру представления состояния игры */
  92. game* g;
  93. g = (game*)malloc(sizeof(game));
  94. if (g == NULL) {
  95. fprintf(stderr, "Not enough memory!");
  96. exit(EXIT_FAILURE);
  97. }
  98.  
  99. /* Инициализируем библиотеку SDL, используем только видеоподсистему */
  100. if (SDL_Init(SDL_INIT_VIDEO) < 0) {
  101. fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
  102. exit(EXIT_FAILURE);
  103. }
  104.  
  105. /* Регистрируем обработчик завершения программы */
  106. atexit(SDL_Quit);
  107.  
  108. /* Инициализируем библиотеку SDL_ttf и загружаем шрифт */
  109. TTF_Init();
  110. g->font = TTF_OpenFont("AbrilFatface-Regular.ttf", 44);
  111.  
  112. /* Выделяем память для структуры представления экрана */
  113. g->screen = (gamescreen*)malloc(sizeof(gamescreen));
  114. if (g->screen == NULL) {
  115. fprintf(stderr, "Not enough memory!");
  116. exit(EXIT_FAILURE);
  117. }
  118.  
  119. /* Инициализируем видеорежим */
  120. g->screen->sprite = SDL_SetVideoMode(1024, 768, 0, SDL_HWSURFACE | SDL_DOUBLEBUF);
  121. if (g->screen->sprite == NULL) {
  122. fprintf(stderr, "Couldn't set video mode: %s\n", SDL_GetError());
  123. exit(EXIT_FAILURE);
  124. }
  125.  
  126. /* Инициализируем фон*/
  127. g->background = (gamebackground*)malloc(sizeof(gamebackground));
  128. if (g->background == NULL) {
  129. fprintf(stderr, "Not enough memory!");
  130. exit(EXIT_FAILURE);
  131. }
  132. g->background->sprite = SDL_LoadBMP("kosmos.bmp");
  133. if (g->background->sprite == NULL) {
  134. fprintf(stderr, "Couldn't load a bitmap: %s\n", SDL_GetError());
  135. exit(EXIT_FAILURE);
  136. }
  137.  
  138. /* Инициализируем ресурсы */
  139. g->resources = (gameresources*)malloc(sizeof(gameresources));
  140. if (g->resources == NULL) {
  141. fprintf(stderr, "Not enough memory!");
  142. exit(EXIT_FAILURE);
  143. }
  144. g->resources->bitcoin = SDL_LoadBMP("bitcoin.bmp");
  145. if (g->resources->bitcoin == NULL) {
  146. fprintf(stderr, "Couldn't load a bitmap: %s\n", SDL_GetError());
  147. exit(EXIT_FAILURE);
  148. }
  149. g->resources->asteroid = SDL_LoadBMP("asteroid.bmp");
  150. if (g->resources->asteroid == NULL) {
  151. fprintf(stderr, "Couldn't load a bitmap: %s\n", SDL_GetError());
  152. exit(EXIT_FAILURE);
  153. }
  154.  
  155. /* Инициализируем астероиды */
  156. g->obstacles = (obstacle*)malloc(sizeof(obstacle));
  157. if (g->obstacles == NULL) {
  158. fprintf(stderr, "Not enough memory!");
  159. exit(EXIT_FAILURE);
  160. }
  161.  
  162. /* Выделяем память для структуры представления корабля */
  163. g->ship = (spaceship*)malloc(sizeof(spaceship));
  164. if (g->ship == NULL) {
  165. fprintf(stderr, "Not enough memory!");
  166. exit(EXIT_FAILURE);
  167. }
  168. g->ship->sprite = SDL_LoadBMP("ship.bmp");
  169. if (g->ship->sprite == NULL) {
  170. fprintf(stderr, "Couldn't load a bitmap: %s\n", SDL_GetError());
  171. exit(EXIT_FAILURE);
  172. }
  173.  
  174. /* Задаем начальное положение кораблю */
  175. g->ship->x = g->screen->sprite->w / 2 - g->ship->sprite->w / 2;
  176. g->ship->y = g->screen->sprite->h - g->ship->sprite->h;
  177.  
  178. /* Задание начальных значений для счетчиков и флагов */
  179. g->resources->bitcoin_count = -1;
  180. g->resources->if_exist = 0;
  181. g->resources->flag = 0;
  182. g->timer = 0;
  183.  
  184. /* Устанавливаем заголовок окна */
  185. SDL_WM_SetCaption("Space explore", NULL);
  186.  
  187. return g;
  188. }
  189.  
  190.  
  191. void run(game* g)
  192. {
  193. int done = 0; // Флажок выхода
  194. unsigned int start_time = SDL_GetTicks();
  195. /* Продолжаем выполнение, пока не поднят флажок */
  196. while (!done) {
  197. /* Структура описания события */
  198. SDL_Event event;
  199.  
  200. /* Извлекаем и обрабатываем все доступные события */
  201. while (SDL_PollEvent(&event)) {
  202. switch (event.type) {
  203. /* Если клавишу нажали */
  204. case SDL_KEYDOWN:
  205. switch (event.key.keysym.sym) {
  206. case SDLK_LEFT:
  207. g->ship->vx += -VXD;
  208. break;
  209. case SDLK_RIGHT:
  210. g->ship->vx += VXD;
  211. break;
  212.  
  213. case SDLK_UP:
  214. g->ship->vy += -VYD;
  215. break;
  216. case SDLK_DOWN:
  217. g->ship->vy += VYD;
  218. break;
  219. case SDLK_ESCAPE:
  220. done = 1;
  221. break;
  222. }
  223. break;
  224. /* Если клавишу отпустили */
  225. case SDL_KEYUP:
  226. switch (event.key.keysym.sym) {
  227. case SDLK_LEFT:
  228. g->ship->vx += VXD;
  229. break;
  230. case SDLK_RIGHT:
  231. g->ship->vx += -VXD;
  232. break;
  233. case SDLK_UP:
  234. g->ship->vy += VYD;
  235. break;
  236. case SDLK_DOWN:
  237. g->ship->vy += -VYD;
  238. break;
  239. default:
  240. break;
  241. }
  242. break;
  243. /* Если закрыли окно */
  244. case SDL_QUIT:
  245. done = 1;
  246. break;
  247. default:
  248. break;
  249. }
  250. }
  251. /* Верхняя граница корабля */
  252. if (g->ship->x + g->ship->vx >= 0 && g->ship->x + g->ship->vx <= g->screen->sprite->w - g->ship->sprite->w)
  253. g->ship->x += g->ship->vx;
  254. /* Нижняя граница корабля */
  255. if (g->ship->y + g->ship->vy >= g->screen->sprite->h / 3 && g->ship->y + g->ship->vy <= g->screen->sprite->h)
  256. g->ship->y += g->ship->vy;
  257. /* Проверка взятия ресурса */
  258. if (g->resources->if_exist == 1)
  259. if (g->ship->x <= g->resources->x + g->resources->bitcoin->w && g->ship->x + g->ship->sprite->w >= g->resources->x)
  260. if (g->ship->y <= g->resources->y + g->resources->bitcoin->h && g->ship->y + g->ship->sprite->h >= g->resources->y)
  261. g->resources->if_exist = 0;
  262.  
  263. /* Получаем значение времени прошедшего с начала игры */
  264. unsigned int current_time = SDL_GetTicks();
  265. g->timer = (current_time - start_time) / 1000;
  266.  
  267. if (g->timer <= 60) {
  268. draw(g);
  269. }
  270. else {
  271. show_mission_status(g);
  272. SDL_Delay(2500);
  273. done = 1;
  274. }
  275. SDL_Delay(10);
  276. }
  277. }
  278.  
  279.  
  280. void draw(game* g)
  281. {
  282. /* Прямоугольники, определяющие зону отображения */
  283. SDL_Rect src, dest;
  284.  
  285. /* Отображаем фон */
  286. src.x = 0;
  287. src.y = 0;
  288. src.w = g->background->sprite->w;
  289. src.h = g->background->sprite->h;
  290.  
  291. dest.x = 0;
  292. dest.y = 0;
  293. dest.w = g->background->sprite->w;
  294. dest.h = g->background->sprite->h;
  295.  
  296. SDL_BlitSurface(g->background->sprite, &src, g->screen->sprite, &dest);
  297.  
  298. /* Отображаем счетчики */
  299. show_counter(g, g->resources->bitcoin_count, 1);
  300. show_counter(g, g->timer, 2);
  301.  
  302. /* Отображаем корабль */
  303. src.x = 0;
  304. src.y = 0;
  305. src.w = g->ship->sprite->w;
  306. src.h = g->ship->sprite->h;
  307.  
  308. dest.x = g->ship->x;
  309. dest.y = g->ship->y;
  310. dest.w = g->ship->sprite->w;
  311. dest.h = g->ship->sprite->h;
  312.  
  313. SDL_SetColorKey(g->ship->sprite, SDL_SRCCOLORKEY, 0x000000); // Удаляем черные пиксели
  314. SDL_BlitSurface(g->ship->sprite, &src, g->screen->sprite, &dest);
  315.  
  316. /* Отображение ресурса */
  317. if (g->resources->if_exist == 0) {
  318. srand(time(NULL));
  319. while (g->resources->flag == 0) {
  320. g->resources->x = rand() % (g->screen->sprite->w - g->resources->bitcoin->w);
  321. g->resources->y = rand() % (g->screen->sprite->h * 2 / 3 - g->resources->bitcoin->h) + g->screen->sprite->h / 3;
  322.  
  323. if (g->ship->x <= g->resources->x + g->resources->bitcoin->w && g->ship->x + g->ship->sprite->w >= g->resources->x) {
  324. if (g->ship->y <= g->resources->y + g->resources->bitcoin->h && g->ship->y + g->ship->sprite->h >= g->resources->y) {
  325. ;
  326. }
  327. else {
  328. g->resources->flag = 1;
  329. }
  330. }
  331. }
  332. g->resources->flag = 0;
  333. g->resources->if_exist = 1;
  334. g->resources->bitcoin_count++;
  335. }
  336.  
  337. src.x = 0;
  338. src.y = 0;
  339. src.w = g->resources->bitcoin->w;
  340. src.h = g->resources->bitcoin->h;
  341.  
  342. dest.x = g->resources->x;
  343. dest.y = g->resources->y;
  344. dest.w = g->resources->bitcoin->w;
  345. dest.h = g->resources->bitcoin->h;
  346.  
  347. SDL_SetColorKey(g->resources->bitcoin, SDL_SRCCOLORKEY, 0x000000);
  348. SDL_BlitSurface(g->resources->bitcoin, &src, g->screen->sprite, &dest);
  349.  
  350. spawn_asteroids(g);
  351.  
  352. /* Отрисовываем обновленный экран */
  353. SDL_Flip(g->screen->sprite);
  354. }
  355.  
  356. void show_counter(game* g, const int counter, const int mode)
  357. {
  358. char text[5] = "";
  359.  
  360. /* Переводим int счетчик в char */
  361. if (sprintf(text, "%d", counter) == 0) {
  362. ;
  363. }
  364. SDL_Surface* fontSurface;
  365. SDL_Color fColor = { 0xff, 0x00, 0x00, 0xff };
  366. SDL_Color bColor = { 0x00, 0x00, 0x00, 0xff };
  367. fontSurface = TTF_RenderUTF8_Shaded(g->font, text, fColor, bColor);
  368.  
  369. int w, h;
  370. TTF_SizeUTF8(g->font, text, &w, &h);
  371.  
  372. SDL_Rect fontRect;
  373. if (mode == 1) {
  374. fontRect.x = 0;
  375. } else {
  376. fontRect.x = g->screen->sprite->w - w;
  377. }
  378. fontRect.y = 0;
  379. SDL_SetColorKey(fontSurface, SDL_SRCCOLORKEY, 0x000000);
  380. SDL_BlitSurface(fontSurface, NULL, g->screen->sprite, &fontRect);
  381. }
  382.  
  383. void show_mission_status(game* g)
  384. {
  385. char text[] = "Mission complete!";
  386.  
  387. SDL_Surface* status;
  388. SDL_Color fColor = { 0x00, 0xff, 0x00, 0xff };
  389. SDL_Color bColor = { 0x00, 0x00, 0x00, 0xff };
  390. status = TTF_RenderUTF8_Shaded(g->font, text, fColor, bColor);
  391.  
  392. int w, h;
  393. TTF_SizeUTF8(g->font, text, &w, &h);
  394.  
  395. SDL_Rect statusRect;
  396. statusRect.x = g->screen->sprite->w / 2 - w / 2;
  397. statusRect.y = g->screen->sprite->h / 2 - h / 2;
  398. SDL_SetColorKey(status, SDL_SRCCOLORKEY, 0x000000);
  399. SDL_BlitSurface(status, NULL, g->screen->sprite, &statusRect);
  400. SDL_Flip(g->screen->sprite);
  401. }
  402.  
  403. void spawn_asteroids(game* g)
  404. {
  405. SDL_Rect src, dest;
  406.  
  407. for (int i = 0; i < 8; i++) {
  408. /* Проверка на существование астероида в плоскости
  409. * и последующее задание ему случайной координаты x
  410. */
  411. if (g->obstacles->if_exist[i] == 0) {
  412. srand(time(NULL));
  413. g->obstacles->if_exist[i] = 1;
  414. g->obstacles->x[i] = rand() % (g->screen->sprite->w - g->resources->asteroid->w);
  415. g->obstacles->y[i] = 0 - g->resources->asteroid->h;
  416. g->obstacles->vx[i] = rand() % (12) - 6;
  417. g->obstacles->vy[i] = rand() % (3);
  418. }
  419. else {
  420. /* Обработка ситуации выхода астероида за границы */
  421. if (g->obstacles->y[i] > g->screen->sprite->h || g->obstacles->x[i] < 0 - g->resources->asteroid->w
  422. || g->obstacles->x[i] > g->screen->sprite->w) {
  423. g->obstacles->if_exist[i] = 0;
  424. }
  425. else {
  426. g->obstacles->x[i] += g->obstacles->vx[i];
  427. g->obstacles->y[i] += g->obstacles->yx[i];
  428. }
  429.  
  430. src.x = 0;
  431. src.y = 0;
  432. src.w = g->resources->asteroid->w;
  433. src.h = g->resources->asteroid->h;
  434.  
  435. dest.x = g->obstacles->x[i];
  436. dest.y = g->obstacles->y[i];
  437. dest.w = g->resources->asteroid->w;
  438. dest.h = g->resources->asteroid->h;
  439.  
  440. SDL_SetColorKey(g->resources->asteroid, SDL_SRCCOLORKEY, 0x000000);
  441. SDL_BlitSurface(g->resources->asteroid, &src, g->screen->sprite, &dest);
  442. }
  443. }
  444. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement