📄 mw_canvas3d.java
字号:
import javax.microedition.lcdui.game.*;
import javax.microedition.lcdui.*;
import java.io.*;
import java.lang.*;
import java.util.*;
import com.mascotcapsule.micro3d.v3.*;
/*
* Main canvas - used to create, manage and display 3D world
*/
public class MW_Canvas3D extends Canvas implements CommandListener
{
// reference to main appplication class
private MW_Main app;
// Soft keys
Command finishWorkWithCamCommand;
Command finishWorkWithCarCommand;
Command exitCommand;
// constants
private final int WIDTH, HEIGHT;
private final int moveStep = 30;
private final int rotStep = 50;
private final int moveObjStep = 20;
private final int rotObjStep = 208;
// to obtain current frame rate
FPS mFps = new FPS();
private Light light = new Light(new Vector3D(-146, 293, 439), 3730, 1626 );
private Effect3D effect = new Effect3D();
// variable used to init camera position
private Vector3D POS = new Vector3D(0, 0, 250);
private Vector3D LOOK = new Vector3D(0, 0, -4096);
private Vector3D UP = new Vector3D(0, 4096, 0);
private int pers = 512; // angle of space visible
// transformates used to control camera position and orientation
private AffineTrans mCamMove = new AffineTrans();
private AffineTrans mCamRotX = new AffineTrans();
private AffineTrans mCamRotY = new AffineTrans();
private AffineTrans mCamRotZ = new AffineTrans();
private AffineTrans mCamera = new AffineTrans();
// camera's current angles
private int mCamAngleX = 0;
private int mCamAngleY = 0;
private int mCamAngleZ = 0;
// true if position or rotation was changed and need update
private boolean mCamereNeedUpdate = true;
// true - camera is moving, false - car is moving
private boolean mControlOnCamera = true;
// precalculated table of sin and cos values: 0-360 degrees
float[] sinTab;
float[] cosTab;
// main cube, "borders" for our world
WallContainer walls;
// a net of stationary, rotating cubes
SpinObstacleContainer obstacles;
// car that can be controled by user
CarUnit myCar;
// constructor
public MW_Canvas3D(MW_Main app)
{
this.app = app;
setFullScreenMode(true);
// Init the Soft keys
finishWorkWithCamCommand = new Command("UsingCam",Command.SCREEN,1);
finishWorkWithCarCommand = new Command("UsingCar",Command.SCREEN,1);
exitCommand = new Command("Quit",Command.EXIT,1);
this.addCommand(exitCommand);
this.addCommand(finishWorkWithCamCommand);
this.setCommandListener(this);
effect.setShadingType(Effect3D.NORMAL_SHADING);
effect.setLight(light);
// set screen width and height variables
WIDTH = getWidth();
HEIGHT = getHeight();
// get random position of car and camera (placed above the car)
// note: carX == -worldX
Random rn = new Random();
int pos = rn.nextInt(400);
if(rn.nextInt(100) > 50 )
pos *= -1;
// init camera
mCamMove.setIdentity();
mCamMove.lookAt( POS, LOOK, UP);
mCamMove.m03 -= pos;
mCamRotX.setIdentity();
mCamRotX.rotationX(mCamAngleX);
mCamRotY.setIdentity();
mCamRotY.rotationY(mCamAngleY);
mCamRotZ.setIdentity();
mCamRotZ.rotationZ(mCamAngleZ);
mCamera.setIdentity();
mCamera.mul(mCamRotX, mCamMove);
mCamereNeedUpdate = false;
// init sin and cos table
sinTab = new float[361];
cosTab = new float[361];
for( int i=0; i<361; ++i ) {
sinTab[i] = (float)Math.sin(Math.toRadians((double)i));
cosTab[i] = (float)Math.cos(Math.toRadians((double)i));
// System.out.println("i: " + i + ", sin: " + sinTab[i] + ", cos: " + cosTab[i]);
}
// create objects
try {
walls = new WallContainer(WIDTH, HEIGHT, mCamera, effect);
obstacles = new SpinObstacleContainer(WIDTH, HEIGHT, -400, 80,
mCamera, effect);
myCar = new CarUnit(pos, 0, -400,
WIDTH, HEIGHT, mCamera, effect,
sinTab, cosTab);
}
catch (Exception e) { e.printStackTrace(); }
}
public void paint( Graphics g )
{
g.setColor(0x77AAAA);
g.fillRect(0,0, WIDTH, HEIGHT);
System.gc();
Graphics3D g3d = new Graphics3D();
if( mCamereNeedUpdate ) {
setCamera();
walls.updateCamPosition(mCamera);
myCar.updateCamPosition(mCamera);
}
// cubes rotates, so they need to be updated anyway
obstacles.updateCamPosition(mCamera);
myCar.updateCamPosition(mCamera);
try {
g3d.bind(g);
walls.render(g3d);
obstacles.render(g3d);
myCar.render(g3d);
g3d.flush();
}
catch(Throwable h) {
h.printStackTrace();
}
finally {
g3d.release( g );
}
mFps.calculateFps();
g.setColor(0x000000);
g.fillRect(0,0,36,15);
g.setColor(0xFFFFFF);
g.drawString(mFps.getFpsString(), 0, 0, 0);
serviceRepaints();
}
public void clearResource()
{
}
// handle soft keys command
public void commandAction(Command command, Displayable displayable)
{
// switch control - now work with car
if(command == finishWorkWithCamCommand)
{
this.removeCommand(finishWorkWithCamCommand);
this.addCommand(finishWorkWithCarCommand);
mControlOnCamera = false;
}
// switch control - now work with camera
else if(command == finishWorkWithCarCommand)
{
this.removeCommand(finishWorkWithCarCommand);
this.addCommand(finishWorkWithCamCommand);
mControlOnCamera = true;
}
else if(command == exitCommand)
{
clearResource();
app.destroyApp(true);
}
}
protected void keyPressed(int keyCode)
{
if( !handleKeyNum(keyCode) )
handleKey(getGameAction(keyCode));
}
protected void keyRepeated(int keyCode)
{
if( !handleKeyNum(keyCode) )
handleKey(getGameAction(keyCode));
}
private void handleKey(int key)
{
if(mControlOnCamera) {
switch(key)
{
case Canvas.UP :
moveWorld(0, 0, -moveStep); // move forward
break;
case Canvas.DOWN :
moveWorld(0, 0, moveStep); // move backward
break;
case Canvas.LEFT :
moveWorld(moveStep, 0, 0); // move left
break;
case Canvas.RIGHT :
moveWorld(-moveStep, 0, 0); // move right
break;
case Canvas.FIRE :
setInitPosition();
break;
}
}
else {
switch(key)
{
case Canvas.UP :
{
// move forward
int[] x = new int[1];
int[] y = new int[1];
x[0] = 0;
y[0] = moveObjStep;
myCar.getMoveLocalToWord(x, y);
myCar.move(x[0], y[0]);
moveWorld(-x[0], y[0], 0);
break;
}
case Canvas.DOWN :
{
// move backward
int[] x = new int[1];
int[] y = new int[1];
x[0] = 0;
y[0] = -moveObjStep;
myCar.getMoveLocalToWord(x, y);
myCar.move(x[0], y[0]);
moveWorld(-x[0], y[0], 0);
break;
}
case Canvas.LEFT :
myCar.rotate(0, rotObjStep, 0); // turn left
rotateWorld(0, 0, rotObjStep); // turn left
break;
case Canvas.RIGHT :
myCar.rotate(0, -rotObjStep, 0); // turn right
rotateWorld(0, 0, -rotObjStep); // turn right
break;
case Canvas.FIRE :
setCamOnObj();
break;
}
}
}
private boolean handleKeyNum(int key)
{
boolean handled = false;
if(mControlOnCamera) {
switch(key)
{
case Canvas.KEY_NUM1 :
rotateWorld(0,0,-rotStep); // rotate clock wise
handled = true;
break;
case Canvas.KEY_NUM2 :
rotateWorld(rotStep,0,0); // turn up
handled = true;
break;
case Canvas.KEY_NUM3 :
moveWorld(0, moveStep, 0); // move up
handled = true;
break;
case Canvas.KEY_NUM4 :
rotateWorld(0,rotStep,0); // turn left
handled = true;
break;
case Canvas.KEY_NUM6 :
rotateWorld(0,-rotStep,0); // turn right
handled = true;
break;
case Canvas.KEY_NUM7 :
rotateWorld(0,0,rotStep); // rotate counter clock wise
handled = true;
break;
case Canvas.KEY_NUM8 :
rotateWorld(-rotStep,0,0); // turn down
handled = true;
break;
case Canvas.KEY_NUM9 :
moveWorld(0, -moveStep, 0); // move down
handled = true;
break;
}
}
else {
switch(key)
{
case Canvas.KEY_NUM4 :
{
// move left
int[] x = new int[1];
int[] y = new int[1];
x[0] = moveObjStep; y[0] = 0;
myCar.getMoveLocalToWord(x, y);
myCar.move(x[0], y[0]);
moveWorld(-x[0], y[0], 0);
handled = true;
break;
}
case Canvas.KEY_NUM6 :
{
// move right
int[] x = new int[1];
int[] y = new int[1];
x[0] = -moveObjStep; y[0] = 0;
myCar.getMoveLocalToWord(x, y);
myCar.move(x[0], y[0]);
moveWorld(-x[0], y[0], 0);
handled = true;
break;
}
case Canvas.KEY_NUM2 :
case Canvas.KEY_NUM8 :
handled = true;
break;
}
}
return handled;
}
// place camera on top of car
private void setCamOnObj()
{
mCamereNeedUpdate = true;
mCamAngleX = 0;
mCamAngleY = 0;
// car is rotating around Z, it is initially rotated 180 degrees
mCamAngleZ = myCar.getSpinAngleY() + 2048;
mCamMove.setIdentity();
mCamMove.lookAt( POS, LOOK, UP);
mCamMove.m03 = -myCar.getPosX(); // carX == -worldX
mCamMove.m13 = myCar.getPosY();
}
// place camera in the center of the world
private void setInitPosition()
{
mCamereNeedUpdate = true;
mCamAngleX = 0;
mCamAngleY = 0;
mCamAngleZ = 0;
mCamMove.setIdentity();
mCamMove.lookAt( POS, LOOK, UP);
}
// update camera's affine transformation according to current position and angles
private void setCamera()
{
mCamRotX.setIdentity();
mCamRotX.rotationX(mCamAngleX);
mCamRotY.setIdentity();
mCamRotY.rotationY(mCamAngleY);
mCamRotZ.setIdentity();
mCamRotZ.rotationZ(mCamAngleZ);
mCamRotX.mul(mCamRotY);
mCamRotX.mul(mCamRotZ);
mCamera.setIdentity();
// one can choose which one is first: rotation or translation
// this one might be better for moving around the world
// mCamera.mul(mCamMove, mCamRotX);
// for folowing car, this order is good
mCamera.mul(mCamRotX, mCamMove);
mCamereNeedUpdate = false;
}
private void moveWorld(int aX, int aY, int aZ)
{
mCamereNeedUpdate = true;
mCamMove.m03 += aX;
mCamMove.m13 += aY;
mCamMove.m23 += aZ;
}
private void rotateWorld(int aX, int aY, int aZ)
{
mCamereNeedUpdate = true;
mCamAngleX += aX;
mCamAngleY += aY;
mCamAngleZ += aZ;
if(mCamAngleX >= 2048)
mCamAngleX = mCamAngleX - 4096;
else if( mCamAngleX <= -2048 )
mCamAngleX = mCamAngleX + 4096;
if(mCamAngleY >= 2048)
mCamAngleY = mCamAngleY - 4096;
else if( mCamAngleY <= -2048 )
mCamAngleY = mCamAngleY + 4096;
if(mCamAngleZ >= 2048)
mCamAngleZ = mCamAngleZ - 4096;
else if( mCamAngleZ <= -2048 )
mCamAngleZ = mCamAngleZ + 4096;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -