OpenlGL游戏编程-简单的机器人制作(三)
!注意本教程是基于java的,我会在这里从创建java项目一步一步的写。(java版本为java8)
开场
上节课,我们之前学习了如何去创建一个窗口,如何让一个机器人显示在屏幕上,那么这节课,我们将学习如何让机器人自己动起来,实现走路的效果,完成一个简单的
首先,将上节课的GameRobot类打开,修改如下,我会将修改处加上注释:
package main;
import com.jogamp.opengl.GL2;
import com.jogamp.opengl.GLAutoDrawable;
public class GameRobot{
//修改处
float legAngle[];
float armAngle[];
boolean leg1 = true;
boolean leg2 = false;
boolean arm1 = false;
boolean arm2 = true;
//修改截止处
GLAutoDrawable glad;
GL2 gl;
public GameRobot(GLAutoDrawable glad) {
this.glad = glad;
gl = glad.getGL().getGL2();
//修改处
legAngle = new float[2];
armAngle = new float[2];
//修改截止处
}
private void drawHead(float xPos, float yPos, float zPos) {
gl.glPushMatrix();
gl.glColor3f(1f, 1f, 1f);
gl.glTranslated(xPos, yPos, zPos);
gl.glScaled(2f, 2f, 2f);
drawCube(0f, 0f, 0f);
gl.glPopMatrix();
}
private void drawBody(float xPos, float yPos, float zPos) {
gl.glPushMatrix();
gl.glColor3f(0f, 1f, 0f);
gl.glTranslated(xPos, yPos, zPos);
gl.glScaled(3f, 5f, 2f);
drawCube(0f, 0f, 0f);
gl.glPopMatrix();
}
private void drawLeg(float xPos, float yPos, float zPos) {
gl.glPushMatrix();
gl.glColor3f(1f, 1f, 0f);
gl.glTranslated(xPos, yPos, zPos);
gl.glScaled(1f, 5f, 1f);
drawCube(0f, 0f, 0f);
gl.glPopMatrix();
}
private void drawArm(float xPos, float yPos, float zPos) {
gl.glPushMatrix();
gl.glColor3f(1f, 0f, 0f);
gl.glTranslated(xPos, yPos, zPos);
gl.glScaled(1f, 4f, 1f);
drawCube(0f, 0f, 0f);
gl.glPopMatrix();
}
private void drawEar(float xPos, float yPos, float zPos) {
gl.glPushMatrix();
gl.glColor3f(0.5f, 0.5f, 0.5f);
gl.glTranslated(xPos, yPos, zPos);
gl.glScaled(0.25f, 0.25f, 0.25f);
drawCube(0f, 0f, 0f);
gl.glPopMatrix();
}
private void drawMouth(float xPos, float yPos, float zPos) {
gl.glPushMatrix();
gl.glColor3f(1f, 0f, 1f);
gl.glTranslated(xPos, yPos, zPos);
gl.glScaled(0.75f, 0.25f, 0.25f);
drawCube(0f, 0f, 0f);
gl.glPopMatrix();
}
private void drawCube(float xPos, float yPos, float zPos) {
gl.glPushMatrix();
gl.glTranslated(xPos, yPos, zPos);
gl.glBegin(GL2.GL_QUADS);
//上面
gl.glVertex3f(0f, 0f, -1f);
gl.glVertex3f(0f, 0f, 0f);
gl.glVertex3f(1f, 0f, 0f);
gl.glVertex3f(1f, 0f, -1f);
//下面
gl.glVertex3f(0f, -1f, -1f);
gl.glVertex3f(0f, -1f, 0f);
gl.glVertex3f(1f, -1f, 0f);
gl.glVertex3f(1f, -1f, -1f);
//正面
gl.glVertex3f(0f, 0f, 0f);
gl.glVertex3f(0f, -1f, 0f);
gl.glVertex3f(1f, -1f, 0f);
gl.glVertex3f(1f, 0f, 0f);
//背面
gl.glVertex3f(0f, 0f, -1f);
gl.glVertex3f(0f, -1f, -1f);
gl.glVertex3f(1f, -1f, -1f);
gl.glVertex3f(1f, 0f, -1f);
//左面
gl.glVertex3f(0f, 0f, -1);
gl.glVertex3f(0f, 0f, 0f);
gl.glVertex3f(0f, -1f, 0f);
gl.glVertex3f(0f, -1f, -1f);
//右面
gl.glVertex3f(1f, 0f, -1);
gl.glVertex3f(1f, 0f, 0f);
gl.glVertex3f(1f, -1f, 0f);
gl.glVertex3f(1f, -1f, -1f);
gl.glEnd();
gl.glPopMatrix();
}
public void drawRobet(float xPos, float yPos, float zPos) {
//开始绘制机器人
gl.glPushMatrix();
gl.glTranslated(xPos, yPos, zPos);
//头绘制
drawHead(2f, 2f, 0f);
//身躯绘制
drawBody(1.5f, 0f, 0f);
//绘制嘴巴
drawMouth(2.625f,0.35f,0.25f);
//绘制耳朵
drawEar(1.75f,1.0f,-0.825f);
drawEar(3.75f,1.0f,-0.825f);
//修改处
//右胳膊开始绘制
gl.glPushMatrix();
if (arm1) {
armAngle[0] += 0.5f;
} else {
armAngle[0] -= 0.5f;
}
if (armAngle[0] >= 15.0f) {
arm1 = false;
}
if (armAngle[0] <= -15.0f) {
arm1 = true;
}
gl.glTranslated(0f, -0.5f, 0f);
gl.glRotatef(armAngle[0], 1f, 0f, 0f);
drawArm(4.5f, 0f, -0.5f);
gl.glPopMatrix();
//右胳膊绘制完毕
//左胳膊开始绘制
gl.glPushMatrix();
if (arm2) {
armAngle[1] += 0.5f;
} else {
armAngle[1] -= 0.5f;
}
if (armAngle[1] >= 15.0f) {
arm2 = false;
}
if (armAngle[1] <= -15.0f) {
arm2 = true;
}
gl.glTranslated(0f, -0.5f, 0f);
gl.glRotatef(armAngle[1], 1f, 0f, 0f);
drawArm(0.5f, 0f, -0.5f);
gl.glPopMatrix();
//左胳膊绘制完毕
//右腿开始绘制
gl.glPushMatrix();
if (leg1) {
legAngle[0] += 0.5f;
} else {
legAngle[0] -= 0.5f;
}
if (legAngle[0] >= 15.0f) {
leg1 = false;
}
if (legAngle[0] <= -15.0f) {
leg1 = true;
}
gl.glTranslated(0f, -0.5f, 0f);
gl.glRotatef(legAngle[0], 1f, 0f, 0f);
drawLeg(4.5f, -4.5f, -0.5f);
gl.glPopMatrix();
//右腿绘制完毕
//左腿开始绘制
gl.glPushMatrix();
if (leg2) {
legAngle[1] += 0.5f;
} else {
legAngle[1] -= 0.5f;
}
if (legAngle[1] >= 15.0f) {
leg2 = false;
}
if (legAngle[1] <= -15.0f) {
leg2 = true;
}
gl.glTranslated(0f, -0.5f, 0f);
gl.glRotatef(legAngle[1], 1f, 0f, 0f);
drawLeg(0.5f, -4.5f, -0.5f);
gl.glPopMatrix();
//左腿绘制完毕
//修改截止处
gl.glPopMatrix();
//机器人绘制完毕
}
}
原理就是用二个布尔类型,还判断前后摆动,用4个浮点型数来控制摆动幅度,在这里非常体现了坐标系调理清晰的重要性,这点,当你自己写的时候就深有体会了,当然你要是想象力逆天我也没有办法-_-!
还记得上节课的GameGLEventListener类么,我们要让他动起来,就需要时刻刷新页面,首先,我们要先将其修改成如下:
package main;
import com.jogamp.opengl.GL2;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.glu.GLU;
import com.jogamp.opengl.util.FPSAnimator;
public class GameGLEventListener implements GLEventListener {
GLU glu = new GLU();
GameRobot robot;
//修改处
float h;
boolean flag = true;
float high = 45f;
//修改截止处
@Override
public void init(GLAutoDrawable glad) {
robot = new GameRobot(glad);
GL2 gl = glad.getGL().getGL2();
gl.glShadeModel(GL2.GL_SMOOTH);
gl.glClearDepth(1.0f);// 设置深度缓存
gl.glEnable(GL2.GL_DEPTH_TEST);// 启用深度测试
gl.glDepthFunc(GL2.GL_LEQUAL);// 所作深度测试的类型
gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL2.GL_NICEST);
}
@Override
public void dispose(GLAutoDrawable glad) {
}
@Override
public void display(GLAutoDrawable glad) {
GL2 gl = glad.getGL().getGL2();
//修改处
gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glLoadIdentity();
glu.gluPerspective(high, h, 0.1f, 100f);
glu.gluLookAt(10f,10f, 10f, 0f, 0f, 0f, 0f, 1f, 0f);
gl.glMatrixMode(GL2.GL_MODELVIEW);
gl.glLoadIdentity();
//修改截止处
//设置清除颜色为黑色,并清除颜色缓存和深度缓存
gl.glClearColor(0f, 0f, 0f, 1f);
gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
//重置坐标系
gl.glLoadIdentity();
//修改处
//开始绘制机器人(正面)
gl.glPushMatrix();
gl.glTranslated(0f, 0f, -30f);
gl.glRotatef(0f, 0f, 1f, 0f);
robot.drawRobet(0f, 0f, 0f);
gl.glPopMatrix();
//机器人绘制完毕
//开始绘制机器人(背面)
gl.glPushMatrix();
gl.glTranslated(0f, 0f, -30f);
gl.glRotatef(180f, 0f, 1f, 0f);
robot.drawRobet(0f, 0f, 0f);
gl.glPopMatrix();
//机器人绘制完毕
//开始绘制机器人(侧面)
gl.glPushMatrix();
gl.glTranslated(-8f, 0f, -30f);
gl.glRotatef(90f, 0f, 1f, 0f);
robot.drawRobet(0f, 0f, 0f);
gl.glPopMatrix();
//机器人绘制完毕
//开始绘制机器人(侧面)
gl.glPushMatrix();
gl.glTranslated(8f, 0f, -30f);
gl.glRotatef(270f, 0f, 1f, 0f);
robot.drawRobet(0f, 0f, 0f);
gl.glPopMatrix();
//机器人绘制完毕
gl.glFlush();
if (flag) {
high += 1f;
if (high >= 180) {
flag = false;
high = 180;
}
} else {
high -= 1f;
if (high <= 1) {
flag = true;
high = 1;
}
}
//修改截止处
}
@Override
public void reshape(GLAutoDrawable glad, int x, int y, int width, int height) {
GL2 gl = glad.getGL().getGL2();
if (height <= 0) {
height = 1;
}
h = (float) width / (float) height;
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glLoadIdentity();
//修改处
glu.gluPerspective(high, h, 0.1f, 100f);
//修改截止处
gl.glMatrixMode(GL2.GL_MODELVIEW);
gl.glLoadIdentity();
}
}
- 修改的地方已经表明出来了,
- glu.gluPerspective(high, h, 0.1f, 100f)这个函数用来投影变换的,具体的我之后会讲解
- glu.gluLookAt(10f,10f, 10f, 0f, 0f, 0f, 0f, 1f, 0f)这个函数用来视口变换的,具体的我之后会讲解
其他类不变
收场
执行成功后效果如下: