⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 standardgame.java

📁 java 3d game jme 工程开发源代码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright (c) 2003-2009 jMonkeyEngine
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 
 *   may be used to endorse or promote products derived from this software 
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
// $Id: StandardGame.java 4091 2009-01-21 19:01:20Z joshua.j.ellen $
package com.jmex.game;

import java.awt.Canvas;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;

import com.jme.app.AbstractGame;
import com.jme.image.Image;
import com.jme.input.InputSystem;
import com.jme.input.MouseInput;
import com.jme.input.joystick.JoystickInput;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.ColorRGBA;
import com.jme.system.DisplaySystem;
import com.jme.system.GameSettings;
import com.jme.system.PreferencesGameSettings;
import com.jme.system.dummy.DummySystemProvider;
import com.jme.system.jogl.JOGLSystemProvider;
import com.jme.util.GameTaskQueue;
import com.jme.util.GameTaskQueueManager;
import com.jme.util.NanoTimer;
import com.jme.util.TextureManager;
import com.jme.util.Timer;
import com.jmex.audio.AudioSystem;
import com.jmex.awt.jogl.JOGLAWTCanvasConstructor;
import com.jmex.awt.lwjgl.LWJGLAWTCanvasConstructor;
import com.jmex.game.state.GameStateManager;

/**
 * A game that implements all of the basic functionality that you will need.
 * <p>
 * This is intended to be the next logical step up from {@link com.jme.app.SimpleGame
 * SimpleGame} and can be utilised in production games.
 * <p>
 * {@code StandardGame} provides the following features to ease game development:
 * 
 * <ul>
 * <li>client/server division without needing any code changes;</li>
 * <li>an alternative settings to replace the PropertiesIO system;</li>
 * <li>built-in (forced) multithreading as the OpenGL thread is managed for you;</li>
 * <li>the ability to inject additional work into the OpenGL thread using a task queue;</li>
 * <li>shadow support;</li>
 * </ul>
 * 
 * as well as re-initialisation of the graphical context (if settings change
 * for example) and everything else a typical game requires.
 * <p>
 * However, even with all of the extras that {@code StandardGame} provides it
 * does not force anything extra on you as the non-necessary items should be
 * put into your {@link com.jmex.game.state.GameState GameState}s and managed
 * there. This process helps to organise the different aspects of your game and
 * get the game process started ASAP to kill the long-standing problem of
 * start-up lag.
 * 
 * @author Matthew D. Hicks
 * @version $Revision: 4091 $, $Date: 2009-01-22 03:01:20 +0800 (星期四, 22 一月 2009) $
 */
public final class StandardGame extends AbstractGame implements Runnable {
    private static final Logger logger = Logger.getLogger(StandardGame.class
            .getName());
    
    public static final int DISPLAY_WINDOW = 1;
    public static final int DISPLAY_CANVAS = 2;
    
    public static boolean THREAD_FRIENDLY = true;
    public static int DISPLAY_MODE = DISPLAY_WINDOW;
    
    public static enum GameType {
        GRAPHICAL, HEADLESS
    }

    private Thread gameThread;
    private String gameName;
    private GameType type;
    private boolean started;
    private Image[] icons;
    
    private Timer timer;
    private Camera camera;
    private ColorRGBA backgroundColor;
    private UncaughtExceptionHandler exceptionHandler;
    
    private Canvas canvas;

    private Lock updateLock;
    
    public StandardGame(String gameName) {
        this(gameName, GameType.GRAPHICAL, null);
    }

    public StandardGame(String gameName, GameType type) {
        this(gameName, type, null);
    }

    public StandardGame(String gameName, GameType type, GameSettings settings) {
        this(gameName, type, settings, null);
    }

    /**
     * @see AbstractGame#getNewSettings()
     */
    protected GameSettings getNewSettings() {
        boolean newNode = true;
        Preferences userPrefsRoot = Preferences.userRoot();
        try {
            newNode = !userPrefsRoot.nodeExists(gameName);
        } catch (BackingStoreException bse) { }

        return new PreferencesGameSettings(
                userPrefsRoot.node(gameName), newNode,
                "game-defaults.properties");

        /* To persist to a .properties file instead of java.util.prefs,
         * subclass StandardGame with a getNewSettings method like this:
        com.jme.system.PropertiesGameSettings pgs =
                new com.jme.system.PropertiesGameSettings("pgs.properties");
        pgs.load();
        return pgs;
        */
    }

