我们用前面用过的知识,画一个运动的机器人.
效果如下:
主窗体类:
package com.gl3dgame.robot; //要是想使用默认包,请去掉这行
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.media.opengl.*;
import com.sun.opengl.util.Animator;
import com.sun.opengl.util.FPSAnimator;
public class RobotMain extends JFrame {
GLRender listener=new GLRender();
static FPSAnimator animator=null;
public RobotMain() throws HeadlessException {
super("画机器人:活用长方体");
setSize(600,480);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GLCapabilities glcaps=new GLCapabilities();
GLCanvas canvas=new GLCanvas(glcaps);
canvas.addGLEventListener(listener);
//canvas.addMouseListener(listener);
getContentPane().add(canvas, BorderLayout.CENTER);
animator=new FPSAnimator(canvas,60,true);
centerWindow(this);
}
private void centerWindow(Component frame) { // 居中窗体
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension frameSize = frame.getSize();
if (frameSize.width > screenSize.width)
frameSize.width = screenSize.width;
if (frameSize.height > screenSize.height)
frameSize.height = screenSize.height;
frame.setLocation((screenSize.width - frameSize.width) >> 1,
(screenSize.height - frameSize.height) >> 1);
}
public static void main(String[] args) {
final RobotMain app = new RobotMain();
// 显示窗体
SwingUtilities.invokeLater(new Runnable() {
public void run() {
app.setVisible(true);
}
});
// 动画线程开始
SwingUtilities.invokeLater(new Runnable() {
public void run() {
animator.start();
}
});
}
}
GL控制类:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.gl3dgame.robot;
import java.awt.Component;
import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.glu.GLU;
/**
*
* @author Administrator
*/
public class GLRender implements GLEventListener {
private GL gl;
private GLU glu;
private Robot robot;
private float rotationAngle;
public void init(GLAutoDrawable drawable) {
gl = drawable.getGL();
glu = new GLU();
robot = new Robot(gl);
rotationAngle = 0.0f;
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
gl.glEnable(GL.GL_DEPTH_TEST);
gl.glDepthFunc(GL.GL_LEQUAL);
gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL);
int w = ((Component) drawable).getWidth();
int h = ((Component) drawable).getHeight();
gl.glViewport(0, 0, w, h); // 设置视点大小reset the viewport to new dimensions
gl.glMatrixMode(GL.GL_PROJECTION); //设置当前矩阵模式 set projection matrix current matrix
gl.glLoadIdentity(); //把当前绘画点移动到屏幕中心 reset projection matrix
//设置摄像机的拍摄性能 calculate aspect ratio of window
glu.gluPerspective(52.0f, (float) w / (float) h, 1.0f, 1000.0f);
gl.glMatrixMode(GL.GL_MODELVIEW); //设置当前矩阵模式 set modelview matrix
gl.glLoadIdentity(); //把当前绘画点移动到屏幕中心 reset modelview matrix
//播放音乐,不要就注释掉
//new AePlayWave("wave/run.wav").start();
}
public void display(GLAutoDrawable drawable) {
//刷新背景颜色 clear screen and depth buffer
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
//把当前绘画点移动到屏幕中心 load the identity matrix (clear to default position and orientation)
gl.glLoadIdentity();
gl.glPushMatrix(); //保存当前矩阵 put current matrix on stack
gl.glLoadIdentity(); //把当前绘画点移动到屏幕中心 reset matrix
gl.glTranslatef(0.0f, 0.0f, -30.0f); //把当前绘画点移动到(x,y,z) move to (0, 0, -30)
gl.glRotatef(rotationAngle, 0.0f, 1.0f, 0.0f); //旋转(角度值,x轴,Y轴,Z轴) rotate the robot on its y-axis
robot.DrawRobot(0.0f, 0.0f, 0.0f); //画机器人 draw the robot
gl.glPopMatrix();
this.Prepare(0.2f); //刷新机器人动作
}
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
}
public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {
}
public void Prepare(float dt) {
rotationAngle += 45.0f * dt; // increase our rotation angle counter
if (rotationAngle >= 360.0f) // if we've gone in a circle, reset counter
{
rotationAngle = 0.0f;
}
robot.Prepare(dt);
}
}
机器人类:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.gl3dgame.robot;
import javax.media.opengl.GL;
/**
*
* @author Administrator
*/
public class Robot {
private GL gl;
private String[] legStates = new String[2];
private String[] armStates = new String[2];
private float[] legAngles = new float[2];
private float[] armAngles = new float[2];
final int LEFT = 0;
final int RIGHT = 1;
public Robot(GL gl) {
this.gl = gl;
armAngles[LEFT] = 0.0f;
armAngles[RIGHT] = 0.0f;
legAngles[LEFT] = 0.0f;
legAngles[RIGHT] = 0.0f;
armStates[LEFT] = "FORWARD_STATE";
armStates[RIGHT] = "BACKWARD_STATE";
legStates[LEFT] = "FORWARD_STATE";
legStates[RIGHT] = "BACKWARD_STATE";
}
private void DrawCube(float xPos, float yPos, float zPos) {
gl.glPushMatrix();
gl.glTranslatef(xPos, yPos, zPos);
gl.glBegin(GL.GL_POLYGON);
gl.glVertex3f(0.0f, 0.0f, 0.0f); // top face
gl.glVertex3f(0.0f, 0.0f, -1.0f);
gl.glVertex3f(-1.0f, 0.0f, -1.0f);
gl.glVertex3f(-1.0f, 0.0f, 0.0f);
gl.glVertex3f(0.0f, 0.0f, 0.0f); // front face
gl.glVertex3f(-1.0f, 0.0f, 0.0f);
gl.glVertex3f(-1.0f, -1.0f, 0.0f);
gl.glVertex3f(0.0f, -1.0f, 0.0f);
gl.glVertex3f(0.0f, 0.0f, 0.0f); // right face
gl.glVertex3f(0.0f, -1.0f, 0.0f);
gl.glVertex3f(0.0f, -1.0f, -1.0f);
gl.glVertex3f(0.0f, 0.0f, -1.0f);
gl.glVertex3f(-1.0f, 0.0f, 0.0f); // left face
gl.glVertex3f(-1.0f, 0.0f, -1.0f);
gl.glVertex3f(-1.0f, -1.0f, -1.0f);
gl.glVertex3f(-1.0f, -1.0f, 0.0f);
gl.glVertex3f(0.0f, 0.0f, 0.0f); // bottom face
gl.glVertex3f(0.0f, -1.0f, -1.0f);
gl.glVertex3f(-1.0f, -1.0f, -1.0f);
gl.glVertex3f(-1.0f, -1.0f, 0.0f);
gl.glVertex3f(0.0f, 0.0f, 0.0f); // back face
gl.glVertex3f(-1.0f, 0.0f, -1.0f);
gl.glVertex3f(-1.0f, -1.0f, -1.0f);
gl.glVertex3f(0.0f, -1.0f, -1.0f);
gl.glEnd();
gl.glPopMatrix();
}
private void DrawArm(float xPos, float yPos, float zPos) {
gl.glPushMatrix();
gl.glColor3f(1.0f, 0.0f, 0.0f); // red
gl.glTranslatef(xPos, yPos, zPos);
gl.glScalef(1.0f, 4.0f, 1.0f); // arm is a 1x4x1 cube
DrawCube(0.0f, 0.0f, 0.0f);
gl.glPopMatrix();
}
private void DrawHead(float xPos, float yPos, float zPos) {
gl.glPushMatrix();
// white
gl.glTranslatef(xPos, yPos, zPos);
gl.glScalef(2.0f, 2.0f, 2.0f); // head is a 2x2x2 cube
gl.glColor3f(1.0f, 1.0f, 1.0f);
DrawCube(0.0f, 0.0f, 0.0f);
gl.glPopMatrix();
}
private void DrawTorso(float xPos, float yPos, float zPos) {
gl.glPushMatrix();
gl.glColor3f(0.0f, 0.0f, 1.0f); // blue
gl.glTranslatef(xPos, yPos, zPos);
gl.glScalef(3.0f, 5.0f, 2.0f); // torso is a 3x5x2 cube
DrawCube(0.0f, 0.0f, 0.0f);
gl.glPopMatrix();
}
private void DrawLeg(float xPos, float yPos, float zPos) {
gl.glPushMatrix();
gl.glTranslatef(xPos, yPos, zPos);
// draw the foot
gl.glPushMatrix();
gl.glTranslatef(0.0f, -0.5f, 0.0f);
DrawFoot(0.0f, -5.0f, 0.0f);
gl.glPopMatrix();
gl.glScalef(1.0f, 5.0f, 1.0f); // leg is a 1x5x1 cube
gl.glColor3f(1.0f, 1.0f, 0.0f); // yellow
DrawCube(0.0f, 0.0f, 0.0f);
gl.glPopMatrix();
}
private void DrawFoot(float xPos, float yPos, float zPos) {
gl.glPushMatrix();
gl.glColor3f(1.0f, 1.0f, 1.0f);
gl.glTranslatef(xPos, yPos, zPos);
gl.glScalef(1.0f, 0.5f, 3.0f);
DrawCube(0.0f, 0.0f, 0.0f);
gl.glPopMatrix();
}
public void DrawRobot(float xPos, float yPos, float zPos) {
gl.glPushMatrix();
gl.glTranslatef(xPos, yPos, zPos); // draw robot at desired coordinates
//画头 draw head and torso parts
DrawHead(1.0f, 2.0f, 0.0f);
DrawTorso(1.5f, 0.0f, 0.0f);
//画左手 move the left arm away from the torso and rotate it to give "walking" effect
gl.glPushMatrix();
gl.glTranslatef(0.0f, -0.5f, 0.0f);
gl.glRotatef(armAngles[LEFT], 1.0f, 0.0f, 0.0f);
DrawArm(2.5f, 0.0f, -0.5f);
gl.glPopMatrix();
//画右手 move the right arm away from the torso and rotate it to give "walking" effect
gl.glPushMatrix();
gl.glTranslatef(0.0f, -0.5f, 0.0f);
gl.glRotatef(armAngles[RIGHT], 1.0f, 0.0f, 0.0f);
DrawArm(-1.5f, 0.0f, -0.5f);
gl.glPopMatrix();
//画左脚 move the left leg away from the torso and rotate it to give "walking" effect
gl.glPushMatrix();
gl.glTranslatef(0.0f, -0.5f, 0.0f);
gl.glRotatef(legAngles[LEFT], 1.0f, 0.0f, 0.0f);
DrawLeg(-0.5f, -5.0f, -0.5f);
gl.glPopMatrix();
//画右脚 move the right leg away from the torso and rotate it to give "walking" effect
gl.glPushMatrix();
gl.glTranslatef(0.0f, -0.5f, 0.0f);
gl.glRotatef(legAngles[RIGHT], 1.0f, 0.0f, 0.0f);
DrawLeg(1.5f, -5.0f, -0.5f);
gl.glPopMatrix();
gl.glPopMatrix(); // pop back to original coordinate system
}
public void Prepare(float dt) {
//机器人动作,实际就是按规则旋转手脚
// if leg is moving forward, increase angle, else decrease angle
for (char side = 0; side < 2; side++) {
// arms
if (armStates[side] == "FORWARD_STATE") {
armAngles[side] += 20.0f * dt;
} else {
armAngles[side] -= 20.0f * dt;
}
// change state if exceeding angles
if (armAngles[side] >= 15.0f) {
armStates[side] = "BACKWARD_STATE";
} else if (armAngles[side] <= -15.0f) {
armStates[side] = "FORWARD_STATE";
}
// legs
if (legStates[side] == "FORWARD_STATE") {
legAngles[side] += 20.0f * dt;
} else {
legAngles[side] -= 20.0f * dt;
}
// change state if exceeding angles
if (legAngles[side] >= 15.0f) {
legStates[side] = "BACKWARD_STATE";
} else if (legAngles[side] <= -15.0f) {
legStates[side] = "FORWARD_STATE";
}
}
}
}
实现原理就是在画所有长方前,先用gl.glRotatef(rotationAngle, 0.0f, 1.0f, 0.0f);//旋转(角度值,x轴,Y轴,Z轴) 使矩阵里的物体旋转,,也就像地球和八大行星围绕太阳公转,,,然后各手脚自转,类似地球自转.
分享自己的技术论坛http://www.itneng.com/forum.php