SDL游戏之路(八)--android+sdl+ndk+3d

因为使用到SDL与opengl的结合

本来以为window,linux下添加3D成功后,android平台也会很顺利。

结果遇到了一个讨厌的错误:

unimplemented OpenGL ES API error

经过google,baidu,发现此错误原因五花八门,解决方法也是千奇百怪。最终也没有找到适合我的。


好吧,这个问题还是解决了。方法有两种:

1.使用 opengl es2. 编译连接的库,头文件,都改成 opengl es2 的内容。这样我的手机测试没有问题。


方法一有什么问题呢?opengl es2 与 opengl es1 差别很大。 而我的非手机端需要使用opengl跟opengl es比较接近。

于是需要只使用opengl es。

最终解决方法是,修改SDL_config_android.h

#define SDL_VIDEO_RENDER_OGL_ES2    0

这样重新编译出了适合手机的 sdl.so


结果发现,我电脑上的模拟器也能运行我的测试程序了,意外收获。

背景上绘制一个旋转的矩形:

主函数:

#include "../sk_game/sk_inc.h"
#include "../sk_src/SkGame.h"

#ifdef __ANDROID__

#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>
#include "SkyparkJni.hpp"
skypark::SkyparkJni g_SkyparkJni;
#ifdef __cplusplus
extern "C" {
#endif
//jni接口 --begin
	void Java_cn_skypark_shouhulongzhu_SkyparkGame_mySetAsset(JNIEnv* env, jclass tis,
			jobject assetManager) {
		AAssetManager * pAAssetManager = AAssetManager_fromJava(env, assetManager);
		g_SkyparkJni.setAAssetManager(env, pAAssetManager);
	}

//jni接口 --end
#ifdef __cplusplus
}
#endif
#endif

#ifdef HAVE_OPENGL

static void Render() {
	//绘制2D的游戏场景

	glPushMatrix();
	glLoadIdentity();
	glOrtho(-g_iScreenWidthHalf, g_iScreenWidthHalf, g_iScreenHeightHalf,
			-g_iScreenHeightHalf, -1000, 1000);
	g_SkGame.show(&g_SkShow);
	glPopMatrix();

	//绘制3D图形
	{
#ifndef __ANDROID__
		glBegin(GL_QUADS);
		glVertex2f(-50,-50);
		glVertex2f(50,-50);
		glVertex2f(50,50);
		glVertex2f(-50,50);
		glEnd();
#else

		GLfloat q3[] = {
			-50,-50,
			50,-50,
			50,50,
			-50,50
		};

		//glEnableClientState(GL_VERTEX_ARRAY);
		glVertexPointer(2, GL_FLOAT, 0, q3);
		glDrawArrays(GL_TRIANGLE_FAN,0,4);
		//glDisableClientState(GL_VERTEX_ARRAY);

#endif
	}

	//绘制3D的立方体
	//draw3D();
	glRotatef(5.0, 1.0, 1.0, 1.0);
}

#endif

