📄 jpctdemo.java
字号:
frame.createBufferStrategy(2);
bufferStrategy=frame.getBufferStrategy();
Graphics g=bufferStrategy.getDrawGraphics();
bufferStrategy.show();
g.dispose();
} else {
frame=new Frame();
frame.setTitle("jPCT "+Config.getVersion());
frame.pack();
Insets insets = frame.getInsets();
titleBarHeight=insets.top;
leftBorderWidth=insets.left;
frame.setSize(width+leftBorderWidth+insets.right, height+titleBarHeight+insets.bottom);
frame.setResizable(false);
frame.show();
gFrame=frame.getGraphics();
}
/**
* The listeners are bound to the AWT frame...they are useless in OpenGL mode.
*/
frame.addWindowListener(new WindowEvents());
keyMapper=new KeyMapper(frame);
}
/**
* The fps counter is blitted into the rendered framebuffer here and the results
* will be displayed (hence the name of the method...:-))
*/
private void display() {
blitNumber((int) totalFps, 5, 2);
blitNumber((int) lastPps, 5, 12);
if (!openGL) {
if (!fullscreen) {
buffer.display(gFrame, leftBorderWidth, titleBarHeight);
} else {
Graphics g=bufferStrategy.getDrawGraphics();
g.drawImage(buffer.getOutputBuffer(), 0, 0, null);
bufferStrategy.show();
g.dispose();
}
} else {
buffer.displayGLOnly();
}
}
/**
* A simple method that does the number-blitting.
*/
private void blitNumber(int number, int x, int y) {
if (numbers!=null) {
String sNum=Integer.toString(number);
for (int i=0; i<sNum.length(); i++) {
char cNum=sNum.charAt(i);
int iNum=cNum-48;
buffer.blit(numbers, iNum*5, 0, x, y, 5, 9, FrameBuffer.TRANSPARENT_BLITTING);
x+=5;
}
}
}
/**
* Does the collision detection and the movement of the player.
*/
private void doMovement() {
/**
* The first part handles the "physics", i.e. it allows the player to fall down.
*/
SimpleVector camPos=camera.getPosition();
camPos.add(new SimpleVector(0, PLAYER_HEIGHT/2f, 0));
SimpleVector dir=new SimpleVector(0, GRAVITY, 0);
dir=theWorld.checkCollisionEllipsoid(camPos, dir, ELLIPSOID_RADIUS, 1);
camPos.add(new SimpleVector(0, -PLAYER_HEIGHT/2f, 0));
dir.x=0;
dir.z=0;
camPos.add(dir);
camera.setPosition(camPos);
/**
* The "falling" part of the player is now finished. Now we care for the horizontal movement.
* Nothing special here and no problems either. One thing worth mentioning is, that the player is
* always moving in the same plane regardless of where he's looking. playerDirection takes
* care of this.
*/
// forward and back may change during excution (threaded!), so we have to ensure to
// reset the camera only if has been changed before.
boolean cameraChanged=false;
if (forward) {
camera.moveCamera(new SimpleVector(0,1,0), PLAYER_HEIGHT/2f);
cameraChanged=true;
tempVector=playerDirection.getZAxis();
theWorld.checkCameraCollisionEllipsoid(tempVector, ELLIPSOID_RADIUS, MOVE_SPEED, 5);
}
if (back) {
if (!cameraChanged) {
camera.moveCamera(new SimpleVector(0,1,0), PLAYER_HEIGHT/2f);
cameraChanged=true;
}
tempVector=playerDirection.getZAxis();
tempVector.scalarMul(-1f);
theWorld.checkCameraCollisionEllipsoid(tempVector, ELLIPSOID_RADIUS, MOVE_SPEED, 5);
}
if (left) {
camera.rotateAxis(camera.getBack().getYAxis(), -TURN_SPEED);
playerDirection.rotateY(-TURN_SPEED);
}
if (right) {
camera.rotateAxis(camera.getBack().getYAxis(), TURN_SPEED);
playerDirection.rotateY(TURN_SPEED);
}
if (up) {
camera.rotateX(TURN_SPEED);
}
if (down) {
camera.rotateX(-TURN_SPEED);
}
if (cameraChanged) {
camera.moveCamera(new SimpleVector(0, -1, 0), PLAYER_HEIGHT/2f);
}
}
/**
* Move the elevator up/down
*/
private void moveElevator() {
if ((elevator.wasTargetOfLastCollision()&&elevatorCountdown--<=0)||
(elevatorPosition!=-90f&&elevatorPosition!=-180f)) {
float tempElevator=elevatorPosition+elevatorOffset;
float tempOffset=elevatorOffset;
if (tempElevator<-180f) {
tempOffset=-180f-elevatorPosition;
elevatorCountdown=50;
elevatorOffset*=-1f;
} else {
if (tempElevator>-90f) {
tempOffset=-90f-elevatorPosition;
elevatorCountdown=50;
elevatorOffset*=-1f;
}
}
elevatorPosition+=tempOffset;
elevator.translate(0, tempOffset, 0);
}
}
/**
* Poll the keyboard using the KeyMapper from com.threed.jpct.util
*/
private void poll() {
KeyState state=null;
do {
state=keyMapper.poll();
if (state!=KeyState.NONE) {
keyAffected(state);
}
} while (state!=KeyState.NONE);
}
/**
* This is the game's main loop. We are doing some additional setup work here and
* rendering the scene in a loop, as well as calling doMovement() to handle the movement
* and the collision detection before each frame.
*/
private void gameLoop() {
World.setDefaultThread(Thread.currentThread());
buffer=new FrameBuffer(width, height, FrameBuffer.SAMPLINGMODE_NORMAL);
buffer.enableRenderer(IRenderer.RENDERER_SOFTWARE);
buffer.setBoundingBoxMode(FrameBuffer.BOUNDINGBOX_NOT_USED);
buffer.optimizeBufferAccess();
Timer timer=new Timer(25);
timer.start();
Timer fpsTimer=new Timer(1000);
fpsTimer.start();
long timerTicks=0;
while (!exit) {
if (!isIdle) {
long ticks=timer.getElapsedTicks();
timerTicks+=ticks;
for (int i=0; i<ticks; i++) {
/**
* Do this as often as ticks have passed. This can
* be improved by calling the method only once and letting
* the collision detection somehow handle the ticks passed.
*/
doMovement();
moveElevator();
}
poll();
if (switchMode!=0) {
switchOptions();
}
buffer.clear();
weapon.getTranslationMatrix().setIdentity();
weapon.translate(camera.getPosition());
weapon.align(camera);
weapon.rotateAxis(camera.getDirection(), (float) Math.sin(timerTicks/6f)/20f);
theWorld.renderScene(buffer);
if (!wireframe) {
theWorld.draw(buffer);
}
else {
theWorld.drawWireframe(buffer, Color.white);
}
buffer.update();
display();
fps++;
pps+=theWorld.getVisibilityList().getSize();
if (fpsTimer.getElapsedTicks()>0) {
totalFps=(fps-lastFps);
lastFps=fps;
lastPps=pps;
pps=0;
}
Thread.yield();
} else {
try {
Thread.sleep(500);
} catch (InterruptedException e) {}
}
}
buffer.dispose();
if (!openGL && fullscreen) {
device.setFullScreenWindow(null);
}
System.exit(0);
}
/**
* This is for switching settings. Currently, only switching from OpenGL to software and
* back is supported here.
*/
private void switchOptions() {
switch (switchMode) {
case (SWITCH_RENDERER): {
isIdle=true;
if (buffer.usesRenderer(IRenderer.RENDERER_OPENGL)) {
keyMapper.destroy();
buffer.disableRenderer(IRenderer.RENDERER_OPENGL);
buffer.enableRenderer(IRenderer.RENDERER_SOFTWARE, IRenderer.MODE_OPENGL);
openGL=false;
if (fullscreen) {
device.setFullScreenWindow(null);
}
frame.hide();
frame.dispose();
initializeFrame();
} else {
frame.hide();
keyMapper.destroy();
buffer.enableRenderer(IRenderer.RENDERER_OPENGL, IRenderer.MODE_OPENGL);
buffer.disableRenderer(IRenderer.RENDERER_SOFTWARE);
openGL=true;
keyMapper=new KeyMapper();
}
isIdle=false;
break;
}
}
switchMode=0;
}
private void keyAffected(KeyState state) {
int code=state.getKeyCode();
boolean event=state.getState();
switch (code) {
case (KeyEvent.VK_ESCAPE): {
exit=event;
break;
}
case (KeyEvent.VK_LEFT): {
left=event;
break;
}
case (KeyEvent.VK_RIGHT): {
right=event;
break;
}
case (KeyEvent.VK_PAGE_UP): {
up=event;
break;
}
case (KeyEvent.VK_PAGE_DOWN): {
down=event;
break;
}
case (KeyEvent.VK_UP): {
forward=event;
break;
}
case (KeyEvent.VK_DOWN): {
back=event;
break;
}
case (KeyEvent.VK_1): {
if (event&&buffer.supports(FrameBuffer.SUPPORT_FOR_RGB_SCALING)) {
theWorld.getLights().setRGBScale(Lights.RGB_SCALE_DEFAULT);
}
break;
}
case (KeyEvent.VK_2): { // 2x scaling
if (event&&buffer.supports(FrameBuffer.SUPPORT_FOR_RGB_SCALING)) {
theWorld.getLights().setRGBScale(Lights.RGB_SCALE_2X);
}
break;
}
case (KeyEvent.VK_4): { // 4x scaling
if (event&&buffer.supports(FrameBuffer.SUPPORT_FOR_RGB_SCALING)) {
theWorld.getLights().setRGBScale(Lights.RGB_SCALE_4X);
}
break;
}
case (KeyEvent.VK_W): { // wireframe mode (w)
if (event) {
wireframe=!wireframe;
}
break;
}
case (KeyEvent.VK_X): { // change renderer (x)
if (event) {
switchMode=SWITCH_RENDERER;
}
break;
}
}
}
/**
* The WindowApapter used for software mode
*/
private class WindowEvents extends WindowAdapter {
public void windowIconified(WindowEvent e) {
isIdle=true;
}
public void windowDeiconified(WindowEvent e) {
isIdle=false;
}
}
private class Timer {
private long ticks=0;
private long granularity=0;
public Timer(int granularity) {
this.granularity=granularity;
}
public void start() {
ticks=System.currentTimeMillis();
}
public void reset() {
start();
}
public long getElapsedTicks() {
long cur=System.currentTimeMillis();
long l=cur-ticks;
if (l>=granularity) {
ticks=cur-(l%granularity);
return l/granularity;
}
return 0;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -