一个简单的基于OpenGL的Lua的游戏引擎的实例
2011-07-07 18:31
645 查看
学习了几天Lua,今天突然想为Lua写一个简单的游戏引擎方便使用Lua单独的开发游戏,下面是一个基本的代码(很简单), Lua的代码也测试通过了但还不完整,稍候再发上来
代码如下:
代码如下:
#define PENQ_LUAGAME #include <string.h> #include <GL/gl.h> #include <GL/glu.h> #include <GL/glut.h> #include <lua/lua.h> #include <lua/lauxlib.h> #include <lua/lualib.h> #include "FreeImage.h" enum { LGME_MOVE = 0x00000001, LGME_DOWN = 0x00000002, LGME_DOWNMOVE = 0x00000004, LGME_UP = 0x00000008, LGME_ENTRY = 0x00000010, LGME_LEAVE = 0x00000020 }; struct LGMain { lua_State * L; GLint w; GLint h; GLfloat zoom; GLuint mouse_event; GLuint key_event; }G_Main = {NULL,0, 0, 0.0f, 0, 0}; struct LGImage { GLint width; GLint height; GLuint texture; GLint has_alpha_channel; }; typedef struct LGImage LGImage; typedef struct { int w; int h; unsigned char *buf; GLint has_alpha_channel; }GLBITMAP; GLBITMAP * FIBitmap2GLBitmap(FIBITMAP *fibmp) { int i, j, k; int pitch = FreeImage_GetPitch(fibmp); unsigned char *bits = FreeImage_GetBits(fibmp); int bpp = FreeImage_GetBPP(fibmp); GLBITMAP *glbmp = (GLBITMAP *)malloc(sizeof(GLBITMAP)); RGBQUAD *palette = NULL; if ( !glbmp ) return NULL; glbmp->has_alpha_channel = 0; glbmp->w = FreeImage_GetWidth(fibmp); glbmp->h = FreeImage_GetHeight(fibmp); switch ( bpp ) { case 8: if ( !(palette = FreeImage_GetPalette(fibmp)) ) return NULL; if ( !(glbmp->buf = (unsigned char *)malloc(glbmp->w*glbmp->h*3)) ) return NULL; for ( i = 0; i < glbmp->h; ++i ) { for ( j = 0; j < glbmp->w; ++j ) { k = bits[i*pitch+j]; glbmp->buf[(i*glbmp->w+j)*3+0] = palette[k].rgbRed; glbmp->buf[(i*glbmp->w+j)*3+1] = palette[k].rgbGreen; glbmp->buf[(i*glbmp->w+j)*3+2] = palette[k].rgbBlue; } } break; case 24: if ( !(glbmp->buf = (unsigned char *)malloc(glbmp->w*glbmp->h*3)) ) return NULL; for ( i = 0; i < glbmp->h; ++i ) { for ( j = 0; j < glbmp->w; ++j ) { glbmp->buf[(i*glbmp->w+j)*3+0] = bits[i*pitch+j*3+2]; glbmp->buf[(i*glbmp->w+j)*3+1] = bits[i*pitch+j*3+1]; glbmp->buf[(i*glbmp->w+j)*3+2] = bits[i*pitch+j*3+0]; } } break; case 32: if ( !(glbmp->buf = (unsigned char *)malloc(glbmp->w*glbmp->h*4)) ) return NULL; glbmp->has_alpha_channel = 1; for ( i = 0; i < glbmp->h; ++i ) { for ( j = 0; j < glbmp->w; ++j ) { glbmp->buf[(i*glbmp->w+j)*4+0] = bits[i*pitch+j*4+2]; glbmp->buf[(i*glbmp->w+j)*4+1] = bits[i*pitch+j*4+1]; glbmp->buf[(i*glbmp->w+j)*4+2] = bits[i*pitch+j*4+0]; glbmp->buf[(i*glbmp->w+j)*4+3] = bits[i*pitch+j*4+3]; } } break; default: return NULL; } return glbmp; } void FreeGLBitmap(GLBITMAP *glbmp) { if ( glbmp ) { if ( glbmp->buf ) free(glbmp->buf); free(glbmp); } } LGImage * LoadLGImage(const char *filename) { FREE_IMAGE_FORMAT fif = FIF_UNKNOWN; FIBITMAP *bitmap = NULL; GLBITMAP *glbmp = NULL; LGImage *image = NULL; fif = FreeImage_GetFileType(filename, 0); if ( FIF_UNKNOWN == fif ) { fif = FreeImage_GetFIFFromFilename(filename); if ( FIF_UNKNOWN == fif ) return 0; } if ( FreeImage_FIFSupportsReading(fif) ) bitmap = FreeImage_Load(fif, filename, 0); if ( !bitmap ) return 0; if ( !(glbmp = FIBitmap2GLBitmap(bitmap)) ) { FreeImage_Unload(bitmap); return 0; } if ( !(image = (LGImage *)malloc(sizeof(LGImage))) ) { FreeGLBitmap(glbmp); FreeImage_Unload(bitmap); return 0; } image->width = glbmp->w; image->height = glbmp->h; image->has_alpha_channel = glbmp->has_alpha_channel; glGenTextures(1, &image->texture); glBindTexture(GL_TEXTURE_2D, image->texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); if ( glbmp->has_alpha_channel ) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, glbmp->w, glbmp->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, glbmp->buf); else glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, glbmp->w, glbmp->h, 0, GL_RGB, GL_UNSIGNED_BYTE, glbmp->buf); FreeGLBitmap(glbmp); FreeImage_Unload(bitmap); return image; } static void init_gl() { glShadeModel(GL_SMOOTH); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClearDepth(1.0f); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); } static void reshape(GLint w, GLint h) { if ( 0 == h ) h = 1; G_Main.w = w; G_Main.h = h; G_Main.zoom = (GLfloat)(w > h ? h : w); glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f, (GLfloat)w/(GLfloat)h, 0.1f, G_Main.zoom); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); if ( G_Main.L ) { lua_getglobal(G_Main.L, "LuaGame_Reshape"); lua_pushnumber(G_Main.L, w); lua_pushnumber(G_Main.L, h); lua_pcall(G_Main.L, 2, 0, 0); } } static void display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glTranslatef(-(GLfloat)(G_Main.w>>1), -(GLfloat)(G_Main.h>>1), -G_Main.zoom); if ( G_Main.L ) { lua_getglobal(G_Main.L, "LuaGame_Display"); lua_pcall(G_Main.L, 0, 0, 0); } glutSwapBuffers(); } static void mouse(int button, int state, int x, int y) { if ( GLUT_DOWN == state ) { if ( G_Main.mouse_event & LGME_DOWN ) { if ( G_Main.L ) { lua_getglobal(G_Main.L, "LuaGame_MouseDown"); lua_pushnumber(G_Main.L, button); lua_pushnumber(G_Main.L, x); lua_pushnumber(G_Main.L, y); lua_pcall(G_Main.L, 3, 0, 0); } } } else if ( GLUT_UP == state ) { if ( G_Main.mouse_event & LGME_UP ) { if ( G_Main.L ) { lua_getglobal(G_Main.L, "LuaGame_MouseUp"); lua_pushnumber(G_Main.L, button); lua_pushnumber(G_Main.L, x); lua_pushnumber(G_Main.L, y); lua_pcall(G_Main.L, 3, 0, 0); } } } } static void mouse_move(int x, int y) { if ( G_Main.mouse_event & LGME_MOVE ) { if ( G_Main.L ) { lua_getglobal(G_Main.L, "LuaGame_MouseMove"); lua_pushnumber(G_Main.L, x); lua_pushnumber(G_Main.L, y); lua_pcall(G_Main.L, 2, 0, 0); } } } static void mouse_down_move(int x, int y) { if ( G_Main.mouse_event & LGME_DOWNMOVE ) { if ( G_Main.L ) { lua_getglobal(G_Main.L, "LuaGame_MouseDownMove"); lua_pushnumber(G_Main.L, x); lua_pushnumber(G_Main.L, y); lua_pcall(G_Main.L, 2, 0, 0); } } } static void mouse_foucs(int state) { if ( GLUT_LEFT == state ) { if ( G_Main.mouse_event & LGME_LEAVE ) { if ( G_Main.L ) { lua_getglobal(G_Main.L, "LuaGame_MouseLeave"); lua_pcall(G_Main.L, 0, 0, 0); } } } else if ( GLUT_ENTERED == state ) { if ( G_Main.mouse_event & LGME_ENTRY ) { if ( G_Main.L ) { lua_getglobal(G_Main.L, "LuaGame_MouseEntry"); lua_pcall(G_Main.L, 0, 0, 0); } } } } static void keyboard(unsigned char key, int x, int y) { if ( G_Main.key_event ) { if ( G_Main.L ) { lua_getglobal(G_Main.L, "LuaGame_Keyboard"); lua_pushnumber(G_Main.L, key); lua_pushnumber(G_Main.L, x); lua_pushnumber(G_Main.L, y); lua_pcall(G_Main.L, 3, 0, 0); } } } /* $@@ 引擎初始化 $@ 返回值: 成功true, 否则false */ static int LuaGame_Init(lua_State *L) { int argc = 1; char *argv[1] = {"LuaGame"}; #if defined(FREEIMAGE_LIB) FreeImage_Initialise(0); #endif glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA); lua_pushboolean(L, 1); return 1; } /* $@@ 创建窗体(5个参数) $@ 第一个参数: 窗体名 $@ 第二个参数: 窗体初始位置的x坐标 $@ 第三个参数: 窗体初始位置的y坐标 $@ 第四个参数: 窗体的宽 $@ 第五个参数: 窗体的高 $@ 返回值: 成功true, 否则false */ static int LuaGame_CreateWindow(lua_State *L) { const char *caption = luaL_checkstring(L, 1); int x = luaL_checknumber(L, 2); int y = luaL_checknumber(L, 3); int w = luaL_checknumber(L, 4); int h = luaL_checknumber(L, 5); glutInitWindowPosition(x, y); glutInitWindowSize(w, h); if ( glutCreateWindow(caption) ) { init_gl(); glutMouseFunc(mouse); glutMotionFunc(mouse_down_move); glutPassiveMotionFunc(mouse_move); glutEntryFunc(mouse_foucs); glutKeyboardFunc(keyboard); glutReshapeFunc(reshape); glutDisplayFunc(display); glutIdleFunc(display); lua_pushboolean(L, 1); } else lua_pushboolean(L, 0); return 1; } /* $@@ 开启鼠标移动监听事件 */ static int LuaGame_SetMouseMove(lua_State *L) { G_Main.mouse_event |= LGME_MOVE; return 0; } /* $@@ 开启鼠标按下监听事件 */ static int LuaGame_SetMouseDown(lua_State *L) { G_Main.mouse_event |= LGME_DOWN; return 0; } /* $@@ 开启鼠标按下时移动监听事件 */ static int LuaGame_SetMouseDownMove(lua_State *L) { G_Main.mouse_event |= LGME_DOWNMOVE; return 0; } /* $@@ 开启鼠标弹起监听事件 */ static int LuaGame_SetMouseUp(lua_State *L) { G_Main.mouse_event |= LGME_UP; return 0; } /* $@@ 开启鼠标进入监听事件 */ static int LuaGame_SetMouseEntry(lua_State *L) { G_Main.mouse_event |= LGME_ENTRY; return 0; } /* $@@ 开启鼠标离开监听事件 */ static int LuaGame_SetMouseLeave(lua_State *L) { G_Main.mouse_event |= LGME_LEAVE; return 0; } /* $@@ 设置键盘监听事件 */ static int LuaGame_SetKeyboard(lua_State *L) { G_Main.key_event = 1; return 0; } static int LuaGame_CreateImage(lua_State *L) { const char *filename = luaL_checkstring(L, 1); LGImage *image = NULL; if ( filename ) { if ( (image = LoadLGImage(filename)) ) { lua_pushboolean(L, 1); lua_pushlightuserdata(L, image); return 2; } } lua_pushboolean(L, 0); lua_pushlightuserdata(L, NULL); return 2; } static int LuaGame_GetImageWidth(lua_State *L) { LGImage *image = lua_touserdata(L, 1); image ? lua_pushnumber(L, image->width) : lua_pushnil(L); return 1; } static int LuaGame_GetImageHeight(lua_State *L) { LGImage *image = lua_touserdata(L, 1); image ? lua_pushnumber(L, image->height) : lua_pushnil(L); return 1; } static int LuaGame_RenderImage(lua_State *L) { LGImage *image = (LGImage *)lua_touserdata(L, 1); GLint x = (GLint)luaL_checknumber(L, 2); GLint y = (GLint)luaL_checknumber(L, 3); if ( image ) { glEnable(GL_TEXTURE_2D); if ( image->has_alpha_channel ) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_DEPTH_TEST); } else { glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); } glBindTexture(GL_TEXTURE_2D, image->texture); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3d(x, y-image->height, 0); glTexCoord2f(1.0f, 0.0f); glVertex3d(x+image->width, y-image->height, 0); glTexCoord2f(1.0f, 1.0f); glVertex3d(x+image->width, y, 0); glTexCoord2f(0.0f, 1.0f); glVertex3d(x, y, 0); glEnd(); if ( image->has_alpha_channel ) { glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); } glDisable(GL_TEXTURE_2D); } return 0; } static int LuaGame_Release(lua_State *L) { return 0; } static int LuaGame_Start(lua_State *L) { glutMainLoop(); #if defined(FREEIMAGE_LIB) FreeImage_DeInitialise(); #endif return 0; } /* $@@ 动态库导出函数(格式: luaopen_+库名) */ #define LUAGAME_REGFUNC(l, f) lua_register(l, #f, f) int luaopen_LuaGame(lua_State *L) { G_Main.L = L; LUAGAME_REGFUNC(L, LuaGame_Init); LUAGAME_REGFUNC(L, LuaGame_CreateWindow); LUAGAME_REGFUNC(L, LuaGame_SetMouseMove); LUAGAME_REGFUNC(L, LuaGame_SetMouseDown); LUAGAME_REGFUNC(L, LuaGame_SetMouseDownMove); LUAGAME_REGFUNC(L, LuaGame_SetMouseUp); LUAGAME_REGFUNC(L, LuaGame_SetMouseEntry); LUAGAME_REGFUNC(L, LuaGame_SetMouseLeave); LUAGAME_REGFUNC(L, LuaGame_SetKeyboard); LUAGAME_REGFUNC(L, LuaGame_CreateImage); LUAGAME_REGFUNC(L, LuaGame_GetImageWidth); LUAGAME_REGFUNC(L, LuaGame_GetImageHeight); LUAGAME_REGFUNC(L, LuaGame_RenderImage); LUAGAME_REGFUNC(L, LuaGame_Start); LUAGAME_REGFUNC(L, LuaGame_Release); return 0; }
相关文章推荐
- 如何创建一个简单的基于OleTx协议的WCF事务实例
- 转载一个简单的lua展示【COCOS2DX-LUA 脚本开发之一】LUA语言基础在Cocos2dX游戏中使用Lua脚本进行游戏开发(基础篇)并介绍脚本在游戏中详细用途!
- 在MFC下使用OpenGL的一个简单的例子(基于单文档程序)
- python hard way中的一个小例子,简单的游戏引擎
- 基于MFC的OpenGL的一个简单例子
- 基于opengl的游戏引擎
- [入门教程]使用Cocos2d-html5游戏引擎编写一个简单的游戏 第一回合: 搭建开发环境
- 用OpenGL简单编写的一个最简单贪吃蛇游戏
- 基于Qt5.9Creator的一个简单socket通信实例(C++语言,win7 64系统)
- 从零开始做一个基于pygame引擎的躲闪小游戏(一)-画矩形、画圆、简单的碰撞检测
- 一个基于python简单的装饰器实例
- 【Android】基于andengine游戏引擎的简单游戏实现(模拟控制器、tiledmap地图)
- 一个基于游戏引擎的可视化框架及应用
- 学习OpenGL(一)一个简单的实例
- cocos2d-x学习(3)---游戏实例开发:一个简单的射击游戏二
- Lua2D游戏脚本引擎(渲染OpenGL) (源码放出)
- Cocos2d-x-Lua 开发一个简单的游戏(记数字步进白色块状)
- 一个简单的游戏框架:Lua相关
- 基于C++和Lua的移动游戏引擎Leadwerks 3发布
- 一个简单的Unity游戏开发框架(lua自更新)