您的位置:首页 > 移动开发 > Android开发

android 3D 游戏实现之综合实例(初步)

2011-05-25 17:07 489 查看
效果比5月份那份代码和谐了一点,但仍有待改进,现在我将代码发上来。


完整项目可以去http://simdanfeg.download.csdn.net/处下载

(1)Activity类

package sim.feel;

import java.io.IOException;
import java.io.InputStream;

import android.app.Activity;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;

public class AdvancedExample extends Activity {
// GLSurfaceView
private GLSurfaceView glView;
// 实例化MyRenderer对象
private MyRenderer mr = new MyRenderer();

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 设置无标题
requestWindowFeature(Window.FEATURE_NO_TITLE);
// 设置全屏
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
// init loadFile
new LoadFile(getResources());
glView = new GLSurfaceView(this);
glView.setRenderer(mr);
setContentView(glView);
}
}

// 载入文件
class LoadFile {
public static Resources resource;

public LoadFile(Resources res) {
resource = res;
}

// file
public static InputStream loadf(String fileName) {
AssetManager am = LoadFile.resource.getAssets();
try {
return am.open(fileName);
} catch (IOException e) {
return null;
}
}

// image
public static Bitmap loadi(int id) {
Bitmap bitmap = BitmapFactory.decodeResource(resource, id);
return bitmap;
}
}


(2)Renderer类

package sim.feel;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.graphics.Bitmap;
import android.opengl.GLSurfaceView.Renderer;

import com.threed.jpct.Camera;
import com.threed.jpct.Config;
import com.threed.jpct.FrameBuffer;
import com.threed.jpct.GenericVertexController;
import com.threed.jpct.Light;
import com.threed.jpct.Loader;
import com.threed.jpct.Matrix;
import com.threed.jpct.Mesh;
import com.threed.jpct.Object3D;
import com.threed.jpct.Primitives;
import com.threed.jpct.RGBColor;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.Texture;
import com.threed.jpct.TextureInfo;
import com.threed.jpct.TextureManager;
import com.threed.jpct.World;
import com.threed.jpct.util.MemoryHelper;

/**
* 一个包含3ds,md2导入及纹理等的综合例子
*
* @author Simdanfeg
*
*/
public class MyRenderer implements Renderer {
// 圆周率
private static float PI = (float) Math.PI;
// FrameBuffer
private FrameBuffer fb = null;
// World对象
private World world = null;
// Object3D对象,分别为平面,人物,岩石,天空
private Object3D plane = null;
private Object3D snork = null;
private Object3D rock = null;
private Object3D dome = null;
// Light对象
private Light sun = null;
// ind
private float ind = 0;
// FPS
private int fps = 0;
// 返回当前毫秒数
private long time = System.currentTimeMillis();
// Bitmap对象
private Bitmap igrass = null;
private Bitmap idisco = null;
private Bitmap irock = null;
private Bitmap inormals = null;
private Bitmap isky = null;
// TextureManager对象
private TextureManager tm = null;

// 默认构造
public MyRenderer() {
// 优化操作
Config.maxPolysVisible = 1000;
Config.farPlane = 1500;
Config.glTransparencyMul = 0.1f;
Config.glTransparencyOffset = 0.1f;
Config.useVBO = true;
Texture.defaultToMipmapping(true);
Texture.defaultTo4bpp(true);
}

// 将载入的图片添加到TextureManager中
public void loadTexture() {
igrass = LoadFile.loadi(R.drawable.grasssample2);
idisco = LoadFile.loadi(R.drawable.disco);
irock = LoadFile.loadi(R.drawable.rock);
inormals = LoadFile.loadi(R.drawable.normals);
isky = LoadFile.loadi(R.drawable.sky);
// TextureManager
tm = TextureManager.getInstance();
tm.addTexture("grass", new Texture(igrass));
tm.addTexture("disco", new Texture(idisco));
tm.addTexture("rock", new Texture(irock));
tm.addTexture("normals", new Texture(inormals));
tm.addTexture("sky", new Texture(isky));
}

public void onDrawFrame(GL10 gl) {
SimpleVector offset = new SimpleVector(1, 0, -1).normalize();
// animate the snork and the dome
animate();
offset.rotateY(0.007f);
// render the scene
fb.clear();
world.renderScene(fb);
world.draw(fb);
fb.display();

// print out the fps to the console

if (System.currentTimeMillis() - time >= 1000) {
System.out.println(fps);
fps = 0;
time = System.currentTimeMillis();
}
fps++;
}

public void onSurfaceChanged(GL10 gl, int width, int height) {
if (fb != null) {
fb = null;
}
fb = new FrameBuffer(gl, width, height);
}

public void onSurfaceCreated(GL10 gl, EGLConfig height) {
// 启用混合
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA);
// Load textures
loadTexture();
// World
world = new World();
// 设置world环境光
world.setAmbientLight(120, 120, 120);

// Load/create and setup objects
// 平面(草地)
plane = Primitives.getPlane(20, 15);
plane.rotateX(PI / 2);
plane.setSpecularLighting(true);
// 设置纹理
plane.setTexture("grass");
plane.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS);
// plane.forceGeometryIndices(true);

