Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * spacexplore.c -- прототип игры управления звездолетом
- *
- * Copyright (c) 2019, Nikita Semenov <ndsemeno@cs.mail.petrsu.ru>
- *
- * This code is licensed under a MIT-style license.
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include <SDL.h>
- #include <SDL_ttf.h>
- #define VXD 6
- #define VYD 6
- #define N 5
- /* Описание экрана игры */
- typedef struct _gamescreen {
- /* Поверхность отрисовки */
- SDL_Surface* sprite;
- } gamescreen;
- /* Описание фона */
- typedef struct _gamebackground {
- /* Поверхность отрисовки */
- SDL_Surface* sprite;
- } gamebackground;
- /* Описание управляемого пользователем корабля */
- typedef struct _spaceship {
- /* Поверхность отрисовки */
- SDL_Surface* sprite;
- /* Координаты корабля */
- int x;
- int y;
- /* Проекции скорости корабля */
- int vx;
- int vy;
- } spaceship;
- /* Описание характеристик астероидов */
- typedef struct _position {
- /* Координаты астероида */
- int x;
- int y;
- /* Проекции скорости астероида */
- int vx;
- int vy;
- } position;
- /* Описание астероидов */
- typedef struct _obstacle {
- /* Поверхность отрисовки */
- SDL_Surface* sprite;
- /* Физические характеристики */
- position *pos[N];
- } obstacle;
- /* Описание ресурса */
- typedef struct _gameresources {
- /* Поверхность отрисовки */
- SDL_Surface* sprite;
- /* Количество собранных ресурсов */
- int count;
- /* Координаты ресурса */
- int x;
- int y;
- } gameresources;
- /* Ресурсы и состояние игры */
- typedef struct _game {
- /* Экран игры */
- gamescreen* screen;
- /* Корабль пользователя */
- spaceship* ship;
- /* Фон */
- gamebackground* background;
- /* Астероиды */
- obstacle* asteroid;
- /* Ресурс */
- gameresources* resource;
- TTF_Font* font;
- int timer;
- } game;
- /**
- * Инициализирует игру
- * @returns g указатель на структуру состояния игры
- */
- game* init();
- /**
- * Инициализирует игру
- * @param g указатель на структуру состояния игры
- */
- void run(game* g);
- /**
- * Отрисовывает объекты в новой позиции
- * @param g указатель на структуру состояния игры
- */
- void draw(game* g);
- /**
- * Проверяет столкновение корабля с объектом
- * @returns true (1) если, обнаружено столкновение
- * В противном случае - false (0)
- */
- int asteroid_crash(spaceship* ship, obstacle* asteroid, int i);
- /**
- * Проверяет столкновение корабля с ресурсом
- * @returns true (1) если, обнаружено столкновение
- * В противном случае - false (0)
- */
- int bitcoin_get(spaceship* ship, gameresources* resource);
- /* Отображает таймер и счетчик ресурсов */
- void show_counter(game* g, const int counter, const int mode);
- /* Отображает статус прохождения игры */
- void show_mission_status(game* g, const int mode);
- /**
- * Основная программа
- */
- int main()
- {
- /* Инициализация генератора псевдослучайных чисел */
- srand(time(NULL));
- /* Инициализируем игру */
- game* g = init();
- /* Запускаем цикл обработки событий игры */
- run(g);
- return 0;
- }
- /**
- * Инициализирует игру
- * @returns g указатель на структуру состояния игры
- */
- game* init()
- {
- /* Создаем структуру представления состояния игры */
- game* g;
- g = (game*)malloc(sizeof(game));
- if (g == NULL) {
- fprintf(stderr, "Not enough memory!\n");
- exit(EXIT_FAILURE);
- }
- /* Инициализируем библиотеку SDL, используем только видеоподсистему */
- if (SDL_Init(SDL_INIT_VIDEO) < 0) {
- fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
- exit(EXIT_FAILURE);
- }
- /* Регистрируем обработчик завершения программы */
- atexit(SDL_Quit);
- /* Инициализируем библиотеку SDL_ttf и загружаем шрифт */
- TTF_Init();
- g->font = TTF_OpenFont("AbrilFatface-Regular.ttf", 44);
- /* Выделяем память для структуры представления экрана */
- g->screen = (gamescreen*)malloc(sizeof(gamescreen));
- if (g->screen == NULL) {
- fprintf(stderr, "Not enough memory!\n");
- exit(EXIT_FAILURE);
- }
- /* Инициализируем видеорежим */
- g->screen->sprite =
- SDL_SetVideoMode(1024, 768, 0, SDL_HWSURFACE | SDL_DOUBLEBUF);
- if (g->screen->sprite == NULL) {
- fprintf(stderr, "Couldn't set video mode: %s\n", SDL_GetError());
- exit(EXIT_FAILURE);
- }
- /* Выделяем память для структуры представления фона */
- g->background = (gamebackground*)malloc(sizeof(gamebackground));
- if (g->background == NULL) {
- fprintf(stderr, "Not enough memory!\n");
- exit(EXIT_FAILURE);
- }
- g->background->sprite = SDL_LoadBMP("background.bmp");
- if (g->background->sprite == NULL) {
- fprintf(stderr, "Couldn't load a bitmap: %s\n", SDL_GetError());
- exit(EXIT_FAILURE);
- }
- /* Выделяем память для структуры представления корабля */
- g->ship = (spaceship*)malloc(sizeof(spaceship));
- if (g->ship == NULL) {
- fprintf(stderr, "Not enough memory!\n");
- exit(EXIT_FAILURE);
- }
- g->ship->sprite = SDL_LoadBMP("ship.bmp");
- if (g->ship->sprite == NULL) {
- fprintf(stderr, "Couldn't load a bitmap: %s\n", SDL_GetError());
- exit(EXIT_FAILURE);
- }
- /* Выделяем память для структуры представления астероидов */
- g->asteroid = (obstacle*)malloc(sizeof(obstacle));
- if (g->asteroid == NULL) {
- fprintf(stderr, "Not enough memory!\n");
- exit(EXIT_FAILURE);
- }
- g->asteroid->sprite = SDL_LoadBMP("asteroid.bmp");
- if (g->asteroid->sprite == NULL) {
- fprintf(stderr, "Couldn't load a bitmap: %s\n", SDL_GetError());
- exit(EXIT_FAILURE);
- }
- /* Выделяем память для структуры представления ресурса */
- g->resource = (gameresources*)malloc(sizeof(gameresources));
- if (g->resource == NULL) {
- fprintf(stderr, "Not enough memory!\n");
- exit(EXIT_FAILURE);
- }
- g->resource->sprite = SDL_LoadBMP("bitcoin.bmp");
- if (g->resource->sprite == NULL) {
- fprintf(stderr, "Couldn't load a bitmap: %s\n", SDL_GetError());
- exit(EXIT_FAILURE);
- }
- /* Выделяем память для структуры представления характеристик астероидов */
- for (int i = 0; i < N; i++) {
- /* Для каждого астероида отдельно */
- g->asteroid->pos[i] = (position*)malloc(sizeof(position));
- if (g->asteroid->pos[i] == NULL) {
- fprintf(stderr, "Not enough memory!\n");
- exit(EXIT_FAILURE);
- }
- }
- /* Помещаем корабль в начальную позицию */
- g->ship->x = (g->screen->sprite->w - g->ship->sprite->w) / 2;
- g->ship->y = g->screen->sprite->h - g->ship->sprite->h;
- /* Помещаем астероиды в начальную позицию */
- for (int i = 0; i < N; i++) {
- /* Для каждого астероида */
- g->asteroid->pos[i]->x = rand() % (g->screen->sprite->w - g->asteroid->sprite->w);
- g->asteroid->pos[i]->y = -(g->asteroid->sprite->h);
- g->asteroid->pos[i]->vx = rand() % 10 - 5;
- g->asteroid->pos[i]->vy = rand() % 10 + 1;
- }
- /* Помещаем ресурс в начальную позицию */
- g->resource->x = rand() % (g->screen->sprite->w - g->resource->sprite->w);
- g->resource->y = rand() % (g->screen->sprite->h * 2 / 3 - g->resource->bitcoin->h) + g->screen->sprite->h / 3;
- g->resource->count = 0;
- /* Устанавливаем заголовок окна */
- SDL_WM_SetCaption("Space Explore", NULL);
- return g;
- }
- /**
- * Инициализирует игру
- * @param g указатель на структуру состояния игры
- */
- void run(game* g)
- {
- /* Флажок выхода */
- int done = 0;
- int left_ship_border = 0;
- int upper_ship_border = (g->screen->sprite->h) / 3;
- int right_ship_border = g->screen->sprite->w - g->ship->sprite->w;
- int lower_ship_border = g->screen->sprite->h - g->ship->sprite->h;
- int left_border = -(g->asteroid->sprite->w);
- int right_border = g->screen->sprite->w;
- int lower_border = g->screen->sprite->h;
- /* Продолжаем выполнение, пока не поднят флажок */
- while (!done) {
- for (int i = 0; i < N; i++) {
- if (asteroid_crash(g->ship, g->asteroid, i))
- done = 1;
- }
- /* Структура описания события */
- SDL_Event event;
- /* Извлекаем и обрабатываем все доступные события */
- while (SDL_PollEvent(&event)) {
- switch (event.type) {
- /* Если клавишу нажали */
- case SDL_KEYDOWN:
- switch (event.key.keysym.sym) {
- case SDLK_LEFT:
- g->ship->vx += -VXD;
- break;
- case SDLK_RIGHT:
- g->ship->vx += VXD;
- break;
- case SDLK_UP:
- g->ship->vy += -VYD;
- break;
- case SDLK_DOWN:
- g->ship->vy += VYD;
- break;
- case SDLK_ESCAPE:
- done = 1;
- break;
- }
- break;
- /* Если клавишу отпустили */
- case SDL_KEYUP:
- switch (event.key.keysym.sym) {
- case SDLK_LEFT:
- g->ship->vx += VXD;
- break;
- case SDLK_RIGHT:
- g->ship->vx += -VXD;
- break;
- case SDLK_UP:
- g->ship->vy += VYD;
- break;
- case SDLK_DOWN:
- g->ship->vy += -VYD;
- break;
- default:
- break;
- }
- break;
- /* Если закрыли окно */
- case SDL_QUIT:
- done = 1;
- break;
- default:
- break;
- }
- }
- /* Проверка выхода корабля за границу */
- if (g->ship->x + g->ship->vx >= left_ship_border &&
- g->ship->x + g->ship->vx <= right_ship_border)
- g->ship->x += g->ship->vx;
- if (g->ship->y + g->ship->vy >= upper_ship_border &&
- g->ship->y + g->ship->vy <= lower_ship_border)
- g->ship->y += g->ship->vy;
- /* Проверка выхода астероида за границу */
- for (int i = 0; i < N; i++) {
- if (g->asteroid->pos[i]->y + g->asteroid->pos[i]->vy > lower_border ||
- g->asteroid->pos[i]->x + g->asteroid->pos[i]->vx < left_border ||
- g->asteroid->pos[i]->x + g->asteroid->pos[i]->vx > right_border)
- {
- g->asteroid->pos[i]->x = rand() % (g->screen->sprite->w + left_border);
- g->asteroid->pos[i]->y = -(g->asteroid->sprite->h);
- g->asteroid->pos[i]->vx = rand() % 10 - 5;
- g->asteroid->pos[i]->vy = rand() % 10 + 1;
- }
- g->asteroid->pos[i]->x += g->asteroid->pos[i]->vx;
- g->asteroid->pos[i]->y += g->asteroid->pos[i]->vy;
- }
- draw(g);
- SDL_Delay(10);
- }
- }
- /**
- * Отрисовывает объекты в новой позиции
- * @param g указатель на структуру состояния игры
- */
- void draw(game* g)
- {
- /* Прямоугольники, определяющие зону отображения */
- SDL_Rect src, dest;
- /* Фон отображаем целиком */
- src.x = 0;
- src.y = 0;
- src.w = g->background->sprite->w;
- src.h = g->background->sprite->h;
- /* Выполняем отображение */
- SDL_BlitSurface(g->background->sprite, &src, g->screen->sprite, &src);
- for (int i = 0; i < N; i++) {
- /* Астероид отображаем целиком */
- src.x = 0;
- src.y = 0;
- src.w = g->asteroid->sprite->w;
- src.h = g->asteroid->sprite->h;
- /* в новую позицию */
- dest.x = g->asteroid->pos[i]->x;
- dest.y = g->asteroid->pos[i]->y;
- dest.w = g->asteroid->sprite->w;
- dest.h = g->asteroid->sprite->h;
- /* Выполняем отображение */
- SDL_SetColorKey(g->asteroid->sprite, SDL_SRCCOLORKEY, 0x000000);
- SDL_BlitSurface(g->asteroid->sprite, &src, g->screen->sprite, &dest);
- }
- /* Корабль отображаем целиком */
- src.x = 0;
- src.y = 0;
- src.w = g->ship->sprite->w;
- src.h = g->ship->sprite->h;
- /* в новую позицию */
- dest.x = g->ship->x;
- dest.y = g->ship->y;
- dest.w = g->ship->sprite->w;
- dest.h = g->ship->sprite->h;
- /* Выполняем отображение */
- SDL_SetColorKey(g->ship->sprite, SDL_SRCCOLORKEY, 0x000000);
- SDL_BlitSurface(g->ship->sprite, &src, g->screen->sprite, &dest);
- if (bitcoin_get(g->ship, g->resource)) {
- /* Проверка столкновения с ресурсом */
- g->resource->x = rand() % (g->screen->sprite->w - g->resource->sprite->w);
- g->resource->y = rand() % (2 * (g->screen->sprite->h) / 3 - g->resource->sprite->h);
- g->resource->y += (g->screen->sprite->h) / 3;
- /* Инкрементируем счетчик ресурсов */
- g->resource->count++;
- }
- /* Ресурс отображаем целиком */
- src.x = 0;
- src.y = 0;
- src.w = g->resource->sprite->w;
- src.h = g->resource->sprite->h;
- /* в новую позицию */
- dest.x = g->resource->x;
- dest.y = g->resource->y;
- dest.w = g->resource->sprite->w;
- dest.h = g->resource->sprite->h;
- /* Выполняем отображение */
- SDL_SetColorKey(g->resource->sprite, SDL_SRCCOLORKEY, 0x000000);
- SDL_BlitSurface(g->resource->sprite, &src, g->screen->sprite, &dest);
- /* Отрисовываем обновленный экран */
- SDL_Flip(g->screen->sprite);
- }
- /**
- * Проверяет столкновение корабля с объектом
- * @returns true (1) если, обнаружено столкновение
- * В противном случае - false (0)
- */
- int asteroid_crash(spaceship* ship, obstacle* asteroid, int i)
- {
- int ship_left, obj_left;
- int ship_top, obj_top;
- int ship_right, obj_right;
- int ship_bottom, obj_bottom;
- int offset = 10;
- /* Получение координат сторон объектов */
- ship_left = ship->x + offset;
- obj_left = asteroid->pos[i]->x + offset;
- ship_top = ship->y + offset;
- obj_top = asteroid->pos[i]->y + offset;
- ship_right = ship->x + ship->sprite->w - 1 - offset;
- obj_right = asteroid->pos[i]->x + asteroid->sprite->w - 1 - offset;
- ship_bottom = ship->y + ship->sprite->h - 1 - offset;
- obj_bottom = asteroid->pos[i]->y + asteroid->sprite->h - 1 - offset;
- /* Проеверка столкновения объектов */
- if (ship_bottom < obj_top) return 0;
- if (ship_top > obj_bottom) return 0;
- if (ship_right < obj_left) return 0;
- if (ship_left > obj_right) return 0;
- return 1;
- }
- /**
- * Проверяет столкновение корабля с ресурсом
- * @returns true (1) если, обнаружено столкновение
- * В противном случае - false (0)
- */
- int bitcoin_get(spaceship* ship, gameresources* resource)
- {
- int ship_left, obj_left;
- int ship_top, obj_top;
- int ship_right, obj_right;
- int ship_bottom, obj_bottom;
- int offset = 10;
- /* Получение координат сторон объектов */
- ship_left = ship->x + offset;
- obj_left = resource->x + offset;
- ship_top = ship->y + offset;
- obj_top = resource->y + offset;
- ship_right = ship->x + ship->sprite->w - 1 - offset;
- obj_right = resource->x + resource->sprite->w - 1 - offset;
- ship_bottom = ship->y + ship->sprite->h - 1 - offset;
- obj_bottom = resource->y + resource->sprite->h - 1 - offset;
- /* Проеверка столкновения объектов */
- if (ship_bottom < obj_top) return 0;
- if (ship_top > obj_bottom) return 0;
- if (ship_right < obj_left) return 0;
- if (ship_left > obj_right) return 0;
- return 1;
- }
- void show_counter(game* g, const int counter, const int mode)
- {
- char text[5] = "";
- /* Переводим int счетчик в char */
- if (sprintf(text, "%d", counter) == 0) {
- ;
- }
- SDL_Surface* fontSurface;
- SDL_Color fColor = { 0xff, 0x00, 0x00, 0xff };
- SDL_Color bColor = { 0x00, 0x00, 0x00, 0xff };
- fontSurface = TTF_RenderUTF8_Shaded(g->font, text, fColor, bColor);
- int w, h;
- TTF_SizeUTF8(g->font, text, &w, &h);
- SDL_Rect fontRect;
- if (mode == 1) {
- fontRect.x = 0;
- }
- else {
- fontRect.x = g->screen->sprite->w - w;
- }
- fontRect.y = 0;
- SDL_SetColorKey(fontSurface, SDL_SRCCOLORKEY, 0x000000);
- SDL_BlitSurface(fontSurface, NULL, g->screen->sprite, &fontRect);
- }
- void show_mission_status(game* g, const int mode)
- {
- SDL_Surface* status;
- if (mode == 0) {
- char text[] = "Mission complete!";
- SDL_Color fColor = { 0x00, 0xff, 0x00, 0xff };
- }
- else {
- char text[] = "Mission failed!";
- SDL_Color fColor = { 0xff, 0x00, 0x00, 0xff };
- }
- SDL_Color bColor = { 0x00, 0x00, 0x00, 0xff };
- status = TTF_RenderUTF8_Shaded(g->font, text, fColor, bColor);
- int w, h;
- TTF_SizeUTF8(g->font, text, &w, &h);
- SDL_Rect statusRect;
- statusRect.x = g->screen->sprite->w / 2 - w / 2;
- statusRect.y = g->screen->sprite->h / 2 - h / 2;
- SDL_SetColorKey(status, SDL_SRCCOLORKEY, 0x000000);
- SDL_BlitSurface(status, NULL, g->screen->sprite, &statusRect);
- SDL_Flip(g->screen->sprite);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement