不知不觉写到了第十篇文章,这次画个陀螺,并且可以用键盘控制它旋转.
主窗体类,,SWING+keylistener
package com.gl3dgame.pegtop; //要是想使用默认包,请去掉这行
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 PegtopMain extends JFrame {
GLRender listener = new GLRender();
static FPSAnimator animator = null;
public PegtopMain() throws HeadlessException {
super("画陀螺");
setSize(600, 480);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GLCapabilities glcaps = new GLCapabilities();
GLCanvas canvas = new GLCanvas(glcaps);
canvas.addGLEventListener(listener);
this.addKeyListener(new keyEventListener());
//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 PegtopMain app = new PegtopMain();
// 显示窗体
SwingUtilities.invokeLater(new Runnable() {
public void run() {
app.setVisible(true);
}
});
// 动画线程开始
SwingUtilities.invokeLater(new Runnable() {
public void run() {
animator.start();
}
});
}
class keyEventListener implements KeyListener {
public void keyTyped(KeyEvent e) {
}
public void keyPressed(KeyEvent e) {
//处理键盘事件
System.out.println(e.getKeyCode());
if (e.getKeyCode() == 38) {
listener.xRot -= 5.0f;
}
if (e.getKeyCode() == 40) {
listener.xRot += 5.0f;
}
if (e.getKeyCode() == 37) {
listener.yRot -= 5.0f;
}
if (e.getKeyCode() == 39) {
listener.yRot += 5.0f;
}
}
public void keyReleased(KeyEvent e) {
}
}
}
GL控制类:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.gl3dgame.pegtop;
import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
/**
*
* @author Administrator
*/
public class GLRender implements GLEventListener {
GL gl;
// 旋转角度
static float xRot = 0.0f;
static float yRot = 0.0f;
boolean iCull = false;
boolean iOutline = false;
boolean iDepth = true;
float x, y, angle; // 存储为坐标和角度
float r,g,b;
public void init(GLAutoDrawable drawable) {
gl = drawable.getGL();
// 黑色背景
gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// 设置绘图颜色为绿色
gl.glColor3f(0.0f, 1.0f, 0.0f);
// 设置颜色着色模型平面
gl.glShadeModel(GL.GL_FLAT);
// Clock wise wound polygons are front facing, this is reversed
// because we are using triangle fans
// 设置CW方向为“正面”,CW即ClockWise,顺时针
gl.glFrontFace(GL.GL_CW);
}
public void display(GLAutoDrawable drawable) {
int iPivot = 1; // Used to flag alternating colors
// Clear the window and the depth buffer
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
// Turn culling on if flag is set
if (iCull) {
gl.glEnable(GL.GL_CULL_FACE); //剔除背面
} else {
gl.glDisable(GL.GL_CULL_FACE);
}
// Enable depth testing if flag is set
if (iDepth) {
gl.glEnable(GL.GL_DEPTH_TEST);
} else {
gl.glDisable(GL.GL_DEPTH_TEST);
}
// Draw back side as a polygon only, if flag is set
//背面绘制多边形只有一个,如果标志设置
if (iOutline) {
gl.glPolygonMode(GL.GL_BACK, GL.GL_LINE);
} else {
gl.glPolygonMode(GL.GL_BACK, GL.GL_FILL);
}
// Save matrix state and do the rotation
//保存矩阵状态,做旋转
gl.glPushMatrix();
gl.glRotatef(xRot, 1.0f, 0.0f, 0.0f);
gl.glRotatef(yRot, 0.0f, 1.0f, 0.0f);
// 开始三角扇形
gl.glBegin(GL.GL_TRIANGLE_FAN);
// Pinnacle of cone is shared vertex for fan, moved up Z axis
// to produce a cone instead of a circle
gl.glVertex3f(0.0f, 0.0f, 75.0f);
// Loop around in a circle and specify even points along the circle
// as the vertices of the triangle fan
//环周围成一个圆圈,并指定甚至点沿为三角形的顶点圆扇
for (angle = 0.0f; angle <= (2.0f * Math.PI+1); angle += (Math.PI / 8.0f)) {
// 计算下一个顶点的x和y位置
x = (float) (50.0f * Math.sin(angle));
y = (float) (50.0f * Math.cos(angle));
//交替颜色红色和绿色
if ((iPivot % 2) == 0) {
gl.glColor3f(0.0f, 1.0f, 0.0f);
} else {
gl.glColor3f(1.0f, 0.0f, 0.0f);
}
//用全随机颜色,不过效果不好看.
//gl.glColor3f((float)Math.random(), (float)Math.random(), (float)Math.random());
// Increment pivot to change color next time
iPivot++;
// Specify the next vertex for the triangle fan
gl.glVertex2f(x, y);
}
// Done drawing fan for cone
gl.glEnd();
// 在底面画三角扇形
gl.glBegin(GL.GL_TRIANGLE_FAN);
// Center of fan is at the origin
gl.glVertex2f(0.0f, 0.0f);
for (angle = 0.0f; angle <= (2.0f * Math.PI+1); angle += (Math.PI / 8.0f)) {
// Calculate x and y position of the next vertex
x = (float) (50.0f * Math.sin(angle));
y = (float) (50.0f * Math.cos(angle));
// Alternate color between red and green
if ((iPivot % 2) == 0) {
gl.glColor3f(0.0f, 1.0f, 0.0f);
} else {
gl.glColor3f(1.0f, 0.0f, 0.0f);
}
//gl.glColor3f((float)Math.random(), (float)Math.random(), (float)Math.random());
// Increment pivot to change color next time
//增加iPivot,下一次改变颜色
iPivot++;
// Specify the next vertex for the triangle fan
gl.glVertex2f(x, y);
}
// Done drawing the fan that covers the bottom
//完成图纸的风扇,包括底部
gl.glEnd();
// Restore transformations
gl.glPopMatrix();
}
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
float nRange = 100.0f;
// 防止为零
if (height == 0) {
height = 1;
}
//视口设置为窗口尺寸
gl.glViewport(0, 0, width, height);
// Reset projection matrix stack
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
//建立剪辑视图,正投影(左,右,底部,顶部,近,远)
if (width <= height) {
gl.glOrtho(-nRange, nRange, -nRange * height / width, nRange * height / width, -nRange, nRange);
} else {
gl.glOrtho(-nRange * width / height, nRange * width / height, -nRange, nRange, -nRange, nRange);
}
// 重置模型观察矩阵堆栈
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();
}
public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {
}
}
大家可以试着修改代码,改改颜色,把陀螺变得像钻石.
分享自己的技术论坛http://www.itneng.com/forum.php