// 岩石
rock = loadModel("rock.3ds", 15f);
rock.translate(0, 0, -90);
rock.rotateX(-PI / 2);
// 设置双重纹理
TextureInfo stoneTex = new TextureInfo(tm.getTextureID("rock"));
stoneTex.add(tm.getTextureID("normals"), TextureInfo.MODE_MODULATE);
rock.setTexture(stoneTex);
rock.setSpecularLighting(true);

// 人物
snork = Loader.loadMD2(LoadFile.loadf("snork.md2"), 0.8f);
snork.translate(0, -25, -50);
snork.rotateY(45);
snork.setTexture("disco");
// 设置碰撞模式
snork.setCollisionMode(Object3D.COLLISION_CHECK_SELF);

// 天空
dome = loadModel("dome.3ds", 0.5f);
dome.build();
dome.setTexture("sky");
dome.calcTextureWrap();
// 优化,但有用此方法显示有问题
// tileTexture(dome, 3);

// 计算plane与dome的差矢量
dome.translate(plane.getTransformedCenter().calcSub(
dome.getTransformedCenter()));
dome.setLighting(Object3D.LIGHTING_NO_LIGHTS);
// dome.forceGeometryIndices(true);
dome.setAdditionalColor(RGBColor.WHITE);

// 将Object3d传入到World对象中
world.addObject(plane);
world.addObject(rock);
world.addObject(snork);
world.addObject(dome);
// 编译world中所有对象
world.buildAllObjects();
// Compile all objects for better performance
plane.compile();
rock.compile();
dome.compile();
plane.strip();
rock.strip();
dome.strip();

// 变形plane,这太有意思了,我喜欢
// Deform the plane
Mesh planeMesh = plane.getMesh();
planeMesh.setVertexController(new Mod(), false);
planeMesh.applyVertexController();
planeMesh.removeVertexController();
// Move camera
Camera cam = world.getCamera();
cam.moveCamera(Camera.CAMERA_MOVEOUT, 150);
cam.moveCamera(Camera.CAMERA_MOVEUP, 100);
cam.lookAt(plane.getTransformedCenter());
cam.setFOV(1.5f);
// Setup dynamic light source
sun = new Light(world);
sun.setIntensity(250, 250, 250);
// 回收内存
MemoryHelper.compact();
}

/*
* 动画
*/
private void animate() {
ind += 0.1f;
if (ind > 1) {
ind -= 1;
}
snork.animate(ind, 2);
snork.rotateY(-0.02f);
snork.translate(0, -50, 0);
SimpleVector dir = snork.getXAxis();
dir = snork.checkForCollisionEllipsoid(dir, new SimpleVector(5, 20, 5),
5);
snork.translate(dir);
dir = snork.checkForCollisionEllipsoid(new SimpleVector(0, 100, 0),
new SimpleVector(5, 20, 5), 1);
snork.translate(dir);
}

// 载入模型
private Object3D loadModel(String filename, float scale) {
// 将载入的3ds文件保存到model数组中
Object3D[] model = Loader.load3DS(LoadFile.loadf(filename), scale);
// 取第一个3ds文件
Object3D o3d = new Object3D(0);
// 临时变量temp
Object3D temp = null;
// 遍历model数组
for (int i = 0; i < model.length; i++) {
// 给temp赋予model数组中的某一个
temp = model[i];
// 设置temp的中心为 origin (0,0,0)
temp.setCenter(SimpleVector.ORIGIN);
// 沿x轴旋转坐标系到正常的坐标系(jpct-ae的坐标中的y,x是反的)
temp.rotateX((float) (-.5 * Math.PI));
// 使用旋转矩阵指定此对象旋转网格的原始数据
temp.rotateMesh();
// new 一个矩阵来作为旋转矩阵
temp.setRotationMatrix(new Matrix());
// 合并o3d与temp
o3d = Object3D.mergeObjects(o3d, temp);
// 主要是为了从桌面版JPCT到android版的移徝(桌面版此处为o3d.build())
o3d.compile();
}
// 返回o3d对象
return o3d;
}

// static class Mod
public static class Mod extends GenericVertexController {
private static final long serialVersionUID = 1L;

public void apply() {
// 返回未修改前plane的Mesh信息
SimpleVector[] s = getSourceMesh();
// 定义SimpleVector得到DestinationMesh
SimpleVector[] d = getDestinationMesh();
// 变形主要操作
for (int i = 0; i < s.length; i++) {
d[i].z = s[i].z
- (10f * ((float) Math.sin(s[i].x / 50f) + (float) Math
.cos(s[i].y / 50f)));
d[i].x = s[i].x;
d[i].y = s[i].y;
}
}
}
}


效果图

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: