Среда, 19 Сентября 2018, 23:29

Приветствую Вас Гость

Меню сайта
Категории каталога
Создание игр [312]
Статьи об общих понятиях связанных с созданием игр.
Программирование [69]
Гайды по программированию на разных ЯП.
Движки и Гейммейкеры [123]
Статьи о программах для создания игр, уроки и описания.
Софт [27]
Различные программы, в том числе в помощь игроделам.
2D-графика [11]
Уроки по рисованию, растр, пиксель-арт, создание спрайтов и пр.
3D-графика [10]
Уроки по моделированию, ландшафт, модели, текстурирование и пр.
Моддинг игр [5]
Модификация компьютерных игр, создание дополнений, перевод, хакинг.
Игры [91]
Статьи об играх, в том числе и сделанных на гейммейкерах.
Разное [67]
Статьи, которые не вошли в определённые разделы.
Наш опрос
Ваше отношение к российским разработкам?
Всего ответов: 5421
Главная » Статьи » Создание игр

[OpenGL С++] Пишем змейку на C++
Всем привет! Что-то последнее время много уроков по конструкторам игр, и не так много по различным языкам программирования. Что бы устранить эту не справедливость, я решил запилить урок по OpenGL C++, надеюсь вы оцените)

Сразу же перейдем к геймдеву и будем писать маленькую игрульку нашего детства.

Для начала подключаем библиотеку OpenGL к своей среде разработки, я лично программирую в Microsoft Visual Studio 2013.

Код

#include "stdafx.h"  
#include <GL/glut.h>
#include <time.h>
#include <random>
#include <iostream> // подключаем все необходимые инклюды.

int N = 30, M = 20; // т.к. змейка будем ездить по квадратикам, создадим их, для нашего окна в идеале будет 30x20 квадратов
int scale = 25; // размер квадрата. Когда OpenGL будет расчерчивать поле для игры, расстояние между гранями квадрата будет 25 пикселей

int w = scale*N; // ширина поля  
int h = scale*M; // его высота

int dir, num = 4; // 4 направления и начальный размер змеи.
struct { int x; int y; } s[100]; // структура змеи, X и Y координаты, массив с длинной.

class fruct // класс фруктов, тех самых, которые будет есть наша змея
{
public:
  int x, y; //координаты фруктов, что и где будет находится

  void New() // паблик с новыми фруктами. Он будет вызываться в начале игры и в тот момент, когда змея съест один из фруктов
  {
  x = rand() % N; // вычисление X координаты через рандом
  y = rand() % M; // вычисление Y координаты через рандом
  }

  void DrawFruct() // паблик, отрисовывающий фрукты
  {
  glColor3f(0.0, 1.0, 1.0); // цвет фруктов. в openGL он задается от 0 до 1, а не от 0 до 256, как многие привыкли
  glRectf(x*scale, y*scale, (x + 1)*scale, (y + 1)*scale); // "Закрашиваем" квадрат выбранным цветом, таким образом в нем "появляется" фрукт
  }
} m[5]; // масив с фруктами, таким образом, у нас появится одновременно 5 фруктов в разных местах, а не один, как мы привыкли <img src="http://s27.ucoz.net/sm/1/smile.gif" border="0" align="absmiddle" alt="smile" />

void Draw() // функция, которая отрисовывает линии
{
  glColor3f(1.0, 0.0, 0.0); // цвет наших линий, в данном слуае - красный
  glBegin(GL_LINES); // начинаем рисовать и указываем, что это линии
  for (int i = 0; i < w; i+= scale) // отрисовываем линии в ширину
  {  
  glVertex2f(i, 0); glVertex2f(i, h); // рисуем прямую
  }
  for (int j = 0; j < h; j += scale) //отрисовываем линии в высоту
  {
  glVertex2f(0, j); glVertex2f(w, j); // рисуем ту же самую прямую, но в другом направлении
  }

  glEnd(); // конец отрисовки
}

void tick() // функция в которой будет все обновляться (двигаться змея и т.д.)
{
  for (int i = num; i > 0; --i) // движение змеи. Система остроумна и проста : блок перемешается вперед, а остальные X блоков, на X+1( 2 блок встанет на место 1, 3 на место 2 и т.д...)
  {
  s[i].x = s[i - 1].x; // задаем Х координату i блока координатой i - 1
  s[i].y = s[i - 1].y; // то же самое делаем и с Y координатой
  }
  // далее у нас система направлений.
  if (dir == 0) s[0].y += 1; // если направление равно 0, то первый фрагмент массива перемещается на один по Y
  if (dir == 1) s[0].x -= 1; // если направление равно 1, то первый фрагмент массива перемещается на минус один по X
  if (dir == 2) s[0].x += 1; // аналогиная система
  if (dir == 3) s[0].y -= 1; // аналогичная система

  for (int i = 0; i < 10; i++) //цикл, в котором наша змея будет расти
  {
  if ((s[0].x == m[i].x) && (s[0].y == m[i].y)) // Если голова нашей змеи находится в одном блоке с фруктом, то...
  {
  num++; //...увеличиваем размер нашей змеи на 1
  m[i].New(); // ... запускаем функцию отрисовки нового фрукта.
  }
  }
  // Следующее нужно, что бы змея не выходила за рамка поля. Действует это просто : если змея выходит за рамки поля, то задаем
  if (s[0].x > N) dir = 1; // Ей обратное направление. Например, если она выйдет за экран по высоте, то задаем ей направление, при котором она ползет
  if (s[0].y > M) dir = 3; // вниз
  if (s[0].x < 0) dir = 2;
  if (s[0].y < 0) dir = 0;

  for (int i = 1; i < num; i++) // с помощью этого цикла мы "обрежем" змею, если она заползет сама на себя
  if (s[0].x == s[i].x && s[0].y == s[i].y) // проверка координат частей змеи, если X и Y координата головной части равно координате любого
  num = i; // другого блока змеи, то задаем ей длину, при которой "откушенная" часть отпадает.
}

