Back to project page java-androidframework.
The source code is released under:
This project is licensed under the [CC0 1.0 Agreement](http://creativecommons.org/publicdomain/zero/1.0/). To the extent possible under law, Pete Schmitz has waived all copyright and related or neigh...
If you think the Android project java-androidframework listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
package com.gamepatriot.framework2d.implementation; // w w w . j ava 2s. c o m import java.util.ArrayList; import java.util.Iterator; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import com.gamepatriot.androidframework.framework.AndroidImage; import com.gamepatriot.androidframework.framework.AndroidInputter; import com.gamepatriot.androidframework.framework.AndroidInputter.AndroidTouchEvent; import com.gamepatriot.androidframework.framework.AndroidRenderer; import com.gamepatriot.androidframework.framework.AndroidShape; import com.gamepatriot.framework2d.classes.FPS; import com.gamepatriot.framework2d.implementation.Inputter.TouchEvent; /** * The Renderer class broadcasts input, broadcasts time-step logic, and renders the application's display. The renderer handles all frame-based actions - Input (by collecting * events from an {@link Inputter}), display (by behaving as a SurfaceView and drawing elements from {@link Screen}s that are associated with a referenced {@link Main} class), and * time-steps (by triggering {@link Screen#update()} in-sync with updating the display). * * @see AndroidRenderer * @author Pete Schmitz, May 9, 2013 * */ public class Renderer extends SurfaceView implements AndroidRenderer, Runnable, SurfaceHolder.Callback { //Config /** The color used to flood fill the canvas before drawing elements. **/ private static int FLOOD_BACKGROUND = 0; private static boolean IGNORE_FLOOD = false; //References /** Reference to the application's {@link Main} object. **/ private final Main main; /** Reference to the holder used to lock and post the buffer canvas. **/ private final SurfaceHolder holder; /** Reference to an {@link Inputter} that will have its {@link TouchEvent}s broadcasted to {@link #main}'s {@link Screen}s. **/ private Inputter inputter; //Flags /** Flag to determine the continuation of updating for this single-thread application. **/ private volatile boolean running = false; /** Flag to determine the {@link #thread}'s dynamic sleep value (to result in a more consistent framerate). **/ private long lastUpdate; private boolean surfaceAvailable = false; //Containers /** Primary thread for this application, controls all display and time-step calls. **/ private Thread thread; /** Canvas for the supplied frame buffer that was created from {@link #main}. **/ private Canvas draw; /** Primary paint used for drawing bitmaps to the canvas/buffer. **/ private final Paint paint; private final FPS fps; public Renderer(Context $main){ super($main); //References main = (Main) $main; holder = getHolder(); holder.addCallback(this); //Containers //draw = new Canvas(frameBuffer); //dstRect = new Rect(); paint = new Paint(); fps = new FPS(); //Set the bitmap-paint flags paint.setAntiAlias(Main.ALLOW_ANTI_ALIASING); paint.setDither(Main.ALLOW_DITHER); paint.setFilterBitmap(Main.ALLOW_ANTI_ALIASING || Main.ALLOW_DITHER); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.d("surface", "Surface changed"); draw = null; } @Override public void surfaceCreated(SurfaceHolder holder) { Log.d("surface", "Surface created"); surfaceAvailable = true; draw = null; } @Override public void surfaceDestroyed(SurfaceHolder holder) { Log.d("surface", "Surface destroyed"); surfaceAvailable = false; draw = null; } @Override public void run() { while (running){ //Calculate delay to apply and adjust update flag accordingly long $delay = (Main.MS_DELAY - (System.currentTimeMillis() - lastUpdate)); lastUpdate = System.currentTimeMillis() + $delay; //Delay thread to match maximum-FPS rate if ($delay > 0){ try { Thread.sleep($delay); } catch (InterruptedException e){ } } //Trigger input inputStep(); //Step update pass updatePass(); // Screen queues main.queueStep(); //Step render-routine (FPS based) renderStep(); } } @Override public void pause() { running = false; while (thread.isAlive()){ try { thread.join(); } catch (InterruptedException e){ //Retry } } } @Override public void resume() { running = true; lastUpdate = System.currentTimeMillis(); thread = new Thread(this); thread.start(); } @Override public void setInputter(AndroidInputter $inputter) { inputter = (Inputter) $inputter; } /** Display step to clear, draw, and post elements to the canvas. **/ private void renderStep() { if (!surfaceAvailable) return; draw = null; try { // Get buffer draw = holder.lockCanvas(); //Clear buffer if (!IGNORE_FLOOD) clearDraw(); // Draw to buffer drawScreens(); // Render FPS fps.tick(draw); } catch (Exception e){ e.printStackTrace(); } finally { // Post buffer if (draw != null) holder.unlockCanvasAndPost(draw); } } /** Flood the buffer (Called at the start of a redraw). **/ private void clearDraw(){ draw.drawRGB((FLOOD_BACKGROUND & 0xFF0000) >> 16, (FLOOD_BACKGROUND & 0xFF00) >> 8, (FLOOD_BACKGROUND & 0xFF)); } /** Render elements from {@link Screen}s contained in the {@link #main} reference. **/ private void drawScreens(){ ArrayList<Screen> $screens = main.getScreens(); ArrayList<AndroidImage> $images; ArrayList<AndroidShape> $shapes; for (Screen $screen : $screens){ if ($screen == null || !$screen.activeRender) continue; $images = $screen.getImages(); for (AndroidImage $image : $images){ render($image); } $shapes = $screen.getShapes(); for (AndroidShape $shape : $shapes){ render($shape); } } } /** Individual image rendering call; Draw the image to the canvas reference. **/ private void render(AndroidImage $androidImage){ Image $image = (Image) $androidImage; paint.setAlpha($image.alpha); if ($image.source == null) return; if ($image.allowMatrix){ draw.drawBitmap($image.matrixFrame, $image.matrix, paint); } else { draw.drawBitmap($image.source, $image.srcRect, $image.dstRect, paint); } if ($image.animate) $image.nextFrame(); } /** Individual shape rendering call; Draw the shape to the canvas reference. **/ private void render(AndroidShape $shape){ $shape.draw(draw); } /** Time-step for {@link Screen}s contained in the {@link #main} reference. **/ private void updatePass(){ ArrayList<Screen> $screens = main.getScreens(); for (Screen $screen : $screens){ $screen.update(); } } /** Input step for {@link Screen}s contained in the {@link #main} reference. **/ private void inputStep(){ if (inputter == null) return; ArrayList<AndroidTouchEvent> $events = inputter.getEvents(); synchronized ($events){ TouchEvent $touchEvent; Iterator<AndroidTouchEvent> $ir = $events.iterator(); Screen $screen; ArrayList<Screen> $screens = main.getScreens(); Iterator<Screen> $screenir; while($ir.hasNext()){ $touchEvent = (TouchEvent) $ir.next(); $screenir = $screens.iterator(); while ($screenir.hasNext()){ $screen = $screenir.next(); switch ($touchEvent.type){ case TouchEvent.TOUCH_PRESS: if ($screen.activeInputter) $screen.touchPress($touchEvent.x, $touchEvent.y); break; case TouchEvent.TOUCH_MOVE: if ($screen.activeInputter) $screen.touchMove($touchEvent.x, $touchEvent.y); break; case TouchEvent.TOUCH_RELEASE: if ($screen.activeInputter) $screen.touchRelease($touchEvent.x, $touchEvent.y); break; case TouchEvent.TOUCH_BACK: if ($screen.activeInputter) $screen.onBackPressed(); break; } } inputter.recycle($touchEvent); } inputter.clear(); } } }