    public StandardGame(String gameName, GameType type, GameSettings settings, UncaughtExceptionHandler exceptionHandler) {
        this.gameName = gameName;
        this.type = type;
        this.settings = settings;
        this.exceptionHandler = exceptionHandler;
        backgroundColor = ColorRGBA.black.clone();

        // if (this.settings == null) this.settings = getNewSettings();
        // To load settings without displaying a Settings widget, enable
        // the preceding if statement, and comment out the following if block.
        if (this.settings == null) {
            //setConfigShowMode(ConfigShowMode.AlwaysShow); // To override dflt.
            getAttributes();
        }

        // Create Lock
        updateLock = new ReentrantLock(true); // Make our lock be fair (first come, first serve)
    }

    public GameType getGameType() {
        return type;
    }

    public void start() {
        gameThread = new Thread(this);
        if (exceptionHandler == null) {
            exceptionHandler = new DefaultUncaughtExceptionHandler(this);
        }
        gameThread.setUncaughtExceptionHandler(exceptionHandler);
        
        // Assign a name to the thread
        gameThread.setName("OpenGL");
        
        gameThread.start();

        // Wait for main game loop before returning
        try {
            while (!isStarted()) {
                Thread.sleep(1);
            }
        } catch (InterruptedException exc) {
            logger.logp(Level.SEVERE, this.getClass().toString(), "start()", "Exception", exc);
        }
    }

    public void run() {
        lock();
        initSystem();
        if (type != GameType.HEADLESS) {
            assertDisplayCreated();
            
            // Default the mouse cursor to off
            MouseInput.get().setCursorVisible(false);
        }
        
        initGame();
        if (type == GameType.GRAPHICAL) {
            timer = Timer.getTimer();
        } else if (type == GameType.HEADLESS) {
            timer = new NanoTimer();
        }

        // Configure frame rate
        int preferredFPS = settings.getFramerate();
        long preferredTicksPerFrame = -1;
        long frameStartTick = -1;
        long frames = 0;
        long frameDurationTicks = -1;
        if (preferredFPS >= 0) {
            preferredTicksPerFrame = Math.round((float)timer.getResolution() / (float)preferredFPS);
        }

        // Main game loop
        float tpf;
        started = true;
        while ((!finished) && (!display.isClosing())) {
            // Fixed framerate Start
            if (preferredTicksPerFrame >= 0) {
                frameStartTick = timer.getTime();
            }

            timer.update();
            tpf = timer.getTimePerFrame();

            if (type == GameType.GRAPHICAL) {
                InputSystem.update();
            }
            update(tpf);
            render(tpf);
            display.getRenderer().displayBackBuffer();

            // Fixed framerate End
            if (preferredTicksPerFrame >= 0) {
                frames++;
                frameDurationTicks = timer.getTime() - frameStartTick;
                while (frameDurationTicks < preferredTicksPerFrame) {
                    long sleepTime = ((preferredTicksPerFrame - frameDurationTicks) * 1000) / timer.getResolution();
                    try {
                        Thread.sleep(sleepTime);
                    } catch (InterruptedException exc) {
                        logger.log(Level.SEVERE,
                                   "Interrupted while sleeping in fixed-framerate",
                                   exc);
                    }
                    frameDurationTicks = timer.getTime() - frameStartTick;
                }
                if (frames == Long.MAX_VALUE) frames = 0;
            }

            if (THREAD_FRIENDLY) Thread.yield();
        }
        started = false;
        cleanup();
        quit();
    }

    protected void initSystem() {
        if (type == GameType.GRAPHICAL) {

            // Configure Joystick
            if (JoystickInput.getProvider() == null) {
                JoystickInput.setProvider(InputSystem.INPUT_SYSTEM_LWJGL);
            }

            display = DisplaySystem.getDisplaySystem(settings.getRenderer());
            displayMins();
            
            display.setTitle(gameName);
            if( icons != null) {
                display.setIcon( icons);
            }

            if (DISPLAY_MODE == DISPLAY_WINDOW) {
                display.createWindow(settings.getWidth(), settings.getHeight(), settings.getDepth(), settings
                                .getFrequency(), settings.isFullscreen());
            } else if (DISPLAY_MODE == DISPLAY_CANVAS) {
            	// XXX: included to preserve current functionality. Probably
				// want to move this to prefs or the user of StandardGame.
                if(JOGLSystemProvider.SYSTEM_IDENTIFIER.equals(settings.getRenderer()))
                    display.registerCanvasConstructor("AWT", JOGLAWTCanvasConstructor.class);
                else
                    display.registerCanvasConstructor("AWT", LWJGLAWTCanvasConstructor.class);
                canvas = (Canvas)display.createCanvas(settings.getWidth(), settings.getHeight());
            }
            camera = display.getRenderer().createCamera(display.getWidth(), display.getHeight());
            display.getRenderer().setBackgroundColor(backgroundColor);

            // Setup Vertical Sync if enabled
            display.setVSyncEnabled(settings.isVerticalSync());

            // Configure Camera
            cameraPerspective();
            cameraFrame();
            camera.update();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -