Android Open Source - SnakeWallpaper Game






From Project

Back to project page SnakeWallpaper.

License

The source code is released under:

Apache License

If you think the Android project SnakeWallpaper listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.jakewharton.snakewallpaper;
/*from  ww  w.j  ava 2 s .  co m*/
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import com.jakewharton.utilities.WidgetLocationsPreference;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.net.Uri;
import android.util.Log;
import android.widget.Toast;

public class Game implements SharedPreferences.OnSharedPreferenceChangeListener {
  /**
   * Possible directions of travel.
   * 
   * @author Jake Wharton
   */
  enum Direction {
    NORTH, SOUTH, EAST, WEST;
    
    
    
    /**
     * Get the direction that is the opposite of this one.
     * 
     * @return Opposite direction.
     */
    public Game.Direction getOpposite() {
      switch (this) {
        case NORTH:
          return Game.Direction.SOUTH;
        case SOUTH:
          return Game.Direction.NORTH;
        case EAST:
          return Game.Direction.WEST;
        case WEST:
          return Game.Direction.EAST;
        default:
          throw new IllegalStateException("This is impossible.");
      }
    }
  }
  
  
  
  /**
   * Single random number generate for this wallpaper.
   */
  /*package*/static final Random RANDOM = new Random();
  
  /**
   * Tag used for logging.
   */
  private static final String TAG = "SnakeWallpaper.Game";
  
  /**
   * Length of the initial snake.
   */
  private static final int INITIAL_LENGTH = 3;
  
  /**
   * Cell value for a wall.
   */
  private static final boolean CELL_WALL = false;
  
  /**
   * Cell value for a blank space.
   */
  private static final boolean CELL_BLANK = true;
  

  
  /**
   * Number of cells on the board horizontally.
   */
  private int mCellsWide;
  
  /**
   * Number of cells on the board vertically.
   */
  private int mCellsTall;
  
  /**
   * Number of cells horizontally between the columns.
   */
  private int mCellColumnSpacing;
  
  /**
   * Number of cells vertically between the rows.
   */
  private int mCellRowSpacing;
  
  private float mScaleX;
  
  private float mScaleY;
  
  /**
   * Height (in pixels) of the screen.
   */
    private int mScreenHeight;
    
    /**
     * Width (in pixels) of the screen.
     */
    private int mScreenWidth;
    
    /**
     * Whether or not the screen is currently in landscape mode.
     */
    private boolean mIsLandscape;
    
    /**
     * Number of icon rows on the launcher.
     */
    private int mIconRows;
    
    /**
     * Number of icon columns on the launcher.
     */
    private int mIconCols;
    
    /**
     * 2-dimensional array of the board's cells.
     */
  private boolean[][] mBoard;
    
    /**
     * Color of the background.
     */
    private int mGameBackground;
    
    /**
     * Top padding (in pixels) of the grid from the screen top.
     */
    private float mDotGridPaddingTop;
    
    /**
     * Left padding (in pixels) of the grid from the screen left.
     */
    private float mDotGridPaddingLeft;
    
    /**
     * Bottom padding (in pixels) of the grid from the screen bottom.
     */
    private float mDotGridPaddingBottom;
    
    /**
     * Right padding (in pixels) of the grid from the screen right.
     */
    private float mDotGridPaddingRight;
    
    /**
     * Path to the user background image (if any).
     */
    private String mBackgroundPath;
    
    /**
     * The user background image (if any).
     */
    private Bitmap mBackground;
    
    /**
     * The locations of widgets on the launcher.
     */
    private List<Rect> mWidgetLocations;
    
    /**
     * Paint to draw the background color.
     */
    private final Paint mBackgroundPaint;
    
    /**
     * Walls forground color.
     */
    private final Paint mWallsForeground;
    
    /**
     * Whether or not we are displaying icon walls
     */
    private boolean mIsDisplayingWalls;
    
    /**
     * Current snake positions
     */
    private final LinkedList<Point> mSnake;
    
    /**
     * Location of apple.
     */
    private Point mApple;
    
    /**
     * Current snake direction.
     */
    private Game.Direction mDirection;
    
    /**
     * Diretion the user wants us to travel in.
     */
    private Game.Direction mWantsToGo;
    
    /**
     * Apple color.
     */
    private final Paint mAppleForeground;
    
    /**
     * Snake color.
     */
    private final Paint mSnakeForeground;
    
    /**
     * Whether or not the snake is drawn in a blocky fashion.
     */
    private boolean mIsBlocky;
    
    /**
     * Precalculated wall rectangles for drawing
     */
    private final List<RectF> mWalls;
    
    
    
    /**
     * Create a new game.
     */
    public Game() {
      if (Wallpaper.LOG_VERBOSE) {
        Log.v(Game.TAG, "> Game()");
      }

        //Create Paints
      this.mWallsForeground = new Paint(Paint.ANTI_ALIAS_FLAG);
      this.mWallsForeground.setStyle(Paint.Style.STROKE);
        this.mBackgroundPaint = new Paint();
        this.mAppleForeground = new Paint(Paint.ANTI_ALIAS_FLAG);
        this.mSnakeForeground = new Paint();
        
        this.mSnake = new LinkedList<Point>();
        this.mWalls = new LinkedList<RectF>();
        
        //Load all preferences or their defaults
        Wallpaper.PREFERENCES.registerOnSharedPreferenceChangeListener(this);
        this.onSharedPreferenceChanged(Wallpaper.PREFERENCES, null);

      if (Wallpaper.LOG_VERBOSE) {
        Log.v(Game.TAG, "< Game()");
      }
    }

    
    
    /**
     * Handle the changing of a preference.
     */
  public void onSharedPreferenceChanged(final SharedPreferences preferences, final String key) {
      if (Wallpaper.LOG_VERBOSE) {
        Log.v(Game.TAG, "> onSharedPreferenceChanged()");
      }
      
    final boolean all = (key == null);
    final Resources resources = Wallpaper.CONTEXT.getResources();
    
    boolean hasLayoutChanged = false;
    boolean hasGraphicsChanged = false;
    
    final String showWalls = resources.getString(R.string.settings_display_showwalls_key);
    if (all || key.equals(showWalls)) {
      this.mIsDisplayingWalls = preferences.getBoolean(showWalls, resources.getBoolean(R.bool.display_showwalls_default));
      
      if (Wallpaper.LOG_DEBUG) {
        Log.d(Game.TAG, "Is Displaying Walls: " + this.mIsDisplayingWalls);
      }
    }
    
    final String widgetLocations = resources.getString(R.string.settings_display_widgetlocations_key);
    if (all || key.equals(widgetLocations)) {
      this.mWidgetLocations = WidgetLocationsPreference.convertStringToWidgetList(preferences.getString(widgetLocations, resources.getString(R.string.display_widgetlocations_default)));
      hasLayoutChanged = true;
      
      if (Wallpaper.LOG_DEBUG) {
        Log.d(Game.TAG, "Widget Locations: " + (this.mWidgetLocations.size() / 4));
      }
    }
    
    final String blocky = resources.getString(R.string.settings_display_isblocky_key);
    if (all || key.equals(blocky)) {
      this.mIsBlocky = preferences.getBoolean(blocky, resources.getBoolean(R.bool.display_isblocky_default));
      
      if (Wallpaper.LOG_DEBUG) {
        Log.d(Game.TAG, "Is Blocky: " + this.mIsBlocky);
      }
    }
    
    
    // COLORS //
        
    final String gameBackground = resources.getString(R.string.settings_color_background_key);
    if (all || key.equals(gameBackground)) {
      this.mGameBackground = preferences.getInt(gameBackground, resources.getInteger(R.integer.color_background_default));
      
      if (Wallpaper.LOG_DEBUG) {
        Log.d(Game.TAG, "Background: #" + Integer.toHexString(this.mGameBackground));
      }
    }
    
    final String wallsForeground = resources.getString(R.string.settings_color_walls_key);
    if (all || key.equals(wallsForeground)) {
      this.mWallsForeground.setColor(preferences.getInt(wallsForeground, resources.getInteger(R.integer.color_walls_default)));
      
      if (Wallpaper.LOG_DEBUG) {
        Log.d(Game.TAG, "Walls Foreground: #" + Integer.toHexString(this.mWallsForeground.getColor()));
      }
    }
    
    final String backgroundImage = resources.getString(R.string.settings_color_bgimage_key);
    if (all || key.equals(backgroundImage)) {
      this.mBackgroundPath = preferences.getString(backgroundImage, null);
      
      if (this.mBackgroundPath != null) {      
        if (Wallpaper.LOG_DEBUG) {
          Log.d(Game.TAG, "Background Image: " + this.mBackgroundPath);
        }
        
        //Trigger performResize
        hasGraphicsChanged = true;
      } else {
        this.mBackground = null;
      }
    }
    
    final String backgroundOpacity = resources.getString(R.string.settings_color_bgopacity_key);
    if (all || key.equals(backgroundOpacity)) {
      this.mBackgroundPaint.setAlpha(preferences.getInt(backgroundOpacity, resources.getInteger(R.integer.color_bgopacity_default)));
      
      if (Wallpaper.LOG_DEBUG) {
        Log.d(Game.TAG, "Background Image Opacity: " + this.mBackgroundPaint.getAlpha());
      }
    }
    
    final String snake = resources.getString(R.string.settings_color_snake_key);
    if (all || key.equals(snake)) {
      this.mSnakeForeground.setColor(preferences.getInt(snake, resources.getInteger(R.integer.color_snake_default)));
      
      if (Wallpaper.LOG_DEBUG) {
        Log.d(Game.TAG, "Snake Foreground: #" + Integer.toHexString(this.mSnakeForeground.getColor()));
      }
    }
    
    final String apple = resources.getString(R.string.settings_color_apple_key);
    if (all || key.equals(apple)) {
      this.mAppleForeground.setColor(preferences.getInt(apple, resources.getInteger(R.integer.color_apple_default)));
      
      if (Wallpaper.LOG_DEBUG) {
        Log.d(Game.TAG, "Apple Foreground: #" + Integer.toHexString(this.mAppleForeground.getColor()));
      }
    }
      
        
    // GRID //
    
    final String dotGridPaddingLeft = resources.getString(R.string.settings_display_padding_left_key);
    if (all || key.equals(dotGridPaddingLeft)) {
      this.mDotGridPaddingLeft = preferences.getInt(dotGridPaddingLeft, resources.getInteger(R.integer.display_padding_left_default));
      hasGraphicsChanged = true;
      
      if (Wallpaper.LOG_DEBUG) {
        Log.d(Game.TAG, "Dot Grid Padding Left: " + this.mDotGridPaddingLeft);
      }
    }

    final String dotGridPaddingRight = resources.getString(R.string.settings_display_padding_right_key);
    if (all || key.equals(dotGridPaddingRight)) {
      this.mDotGridPaddingRight = preferences.getInt(dotGridPaddingRight, resources.getInteger(R.integer.display_padding_right_default));
      hasGraphicsChanged = true;
      
      if (Wallpaper.LOG_DEBUG) {
        Log.d(Game.TAG, "Dot Grid Padding Right: " + this.mDotGridPaddingRight);
      }
    }

    final String dotGridPaddingTop = resources.getString(R.string.settings_display_padding_top_key);
    if (all || key.equals(dotGridPaddingTop)) {
      this.mDotGridPaddingTop = preferences.getInt(dotGridPaddingTop, resources.getInteger(R.integer.display_padding_top_default));
      hasGraphicsChanged = true;
      
      if (Wallpaper.LOG_DEBUG) {
        Log.d(Game.TAG, "Dot Grid Padding Top: " + this.mDotGridPaddingTop);
      }
    }

    final String dotGridPaddingBottom = resources.getString(R.string.settings_display_padding_bottom_key);
    if (all || key.equals(dotGridPaddingBottom)) {
      this.mDotGridPaddingBottom = preferences.getInt(dotGridPaddingBottom, resources.getInteger(R.integer.display_padding_bottom_default));
      hasGraphicsChanged = true;
      
      if (Wallpaper.LOG_DEBUG) {
        Log.d(Game.TAG, "Dot Grid Padding Bottom: " + this.mDotGridPaddingBottom);
      }
    }
    
    
    // CELLS //
    
    final String iconRows = resources.getString(R.string.settings_display_iconrows_key);
    if (all || key.equals(iconRows)) {
      this.mIconRows = preferences.getInt(iconRows, resources.getInteger(R.integer.display_iconrows_default));
      hasLayoutChanged = true;
      
      if (Wallpaper.LOG_DEBUG) {
        Log.d(Game.TAG, "Icon Rows: " + this.mIconRows);
      }
    }
    
    final String iconCols = resources.getString(R.string.settings_display_iconcols_key);
    if (all || key.equals(iconCols)) {
      this.mIconCols = preferences.getInt(iconCols, resources.getInteger(R.integer.display_iconcols_default));
      hasLayoutChanged = true;
      
      if (Wallpaper.LOG_DEBUG) {
        Log.d(Game.TAG, "Icon Cols: " + this.mIconCols);
      }
    }
    
    final String cellSpacingRow = resources.getString(R.string.settings_display_rowspacing_key);
    if (all || key.equals(cellSpacingRow)) {
      this.mCellRowSpacing = preferences.getInt(cellSpacingRow, resources.getInteger(R.integer.display_rowspacing_default));
      hasLayoutChanged = true;
      
      if (Wallpaper.LOG_DEBUG) {
          Log.d(Game.TAG, "Cell Row Spacing: " + this.mCellRowSpacing);
      }
    }
    
    final String cellSpacingCol = resources.getString(R.string.settings_display_colspacing_key);
    if (all || key.equals(cellSpacingCol)) {
      this.mCellColumnSpacing = preferences.getInt(cellSpacingCol, resources.getInteger(R.integer.display_colspacing_default));
      hasLayoutChanged = true;
      
      if (Wallpaper.LOG_DEBUG) {
          Log.d(Game.TAG, "Cell Column Spacing: " + this.mCellColumnSpacing);
      }
    }
    
    if (hasLayoutChanged) {
        this.mCellsWide = (this.mIconCols * (mCellColumnSpacing + 1)) + 1;
        this.mCellsTall = (this.mIconRows * (mCellRowSpacing + 1)) + 1;
        
        if (Wallpaper.LOG_DEBUG) {
          Log.d(Game.TAG, "Cells Wide: " + this.mCellsWide);
          Log.d(Game.TAG, "Cells Tall: " + this.mCellsTall);
        }
        
        //Create playing board
          this.mBoard = new boolean[this.mCellsTall][this.mCellsWide];
    }
    if (hasLayoutChanged || hasGraphicsChanged) {
      if ((this.mScreenWidth > 0) && (this.mScreenHeight > 0)) {
        //Resize everything to fit
        this.performResize(this.mScreenWidth, this.mScreenHeight);
      }

        this.newGame();
    }

      if (Wallpaper.LOG_VERBOSE) {
        Log.v(Game.TAG, "< onSharedPreferenceChanged()");
      }
  }

    /**
     * Test if a Point is a valid coordinate on the game board.
     * 
     * @param position Point representing coordinate.
     * @return Boolean indicating whether or not the position is valid.
     */
  private boolean isValidPosition(final Point position) {
    return ((position.x >= 0) && (position.x < this.mCellsWide)
        && (position.y >= 0) && (position.y < this.mCellsTall)
        && (this.mBoard[position.y][position.x] == Game.CELL_BLANK));
  }
    
    /**
     * Reset the game state to that of first initialization.
     */
    public void newGame() {
      if (Wallpaper.LOG_VERBOSE) {
        Log.v(Game.TAG, "> newGame()");
      }

      //Initialize board
      final int cellWidth = this.mCellColumnSpacing + 1;
      final int cellHeight = this.mCellRowSpacing + 1;
      for (int y = 0; y < this.mCellsTall; y++) {
        for (int x = 0; x < this.mCellsWide; x++) {
          this.mBoard[y][x] = ((x % cellWidth == 0) || (y % cellHeight == 0)) ? Game.CELL_BLANK : Game.CELL_WALL;
        }
      }
      
      //Remove board under widgets
      for (final Rect widget : this.mWidgetLocations) {
        if (Wallpaper.LOG_DEBUG) {
          Log.d(Game.TAG, "Widget: L=" + widget.left + ", T=" + widget.top + ", R=" + widget.right + ", B=" + widget.bottom);
        }
        
        final int left = (widget.left * cellWidth) + 1;
        final int top = (widget.top * cellHeight) + 1;
        final int bottom = (widget.bottom * cellHeight) + this.mCellRowSpacing;
        final int right = (widget.right * cellWidth) + this.mCellColumnSpacing;
        for (int y = top; y <= bottom; y++) {
          for (int x = left; x <= right; x++) {
            this.mBoard[y][x] = Game.CELL_WALL;
          }
        }
      }

      this.newApple();
      this.newLife();
      
      if (Wallpaper.LOG_VERBOSE) {
        Log.v(Game.TAG, "< newGame()");
      }
    }
    
    /**
     * Position snake a random valid location.
     */
    private void newLife() {
      //Clear snake
      this.mSnake.clear();
      
      boolean done = true;
      do {
        //Create snake tail
        Point last = this.getRandomValidPosition(true);
        this.mSnake.add(last);
        
        //Work our way forward to the head
        for (int i = 1; i < Game.INITIAL_LENGTH; i++) {
          //Direction toward apple
          this.determineNextDirection();
          last = Game.move(last, this.mDirection);
          
          if (Game.pointEquals(last, this.mApple)) {
            //We hit the apple, start over
            done = false;
            break;
          } else {
            //Add to head
            this.mSnake.add(0, last);
          }
        }
      }
      while (!done);
      
      //Make sure we get a new direction next tick
      this.mWantsToGo = null;
    }
    
    /**
     * Get a new apple location.
     */
    private void newApple() {
      this.mApple = this.getRandomValidPosition(false);
    }
    
    /**
     * Get a random valid location on the game board.
     * 
     * @return Point.
     */
    private Point getRandomValidPosition(boolean checkApple) {
      Point p;
      while (true) {
        p = new Point(Game.RANDOM.nextInt(this.mCellsWide), Game.RANDOM.nextInt(this.mCellsTall));
        if (this.isValidPosition(p)) {
          boolean entityValid = true;
          for (final Point test : this.mSnake) {
            if (Game.pointEquals(test, p)) {
              entityValid = false;
              break;
            }
          }
          if (checkApple && entityValid && Game.pointEquals(this.mApple, p)) {
            entityValid = false;
          }
          if (entityValid) {
            return p;
          }
        }
      }
    }
    
    /**
     * Set the user 
     * @param direction
     */
    public void setWantsToGo(final Game.Direction direction) {
      this.mWantsToGo = direction;
      
      if (Wallpaper.LOG_DEBUG) {
        Log.d(Game.TAG, "Wants To Go: " + direction.toString());
      }
    }
    
    /**
     * Determine whether a point intersects with the snake.
     * 
     * @param newPoint Point to check.
     * @return Boolean.
     */
    private boolean isPointInSnake(final Point newPoint) {
      //check for a collision with self
      for (final Point test : this.mSnake) {
        if (Game.pointEquals(test, newPoint)) {
          return true;
        }
      }
      return false;
    }
    
    /**
     * Iterate all entities one step.
     */
    public void tick() {
      this.determineNextDirection();
      final Point newPoint = Game.move(this.mSnake.getFirst(), this.mDirection);
      
      if (this.isPointInSnake(newPoint)) {
        this.newLife();
      } else {
        this.mSnake.addFirst(newPoint);
        if (!Game.pointEquals(newPoint, this.mApple)) {
          this.mSnake.removeLast();
        } else {
          this.newApple();
        }
      }
    }
    
    /**
     * Use line-of-sight to determine next direction of travel.
     */
    private void determineNextDirection() {
    final Point snakeHead = this.mSnake.getFirst();
    
    //Try the user direction first
    final Point newPoint = Game.move(snakeHead, this.mWantsToGo);
    if ((this.mWantsToGo != null) && this.isValidPosition(newPoint) && !this.isPointInSnake(newPoint)) {
      //Follow user direction and GTFO
      this.mDirection = this.mWantsToGo;
      return;
    }
    
    Point nextPoint;
    double nextDistance;
    double shortestDistance = Double.MAX_VALUE;
    Direction nextDirection = null;
    
    for (final Direction direction : Direction.values()) {
      if ((this.mDirection == null) || (direction != this.mDirection.getOpposite())) {
        nextPoint = Game.move(snakeHead, direction);
        nextDistance = Math.sqrt(Math.pow(nextPoint.x - this.mApple.x, 2) + Math.pow(nextPoint.y - this.mApple.y, 2));
        
        if (this.isValidPosition(nextPoint) && (nextDistance < shortestDistance) && !this.isPointInSnake(nextPoint)) {
          nextDirection = direction;
          shortestDistance = nextDistance; 
        }
      }
    }
    
    //Temporary last ditch effort: pick a random direction
    if (nextDirection == null) {
      while (true) {
        final Game.Direction direction = Game.Direction.values()[Game.RANDOM.nextInt(Game.Direction.values().length)];
        if (this.isValidPosition(Game.move(snakeHead, direction))) {
          nextDirection = direction;
          break;
        }
      }
    }
    
    //If the wants-to-go direction exists and the AI forced us to change direction then wants-to-go direction
    //is impossible and should be cleared
    if ((this.mWantsToGo != null) && (this.mDirection != nextDirection)) {
      this.mWantsToGo = null;
      
      if (Wallpaper.LOG_DEBUG) {
        Log.d(Game.TAG, "Clearing wants-to-go direction via AI.");
      }
    }
    
    this.mDirection = nextDirection;
    }

    /**
     * Resize the game board and all entities according to a new width and height.
     * 
     * @param screenWidth New width.
     * @param screenHeight New height.
     */
    public void performResize(int screenWidth, int screenHeight) {
      if (Wallpaper.LOG_VERBOSE) {
        Log.v(Game.TAG, "> performResize(width = " + screenWidth + ", height = " + screenHeight + ")");
      }
      
      //Background image
      if (this.mBackgroundPath != null) {
      try {
        final Bitmap temp = BitmapFactory.decodeStream(Wallpaper.CONTEXT.getContentResolver().openInputStream(Uri.parse(this.mBackgroundPath)));
        final float pictureAR = temp.getWidth() / (temp.getHeight() * 1.0f);
        final float screenAR = screenWidth / (screenHeight * 1.0f);
        int newWidth;
        int newHeight;
        int x;
        int y;
        
        if (pictureAR > screenAR) {
          //wider than tall related to the screen AR
          newHeight = screenHeight;
          newWidth = (int)(temp.getWidth() * (screenHeight / (temp.getHeight() * 1.0f)));
          x = (newWidth - screenWidth) / 2;
          y = 0;
        } else {
          //taller than wide related to the screen AR
          newWidth = screenWidth;
          newHeight = (int)(temp.getHeight() * (screenWidth / (temp.getWidth() * 1.0f)));
          x = 0;
          y = (newHeight - screenHeight) / 2;
        }
        
          final Bitmap scaled = Bitmap.createScaledBitmap(temp, newWidth, newHeight, false);
          this.mBackground = Bitmap.createBitmap(scaled, x, y, screenWidth, screenHeight);
      } catch (final Exception e) {
        e.printStackTrace();
        Log.w(Game.TAG, "Unable to load background bitmap.");
        Toast.makeText(Wallpaper.CONTEXT, "Unable to load background bitmap.", Toast.LENGTH_SHORT).show();
        this.mBackground = null;
      }
      }
      
      this.mIsLandscape = (screenWidth > screenHeight);
      this.mScreenWidth = screenWidth;
      this.mScreenHeight = screenHeight;
      
      if (this.mIsLandscape) {
        this.mScaleX = (screenWidth - (this.mDotGridPaddingLeft + this.mDotGridPaddingRight + this.mDotGridPaddingBottom)) / (this.mCellsWide * 1.0f);
        this.mScaleY = (screenHeight - this.mDotGridPaddingTop) / (this.mCellsTall * 1.0f);
      } else {
        this.mScaleX = (screenWidth - (this.mDotGridPaddingLeft + this.mDotGridPaddingRight)) / (this.mCellsWide * 1.0f);
        this.mScaleY = (screenHeight - (this.mDotGridPaddingTop + this.mDotGridPaddingBottom)) / (this.mCellsTall * 1.0f);
      }
      
      //Calculate walls
      this.mWalls.clear();
      final float cellOverEight = 1 / 8.0f;
    
      //Widget walls
      for (final Rect widget : this.mWidgetLocations) {
      float left = (widget.left * (this.mCellColumnSpacing + 1)) + 1;
      float top = (widget.top * (this.mCellRowSpacing + 1)) + 1;
        float right = ((widget.right * (this.mCellColumnSpacing + 1)) + this.mCellColumnSpacing + 1);
        float bottom = ((widget.bottom * (this.mCellRowSpacing + 1)) + this.mCellRowSpacing + 1);
      
      this.mWalls.add(new RectF(left, top, right, bottom));
      
      left += cellOverEight;
      top += cellOverEight;
      right -= cellOverEight;
      bottom -= cellOverEight;

      this.mWalls.add(new RectF(left, top, right, bottom));
      }
    
      //Icon walls
      for (int y = 0; y < this.mIconRows; y++) {
        for (int x = 0; x < this.mIconCols; x++) {
          boolean contained = false;
          for (final Rect widget : this.mWidgetLocations) {
            if (x >= widget.left && x <= widget.right && y >= widget.top && y <= widget.bottom) {
              contained = true;
              break;
            }
          }
          if (contained) {
            continue;
          }
          
          float left = (x * (this.mCellColumnSpacing + 1)) + 1;
          float top = (y * (this.mCellRowSpacing + 1)) + 1;
          float right = left + this.mCellColumnSpacing;
          float bottom = top + this.mCellRowSpacing;

          this.mWalls.add(new RectF(left, top, right, bottom));
          
          left += cellOverEight;
          top += cellOverEight;
          right -= cellOverEight;
          bottom -= cellOverEight;

          this.mWalls.add(new RectF(left, top, right, bottom));
        }
      }
      
      if (Wallpaper.LOG_DEBUG) {
        Log.d(Game.TAG, "Is Landscape: " + this.mIsLandscape);
        Log.d(Game.TAG, "Screen Width: " + screenWidth);
        Log.d(Game.TAG, "Screen Height: " + screenHeight);
        Log.d(Game.TAG, "Scale X: " + this.mScaleX);
        Log.d(Game.TAG, "Scale Y: " + this.mScaleY);
      }

      if (Wallpaper.LOG_VERBOSE) {
        Log.v(Game.TAG, "< performResize()");
      }
    }
    
