/** * Copyright 2008 - 2015 The Loon Game Engine Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. * * @project loon * @author cping * @email:javachenpeng@yahoo.com * @version 0.5 */ package loon; import loon.LGame.Status; import loon.canvas.LColor; import loon.event.GameKey; import loon.event.GameTouch; import loon.event.InputMake; import loon.event.KeyMake; import loon.event.MouseMake; import loon.event.SysInputFactory; import loon.event.TouchMake; import loon.event.Updateable; import loon.geom.Vector2f; import loon.opengl.GLEx; import loon.opengl.LSTRDictionary; import loon.utils.ListMap; import loon.utils.MathUtils; import loon.utils.TArray; import loon.utils.processes.RealtimeProcess; import loon.utils.processes.RealtimeProcessManager; import loon.utils.reply.Port; import loon.utils.timer.LTimerContext; public class LProcess extends PlayerUtils { TArray<Updateable> loads; TArray<Updateable> unloads; EmulatorListener emulatorListener; private EmulatorButtons emulatorButtons; private final ListMap<CharSequence, Screen> _screenMap; private final TArray<Screen> _screens; private boolean isInstance; private int id; private boolean _waitTransition; private boolean _running; private Screen _currentScreen, _loadingScreen; private LTransition _transition; private LogDisplay _logDisplay; private final Bundle<?> _bundle; private final SysInputFactory _currentInput; private final LGame _game; public LProcess(LGame game) { super(); this._game = game; this._bundle = new MapBundle(); this._currentInput = new SysInputFactory(this); this._screens = new TArray<Screen>(); this._screenMap = new ListMap<CharSequence, Screen>(); this.clear(); InputMake input = game.input(); if (input != null) { if (!game.setting.emulateTouch && !game.isMobile()) { input.mouseEvents.connect(new MouseMake.ButtonSlot() { public void onEmit(MouseMake.ButtonEvent event) { _currentInput.callMouse(event); } }); } else { input.touchEvents.connect(new Port<TouchMake.Event[]>() { @Override public void onEmit(TouchMake.Event[] events) { _currentInput.callTouch(events); } }); } input.keyboardEvents.connect(new KeyMake.KeyPort() { @Override public void onEmit(KeyMake.KeyEvent e) { _currentInput.callKey(e); } }); } game.status.connect(new Port<LGame.Status>() { @Override public void onEmit(Status event) { switch (event) { case EXIT: stop(); break; case RESUME: LSystem.PAUSED = false; resume(); break; case PAUSE: LSystem.PAUSED = true; pause(); break; default: break; } } }); // 当处于html5时,让本地字体渲染的创建过程异步 LSTRDictionary.get().setAsyn(game.isHTML5()); } private final static void callUpdateable(final TArray<Updateable> list) { TArray<Updateable> loadCache; synchronized (list) { loadCache = new TArray<Updateable>(list); list.clear(); } for (int i = 0, size = loadCache.size; i < size; i++) { Updateable _running = loadCache.get(i); synchronized (_running) { _running.action(null); } } loadCache = null; } public final SysInputFactory getCurrentSysInput() { return _currentInput; } // --- Load start ---// public void addLoad(Updateable u) { synchronized (loads) { loads.add(u); } } public void removeLoad(Updateable u) { synchronized (loads) { loads.remove(u); } } public void removeAllLoad() { synchronized (loads) { loads.clear(); } } public void load() { if (isInstance) { final int count = loads.size; if (count > 0) { callUpdateable(loads); } } } // --- Load end ---// // --- UnLoad start ---// public void addUnLoad(Updateable u) { synchronized (unloads) { unloads.add(u); } } public void removeUnLoad(Updateable u) { synchronized (unloads) { unloads.remove(u); } } public void removeAllUnLoad() { synchronized (unloads) { unloads.clear(); } } public void unload() { if (isInstance) { final int count = unloads.size; if (count > 0) { callUpdateable(unloads); } } } // --- UnLoad end ---// private void setScreen(final Screen screen, boolean put) { if (_loadingScreen != null && _loadingScreen.isOnLoadComplete()) { return; } synchronized (this) { if (screen == null) { this.isInstance = false; throw LSystem.re("Cannot create a [Screen] instance !"); } if (!_game.display().showLogo) { if (_currentScreen != null) { setTransition(screen.onTransition()); } else { // 为了防止画面单调,Loon默认为无设定Transition的,首个Screen随机增加一个特效 // 不想使用,或者需要设定的话,请重载Screen的onTransition函数。 // 不使用:返回: LTransition.newEmpty() // 使用:返回: 设定或者自定义一个LTransition对象. LTransition _transition = screen.onTransition(); if (_transition == null) { int rad = MathUtils.random(0, 10); switch (rad) { case 0: _transition = LTransition.newFadeIn(); break; case 1: _transition = LTransition.newArc(); break; case 2: _transition = LTransition.newSplitRandom(LColor.black); break; case 3: _transition = LTransition.newCrossRandom(LColor.black); break; case 4: _transition = LTransition.newFadeOvalIn(LColor.black); break; case 5: _transition = LTransition.newPixelWind(LColor.white); break; case 6: _transition = LTransition.newPixelDarkOut(LColor.black); break; case 7: _transition = LTransition.newPixelThunder(LColor.black); break; case 8: _transition = LTransition.newFadeDotIn(LColor.black); break; case 9: _transition = LTransition.newFadeTileIn(LColor.black); break; case 10: _transition = LTransition.newFadeSpiralIn(LColor.black); break; } } setTransition(_transition); } } clearLog(); screen.setOnLoadState(false); if (_currentScreen == null) { _currentScreen = screen; } else { killScreen(screen); } this.isInstance = true; if (screen instanceof EmulatorListener) { setEmulatorListener((EmulatorListener) screen); } else { setEmulatorListener(null); } screen.onCreate(LSystem.viewSize.getWidth(), LSystem.viewSize.getHeight()); RealtimeProcess process = new RealtimeProcess() { @Override public void run(LTimerContext time) { if (!LSystem._base.display().showLogo) { startTransition(); screen.setClose(false); screen.resetSize(); screen.onLoad(); screen.onLoaded(); screen.setOnLoadState(true); screen.resume(); endTransition(); kill(); } } }; process.setDelay(0); RealtimeProcessManager.get().addProcess(process); if (put) { _screens.add(screen); } _loadingScreen = null; } } private void killScreen(Screen screen) { synchronized (_currentScreen) { if (screen == _currentScreen) { screen.pause(); } screen.destroy(); _currentScreen = screen; } } public void start() { if (!_running) { if (_loadingScreen != null) { setScreen(_loadingScreen); } _running = true; } } public void resize(int w, int h) { if (isInstance) { _currentScreen.resize(w, h); } } public void resume() { if (isInstance) { _currentScreen.resume(); } } public void pause() { if (isInstance) { _currentScreen.pause(); } } public void stop() { _running = false; if (isInstance) { _currentScreen.stop(); } endTransition(); if (isInstance) { isInstance = false; unloads.clear(); if (_currentScreen != null) { _currentScreen.destroy(); _currentScreen = null; } if (_game != null && _game.display() != null) { _game.assets().close(); _game.display().close(); } RealtimeProcessManager.get().dispose(); LSTRDictionary.get().dispose(); LTextures.dispose(); } LSystem.debug("The Loon Game Engine is End"); } public void resetTouch() { _currentInput.resetSysTouch(); } public void clear() { if (loads == null) { loads = new TArray<Updateable>(10); } else { loads.clear(); } if (unloads == null) { unloads = new TArray<Updateable>(10); } else { unloads.clear(); } clearScreens(); } public void calls() { if (isInstance) { LTextureBatch.clearBatchCaches(); } } public boolean next() { if (isInstance) { if (_currentScreen.next() && !LSystem.PAUSED) { return true; } } return false; } public void runTimer(LTimerContext context) { if (isInstance) { if (_waitTransition) { if (_transition != null) { switch (_transition.code) { default: if (!_currentScreen.isOnLoadComplete()) { _transition.update(context.timeSinceLastUpdate); } break; case 1: if (!_transition.completed()) { _transition.update(context.timeSinceLastUpdate); } else { endTransition(); } break; } } } else { _currentScreen.runTimer(context); return; } } } public void draw(GLEx g) { if (isInstance) { if (_waitTransition) { if (_transition != null) { if (_transition.isDisplayGameUI) { _currentScreen.createUI(g); } switch (_transition.code) { default: if (!_currentScreen.isOnLoadComplete()) { _transition.draw(g); } break; case 1: if (!_transition.completed()) { _transition.draw(g); } break; } } } else { _currentScreen.createUI(g); return; } } } public void drawEmulator(GLEx gl) { if (emulatorButtons != null) { emulatorButtons.draw(gl); } } public LColor getBackgroundColor() { if (isInstance) { return _currentScreen.getBackgroundColor(); } return null; } public float getScaleX() { if (isInstance) { return _currentScreen.getScaleX(); } return 1f; } public float getScaleY() { if (isInstance) { return _currentScreen.getScaleY(); } return 1f; } public boolean isFlipX() { if (isInstance) { return _currentScreen.isFlipX(); } return false; } public boolean isFlipY() { if (isInstance) { return _currentScreen.isFlipY(); } return false; } public float getRotation() { if (isInstance) { return _currentScreen.getRotation(); } return 0; } public LTexture getBackground() { if (isInstance || _currentScreen != null) { return _currentScreen.getBackground(); } return null; } public int getRepaintMode() { if (isInstance) { return _currentScreen.getRepaintMode(); } return Screen.SCREEN_NOT_REPAINT; } /** * 设定模拟按钮监听器 * * @param emulatorListener */ public void setEmulatorListener(EmulatorListener emulator) { this.emulatorListener = emulator; if (emulatorListener != null) { if (emulatorButtons == null) { emulatorButtons = new EmulatorButtons(emulatorListener, LSystem.viewSize.getWidth(), LSystem.viewSize.getHeight()); } else { emulatorButtons.setEmulatorListener(emulator); } } else { emulatorButtons = null; } } /** * 获得模拟器监听 * * @return */ public EmulatorListener getEmulatorListener() { return emulatorListener; } /** * 获得模拟器按钮 * * @return */ public EmulatorButtons getEmulatorButtons() { return emulatorButtons; } public void setScreenID(int id) { if (isInstance) { _currentScreen.setID(id); } } public int getScreenID() { return isInstance ? -1 : _currentScreen.getID(); } public void setID(int id) { this.id = id; } public int getID() { return id; } public final void setTransition(LTransition t) { this._transition = t; } public final boolean isTransitioning() { return _waitTransition; } public boolean isTransitionCompleted() { return !_waitTransition; } public final LTransition getTransition() { return this._transition; } private final void startTransition() { if (_transition != null) { _waitTransition = true; if (isInstance) { _currentScreen.setLock(true); } } } private final void endTransition() { if (_transition != null) { switch (_transition.code) { default: _waitTransition = false; _transition.close(); break; case 1: if (_transition.completed()) { _waitTransition = false; _transition.close(); } break; } if (isInstance) { _currentScreen.setLock(false); } } else { _waitTransition = false; } } public LColor getColor() { if (isInstance) { return _currentScreen.getColor(); } return LColor.white; } public float getX() { if (isInstance) { return _currentScreen.getX(); } return 0; } public float getY() { if (isInstance) { return _currentScreen.getY(); } return 0; } private final static Vector2f _tmpLocaltion = new Vector2f(); public Vector2f convertXY(float x, float y) { float newX = ((x - getX()) / (LSystem.getScaleWidth())); float newY = ((y - getY()) / (LSystem.getScaleHeight())); if (isInstance && _currentScreen.isTxUpdate()) { float oldW = getWidth(); float oldH = getHeight(); float newW = getWidth() * getScaleX(); float newH = getHeight() * getScaleY(); float offX = oldW / 2f - newW / 2f; float offY = oldH / 2f - newH / 2f; float nx = (newX - offX); float ny = (newY - offY); final int r = (int) getRotation(); switch (r) { case -90: offX = oldH / 2f - newW / 2f; offY = oldW / 2f - newH / 2f; nx = (newX - offY); ny = (newY - offX); _tmpLocaltion.set(nx / getScaleX(), ny / getScaleY()).rotate(-90); _tmpLocaltion.set(-(_tmpLocaltion.x - getWidth()), MathUtils.abs(_tmpLocaltion.y)); break; case 0: case 360: _tmpLocaltion.set(nx / getScaleX(), ny / getScaleY()); break; case 90: offX = oldH / 2f - newW / 2f; offY = oldW / 2f - newH / 2f; nx = (newX - offY); ny = (newY - offX); _tmpLocaltion.set(nx / getScaleX(), ny / getScaleY()).rotate(90); _tmpLocaltion.set(-_tmpLocaltion.x, MathUtils.abs(_tmpLocaltion.y - getHeight())); break; case -180: case 180: _tmpLocaltion.set(nx / getScaleX(), ny / getScaleY()).rotate(getRotation()).addSelf(getWidth(), getHeight()); break; default: // 原则上不处理非水平角度的触点 _tmpLocaltion.set(newX, newY); break; } } else { _tmpLocaltion.set(newX, newY); } if (isFlipX() || isFlipY()) { Director.local2Global(isFlipX(), isFlipY(), getWidth() / 2, getHeight() / 2, _tmpLocaltion.x, _tmpLocaltion.y, _tmpLocaltion); return _tmpLocaltion; } return _tmpLocaltion; } public Screen getScreen() { return _currentScreen; } public void clearScreens() { _screenMap.clear(); _screens.clear(); } public void clearScreenMaps() { _screenMap.clear(); } public void addScreen(CharSequence name, Screen screen) { if (!_screenMap.containsKey(name)) { _screenMap.put(name, screen); addScreen(screen); } } public Screen getScreen(CharSequence name) { Screen screen = _screenMap.get(name); if (screen != null) { return screen; } return null; } public Screen runScreenClassName(CharSequence name) { for (Screen screen : _screens) { if (screen != null) { if (name.equals(screen.getName())) { setScreen(screen); return screen; } } } return null; } public Screen runScreenName(CharSequence name) { for (Screen screen : _screens) { if (screen != null) { if (name.equals(screen.getScreenName())) { setScreen(screen); return screen; } } } return null; } public Screen runScreen(CharSequence name) { Screen screen = getScreen(name); if (screen != null) { setScreen(screen); return screen; } return null; } public void runPopScreen() { int size = _screens.size; if (size > 0) { Screen o = _screens.pop(); if (o != _currentScreen) { setScreen((Screen) o, false); } } } public void runPeekScreen() { runLastScreen(); } public void runFirstScreen() { int size = _screens.size; if (size > 0) { Screen o = _screens.first(); if (o != _currentScreen) { setScreen((Screen) o, false); } } } public void runLastScreen() { int size = _screens.size; if (size > 0) { Screen o = _screens.last(); if (o != _currentScreen) { setScreen(o, false); } } } public void runPreviousScreen() { int size = _screens.size; if (size > 0) { for (int i = 0; i < size; i++) { if (_currentScreen == _screens.get(i)) { if (i - 1 > -1) { setScreen(_screens.get(i - 1), false); return; } } } } } public void runNextScreen() { int size = _screens.size; if (size > 0) { for (int i = 0; i < size; i++) { if (_currentScreen == _screens.get(i)) { if (i + 1 < size) { setScreen(_screens.get(i + 1), false); return; } } } } } public void runIndexScreen(int index) { int size = _screens.size; if (size > 0 && index > -1 && index < size) { Object o = _screens.get(index); if (_currentScreen != o) { setScreen(_screens.get(index), false); } } } public boolean containsScreen(final Screen screen) { if (screen == null) { throw LSystem.runThrow("Cannot create a [IScreen] instance !"); } return _screens.contains(screen); } public void addScreen(final Screen screen) { if (screen == null) { throw LSystem.runThrow("Cannot create a [IScreen] instance !"); } if (!_screens.contains(screen)) { _screens.add(screen); } } public TArray<Screen> getScreens() { return _screens; } public int getScreenCount() { return _screens.size; } public void setScreen(final Screen screen) { if (screen.handler == null) { screen.resetSize(); } if (_game.setting.isLogo && _game.display().showLogo) { _loadingScreen = screen; } else { setScreen(screen, true); } } public int getHeight() { if (isInstance) { return _currentScreen.getHeight(); } return 0; } public int getWidth() { if (isInstance) { return _currentScreen.getWidth(); } return 0; } public void setCurrentScreen(final Screen screen) { setCurrentScreen(screen, true); } public void setCurrentScreen(final Screen screen, boolean closed) { if (screen != null) { this.isInstance = false; if (closed && _currentScreen != null) { _currentScreen.destroy(); } this._currentScreen = screen; _currentScreen.setLock(false); _currentScreen.setLocation(0, 0); _currentScreen.setClose(false); _currentScreen.setOnLoadState(true); if (screen.getBackground() != null) { _currentScreen.setRepaintMode(Screen.SCREEN_TEXTURE_REPAINT); } this.isInstance = true; if (screen instanceof EmulatorListener) { setEmulatorListener((EmulatorListener) screen); } else { setEmulatorListener(null); } this._screens.add(screen); } } public void keyDown(GameKey e) { if (isInstance) { _currentScreen.keyPressed(e); } } public void keyUp(GameKey e) { if (isInstance) { _currentScreen.keyReleased(e); } } public void keyTyped(GameKey e) { if (isInstance) { _currentScreen.keyTyped(e); } } public void mousePressed(GameTouch e) { if (isInstance) { _currentScreen.mousePressed(e); } } public void mouseReleased(GameTouch e) { if (isInstance) { _currentScreen.mouseReleased(e); } } public void mouseMoved(GameTouch e) { if (isInstance) { _currentScreen.mouseMoved(e); } } public void mouseDragged(GameTouch e) { if (isInstance) { _currentScreen.mouseDragged(e); } } public void clearLog() { if (_logDisplay != null) { _logDisplay.clear(); } } public void addLog(String mes, LColor col) { if (_logDisplay == null) { _logDisplay = new LogDisplay(); } _logDisplay.addText(mes, col); } public void addLog(String mes) { if (_logDisplay == null) { _logDisplay = new LogDisplay(); } _logDisplay.addText(mes); } public LogDisplay getLogDisplay() { return _logDisplay; } protected void paintLog(final GLEx g, int x, int y) { if (_logDisplay == null) { _logDisplay = new LogDisplay(); } _logDisplay.paint(g, x, y); } public Bundle<?> getBundle() { return _bundle; } public Screen getCurrentScreen() { return _currentScreen; } public LGame getGame() { return _game; } }