void Snake() // выводим змейку на экран
{
  glColor3f(0.1, 1.0, 0.0); //цвет змеи
  for (int i = 0; i < num; i++) // цикл отрисовки.
  {
  glRectf(s[i].x*scale, s[i].y*scale, (s[i].x + 0.9)*scale, (s[i].y + 0.9)*scale); //Рисуем квадраты, те самые "блоки" змеи
  }
}

void Key(int key, int a, int b) // функция нажатия клавиш
{
  switch (key) // используем оператор switch
  {
  case 101: dir = 0; break; // при нажатии клавиш, задаем направление змеи(вверх, вниз, влево, вправо)
  case 102: dir = 2; break;
  case 100: dir = 1; break;
  case 103: dir = 3; break;
  }
}

void Display() //функция общий отрисовки
{
  glClear(GL_COLOR_BUFFER_BIT); // очищаем окно перед началом отрисовки
   
  Draw(); // вызов функции Draw, отвечающей за отрисовку фруктов
  Snake(); // вызов функции Snake, отвечающей за отрисовку змейки
   
  for (int i = 0; i < 5; i++) // заполнение карты фруктами
  m[i].DrawFruct();

  glFlush(); // выводим на экран все вышеописанное
  glutSwapBuffers();
}

void timer(int = 0) // Таймер игры(промежуток времени, в котором будет производится все процессы)
{
  Display(); // Вызов функций  
  tick();
  glutTimerFunc(100, timer, 0); // новый вызов таймера( 100 - промежуток времени(в милисекундах), через который он будет вызыватся, timer - вызываемый паблик)
}

int main(int argc, char **argv) // Главная функция
{
  std::cout << "Snake by Alexey Ovchinnikov :P\n Loading..."; // крутой текст в консоле при загрузке
  srand(time(0));
  for (int i = 0; i<10; i++) // начальная, самая первая отрисовка фруктов
  m[i].New();

  s[0].x = 10; // начальное положение змейки по X
  s[0].y = 10; // и Y координате
  // следующие функции абсолютно идиентичных почти во всех программах на OpenGL, так то запоминать их не обязательно, кроме ...
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
  glutInitWindowSize(w, h); // ... этой, она создаем окно (w - ширина, h - высота)
  glutCreateWindow("Game"); // ... этой, она задает название окна
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluOrtho2D(0, 640, 0, 480);
  glutDisplayFunc (Display); // ... и этой, она вызывает начальную функцию, в нашем случае это главная функция отрисовки - Display
  glutSpecialFunc(Key);
  glutTimerFunc(50, timer, 0); // ... Ну и в начале программы задаем рекурсивный таймер.
  glutMainLoop();

  return 0;
}


И так, на этом все, запускаем, играем. Постарался объяснить максимально понятно, если будут вопросы - задавайте.
P.S. И пожалуйста, не кидайтесь тапками если что-то не понятно или не так написал, первый урок в моей жизни. smile

Всем удачи!
Категория: Создание игр | Добавил: HardcoreCoder (14 Мая 2015)
Просмотров: 18632 | Комментарии: 4 | Рейтинг: 4.2/8 |
Теги: урок, Visual Studio, Visual Studio 2013, OpenGl, Microsoft Visual Studio 2013, GameDev, ЯП, Пишем, Змейка, C++
Дополнительные опции:
Также если вы считаете, что данный материал мог быть интересен и полезен кому-то из ваших друзей, то вы бы могли посоветовать его, отправив сообщение на e-mail друга:

Игровые объявления и предложения:
Если вас заинтересовал материал «[OpenGL С++] Пишем змейку на C++», и вы бы хотели прочесть что-то на эту же тему, то вы можете воспользоваться списком схожих материалов ниже. Данный список сформирован автоматически по тематическим меткам раздела. Предлагаются такие схожие материалы: Если вы ведёте свой блог, микроблог, либо участвуете в какой-то популярной социальной сети, то вы можете быстро поделиться данной заметкой со своими друзьями и посетителями.

Всего комментариев: 4
+1-
3 PoidetLi   (15 Мая 2015 20:18)
PoidetLi
Код
<img src="http://s27.ucoz.net/sm/1/smile.gif" border="0" align="absmiddle" alt="smile" />

что этот код забыл?

+1-
4 HardcoreCoder   (15 Мая 2015 20:27)
HardcoreCoderЭто я пытался вставить смайлики biggrin Прости, исправил.

+0-
1 TLT   (15 Мая 2015 17:49)
TLTВ следующий раз ещё скрин делай того, что получается - было бы нагляднее.

+2-
2 HardcoreCoder   (15 Мая 2015 17:54)
HardcoreCoderХорошо! smile

Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Поиск по сайту
10 случ. движков
  • Tombstone Engine
  • Grit
  • ReMooD
  • RTADS
  • Mortal Szombat
  • Virtools
  • Qfusion
  • PixelLight
  • jPCT
  • Panda3D
  • Друзья сайта
    Игровой форум GFAQ.ru Перевод консольных игр
    Все права сохранены. GcUp.ru © 2008-2018 Рейтинг