    /**
     * Render the board and all entities on a Canvas.
     * 
     * @param c Canvas to draw on.
     */
    public void draw(final Canvas c) {
      c.save();
      
      //Clear the screen in case of transparency in the image
    c.drawColor(this.mGameBackground);
      if (this.mBackground != null) {
        //Bitmap should already be sized to the screen so draw it at the origin
        c.drawBitmap(this.mBackground, 0, 0, this.mBackgroundPaint);
      }
        
        c.translate(this.mDotGridPaddingLeft, this.mDotGridPaddingTop);
        c.scale(this.mScaleX, this.mScaleY);
        
        //Draw dots and walls
        this.drawGameBoard(c);
        
        c.restore();
    }

    /**
     * Render the dots and walls.
     * 
     * @param c Canvas to draw on.
     */
    private void drawGameBoard(final Canvas c) {
      //draw apple
      c.drawCircle(this.mApple.x + 0.5f, this.mApple.y + 0.5f, 0.333f, this.mAppleForeground);
      
      //draw snake
      for (final Point position : this.mSnake) {
        final float left = position.x + (this.mIsBlocky ? 0.1f : 0);
        final float top = position.y + (this.mIsBlocky ? 0.1f : 0);
        final float right = left + 1 + (this.mIsBlocky ? -0.1f : 0);
        final float bottom = top + 1 + (this.mIsBlocky ? -0.1f : 0);
        c.drawRect(left, top, right, bottom, this.mSnakeForeground);
      }
      
        //draw walls if enabled
        if (this.mIsDisplayingWalls) {
          for (final RectF wall : this.mWalls) {
            c.drawRect(wall, this.mWallsForeground);
          }
        }
    }

    

  /**
   * Update the point one step in the direction specified.
   * 
   * @param point Point of original coordinates.
   * @param direction Direction in which to move the point.
   * @return New point coordinates.
   */
    private static Point move(final Point point, final Game.Direction direction) {
      final Point newPoint = new Point(point);
      if (direction != null) {
        switch (direction) {
          case NORTH:
            newPoint.y -= 1;
          break;
          
          case SOUTH:
            newPoint.y += 1;
          break;
          
          case WEST:
            newPoint.x -= 1;
          break;
          
          case EAST:
            newPoint.x += 1;
          break;
        }
      }
      return newPoint;
    }
    
    /**
     * Determine whether two points represent the same coordinate.
     * 
     * @param one Point one.
     * @param two Point two.
     * @return Boolean.
     */
    private static boolean pointEquals(final Point one, final Point two) {
      return ((one.x == two.x) && (one.y == two.y));
    }
}




Java Source Code List

com.jakewharton.snakewallpaper.About.java
com.jakewharton.snakewallpaper.Game.java
com.jakewharton.snakewallpaper.Picker.java
com.jakewharton.snakewallpaper.Preferences.java
com.jakewharton.snakewallpaper.Wallpaper.java
com.jakewharton.utilities.ColorPreference.java
com.jakewharton.utilities.IconPreference.java
com.jakewharton.utilities.IntegerListPreference.java
com.jakewharton.utilities.NumberPreference.java
com.jakewharton.utilities.WidgetLocationsPreference.java