1. 程式人生 > >一個簡單的基於OpenGL的Lua的遊戲引擎的例項

一個簡單的基於OpenGL的Lua的遊戲引擎的例項

學習了幾天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);
		}
	}
}






/*
	
[email protected]
@ 引擎初始化 [email protected] 返回值: 成功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; } /*
[email protected]
@ 建立窗體(5個引數) [email protected] 第一個引數: 窗體名 [email protected] 第二個引數: 窗體初始位置的x座標 [email protected] 第三個引數: 窗體初始位置的y座標 [email protected] 第四個引數: 窗體的寬 [email protected] 第五個引數: 窗體的高 [email protected] 返回值: 成功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; } /*
[email protected]
@ 開啟滑鼠移動監聽事件 */ static int LuaGame_SetMouseMove(lua_State *L) { G_Main.mouse_event |= LGME_MOVE; return 0; } /* [email protected]@ 開啟滑鼠按下監聽事件 */ static int LuaGame_SetMouseDown(lua_State *L) { G_Main.mouse_event |= LGME_DOWN; return 0; } /* [email protected]@ 開啟滑鼠按下時移動監聽事件 */ static int LuaGame_SetMouseDownMove(lua_State *L) { G_Main.mouse_event |= LGME_DOWNMOVE; return 0; } /* [email protected]@ 開啟滑鼠彈起監聽事件 */ static int LuaGame_SetMouseUp(lua_State *L) { G_Main.mouse_event |= LGME_UP; return 0; } /* [email protected]@ 開啟滑鼠進入監聽事件 */ static int LuaGame_SetMouseEntry(lua_State *L) { G_Main.mouse_event |= LGME_ENTRY; return 0; } /* [email protected]@ 開啟滑鼠離開監聽事件 */ static int LuaGame_SetMouseLeave(lua_State *L) { G_Main.mouse_event |= LGME_LEAVE; return 0; } /* [email protected]@ 設定鍵盤監聽事件 */ 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; } /* [email protected]@ 動態庫匯出函式(格式: 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; }



相關推薦

基於Blazor寫一個簡單的五子棋遊戲

寫這個五子棋遊戲,其實主要目的是想嘗試一下微軟新作Blazor。Blazor對於那些搞.NET的程式設計師,又想做一些前端工作,真的挺友好,不用一句JS就可搞定前端互動,美哉。現在已經有很流行的前端框架,如vue、react、angular等,微軟出這個blazor框架,目前觀測下來,在國外還滿火的,國內

基於 Roslyn 實現一個簡單的條件解析引擎

# 基於 Roslyn 實現一個簡單的條件解析引擎 ## Intro 最近在做一個勳章的服務,我們想定義一些勳章的獲取條件,滿足條件之後就給使用者頒發一個勳章,定義條件的時候會定義需要哪些引數,引數的型別,獲取勳章的時候會提供鎖需要的引數,有一些內建的引數,內建的引數解析器(ParamResolver)。

用java做一個簡單的打字遊戲

Java也是可以做桌面程式的。只不過需要執行在裝有JDK的電腦環境上,所以應用不是很廣泛,但是用來提高自身的程式碼邏輯還是可以的!偶有一天看到金山的打字通,就想起何不做個簡單的打字遊戲用來練練手。於是就有了下文 首先建一個類MyTyping,只有main方法   執行main方法

java實現一個簡單的五子棋遊戲

import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Toolkit; import java.awt.event.MouseEvent; import

cocos2dx 製作一個簡單的三消遊戲

很多時候在學習或者嘗試做遊戲的時候總是會無疾而終,現在把自己的收穫和做出來的示例記下來給自己一個督促吧。 平臺環境: cocos2dx(3.8)+lua vs2012 關於三消遊戲的認識 基礎的三消遊戲是在一個二維空間上,放置不同的元素,通過滑動消除相

用c++寫一個簡單的打字遊戲

#include <graphics.h>  //圖形介面的標頭檔案 #include <conio.h> #include <time.h>     //隨機數 #include <stdio.h> #include <

比較簡單的2D遊戲引擎C++類

//GameEngine.h檔案: #pragma once#include <windows.h> LRESULT CALLBACK WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);clas

Qt5.9佈局管理器例項(QVBoxLayout,QHBoxLayout,QGridLayout)(一個簡單的手寫介面例項

本部落格主要總結用Qt5.9手寫一個介面,該介面的pushButton,linetxt控制元件都用程式碼來實現,同時手寫水平佈局、垂直佈局、柵格佈局,具體的用法如下所述。注意:QGridLayout,QHLayout,QVLayout三個佈局管理器類,可以混合包括,但是有且只

基於Laya遊戲引擎實現微信小遊戲排行榜

我們都知道,微信小遊戲和小程式目前風頭十足,很多公司都逐漸增加了相關業務線來迅速推廣自己的產品和搶佔使用者群。說到微信小遊戲,就不得不提到排行榜這個功能,就目前遊戲行業,似乎都離不開排行榜這個重要功能,使用者很大一部分留存都是依仗這個看似不起眼的模組。那麼,微信

一個簡單的Android Intent使用例項,包括顯式/隱式2種呼叫

最近又開始接觸了一下Android,準備將每次寫的小Demo都在這裡備份一下,以防以後忘記了,Demo相對來說都比較簡單,內容也比較片面。今天主要就是練習了一下intent的使用,主要涉及到的知識點有:intent傳值,隱式呼叫。 1.傳值: 傳送端:intent.putE

Scratch中做一個簡單迷宮小遊戲,值得您收藏!

“ 孩子們都喜歡從彎彎繞繞中體驗冒險與成功,如果讓孩子參與迷宮設計,在組合排列中設計一條又一條“道路”,他的思維一定可以得到極大的鍛鍊,其中的成就感也是不言而喻的。”01——效果展示—---Scratc

一個簡單的Android 動態Fragment例項

很簡單的目錄結構,其中fragment2還是做為靜態UI使用,動態載入的是fragment1跟fragment3,這裡對fragment2的程式碼不再展示 先看看fragment1.java跟fragment3.java檔案,這裡沒什麼特別的。 package com.

用construct2製作一個簡單的platform遊戲

construct2作為一個簡單的遊戲製作工具,能為你們帶來製作遊戲的快樂,接下來我將講述一下有關construct中platform遊戲的製作.學習platform遊戲的製作,我們就可以輕鬆的做出類似超級馬里奧的遊戲了.下面我將帶來一個製作platform遊戲

老闆要我開發一個簡單的工作流引擎

第1關 一天,老闆找到我,說要做個簡單的工作流引擎。 我查了一天啥是工作流,然後做出瞭如下版本: 按順序新增任意個審批人組成一個連結串列,最後加一個結束節點 記錄當前審批人,當審批完後,審批人向後移動一位 當審批人對應結束節點時,流程結束 老闆:簡陋了點。 第2關 老闆又來了:要支援會籤節點。 我又查

一個簡單基於OpenGL的Lua的遊戲引擎例項

學習了幾天Lua,今天突然想為Lua寫一個簡單的遊戲引擎方便使用Lua單獨的開發遊戲,下面是一個基本的程式碼(很簡單), Lua的程式碼也測試通過了但還不完整,稍候再發上來程式碼如下:#define PENQ_LUAGAME #include <string.h>

物理引擎Havok的一個簡單例項(使用Ogre渲染)

    Intel免費了Havok物理引擎之後,好奇心驅使看了看,發現非常不錯,於是決定好好學習一下。Havok自帶的框架真的是非常複雜,網上這方面的資料又非常少,所以自己寫了一個比較簡單的例項,使用了

基於ABP做一個簡單的系統——實戰篇:4.基於富文字編輯器,Razor模板引擎生成內容並匯出Word 填坑記錄

起因 需求是這樣的,有一種協議需要生成,協議的模板是可配置的,在生成過程中,模板中的內容可以根據約定的標記進行替換(就像mvc的razor模板一樣)。生成後的內容還需要匯出成word或pdf。 常見的使用場景比如租賃協議生成,郵件內容模板生成等等,不要傻傻的hard-code像‘#name#’這樣的標記了。

Epii.js 一個極其簡單的Js模板引擎

idt 定義 images 更多 mas play 寫法 ren gin Epii.js 簡約而不簡單的JavaScript模板引擎 項目地址 https://github.com/epaii/epii.js 極低門檻,拿來即用,別忘記star

Java動畫 重力彈球 如鵬遊戲引擎 精靈 設計一個小球加速落地又減速彈起並反復直到停止的Java程序

ble ack pause ani ring pen nts game 遊戲 package com.swift; import com.rupeng.game.GameCore; public class BouncingBall implements Runnab

一個簡單基於BIO的RPC框架

簡單的 png 1-1 -s github 幫助 spa 兩個類 還需 github地址:https://github.com/Luyu05/BioRpcExample PART1:先來整體看下項目的構成 其中bio-rpc-core就是所謂的rpc框架 bio-rp