说是原创,其实都是参考了libgdx wiki里的教程。不过我自己都做过,一点点的打字,一张张图的截下来。
看到太多LIBGDX 2D方面的教程,于是冲动着自己想学点3D方面的东西。毕竟,如果只做2D,用libgdx还不如cocos2d-x来得方便。
假设已经通过 gdx-setup-ui.jar 建好了libgdx的项目,并且import到eclipse中。以下内容实在是太初级,菜鸟可能都有踩两脚的冲动。
我这里看起来是这样的。
通过gdx-setup-ui.jar建立的项目,大体上分为主项目,和android/ios/desktop/html项目。
这个是一个可运行的项目,运行desktop下的Main.java,然后就能得到:
接下来,对这个项目稍做修改:
新建Class: com.kyugao.nehe.NeHeLibgdx extends Game. 删掉原来的com.kyugao.nehe.MyGdxGame. 然后,添上几行代码如下:
package com.kyugao.nehe;
import com.badlogic.gdx.Game;
import com.badlogic.gdx.graphics.FPSLogger;
import com.kyugao.screen.FirstPolygon;
public class NeHeLibgdx extends Game {
private FPSLogger fpsLogger;
@Override
public void create() {
// TODO Auto-generated method stub
setScreen(new FirstPolygon());
fpsLogger = new FPSLogger();
}
@Override
public void render() {
// TODO Auto-generated method stub
super.render();
fpsLogger.log();
}
}
接下来就要定义我们的FirstPolygon screen. 新建一个包,com.kyugao.screen。如果我有坚持下去,每一课都会在这里新添加一个screen.
那第一课的screen就是com.kyugao.screen.FirstPolygon implements Screen.
代码如下:
package com.kyugao.screen;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.Mesh;
import com.badlogic.gdx.graphics.VertexAttribute;
import com.badlogic.gdx.graphics.VertexAttributes.Usage;
public class FirstPolygon implements Screen {
private Mesh triangleMesh;
@Override
public void render(float delta) {
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
drawGLScene();
}
private boolean drawGLScene() {
triangleMesh.render(GL10.GL_TRIANGLES, 0, 3);
return true;
}
@Override
public void show() {
triangleMesh = new Mesh(true, 3, 3, new VertexAttribute(Usage.Position,
3, "a_position"));
triangleMesh.setVertices(new float[] { -0.5f, -0.5f, 0, // point 1
0.5f, -0.5f, 0, // point 2
0, 0.5f, 0 }); // point 3
triangleMesh.setIndices(new short[] { 0, 1, 2 });
}
@Override
public void hide() {
}
@Override
public void pause() {
}
@Override
public void resume() {
}
@Override
public void dispose() {
}
@Override
public void resize(int width, int height) {
}
}
screen的方法,这里重写了show()和render().
Screen下面的show方法,会在被Game设置后调用一次, 之后就反复的通过render去绘制画面了。
render方法中:
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT); // opengl中的清屏函数,在这里,默认的清屏颜色是黑色,所以看到的背景色都是黑的。通过glClearColor可以自定义这个清屏颜色,比如,我们想要红色的背景Gdx.gl.glClearColor(1, 0, 0, 1),那每次render时填充的颜色就是红色。可以提到一下,如果不需要背景颜色变幻,那glClearColor只要一次指定就好,所以可以写在show()里。
在通过glClear清屏之后,调用drawGLScene来画图形。
show方法:
初始化mesh, 关于mesh,iciba翻译是网格,所以很简单的理解,我定义了三个点的,分别如坐标上写的。然后指定了他们的indices(index), 0, 1, 2
再次运行desktop project下面的Main. 可以得到下面这个图形:
一个三角形,一个正方形:
// glTranslatef(-1.5f,0.0f,-6.0f);
// glVertex3f( 0.0f, 1.0f, 0.0f); // Top
// glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
// glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
// glTranslatef(3.0f,0.0f,0.0f);
// glVertex3f(-1.0f, 1.0f, 0.0f); // Top Left
// glVertex3f( 1.0f, 1.0f, 0.0f); // Top Right
// glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
// glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
先计算一下三角形的三个点,glTranslatef 与 三个顶点相加:TOP: -1.5f, 1.0f, -6.0f
BL: -2.5f, -1.0f, -6.0f
BR: -0.5f, -1.0f, -6.0f
然后正方形的:// glTranslatef(-1.5f,0.0f,-6.0f); + // glTranslatef(3.0f,0.0f,0.0f); = glTranslatef(1.5f, 0.0f, -6.0f),于是:
TL: 0.5f, 1.0f, -6.0f
TR: 2.5f, 1.0f, -6.0f
BR: 2.5f, -1.0f, -6.0f
BL: 0.5f, -1.0f, -6.0f
根据计算值,我重新构建了两个mesh,并且修改drawGLScene方法, 如下:
private Mesh triangleMesh, squareMesh;
private boolean drawGLScene() {
triangleMesh.render(GL10.GL_TRIANGLES, 0, 3);
squareMesh.render(GL10.GL_TRIANGLE_STRIP, 0, 4);
return true;
}
@Override
public void show() {
triangleMesh = new Mesh(true, 3, 3, new VertexAttribute(Usage.Position,
3, "a_position"));
squareMesh = new Mesh(true, 4, 4, new VertexAttribute(Usage.Position,
3, "b_position"));
triangleMesh.setVertices(new float[] { //
-1.5f, 1.0f, -6.0f, // point 1
-2.5f, -1.0f, -6.0f, // point 2
-0.5f, -1.0f, -6.0f }); // point 3
triangleMesh.setIndices(new short[] { 0, 1, 2 });
squareMesh.setVertices(new float[] { 0.5f, -1.0f, -6.0f,// point BL
2.5f, -1.0f, -6.0f,// point BR
0.5f, 1.0f, -6.0f, // point TL
2.5f, 1.0f, -6.0f // point TR
});
squareMesh.setIndices(new short[] { 0, 1, 2, 3 });
}
可是,当我一运行,屏幕上只有一片黑色,这个就不截图了。
扩展3D空间,将纸,换成取景器Camera:
平面上画图,一张纸就够了,可是在3D空间里,为了更好的观察,我们要用一个照像机:
package com.kyugao.screen;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.Mesh;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.graphics.VertexAttribute;
import com.badlogic.gdx.graphics.VertexAttributes.Usage;
public class FirstPolygon implements Screen {
private Mesh triangleMesh, squareMesh;
private PerspectiveCamera camera;
@Override
public void render(float delta) {
camera.update();
camera.apply(Gdx.graphics.getGL10());
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
drawGLScene();
}
private boolean drawGLScene() {
triangleMesh.render(GL10.GL_TRIANGLES, 0, 3);
squareMesh.render(GL10.GL_TRIANGLE_STRIP, 0, 4);
return true;
}
@Override
public void show() {
triangleMesh = new Mesh(true, 3, 3, new VertexAttribute(Usage.Position,
3, "a_position"));
squareMesh = new Mesh(true, 4, 4, new VertexAttribute(Usage.Position,
3, "b_position"));
triangleMesh.setVertices(new float[] { //
-1.5f, 1.0f, -6.0f, // point 1
-2.5f, -1.0f, -6.0f, // point 2
-0.5f, -1.0f, -6.0f }); // point 3
triangleMesh.setIndices(new short[] { 0, 1, 2 });
squareMesh.setVertices(new float[] { 0.5f, -1.0f, -6.0f,// point BL
2.5f, -1.0f, -6.0f,// point BR
0.5f, 1.0f, -6.0f, // point TL
2.5f, 1.0f, -6.0f // point TR
});
squareMesh.setIndices(new short[] { 0, 1, 2, 3 });
}
@Override
public void hide() {
}
@Override
public void pause() {
}
@Override
public void resume() {
}
@Override
public void dispose() {
}
@Override
public void resize(int width, int height) {
float aspectRatio = (float) width / (float) height;
camera = new PerspectiveCamera(45, 2f * aspectRatio, 2f);
}
}
上面是Screen的全部代码,主要是添加了一个照相机 camera,形象一点说,是一个取景器。
在窗口大小改变时,就是取景器的大小改变了,新建一个camera, 然后在每一次render时,更新camera属性,重新render画面。
new PerspectiveCamera(45, 2f * aspectRatio, 2f);
相机参数:45是角度,如果你的眼睛可以看面前的180度,那就把45改掉。
2f * aspectRatio, 2f,分别是宽与高,在默认情况下,opengl es把窗口定义为, 以中心点为原点,x, y轴的正负方向各单位1的长度。
(from http://code.google.com/p/libgdx)
但是,如果窗口的长与宽比不是1:1,比如,我横向拉伸了窗后,上面的正方形就变成了:
(from http://code.google.com/p/libgdx)
所以,要计算camera的长宽比。最终,运行一下程序,得到了:
第一课结束。