Mostrando entradas con la etiqueta motor de videojuegos. Mostrar todas las entradas
Mostrando entradas con la etiqueta motor de videojuegos. Mostrar todas las entradas

domingo, 12 de febrero de 2012

Arnow2D. Como crear una ventana sin GLUT.


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


Hola a todos...

Antes que nada mis disculpas por estar tanto tiempo sin escribir, pero entre la gripe y la vida personal me ha sido complicado escribir antes....

El capitulo de hoy tratará de algo tan sencillo como crear una ventana de windows (que luego nos servirá de base para el resto del proyecto). Esto ya lo hicimos en su momento aquí , pero como ya dije en su momento, no me gusta mucho usar glut, así que esta vez lo haremos usando la API de windows directamente (lo siento por los linuxeros, si hay algún voluntario para hacer el código en linux lo colgaré gustosamente).

Realmente en este capitulo he hecho poco, sencillamente copiar el capitulo 1 de nehe y reorganizarlo un poco... Veréis que poco a poco este código lo iré transformando hasta que el parecido con el principio sea mínimo pero haciendo lo que nosotros queremos que haga.

EDIT: Aquí teneis el link de descarga

Espero que os guste:

main.cpp

#include "Arnow2D.h"

HDC hDC=NULL; // Private GDI Device Context
HGLRC hRC=NULL; // Permanent Rendering Context
HWND hWnd=NULL; // Holds Our Window Handle
HINSTANCE hInstance; // Holds The Instance Of The Application

bool active=TRUE; // Window Active Flag Set To TRUE By Default
bool fullscreen=TRUE; // Fullscreen Flag Set To Fullscreen Mode By Default
bool keys[256]; // Array Used For The Keyboard Routine

int WINAPI WinMain( HINSTANCE hInstance, // Instance
HINSTANCE hPrevInstance, // Previous Instance
LPSTR lpCmdLine, // Command Line Parameters
int nCmdShow) // Window Show State
{
MSG msg; // Windows Message Structure
BOOL done=FALSE; // Bool Variable To Exit Loop

// Ask The User Which Screen Mode They Prefer
if (MessageBox(NULL,"Quieres ejecutar en modo fullscreen?", "FullScreen?",MB_YESNO|MB_ICONQUESTION)==IDNO)
{
fullscreen=FALSE; // Windowed Mode
}

// Create Our OpenGL Window
if (!CreateGLWindow("Arnow2D",640,480,16,fullscreen))
{
return 0; // Quit If Window Was Not Created
}

while(!done) // Loop That Runs While done=FALSE
{
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) // Is There A Message Waiting?
{
if (msg.message==WM_QUIT) // Have We Received A Quit Message?
{
done=TRUE; // If So done=TRUE
}
else // If Not, Deal With Window Messages
{
TranslateMessage(&msg); // Translate The Message
DispatchMessage(&msg); // Dispatch The Message
}
}
else // If There Are No Messages
{
// Draw The Scene.  Watch For ESC Key And Quit Messages From DrawGLScene()
if (active) // Program Active?
{
if (keys[VK_ESCAPE]) // Was ESC Pressed?
{
done=TRUE; // ESC Signalled A Quit
}
else // Not Time To Quit, Update Screen
{
DrawGLScene(); // Draw The Scene
SwapBuffers(hDC); // Swap Buffers (Double Buffering)
}
}

if (keys[VK_F1]) // Is F1 Being Pressed?
{
keys[VK_F1]=FALSE; // If So Make Key FALSE
KillGLWindow(); // Kill Our Current Window
fullscreen=!fullscreen; // Toggle Fullscreen / Windowed Mode
// Recreate Our OpenGL Window
if (!CreateGLWindow("NeHe's OpenGL Framework",640,480,16,fullscreen))
{
return 0; // Quit If Window Was Not Created
}
}
}
}

// Shutdown
KillGLWindow(); // Kill The Window
return (msg.wParam); // Exit The Program
}

Arnow2D.cpp

#include "Arnow2D.h"

extern HDC hDC; // Private GDI Device Context
extern HGLRC hRC; // Permanent Rendering Context
extern HWND    hWnd; // Holds Our Window Handle
extern HINSTANCE hInstance; // Holds The Instance Of The Application

extern bool active; // Window Active Flag Set To TRUE By Default
extern bool fullscreen; // Fullscreen Flag Set To Fullscreen Mode By Default
extern bool keys[256]; // Array Used For The Keyboard Routine

GLvoid ReSizeGLScene(GLsizei width, GLsizei height) // Resize And Initialize The GL Window
{
if (height==0) // Prevent A Divide By Zero By
{
height=1; // Making Height Equal One
}

glViewport(0,0,width,height); // Reset The Current Viewport

glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
glLoadIdentity(); // Reset The Projection Matrix

glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
glLoadIdentity(); // Reset The Modelview Matrix
}

int InitGL(GLvoid) // All Setup For OpenGL Goes Here
{
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
return TRUE; // Initialization Went OK
}

int DrawGLScene(GLvoid) // Here's Where We Do All The Drawing
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer
glLoadIdentity(); // Reset The Current Modelview Matrix
return TRUE; // Everything Went OK
}

GLvoid KillGLWindow(GLvoid) // Properly Kill The Window
{
if (fullscreen) // Are We In Fullscreen Mode?
{
ChangeDisplaySettings(NULL,0); // If So Switch Back To The Desktop
ShowCursor(TRUE); // Show Mouse Pointer
}

if (hRC) // Do We Have A Rendering Context?
{
if (!wglMakeCurrent(NULL,NULL)) // Are We Able To Release The DC And RC Contexts?
{
MessageBox(NULL,"Release Of DC And RC Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
}

if (!wglDeleteContext(hRC)) // Are We Able To Delete The RC?
{
MessageBox(NULL,"Release Rendering Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
}
hRC=NULL; // Set RC To NULL
}

if (hDC && !ReleaseDC(hWnd,hDC)) // Are We Able To Release The DC
{
MessageBox(NULL,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hDC=NULL; // Set DC To NULL
}

if (hWnd && !DestroyWindow(hWnd)) // Are We Able To Destroy The Window?
{
MessageBox(NULL,"Could Not Release hWnd.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hWnd=NULL; // Set hWnd To NULL
}

if (!UnregisterClass("OpenGL",hInstance)) // Are We Able To Unregister Class
{
MessageBox(NULL,"Could Not Unregister Class.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hInstance=NULL; // Set hInstance To NULL
}
}

/* This Code Creates Our OpenGL Window.  Parameters Are: *
 * title - Title To Appear At The Top Of The Window *
 * width - Width Of The GL Window Or Fullscreen Mode *
 * height - Height Of The GL Window Or Fullscreen Mode *
 * bits - Number Of Bits To Use For Color (8/16/24/32) *
 * fullscreenflag - Use Fullscreen Mode (TRUE) Or Windowed Mode (FALSE) */

BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)
{
GLuint PixelFormat; // Holds The Results After Searching For A Match
WNDCLASS wc; // Windows Class Structure
DWORD dwExStyle; // Window Extended Style
DWORD dwStyle; // Window Style
RECT WindowRect; // Grabs Rectangle Upper Left / Lower Right Values
WindowRect.left=(long)0; // Set Left Value To 0
WindowRect.right=(long)width; // Set Right Value To Requested Width
WindowRect.top=(long)0; // Set Top Value To 0
WindowRect.bottom=(long)height; // Set Bottom Value To Requested Height

fullscreen=fullscreenflag; // Set The Global Fullscreen Flag

hInstance = GetModuleHandle(NULL); // Grab An Instance For Our Window
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Size, And Own DC For Window.
wc.lpfnWndProc = (WNDPROC) WndProc; // WndProc Handles Messages
wc.cbClsExtra = 0; // No Extra Window Data
wc.cbWndExtra = 0; // No Extra Window Data
wc.hInstance = hInstance; // Set The Instance
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Load The Default Icon
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Load The Arrow Pointer
wc.hbrBackground = NULL; // No Background Required For GL
wc.lpszMenuName = NULL; // We Don't Want A Menu
wc.lpszClassName = "OpenGL"; // Set The Class Name

if (!RegisterClass(&wc)) // Attempt To Register The Window Class
{
MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

if (fullscreen) // Attempt Fullscreen Mode?
{
DEVMODE dmScreenSettings; // Device Mode
memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); // Makes Sure Memory's Cleared
dmScreenSettings.dmSize=sizeof(dmScreenSettings); // Size Of The Devmode Structure
dmScreenSettings.dmPelsWidth = width; // Selected Screen Width
dmScreenSettings.dmPelsHeight = height; // Selected Screen Height
dmScreenSettings.dmBitsPerPel = bits; // Selected Bits Per Pixel
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;

// Try To Set Selected Mode And Get Results.  NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
{
// If The Mode Fails, Offer Two Options.  Quit Or Use Windowed Mode.
if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
{
fullscreen=FALSE; // Windowed Mode Selected.  Fullscreen = FALSE
}
else
{
// Pop Up A Message Box Letting User Know The Program Is Closing.
MessageBox(NULL,"Program Will Now Close.","ERROR",MB_OK|MB_ICONSTOP);
return FALSE; // Return FALSE
}
}
}

if (fullscreen) // Are We Still In Fullscreen Mode?
{
dwExStyle=WS_EX_APPWINDOW; // Window Extended Style
dwStyle=WS_POPUP; // Windows Style
ShowCursor(FALSE); // Hide Mouse Pointer
}
else
{
dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window Extended Style
dwStyle=WS_OVERLAPPEDWINDOW; // Windows Style
}

AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); // Adjust Window To True Requested Size

// Create The Window
if (!(hWnd=CreateWindowEx( dwExStyle, // Extended Style For The Window
"OpenGL", // Class Name
title, // Window Title
dwStyle | // Defined Window Style
WS_CLIPSIBLINGS | // Required Window Style
WS_CLIPCHILDREN, // Required Window Style
0, 0, // Window Position
WindowRect.right-WindowRect.left, // Calculate Window Width
WindowRect.bottom-WindowRect.top, // Calculate Window Height
NULL, // No Parent Window
NULL, // No Menu
hInstance, // Instance
NULL))) // Dont Pass Anything To WM_CREATE
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

static PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be
{
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
1, // Version Number
PFD_DRAW_TO_WINDOW | // Format Must Support Window
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
PFD_DOUBLEBUFFER, // Must Support Double Buffering
PFD_TYPE_RGBA, // Request An RGBA Format
bits, // Select Our Color Depth
0, 0, 0, 0, 0, 0, // Color Bits Ignored
0, // No Alpha Buffer
0, // Shift Bit Ignored
0, // No Accumulation Buffer
0, 0, 0, 0, // Accumulation Bits Ignored
16, // 16Bit Z-Buffer (Depth Buffer)
0, // No Stencil Buffer
0, // No Auxiliary Buffer
PFD_MAIN_PLANE, // Main Drawing Layer
0, // Reserved
0, 0, 0 // Layer Masks Ignored
};

if (!(hDC=GetDC(hWnd))) // Did We Get A Device Context?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd))) // Did Windows Find A Matching Pixel Format?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

if(!SetPixelFormat(hDC,PixelFormat,&pfd)) // Are We Able To Set The Pixel Format?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

if (!(hRC=wglCreateContext(hDC))) // Are We Able To Get A Rendering Context?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

if(!wglMakeCurrent(hDC,hRC)) // Try To Activate The Rendering Context
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

ShowWindow(hWnd,SW_SHOW); // Show The Window
SetForegroundWindow(hWnd); // Slightly Higher Priority
SetFocus(hWnd); // Sets Keyboard Focus To The Window
ReSizeGLScene(width, height); // Set Up Our Perspective GL Screen

if (!InitGL()) // Initialize Our Newly Created GL Window
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

return TRUE; // Success
}

LRESULT CALLBACK WndProc( HWND hWnd, // Handle For This Window
UINT uMsg, // Message For This Window
WPARAM wParam, // Additional Message Information
LPARAM lParam) // Additional Message Information
{
switch (uMsg) // Check For Windows Messages
{
case WM_ACTIVATE: // Watch For Window Activate Message
{
if (!HIWORD(wParam)) // Check Minimization State
{
active=TRUE; // Program Is Active
}
else
{
active=FALSE; // Program Is No Longer Active
}

return 0; // Return To The Message Loop
}

case WM_SYSCOMMAND: // Intercept System Commands
{
switch (wParam) // Check System Calls
{
case SC_SCREENSAVE: // Screensaver Trying To Start?
case SC_MONITORPOWER: // Monitor Trying To Enter Powersave?
return 0; // Prevent From Happening
}
break; // Exit
}

case WM_CLOSE: // Did We Receive A Close Message?
{
PostQuitMessage(0); // Send A Quit Message
return 0; // Jump Back
}

case WM_KEYDOWN: // Is A Key Being Held Down?
{
keys[wParam] = TRUE; // If So, Mark It As TRUE
return 0; // Jump Back
}

case WM_KEYUP: // Has A Key Been Released?
{
keys[wParam] = FALSE; // If So, Mark It As FALSE
return 0; // Jump Back
}

case WM_SIZE: // Resize The OpenGL Window
{
ReSizeGLScene(LOWORD(lParam),HIWORD(lParam));  // LoWord=Width, HiWord=Height
return 0; // Jump Back
}
}

// Pass All Unhandled Messages To DefWindowProc
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}

Arnow2D.h:


#include <windows.h> // Header File For Windows
#include <gl\gl.h> // Header File For The OpenGL32 Library

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration For WndProc
BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag);
GLvoid KillGLWindow(GLvoid);
int DrawGLScene(GLvoid) ;
int InitGL(GLvoid);
GLvoid ReSizeGLScene(GLsizei width, GLsizei height) ;



Poco a poco lo iré remodelando y ampliando. A ver si mañana puedo poner los archivos en algún servidor para que os descargeis directamente el proyecto.

Que lo disfruteis

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

lunes, 26 de septiembre de 2011

LPGameEngine: Capitulo 0 . Reescribiendo el motor

Hola a todos

Antes que nada, disculpad la tardanza en postear, pero entre el niño y los númerosos cambios que estamos teniendo en la estructura del motor de juego me ha sido imposible postear antes...

Si os fijais vereis que la etiqueta que he puesto es la de LPGameEngine (por contra de la que utilizaba hasta ahora de GameEngine) y que la numeración la he empezado desde el principio... NO, no me he vuelto loco, al menos no más de lo que ya estaba en su momento :D.

Este cambio es debido a que todo el motor lo estoy reescribiendo desde 0 (aprovechando todo lo que puedo de lo que ya tenia hecho) a fin de obtener un proyecto más mantenible. Había llegado a un punto en que me resultaba imposible incluir más código sin que me petara todo.

Coincidiendo con la reescritura del motor, killrazor ha empezado a colaborar con el furor de un adolescente hormonado (y eso que me consta que la adolescencia le queda lejos :D ) y ha propuesto numerosos cambios en la estructura organizativa del proyecto que me han parecido muy acertadas:
1. Tenemos página del googlecode: http://code.google.com/p/lpgameengine/ Es decir, tenemos repositorio donde dejar el código. No lo volveré a dejar en el megaupload con los numerosos problemas que había. Si quereis saber como bajaros el proyecto echadle un ojo aquí y postead pidiendo ayuda si teneís problemas
2. Tenemos grupo de googlegrouphs: http://groups.google.com/group/lpgameengine . El blog seguirá sirviendo para postear los tutoriales y las noticias y el grupo servirá para plantear los problemas y los dilemas del desarollo del engine. Hechadle un ojo, vereis que tenemos temas interesantes abiertos.

Como temas interesantes adicionales tenemos que usaremos la libreria BOOST para el desarollo del proyecto (a dia de hoy la encuesta es bastante favorable a su uso) que no es más que una especie de C++++ :). kill tiene tutoriales en su blog.

Los capitulos que vaya posteando bajo esta etiqueta serán los que aporten nueva información al proyecto. No me dedicaré a repostear lo que hice en su momento en el motor original.

Aparte de todo esto, el grupo de trabajo que estamos ahora nos dedicaremos a tener un motor funcional, esto quiere decir que habrá muchos flecos abiertos para que el resto de la comunidad pueda ir rellenandolos si quiere (nuevos managers, mejora de los existentes, "nuevos drivers")

Sin más, ahora os subiré el capitulo del sound mananger.

Espero que os guste, que aprendais y que querrais participar.

Nos vemos

LordPakusBlog

domingo, 29 de mayo de 2011

Inicio del proyecto GameEngine

Hola a todos,

Si estais leyendo esto es por que os interesa la programación de videojuegos y las frikadas en general.

Si yo estoy escribiendo esto por que me siento en deuda con la sociedad por que ésta es la que ha subvencionado mi formación y por lo tanto, es merecedora que comparta mis conocimientos (que no son muchos, ya os aviso ahora).

Dicho esto, muchos os planteareis el porqué de crear un motor de videojuegos. Los motivos pueden ser varios, pero normalmente, en nuestro caso, es el hecho de aprender. Adicionalmente podremos usar estos conocimientos para crear videojuegos, pero yo creo que eso es lo menos importante :D.

Muchos de vosotros habreís creado ya vuestro juegos amateur (si no es así tranquilo, ya irás aprendiendo) y el proyecto más grande con el que habreis trabajado contará con 1k o 10k de lineas de código propio. Bien, esto en el mundo real no es así. En el mundo real el código ocupa centenares de miles de lineas de código (y no estoy exagerando, más bien me estoy quedando corto)  creado por decenas por programadores cada uno de ellos con estilos de programación y aptitudes diferentes. Si cada vez que hicieramos un juego tuvieramos esas condiciones de trabajo nuestros proyectos moririan antes de nacer. Es por ello que apareció el concepto de game engine.

Un game engine es un conjunto de funcionalidades más o menos extensa que nos permite crear juegos con menos esfuerzo que el nos implicaria hacerlos sin engine. Lógicamente, las horas de dedicación para hacer un motor de juegos es (¿bastante?) superior al de hacer solamente un juego, pero a mi modo de ver, a la (no muy) larga compensa.

Así pues, a medida que vaya creando mi propio motor de videojuegos iré posteando el código y la filosofia a seguir a fin de que vosotros también podais crear vuestro propio motor (o copypastearos el mio). Obviamente, soy humano, así que haré fallos, tanto de código como de diseño y os insto a que vuestro feedback ayude a mejorar el proyecto.

Ya solo por finalizar, si os interesa este post y no teneis muy claro C++ como funciona, iroslo repasando, ya que el código estará en este lenguaje y no tengo pensado hacer cursillos de C++ (por internés ya hay muchos y muy buenos)...

En fin, aqui lo dejo, en breve nos veremos con el inicio del proyecto.

Lord Pakus


LordPakusBlog

sábado, 28 de mayo de 2011

1, 2 ,3 ... probando probando...

Esta es la primera entrada a un blog que intenta difundir conocimiento de lo que se (que no es mucho) y de lo que vaya aprendiendo (que espero que sea considerable)....

 Ahora mismo no dispongo de mucho tiempo, así que supongo que este blog estará un poco muerto durante un tiempo pero uno de mis objetivos a corto-medio-largo plazo (vamos, cuando caiga) es poder enseñar a implementar un motor de videojuegos por fasciculos....

De mientras, para ir abriendo boca, os pongo el link de mi proyecto final de carrera. No tiene nada que ver con los videojuegos pero creo que es una frikada digna de mención..."Implementación y evaluación de la factorización de cholesky mediante TBB y threads (y SSE)"


Nos vemos
LordPakusBlog

Entradas populares