LGameAndroid2DView.java :  » Game » ghostfortchess » org » loon » framework » android » game » Android Open Source

Android Open Source » Game » ghostfortchess 
ghostfortchess » org » loon » framework » android » game » LGameAndroid2DView.java
package org.loon.framework.android.game;

import java.util.concurrent.TimeUnit;

import org.loon.framework.android.game.core.EmulatorButtons;
import org.loon.framework.android.game.core.EmulatorListener;
import org.loon.framework.android.game.core.LSystem;
import org.loon.framework.android.game.core.graphics.IScreen;
import org.loon.framework.android.game.core.graphics.LColor;
import org.loon.framework.android.game.core.graphics.LFont;
import org.loon.framework.android.game.core.graphics.LImage;
import org.loon.framework.android.game.core.graphics.device.LGraphics;
import org.loon.framework.android.game.core.timer.LTimerContext;
import org.loon.framework.android.game.core.timer.SystemTimer;
import org.loon.framework.android.game.utils.GraphicsUtils;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

/**
 * 
 * Copyright 2008 - 2010
 * 
 * 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 loonframework
 * @author chenpeng
 * @email ceponline@yahoo.com.cn
 * @version 0.1.0
 */
public class LGameAndroid2DView extends SurfaceView implements
    SurfaceHolder.Callback, Android2DSurface {

  private final static long MAX_INTERVAL = 1000L;

  final static private Matrix tmp_matrix = new Matrix();

  final static private LFont fpsFont = LFont
      .getFont(LSystem.FONT_NAME, 0, 20);

  final static private int fpsX = 5;

  final static private int fpsY = 20;

  private boolean isFPS, isDebug, isLogo, paused, running;

  private int width, height, drawPriority;

  private long maxFrames, before, curTime, startTime, offsetTime, curFPS,
      calcInterval;

  private double frameCount;

  private Bitmap currentScreen;

  private SurfaceHolder surfaceHolder;

  private CanvasThread mainLoop;

  private volatile LImage logo;

  private ViewAnimator animator;

  private LGraphics gl;

  private IAndroid2DHandler handler;

  private LGameAndroid2DActivity activity;

  private Rect rect;

  private Canvas canvas;

  private Paint resizePaint;

  private LImage canvasImage;

  private int number, shake;

  protected static IScreen control;

  private EmulatorListener emulatorListener;

  private EmulatorButtons emulatorButtons;

  public LGameAndroid2DView(LGameAndroid2DActivity activity,
      boolean isLandscape) {
    super(activity.getApplicationContext());
    try {
      LSystem.setupHandler(activity, this, isLandscape);
      this.handler = (IAndroid2DHandler) LSystem.getSystemHandler();
      this.handler.initScreen();
      this.activity = handler.getLGameActivity();
      this.createScreen();
    } catch (Exception e) {
    }
  }

  protected void onAttachedToWindow() {
    if (animator != null) {
      animator.start();
    }
    super.onAttachedToWindow();
  }

  protected void onDetachedFromWindow() {
    if (animator != null) {
      animator.stop();
    }
    super.onDetachedFromWindow();
  }

  public void setPaused(boolean paused) {
    this.paused = paused;
    LSystem.isPaused = paused;
  }

  public boolean isPaused() {
    return paused;
  }

  /**
   * 
   */
  private void createScreen() {
    this.canvasImage = new LImage(width = handler.getWidth(),
        height = handler.getHeight(), false);
    this.gl = canvasImage.getLGraphics();
    this.currentScreen = canvasImage.getBitmap();
    this.rect = new Rect(0, 0, width, height);
    this.surfaceHolder = getHolder();
    this.isLogo = true;
    int mode = 0;
    try {
      mode = 1;
      surfaceHolder
          .setType(android.view.SurfaceHolder.SURFACE_TYPE_HARDWARE);
    } catch (Exception e) {
      try {
        mode = 2;
        surfaceHolder
            .setType(android.view.SurfaceHolder.SURFACE_TYPE_GPU);
      } catch (Exception e2) {
        surfaceHolder
            .setType(android.view.SurfaceHolder.SURFACE_TYPE_NORMAL);
      }
    }

    switch (mode) {
    case 1:
      Log.i("Android2DView", "Hardware surface");
      break;
    case 2:
      Log.i("Android2DView", "GPU surface");
      break;
    default:
      Log.i("Android2DView", "No hardware acceleration available");
    }
    this.surfaceHolder.addCallback(this);
    this.surfaceHolder.setFormat(PixelFormat.RGB_565);
    this.setFPS(LSystem.DEFAULT_MAX_FPS);
    this.setClickable(false);
    this.setFocusable(true);
    this.setFocusableInTouchMode(true);
    this.setHapticFeedbackEnabled(false);
    this.setKeepScreenOn(true);
    this.setLongClickable(false);
    this.setDrawingCacheEnabled(false);
    this.setWillNotCacheDrawing(true);
    this.setWillNotDraw(true);
  }

  /**
   * 
   * 
   * @param emulatorListener
   */
  public void setEmulatorListener(EmulatorListener emulator) {
    this.emulatorListener = emulator;
    if (emulatorListener != null) {
      if (emulatorButtons == null) {
        emulatorButtons = new EmulatorButtons(emulatorListener, width,
            height);
      } else {
        emulatorButtons.setEmulatorListener(emulator);
      }
    } else {
      emulatorButtons = null;
    }
  }

  /**
   * 
   * 
   * @return
   */
  public EmulatorListener getEmulatorListener() {
    return emulatorListener;
  }

  /**
   * 
   * 
   * @return
   */
  public EmulatorButtons getEmulatorButtons() {
    return emulatorButtons;
  }

  public void setScreen(IScreen screen) {
    this.handler.setScreen(screen);
  }

  public final Bitmap getAndroid2DBitmap() {
    return currentScreen;
  }

  public final LImage getAndroid2DImage() {
    return canvasImage;
  }

  public void destroyView() {
    try {
      synchronized (this) {

        handler.getAssetsSound().stopSoundAll();
        handler.destroy();
        LSystem.destroy();
        releaseResources();
        notifyAll();

      }
    } catch (Exception e) {
    }
  }

  /**
   * 
   * 
   */
  public void update() {
    try {
      if (!running) {
        return;
      }
      if (currentScreen == null) {
        return;
      }
      canvas = surfaceHolder.lockCanvas(rect);
      if (canvas != null) {
        synchronized (surfaceHolder) {
          canvas.drawBitmap(currentScreen, 0, 0, null);
        }
        surfaceHolder.unlockCanvasAndPost(canvas);
      }
    } catch (Exception e) {
    }
  }

  /**
   * 
   * 
   * @param bit
   * @param x
   * @param y
   */
  public void updateLocation(Bitmap bit, int x, int y) {
    try {
      if (!running) {
        return;
      }
      if (bit == null) {
        return;
      }
      canvas = surfaceHolder.lockCanvas(rect);
      if (canvas != null) {
        synchronized (surfaceHolder) {
          canvas.drawBitmap(bit, x, y, null);
          if (emulatorButtons != null) {
            emulatorButtons.draw(canvas);
          }
        }
        surfaceHolder.unlockCanvasAndPost(canvas);
      }
    } catch (Exception e) {
    }
  }

  /**
   * 
   * 
   * @param img
   * @param x
   * @param y
   */
  public void updateLocation(LImage img, int x, int y) {
    if (img == null) {
      return;
    }
    updateLocation(img.getBitmap(), x, y);
  }

  /**
   * 
   * 
   * @param img
   */
  public void update(LImage img) {
    if (img == null) {
      return;
    }
    update(img.getBitmap());
  }

  /**
   * 
   * 
   * @param img
   */
  public void update(Bitmap bit) {
    try {
      if (!running) {
        return;
      }
      if (bit == null) {
        return;
      }
      canvas = surfaceHolder.lockCanvas(rect);
      if (canvas != null) {
        synchronized (surfaceHolder) {
          canvas.drawBitmap(bit, 0, 0, null);
          if (emulatorButtons != null) {
            emulatorButtons.draw(canvas);
          }
        }
        surfaceHolder.unlockCanvasAndPost(canvas);
      }
    } catch (Exception e) {
    }
  }

  /**
   * 
   * 
   * @param img
   * @param w
   * @param h
   */
  public void update(LImage img, int w, int h) {
    if (img == null) {
      return;
    }
    update(img.getBitmap(), w, h);
  }

  /**
   * 
   * 
   * @param bit
   * @param w
   * @param h
   */
  public void update(Bitmap bit, int w, int h) {
    if (!running) {
      return;
    }
    if (bit == null) {
      return;
    }
    canvas = surfaceHolder.lockCanvas(rect);
    if (canvas != null) {
      synchronized (surfaceHolder) {
        canvas.drawBitmap(bit, width / 2 - w / 2, height / 2 - h / 2,
            null);
        if (emulatorButtons != null) {
          emulatorButtons.draw(canvas);
        }
      }
      surfaceHolder.unlockCanvasAndPost(canvas);
    }
  }

  /**
   * 
   * 
   * @param img
   * @param w
   * @param h
   */
  public void updateFull(LImage img, int w, int h) {
    if (img == null) {
      return;
    }
    updateFull(img.getBitmap(), w, h);
  }

  /**
   * 
   * 
   * @param img
   * @param w
   * @param h
   */
  public void updateFull(Bitmap bit, int w, int h) {
    if (!running) {
      return;
    }
    if (bit == null) {
      return;
    }
    canvas = surfaceHolder.lockCanvas(rect);
    if (canvas != null) {
      int nw = bit.getWidth();
      int nh = bit.getHeight();
      if (nw == w && nh == h) {
        synchronized (surfaceHolder) {
          canvas.drawBitmap(bit, width / 2 - w / 2, height / 2 - h
              / 2, null);
          if (emulatorButtons != null) {
            emulatorButtons.draw(canvas);
          }
        }
        surfaceHolder.unlockCanvasAndPost(canvas);
        return;
      }
      if (LSystem.isOverrunOS21()) {
        float scaleWidth = ((float) w) / nw;
        float scaleHeight = ((float) h) / nh;
        tmp_matrix.reset();
        tmp_matrix.postScale(scaleWidth, scaleHeight);
        tmp_matrix.postTranslate(width / 2 - w / 2, height / 2 - h / 2);
        synchronized (surfaceHolder) {
          canvas.drawBitmap(bit, tmp_matrix, null);
          if (emulatorButtons != null) {
            emulatorButtons.draw(canvas);
          }
        }
        surfaceHolder.unlockCanvasAndPost(canvas);
      } else {
        int x = width / 2 - w / 2;
        int y = height / 2 - h / 2;
        Rect srcR = new Rect(0, 0, w, h);
        Rect dstR = new Rect(x, y, x + w, y + h);
        synchronized (surfaceHolder) {
          canvas.drawBitmap(bit, srcR, dstR, null);
          if (emulatorButtons != null) {
            emulatorButtons.draw(canvas);
          }
        }
        surfaceHolder.unlockCanvasAndPost(canvas);
      }
    }
  }

  /**
   * 
   * 
   * @param img
   * @param w
   * @param h
   */
  public void updateResize(LImage img, int w, int h) {
    if (img == null) {
      return;
    }
    updateResize(img.getBitmap(), w, h);
  }

  /**
   * 
   * 
   * @param bit
   * @param w
   * @param h
   */
  public void updateResize(Bitmap bit, int w, int h) {
    if (!running) {
      return;
    }
    if (bit == null) {
      return;
    }
    canvas = surfaceHolder.lockCanvas(rect);
    if (canvas != null) {
      int nw = bit.getWidth();
      int nh = bit.getHeight();
      float scaleWidth = ((float) w) / nw;
      float scaleHeight = ((float) h) / nh;
      tmp_matrix.reset();
      tmp_matrix.postScale(scaleWidth, scaleHeight);
      tmp_matrix.postTranslate(width / 2 - w / 2, height / 2 - h / 2);
      synchronized (surfaceHolder) {
        if (resizePaint == null) {
          resizePaint = new Paint();
        }
        resizePaint.setFilterBitmap(true);
        canvas.drawBitmap(bit, tmp_matrix, resizePaint);
        resizePaint.setFilterBitmap(false);
        if (emulatorButtons != null) {
          emulatorButtons.draw(canvas);
        }
      }
      surfaceHolder.unlockCanvasAndPost(canvas);
    }
  }

  private long innerClock() {
    long now = System.currentTimeMillis();
    long ret = now - before;
    before = now;
    return ret;
  }

  final private class CanvasThread extends Thread {

    public CanvasThread() {
      running = true;
      setName("CanvasThread");
    }

    /**
     * logo
     */
    private void showLogo() {
      try {
        long elapsedTime;
        int cx = 0, cy = 0;
        double delay;
        try {
          if (logo == null) {
            logo = GraphicsUtils.loadNotCacheImage(
                "system/images/logo.png", true);
          }
          cx = LGameAndroid2DView.this.getWidth() / 2
              - logo.getWidth() / 2;
          cy = LGameAndroid2DView.this.getHeight() / 2
              - logo.getHeight() / 2;
        } catch (Exception e) {

        }
        float alpha = 0.0f;
        boolean firstTime = true;
        elapsedTime = innerClock();
        gl.setAntiAlias(true);
        while (alpha < 1.0f) {
          gl.drawClear();
          gl.setAlpha(alpha);
          gl.drawImage(logo, cx, cy);
          if (firstTime) {
            firstTime = false;
          }
          elapsedTime = innerClock();
          delay = 0.00065 * elapsedTime;
          if (delay > 0.22) {
            delay = 0.22 + (delay / 6);
          }
          alpha += delay;
          update();
        }
        while (number < 3000) {
          number += innerClock();
          update();
        }
        alpha = 1.0f;
        while (alpha > 0.0f) {
          gl.drawClear();
          gl.setAlpha(alpha);
          gl.drawImage(logo, cx, cy);
          elapsedTime = innerClock();
          delay = 0.00055 * elapsedTime;
          if (delay > 0.15) {
            delay = 0.15 + ((delay - 0.04) / 2);
          }
          alpha -= delay;
          update();
        }
        gl.setAntiAlias(false);
      } catch (Throwable e) {
      } finally {
        isLogo = false;
      }
    }

    /**
     * 
     */
    public void run() {
      if (isLogo) {
        showLogo();
      }
      try {
        final LTimerContext timerContext = new LTimerContext();
        final SystemTimer timer = LSystem.getSystemTimer();
        boolean reapint = false;
        timerContext.setTimeMillis(startTime = timer.getTimeMillis());
        do {
          if (paused || !isFocusable()) {
            pause(500);
            continue;
          }
          if (!control.next()) {
            continue;
          }
          reapint = LSystem.AUTO_REPAINT;
          if (reapint) {
            canvas = surfaceHolder.lockCanvas(rect);
            shake = control.getShakeNumber();
            if (shake > 0) {
              gl.drawBitmap(control.getBackground(), shake / 2
                  - LSystem.random.nextInt(shake), shake / 2
                  - LSystem.random.nextInt(shake));
            } else if (shake == -1) {
              gl.drawBitmap(control.getBackground(), 0, 0);
            }
          }
          curTime = timer.getTimeMillis();
          timerContext.timeSinceLastUpdate = curTime
              - timerContext.millisTime;
          timerContext.millisSleepTime = (offsetTime - timerContext.timeSinceLastUpdate)
              - timerContext.millisOverSleepTime;
          if (timerContext.millisSleepTime > 0) {
            pause(timerContext.millisSleepTime);
            timerContext.millisOverSleepTime = ((timer
                .getTimeMillis() - curTime) - timerContext.millisSleepTime);
          } else {
            timerContext.millisOverSleepTime = 0L;
          }
          timerContext.millisTime = timer.getTimeMillis();
          control.callEvents(true);
          control.runTimer(timerContext);
          if (reapint) {
            control.createUI(gl);
            if (isFPS) {
              tickFrames();
              gl.setAntiAlias(true);
              gl.setFont(fpsFont);
              gl.setColor(LColor.white);
              gl.drawString("FPS:" + curFPS, fpsX, fpsY);
            }
            if (canvas != null) {
              synchronized (surfaceHolder) {
                if (emulatorButtons != null) {
                  emulatorButtons.draw(gl);
                }
                canvas.drawBitmap(currentScreen, tmp_matrix,
                    null);
              }
              surfaceHolder.unlockCanvasAndPost(canvas);
            }
          }
        } while (running);
      } catch (Exception ex) {
        // ex.printStackTrace();
        if (isDebug) {
          try {
            // 
            activity.showAndroidException(ex);
          } catch (Exception e) {
          }
        }
      } finally {
        destroyView();
      }
    }

    private final void pause(long sleep) {
      try {
        TimeUnit.MILLISECONDS.sleep(sleep);
      } catch (InterruptedException e) {
      }
    }

    private void tickFrames() {
      frameCount++;
      calcInterval += offsetTime;
      if (calcInterval >= MAX_INTERVAL) {
        long timeNow = System.currentTimeMillis();
        long realElapsedTime = timeNow - startTime;
        curFPS = (long) ((frameCount / realElapsedTime) * MAX_INTERVAL);
        frameCount = 0L;
        calcInterval = 0L;
        startTime = timeNow;
      }
    }

  }

  public boolean isShowLogo() {
    return isLogo;
  }

  public void setShowLogo(boolean showLogo) {
    this.isLogo = showLogo;
  }

  public void setLogo(LImage img) {
    logo = img;
  }

  public LImage getLogo() {
    return logo;
  }

  public void setDebug(boolean debug) {
    this.isDebug = debug;
  }

  public boolean isDebug() {
    return isDebug;
  }

  public Thread getMainLoop() {
    return mainLoop;
  }

  public void setFPS(long frames) {
    this.maxFrames = frames;
    this.offsetTime = (long) (1.0 / maxFrames * MAX_INTERVAL);
  }

  public long getMaxFPS() {
    return this.maxFrames;
  }

  public long getCurrentFPS() {
    return this.curFPS;
  }

  public void setShowFPS(boolean isFPS) {
    this.isFPS = isFPS;
  }

  public boolean isRunning() {
    return running;
  }

  public void setRunning(boolean running) {
    this.running = running;
  }

  public void surfaceChanged(SurfaceHolder holder, int format, int width,
      int height) {
  }

  public void surfaceCreated(SurfaceHolder holder) {
    try {
      if (!running) {
        this.setRunning(true);
        if (mainLoop == null) {
          this.mainLoop = new CanvasThread();
          this.drawPriority = Thread.NORM_PRIORITY;
          this.mainLoop.setPriority(drawPriority);
          this.mainLoop.start();
        }
      }
    } catch (Exception e) {

    }
  }

  public void surfaceDestroyed(SurfaceHolder holder) {
    try {
      if (!paused) {
        if (mainLoop != null) {
          this.setRunning(false);
          this.mainLoop = null;
        }
      }
    } catch (Exception e) {

    }
  }

  private void stopThread() {
    try {
      if (mainLoop != null) {
        boolean result = true;
        setRunning(false);
        while (result) {
          try {
            mainLoop.join();
            result = false;
          } catch (InterruptedException e) {
          }
        }

      }
    } catch (Exception e) {

    }
  }

  private void releaseResources() {
    try {
      if (surfaceHolder != null) {
        surfaceHolder.removeCallback(this);
        surfaceHolder = null;
      }
      stopThread();
    } catch (Exception e) {

    }
  }

  public int getDrawPriority() {
    return drawPriority;
  }

  public void setDrawPriority(int drawPriority) {
    if (drawPriority >= 0 && drawPriority <= 10) {
      this.drawPriority = drawPriority;
      if (mainLoop != null) {
        try {
          mainLoop.setPriority(drawPriority);
        } catch (Exception e) {
        }
      }
    }
  }

  public boolean onTouchEvent(MotionEvent e) {
    activity.onTouchEvent(e);
    if (emulatorButtons != null) {
      emulatorButtons.onEmulatorButtonEvent(e);
    }
    try {
      Thread.sleep(16);
    } catch (Exception ex) {
    }
    return true;
  }

  public IAndroid2DHandler getGameHandler() {
    return handler;
  }

}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.