Mostrando entradas con la etiqueta motor gráfico 2D. Mostrar todas las entradas
Mostrando entradas con la etiqueta motor gráfico 2D. Mostrar todas las entradas

domingo, 19 de febrero de 2012

Arnow2D. Como crear una ventana con GLFW

Artículo perteneciente a la sección de motores gráficos

Hola a todos,

Dicen que rectificar es de sabios, así que durante unos instantes seré sabio :D. Me empeciné en no usar ninguna librería para este motor gráfico con el fin de que os fuera más fácil de entender, pero realmente lo complicaba todo más. Gracias a Dios que KillRazor y StrongCoder estaban ahí para hacerme ver el error (aunque reconozco que me costó :D).

Quien quiera ver toda la historia como fue que vea el siguiente link

En fin, al tema, el motor gráfico Arnow2D lo implementaré con la librería GLFW que aparte de ser totalmente libre (no como GLUT) nos da funcionalidades muy sencillas para poder crear ventanas y gestionar las entradas de usuario.

Para instalar la libreria y crear este tutorial me he basado en el siguiente link

Si tenéis problemas en la instalación o el linkado decidmelo y buscaremos solución a cada uno de los problemas puntuales que podáis tener.

Por ahora lo único que haremos será copypastear el tutorial de creación de ventanas con GLFW y ver que funciona. A partir de ahí iremos construyendo nuestro motor.

EDIT: Aqui os dejo el link donde bajaros el proyecto
Código:

#include <stdlib.h>
#include <GL/glfw.h>

void Init(void);
void Shut_Down(int return_code);
void Main_Loop(void);
void Draw_Square(float red, float green, float blue);
void Draw(void);

float rotate_y = 0,
      rotate_z = 0;
const float rotations_per_tick = .2;

int main(void)
{
  Init();
  Main_Loop();
  Shut_Down(0);
}

void Init(void)
{
  const int window_width = 800,
            window_height = 600;

  if (glfwInit() != GL_TRUE)
    Shut_Down(1);

  // 800 x 600, 16 bit color, no depth, alpha or stencil buffers, windowed
  if (glfwOpenWindow(window_width, window_height, 5, 6, 5, 0, 0, 0, GLFW_WINDOW) != GL_TRUE)
    Shut_Down(1);

  glfwSetWindowTitle("The GLFW Window");

  // set the projection matrix to a normal frustum with a max depth of 50
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  float aspect_ratio = ((float)window_height) / window_width;
  glFrustum(.5, -.5, -.5 * aspect_ratio, .5 * aspect_ratio, 1, 50);
  glMatrixMode(GL_MODELVIEW);
}

void Shut_Down(int return_code)
{
  glfwTerminate();
  exit(return_code);
}

void Main_Loop(void)
{
  // the time of the previous frame
  double old_time = glfwGetTime();
  // this just loops as long as the program runs
  while(1)
  {
    // calculate time elapsed, and the amount by which stuff rotates
    double current_time = glfwGetTime(),
           delta_rotate = (current_time - old_time) * rotations_per_tick * 360;
    old_time = current_time;
    // escape to quit, arrow keys to rotate view
    if (glfwGetKey(GLFW_KEY_ESC) == GLFW_PRESS)
      break;

    if (glfwGetKey(GLFW_KEY_LEFT) == GLFW_PRESS)
      rotate_y += delta_rotate;

    if (glfwGetKey(GLFW_KEY_RIGHT) == GLFW_PRESS)
      rotate_y -= delta_rotate;

    // z axis always rotates
    rotate_z += delta_rotate;

    // clear the buffer
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // draw the figure
    Draw();

    // swap back and front buffers
    glfwSwapBuffers();
  }
}

void Draw_Square(float red, float green, float blue)
{
  // Draws a square with a gradient color at coordinates 0, 10
  glBegin(GL_QUADS);
  {
    glColor3f(red, green, blue);
    glVertex2i(1, 11);
    glColor3f(red * .8, green * .8, blue * .8);
    glVertex2i(-1, 11);
    glColor3f(red * .5, green * .5, blue * .5);
    glVertex2i(-1, 9);
    glColor3f(red * .8, green * .8, blue * .8);
    glVertex2i(1, 9);
  }
  glEnd();
}

void Draw(void)
{
  // reset view matrix
  glLoadIdentity();

  // move view back a bit
  glTranslatef(0, 0, -30);

  // apply the current rotation
  glRotatef(rotate_y, 0, 1, 0);
  glRotatef(rotate_z, 0, 0, 1);

  // by repeatedly rotating the view matrix during drawing, the
  // squares end up in a circle
  int i = 0, squares = 15;
  float red = 0, blue = 1;

  for (; i < squares; ++i)
  {
    glRotatef(360.0/squares, 0, 0, 1);

    // colors change for each square
    red += 1.0/12;
    blue -= 1.0/12;
    Draw_Square(red, .6, blue);
  }

}

Podría ser que os saliera una ventana de cmd diciendoos que no puede abrir GLFW, que no puede crear la ventana, y/o que el formato de pixel no es válido, tranquilos, actualizad los drivers de la tarjeta gráfica y os debería funcionar todo a la perfección. Si os da otros problemas, decidlo y le buscaremos solución.

Una vez ya lo tengaís funcionando copiad esta linea al principio para quitar la consola (extraido del LPEngine)


//Delete console
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")


Espero que os sirva, nos vemos

LordPakusBlog

miércoles, 1 de febrero de 2012

Inicio de proyecto : "Motor Gráfico 2D: Arnow"

Artículo perteneciente a la sección de motores gráficos

Hola a todos,

Este post es para anunciaros que en breve empezaré un modesto motor 2D en C mediante OpenGL.

El motivo de este motor es hacer de puente entre los que están aprendiendo a programar mediante http://lordpakus.blogspot.com/p/tutorial-de-programacion-cc-desde-0.html y los conocimientos necesarios para crear un game engine como el que empecé a explicar y desarollar : http://lordpakus.blogspot.com/p/lordpakus-game-engine.html

Realmente, la idea inicial era crear un sencillo tutorial sobre como instalar y usar alguna libreria 2D más o menos conocida como Allegro o SDL pero me dí cuenta que crear un tutorial que tuviera en cuenta todos los casos de instalación podía ser una tarea un poco más complicada de lo que yo desearía.

Así pues, en  muy breve empezaré con el motor gráfico 2D. Lo programaré en C para que la sintaxis de C++ no nos suponga un problema añadido (si el proyecto sigue adelante lo reimplementaré mediante C++ que tampoco será tan complicado) y el pintado de 2D se hará mediante OpenGL, de forma muy parecida a como implementé el modulo de 2D dentro del LPE.

La idea es que al no tener todo lo que envuelve al game engine, el motor gráfico se pueda entender de forma sencilla y pueda ser lo suficientemente sencillo de usar como para que os animéis ha hacer vuestros primeros juegecillos.

Espero vuestras opiniones y sugerencias.

Nos vemos


LordPakusBlog

martes, 14 de junio de 2011

GameEngine: Capitulo 9. Graphics2DManager

Hola a todos,

Bienvenidos a otro capitulo de como crear tu propio game engine desde 0...

El capitulo de hoy tratará del Graphics2D Engine, o lo que es lo mismo, como pintar graficos 2D por pantalla.

La forma como he abordado el problema (hay diferentes maneras, yo creo que he elegido la más actual) es mediante la texturización de un cuadrado ortogonal a la vista de la camara de manera, que el jugador no sabe que lo que ve realmente es un cuadrado 3D orientado hacia el.

El código es sencillo y se ha modificado parte del pintado de fuentes de otros capitulos para colocarlos dentro del graphics 2D engine. Si observais el código vereis que realmente no está acabado, pero que por ahora nos permite pintar algo 2D por pantalla. En capitulos posteriores iremos puliendo este módulo.

Sin más, os dejo con el código:

Graphics2DManager.cpp:
/**************************************************************************************************/
// Código creado por F.Bordas (LordPakus) como ejemplo de creación de un game engine
// para el blog LordPakus (http://lordpakus.blogspot.com/).
// Prohibida la distribución fuera de este blog sin el permiso expreso del autor
/**************************************************************************************************/

/**************************************************************************************************/
// Graphics2DManager.cpp : Código de la parte del motor gráfico 2D
/**************************************************************************************************/

#include "Graphics2DManager.h"
#include "MyGL.h"
#include "TextureManager.h"
#include "FontManager.h" //Inclusión del gestor de fuentes

#include <iostream> //Usada para imprimir por consola

#include <ctime> //Funciones de tiempo

using namespace std;

//Instancia única del graphics 3D manager
Graphics2DManager Graphics2DManager::instance;

//Constructor
Graphics2DManager::Graphics2DManager()
{
}

//Destructor
Graphics2DManager::~Graphics2DManager()
{
}

