Астероиды, C#, 3D и OpenGL

Грэг Дункан

Сегодняшний проект – простой пример использования OpenGL и C#/WinForm для создания игры начального уровня. Что в ней нравится, так это то, что она действительно очень простая, с легко понимаемым кодом, и с ней легко начать работать…

Трехмерная игра начального уровня «Астероиды» на openGL с C#

Эта статья предназначена для начинающих, кто хочет приступить к программированию трехмерных игр, но не знает, с чего начать. Игра сделана на OpenGL с использованием VS2008 и маленького графического движка, созданного мною и называющегося Shadowengine. Она имеет лишь основное, что должно быть у игры: счет, уровни сложности и живой счетчик. Всё это занимает небольшое число строк кода с простыми и понятными целями.

Первой проблемой, с которой я столкнулся, была сцена, которая должна выглядеть как дальний космос. Для нее я сделал фон черным. В OpenGL это достигается следующим образом:

...

Счет – это число, увеличивающееся со временем, и скорость его роста каждый раз увеличивается с переходом на следующий уровень. Уровень увеличивается через каждые 450 кадров.

Последней проблемой, с которой я столкнулся, были столкновения с астероидом. Я выделил для корабля три позиции (одну для корпуса корабля и две для крыльев) и каждый раз проверял расстояния между всеми астероидами и этими тремя позициями. Если расстояние оказывалось меньше заранее заданной величины, регистрировалось столкновение.

В проекте шесть классов:

  • AsteroidGenerator . cs – Он управляет появлением в случайном месте астероида случайного размера и скорости. В нем есть метод, определяющий было или нет столкновение между кораблем и астероидом.
  • Asteroid . cs – Он управляет всем, имеющим отношение к астероиду: движением, выбором текстуры, прорисовкой и другими параметрами.
  • Star . cs – Класс содержит метод создания случайных белых точек и их прорисовки.
  • Camera . cs – Класс управляет выбором камеры пользователя и задает правильную перспективу сцены.
  • SpaceShip . cs – Этот класс содержит методы и атрибуты, имеющие отношение к космическому кораблю: перемещения, прорисовка и т. д.
  • Controller . cs – Этот класс управляет инициализацией игры, ее логикой и содержит все классы, необходимые для запуска игры. Вот фрагмент кода:
  • ...

Main . cs – Это форма, содержащая все визуальные компоненты игры. Она включает класс Controllerи предоставляет игроку информацию об всех элементах управления. В ней есть таймер, периодически перерисовывающий сцену и код для загрузки текстуры и объекта.

...

Хотя игра написана для VS2008, у меня она прекрасно загрузилась в VS2010 (и была конвертирована). После загрузки она скомпилировалась и запустилась с первого раза…

clip_image002

clip_image004

Игра очень проста. Используя клавиши WASD, вы уворачиваетесь от налетающих астероидов. 

И хотя комментарии и строковые переменные выполнены не на английском языке, код вполне понятен:

 public Main()
  {
      InitializeComponent();
      hdc = (uint)pnlViewPort.Handle;
      string error = "";
      //Comando de inicializacion de la ventana grafica
      OpenGLControl.OpenGLInit(ref hdc, pnlViewPort.Width, pnlViewPort.Height, ref error);
      //inicia la posicion de la camara asi como define en angulo de perspectiva,etc etc
      controladora.Camara.SetPerspective();
      if (error != "")
      {
          MessageBox.Show("Something happened");
      }
 
      #region lights
 
      //Configuracion de las luces
      float[] materialAmbient = { 0.5F, 0.5F, 0.5F, 1.0F };
      float[] materialDiffuse = { 1f, 1f, 1f, 1.0f };
      float[] materialSpecular = { 1.0F, 1.0F, 1.0F, 1.0F };
      //brillo del material
      float[] materialShininess = { 1.0F };
      //posicion de la luz
      float[] ambientLightPosition = { 10F, -10F, 10F, 1.0F };
      // intensidad de la luz en RGB
      float[] lightAmbient = { 0.85F, 0.85F, 0.85F, 1.0F };
 
      Lighting.MaterialAmbient = materialAmbient;
      Lighting.MaterialDiffuse = materialDiffuse;
      Lighting.MaterialSpecular = materialSpecular;
      Lighting.MaterialShininess = materialShininess;
      Lighting.AmbientLightPosition = ambientLightPosition;
      Lighting.LightAmbient = lightAmbient;
 
      #endregion
 
      //Habilita las luces
      Lighting.SetupLighting();
      //cargar texturas
      ContentManager.SetModelList("modelos\\");
      ContentManager.LoadModels();
      ContentManager.SetTextureList("texturas\\");
      ContentManager.LoadTextures();
      //AudioPlayback.SoundDir = "sonidos\\";
      //AudioPlayback.LoadSounds();
      controladora.CreateObjects();
      //Color de fondo
      Gl.glClearColor(0, 0, 0, 1);
//red green blue alpha
 
      Gl.glShadeModel(Gl.GL_SMOOTH);
    }
 
  private void tmrPaint_Tick(object sender, EventArgs e)
  {
      // limpia opengl
      Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
      //dibuja la escena
      controladora.DrawScene();
      //cambia los buffer
      Winapi.SwapBuffers(hdc);
      //termina de pintar
      Gl.glFlush();
 
      if (started)
      {
          score += 1;
          count1++;
          count2++;
          levelCount++;
          if (levelCount == 450)
          {
              level++;
              AsteroidGenerator.GenerateAsteroid(35, false);
              lblLevel.Text = level.ToString();
              levelCount = 0;
          }
          if (count1 == 4)
          {
              lblScore.Text = score.ToString();
              count1 = 0;
              lives = controladora.Nave.Vidas;
          }
          if (count2 == 20)
          {
              ShowLife(lives);
              count2 = 0;
              if (lives == 0)
              {
                  started = false;
 
                  MessageBox.Show("Game Over");
                  controladora.ResetGame();
                  score = 0;
                  level = 1;
                  lives = 3;
                  started = true;
                  count1 = 0;
                  count2 = 0;
                  lblLevel.Text = level.ToString();
                 }
          }
      }
  }

Если вы задумываетесь над написанием трехмерных игр, в космосе или нет, этот проект – хорошая стартовая точка для вас…