int main(int argc, char *argv[]) {
	//游戏引擎初始化
	int iRet = g_SkComm.init();
	if (iRet != 0) {
		g_SkComm.log("[%s][%d]g_SkComm.init!=0 %d,%s\n", __FILE__, __LINE__,
				iRet, g_SkComm.getErrMsg());
		exit(0);
	}
	//显示模块初始化
	g_SkShow.init(g_SkComm.getRenderer());

	Sint64 siGameBegin = g_SkGameTimer.getGameMTime();
	g_SkGameTimer.m_siGameLastTime = siGameBegin;
	g_SkGameThread.run(g_SkGameTimer.m_siGameLastTime);
	Sint64 siShowBegin = siGameBegin;
	//游戏初始化
	g_SkGame.init();
	//g_SkComm.msleep(3000);
	//g_SkComm.myexit();

#ifdef HAVE_OPENGL
	{
#ifdef __ANDROID__

		glMatrixMode(GL_PROJECTION | GL_MODELVIEW);
		glLoadIdentity();
		//坐标统一,设置大小为窗口一半
		glOrtho(-g_iScreenWidthHalf, g_iScreenWidthHalf, g_iScreenHeightHalf,
				-g_iScreenHeightHalf, -1000, 1000);
		sk_gl_setOrtho(-g_iScreenWidthHalf, g_iScreenWidthHalf,
				g_iScreenHeightHalf, -g_iScreenHeightHalf, 0, 1);
#else
		//g_SkComm.log("[%s][%d]context=%d", __FILE__, __LINE__, context);
		glMatrixMode(GL_PROJECTION | GL_MODELVIEW);
		glLoadIdentity();
		//坐标统一,设置大小为窗口一半
		glOrtho(-g_iScreenWidthHalf, g_iScreenWidthHalf, g_iScreenHeightHalf,
				-g_iScreenHeightHalf, -1000, 1000);
		sk_gl_setOrtho(-g_iScreenWidthHalf, g_iScreenWidthHalf,
				g_iScreenHeightHalf, -g_iScreenHeightHalf, 0, 1);
#endif
	}
#endif
	while (true) {
		SkEvent event;
		while (g_SkComm.poll_event(&event)) {
			g_SkGame.doEvent(&event);
		}
		Sint64 iCurTime = g_SkGameTimer.getGameMTime();
		while (g_SkGameTimer.m_siGameLastTime + g_SkGameTimer.siGameLoopMsec
				< iCurTime) {
			g_SkGameTimer.m_siGameLastTime += g_SkGameTimer.siGameLoopMsec;
			g_SkGameThread.run(g_SkGameTimer.m_siGameLastTime);
		}
		bool bShow = true;
		while (siShowBegin + g_SkGameTimer.siShowLoopMsec < iCurTime) {
			siShowBegin += g_SkGameTimer.siShowLoopMsec;
			if (bShow) {
#ifdef HAVE_OPENGL
				Render();
#else
				g_SkGame.show(&g_SkShow);
#endif
				g_SkShow.flush();
				bShow = false;
			}
		}
		//g_SkComm.log("[%s][%d]\n", __FILE__, __LINE__);
		//g_SkComm.msleep(3000);
		g_SkComm.msleep(SkGameTimer::siGameManLoopMsec);
	}
	g_SkComm.myexit();
	return 0;
}


效果如下:



#include #include //用键盘控制精灵移动 int main(int argc, char ** argv) { SDL_Surface * screen; //主表面 SDL_Surface * image; //用来放MM-----的图片信息(像素) SDL_Surface * PlayerImage; //用来测试的图片 SDL_Event event; Uint32 BeginTicks, EndTicks; SDL_Rect PRect, BRect; //PRect对应精灵的移动的小图位置(实现动画),BRect对应精灵在屏幕的位置。 unsigned char PlayerStarts = 0; unsigned char PlayerIndex = 0; bool bAppRun = true; //初始化SDL if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) == -1) { fprintf(stderr, "SDL_Init %s\n", SDL_GetError()); return -1; } //初始化成功设置退出要调用的函数SDL_Quit atexit(SDL_Quit); //创建一个640X480 16-bit 模式的主表面 16位可以让MM的效果好看一点 screen = SDL_SetVideoMode(230, 230, 16, SDL_SWSURFACE); if (screen == NULL) { fprintf(stderr, "Couldn't set 640x480x8 video mode %s\n", SDL_GetError()); return -1; } //读取MM图片信息,并创建一个表面,并把数据填入该表面中。 image = SDL_LoadBMP("./mm.bmp"); //请在终端里运行该程序 if (image == NULL) { fprintf(stderr, "Couldn't load MM, %s\n", SDL_GetError()); //遗憾你不能显示MM了,不过你可以用图片浏览程序看。 return -1; } //读取player.bmp PlayerImage = SDL_LoadBMP("./player.bmp"); //请在终端里运行该程序 if (image == NULL) { fprintf(stderr, "Couldn't load MM, %s\n", SDL_GetError()); //遗憾你不能显示MM了,不过你可以用图片浏览程序看。 return -1; } //读取第一个像素 Uint8 key = *((Uint8 *)PlayerImage->pixels); //设置色键 SDL_SetColorKey(PlayerImage, SDL_SRCCOLORKEY, key); //有了MM的表面了,就可以显示了。 //将MM的表面画在我们的主表面上,用MM来作为背景 if (SDL_BlitSurface(image, NULL, screen, NULL) < 0) { //解释一下NULL,第一个是按照image的尺寸显示,第二个是默认显示。你也可以指定大小,不过要用到SDL_Rect你可以看一看帮助。 fprintf(stderr, "BlitSurface error: %s\n", SDL_GetError()); //看看提示吧 return -1; } PRect.x = 0; //初始化动画显示的图片。 PRect.y = 0; PRect.w = 32; PRect.h = 48; BRect.x = 0; //初始化精灵的位置。 BRect.y = 0; BRect.w = 32; BRect.h = 48; //贴上测试用的表面 if (SDL_BlitSurface(PlayerImage, &PRect, screen, &BRect) w, image->h); BeginT
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值