//Devolvemos el puntero al singleton
Graphics2DManager& Graphics2DManager::singleton()
{
return instance;
}

//Funcion para inicializar el motor gráfico
void Graphics2DManager::Init(int* argc, char* argv[])
{
cout << "Inicializamos el Graphics 2D Manager\n";
FontManager::singleton().Init(argc,argv); //Inicializamos la parte de fuentes.
}

//Funcion para desinicializar el bucle principal
void Graphics2DManager::DeInit()
{
cout << "Desinicializamos el Graphics 2D Manager\n";
FontManager::singleton().DeInit(); //Desinicializamos la parte de fuentes.
}

void Graphics2DManager::Draw(float x, float y, char cad[])
{
TextureManager::singleton().Texture(cad); //Usamos la textura

glBegin(GL_QUADS);
glTexCoord2f( 1.0f, 1.0f); glVertex2i( x + 256 , y + 256); // Top Right Of The Quad (Front)
glTexCoord2f( 0.0f, 1.0f); glVertex2i( x , y + 256); // Top Left Of The Quad (Front)
glTexCoord2f( 0.0f, 0.0f); glVertex2i( x , y ); // Bottom Left Of The Quad (Front)
glTexCoord2f( 1.0f, 0.0f); glVertex2i( x + 256 , y ); // Bottom Right Of The Quad (Front)
glEnd();
}


//Pasamos a modo 2D
void switchToOrtho(void)
{
glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0, 640, 0, 480, -5, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

//Volvemos al modo 3D
void switchBackToFrustum (void)
{
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}

//Función de calculo de FPS
int CalcFPS()
{
static clock_t timer = clock(); //Temporizador para los FPS
static int FPS = 0;
static int LastFPS = 0;
FPS++;

if ( (clock() - timer) > 1000 )
{
LastFPS = FPS;
FPS = 0;
timer = clock();
}

return LastFPS;
}

//Funcion que se ejecuta automaticamente desde glut (por ahora)
void Graphics2DManager::Render()
{
char cadFPS[50];

glLoadIdentity(); // Reset The View
switchToOrtho();

glEnable(GL_TEXTURE_2D);

Draw(200,200,"TITULO");
//Pintamos FPS
sprintf(cadFPS,"FPS: %d",CalcFPS());
FontManager::Print(10,10,cadFPS);

switchBackToFrustum();

glDisable(GL_TEXTURE_2D);
}

//Por el momento la dejamos comentada por que no nos hace falta
//void Graphics2DManager::Reshape()
//{
// //AQUI IRÁ NUESTRA FUNCIÓN DE REESCALADO. Por ahora vacia
//}


Graphics2DManager.h
/**************************************************************************************************/
// Código creado por F.Bordas (LordPakus) como ejemplo de creación de un game engine
// para el blog LordPakus (http://lordpakus.blogspot.com/).
// Prohibida la distribución fuera de este blog sin el permiso expreso del autor
/**************************************************************************************************/

/**************************************************************************************************/
// Graphics2DManager.h : Código de la parte de 2D del motor gráfico.
// Caracteristicas especiales: Esta clase implementa un singleton, es decir, solo podrá existir un objeto de esta clase en todo el proyecto
/**************************************************************************************************/

#ifndef __Graphics2DManager__
#define __Graphics2DManager__

class Graphics2DManager
{
private:
// Constructor y destructor de la clase
static Graphics2DManager instance;
Graphics2DManager();
~Graphics2DManager();

public:
static Graphics2DManager& singleton();

public:
//Funcion para inicializar el motor de gráficos
void Init(int* argc, char* argv[]);

//Funcion para desinicializar el motor de gráficos
void DeInit();
//Funcion para pintar nuestros gráficos
void Render();
//Función para reescalar los gráficos
void Reshape();

//Función para pintar un gráfico 2D
void Draw(float x, float y, char cad[]);

private:
//Aqui irán los diferentes objetos que complementen el graphics3Dmanager
};

#endif

Las uniones con el resto del código las dejo para vosotros (no es diferente que para el Graphics3DManager), si teneis cualquier problema decidlo y lo solucionaremos.

El video de como deberia quedar es el siguiente:


Vereis que aunque este módulo es muy sencillo es la base para TODOS los juegos de 2D que se os puedan ocurrir (que no son pocos). Es uno de los modulos con los que más trabajaremos, así que si teneis dudas de su funcionamiento idlas haciendo ahora.

LordPakusBlog
Sin más, espero que os hayais divertido y hayais aprendido algo.

Nos vemos

Entradas populares