Android Open Source - Freebloks-Android Wheel






From Project

Back to project page Freebloks-Android.

License

The source code is released under:

GNU General Public License

If you think the Android project Freebloks-Android 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 de.saschahlusiak.freebloks.view.model;
//  www .  j  a  v a 2s.  c  o m
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;

import javax.microedition.khronos.opengles.GL10;

import android.graphics.PointF;
import android.os.Handler;
import android.util.Log;
import de.saschahlusiak.freebloks.Global;
import de.saschahlusiak.freebloks.model.Player;
import de.saschahlusiak.freebloks.model.Stone;
import de.saschahlusiak.freebloks.view.BoardRenderer;
import de.saschahlusiak.freebloks.view.FreebloksRenderer;

public class Wheel implements ViewElement {
  private final static String tag = Wheel.class.getSimpleName();

  final float MAX_FLING_SPEED = 100.0f;
  final float MIN_FLING_SPEED = 2.0f;
  final float MAX_STONE_DRAG_DISTANCE = 3.5f;

  enum Status {
    IDLE, SPINNING, FLINGING
  }

  private Stone highlightStone;
  private float currentOffset;  /* the current offset */
  private float lastOffset;    /* the offset on last touch down; rotate back to here when idle */
  private float maxOffset;    /* the maximum offset till reaching the right end */
  private float originalX, originalY;

  private float flingSpeed, lastFlingOffset;

  private Status status = Status.IDLE;
  private ArrayList<Stone> stones;
  private int currentPlayer; /* the currently shown player */
  private ViewModel model;
  private boolean moves_left;

  private PointF tmp = new PointF();
  private Handler handler = new Handler();
  private Timer timer = new Timer();
  private TimerTask task;

  private static final float stone_spacing = 5.5f * BoardRenderer.stone_size * 2.0f;

  public Wheel(ViewModel model) {
    this.model = model;
    stones = new ArrayList<Stone>();
    currentPlayer = -1;
  }

  public synchronized void update(int player) {
    stones.clear();
    if (player < 0)
      return;
    if (model.spiel == null)
      return;
    Player p = model.spiel.get_player(player);
    moves_left = p.m_number_of_possible_turns > 0;
    for (int i = 0; i < Stone.STONE_COUNT_ALL_SHAPES; i++) {
      Stone s = p.get_stone(i);
      if (s != null && s.get_available() > 0)
        stones.add(s);
    }
    this.highlightStone = null;
    maxOffset = (float)((stones.size() - 1)/ 2) * stone_spacing;

    if (stones.size() > 0)
      rotateTo((stones.size() + 1) / 2 - 2);

    this.currentPlayer = player;
  }

  private void rotateTo(int column) {
    lastOffset = (float)column * stone_spacing;
    if (lastOffset < 0.0f)
      lastOffset = 0.0f;
    if (lastOffset > maxOffset)
      lastOffset = maxOffset;
    if (!model.hasAnimations())
      currentOffset = lastOffset;
  }

  private int getStonePositionInWheel(int stone) {
    for (int i = 0; i < stones.size(); i++)
      if (stones.get(i).get_number() == stone)
        return i;
    return 0;
  }

  /* makes sure the given stone is visible in the wheel */
  public void showStone(int stone) {
    rotateTo(getStonePositionInWheel(stone) / 2);
  }

  /* returns the player number currently shown in the wheel (aka. last call of update) */
  public final int getCurrentPlayer() {
    return this.currentPlayer;
  }

  /* returns the currently highlighted stone in the wheel */
  public Stone getCurrentStone() {
    return this.highlightStone;
  }

  public void setCurrentStone(Stone stone) {
    this.highlightStone = stone;
  }

  @Override
  synchronized public boolean handlePointerDown(final PointF m) {
    status = Status.IDLE;
    if (model.spiel == null)
      return false;

    lastOffset = currentOffset;
    lastFlingOffset = currentOffset;
    flingSpeed = 0.0f;

    tmp.x = m.x;
    tmp.y = m.y;
    model.board.modelToBoard(tmp);
    model.board.boardToUnified(tmp);
    if (!model.vertical_layout) {
      float t = tmp.x;
      tmp.x = tmp.y;
      tmp.y = model.spiel.m_field_size_x - t - 1;
    }

    originalX = tmp.x;
    originalY = tmp.y;

    if (tmp.y > 0)
      return false;

    int row = (int) (-(tmp.y + 2.0f) / 6.7f);
    int col = (int) ((tmp.x - (float) model.spiel.m_field_size_x / 2.0f + lastOffset) / stone_spacing + 0.5f);

    if (!model.spiel.is_local_player() || model.spiel.current_player() != currentPlayer) {
      status = Status.SPINNING;
      return true;
    }

    int nr = col * 2 + row;
    if (nr < 0 || nr >= stones.size() || row > 1)
      highlightStone = null;
    else
      highlightStone = stones.get(nr);
    if (highlightStone != null && highlightStone.get_available() <= 0)
      highlightStone = null;
    else if (highlightStone != null) {
      /* we tapped on a stone; start timer */
      if (task != null)
        task.cancel();
      if (model.currentStone.stone != null && model.currentStone.stone != highlightStone) {
        model.soundPool.play(model.soundPool.SOUND_CLICK2, 1.0f, 1);
        status = Status.SPINNING;
      } else {
        status = Status.SPINNING;
        timer.schedule(task = new TimerTask() {

          @Override
          public void run() {
            if (status != Status.SPINNING)
              return;
            if (highlightStone == null)
              return;
            if (Math.abs(currentOffset - lastOffset) > 3.0f)
              return;
            if (!model.spiel.is_local_player())
              return;

            handler.post(new Runnable() {
              @Override
              public void run() {
                if (highlightStone == null)
                  return;
                tmp.x = m.x;
                tmp.y = m.y;
                model.board.modelToBoard(tmp);

                if (model.soundPool != null && !model.soundPool.play(model.soundPool.SOUND_CLICK2, 1.0f, 1))
                  model.activity.vibrate(Global.VIBRATE_START_DRAGGING);
                showStone(highlightStone.get_number());
                model.currentStone.startDragging(tmp, highlightStone, model.getPlayerColor(currentPlayer));
                model.currentStone.hasMoved = true;
                model.board.resetRotation();
                status = Status.IDLE;
                model.view.requestRender();
              }
            });
            status = Status.IDLE;
          }
        }, 500);
      }
    } else
      status = Status.SPINNING;

    return true;
  }

  @Override
  synchronized public boolean handlePointerMove(PointF m) {
    if (status != Status.SPINNING)
      return false;

    tmp.x = m.x;
    tmp.y = m.y;
    model.board.modelToBoard(tmp);
    model.board.boardToUnified(tmp);

    if (!model.vertical_layout) {
      float t = tmp.x;
      tmp.x = tmp.y;
      tmp.y = model.spiel.m_field_size_x - t - 1;
    }

    /* everything underneath row 0 spins the wheel */
    float offset = (originalX - tmp.x) * 1.7f;
    offset *= 1.0f / (1.0f + Math.abs(originalY - tmp.y) / 2.3f);
    currentOffset += offset;
    if (currentOffset < 0.0f)
      currentOffset = 0.0f;
    if (currentOffset > maxOffset)
      currentOffset = maxOffset;

    originalX = tmp.x;

    model.redraw = true;
    if (!model.spiel.is_local_player() || model.spiel.current_player() != currentPlayer) {
      return true;
    }

    /* if the wheel is moved too far, deselect highlighted stone */
    if (Math.abs(currentOffset - lastOffset) >= MAX_STONE_DRAG_DISTANCE) {
      highlightStone = null;
    }

    if (highlightStone != null && (tmp.y >= 0.0f || Math.abs(tmp.y - originalY) >= 3.5f)) {
      tmp.x = m.x;
      tmp.y = m.y;
      model.board.modelToBoard(tmp);
      showStone(highlightStone.get_number());
      if (model.currentStone.stone != highlightStone)
        model.soundPool.play(model.soundPool.SOUND_CLICK2, 1.0f, 1);
      model.currentStone.startDragging(tmp, highlightStone, model.getPlayerColor(currentPlayer));
      status = Status.IDLE;
      model.board.resetRotation();
    }
    return true;
  }

  @Override
  public boolean handlePointerUp(PointF m) {
    if (task != null)
      task.cancel();
    task = null;
    if (status == Status.SPINNING) {
      if (highlightStone != null && model.currentStone.stone != highlightStone && (Math.abs(lastOffset - currentOffset) < 0.5f)) {
        if (model.currentStone.stone != null)
          model.currentStone.startDragging(null, highlightStone, model.getPlayerColor(currentPlayer));
        model.currentStone.status = CurrentStone.Status.IDLE;
        showStone(highlightStone.get_number());
        status = Status.IDLE;
      } else {
        lastOffset = currentOffset;
        if (model.hasAnimations())
          status = Status.FLINGING;
        else
          status = Status.IDLE;
      }
      return true;
    }
    return false;
  }

  public synchronized void render(FreebloksRenderer renderer, GL10 gl) {
    if (model.spiel == null)
      return;

    gl.glTranslatef(-currentOffset, 0, BoardRenderer.stone_size * (model.spiel.m_field_size_x + 10));
    for (int i = stones.size() - 1; i >= 0; i--) {
      Stone s = stones.get(i);

      if (s.get_available() - ((s == model.currentStone.stone) ? 1 : 0) > 0) {
        final float col = i / 2;
        final float row = i % 2;
        final float offset = -((float)(s.get_stone_size()) - 1.0f) * BoardRenderer.stone_size;

        final float x = col * stone_spacing;
        final float effect = 12.5f / (12.5f + (float)Math.pow(Math.abs(x - currentOffset) * 0.5f, 2.5f));
        float y = 0.35f + effect * 0.75f;
        final float z = row * stone_spacing;
        final float scale = 0.9f + effect * 0.3f;
        float rotate = 90.0f * model.board.centerPlayer;
        if (!model.vertical_layout)
          rotate -= 90.0f;

        float alpha = 1.0f;

        if (highlightStone == s && s != model.currentStone.stone)
          y += 1.2f;

        if (!moves_left && !model.spiel.isFinished())
          alpha *= 0.65f;
        alpha *= 0.75f + effect * 0.25f;

        gl.glPushMatrix();
        gl.glTranslatef(x, 0, z);
        
        gl.glScalef(scale, scale, scale);

        
        if (s.get_available() > 1 && s == highlightStone && s != model.currentStone.stone) {
          gl.glPushMatrix();
          gl.glTranslatef(BoardRenderer.stone_size, 0, BoardRenderer.stone_size * 0.6f);
          gl.glRotatef(rotate, 0, 1, 0);
          gl.glScalef(0.85f, 0.85f, 0.85f);
          gl.glTranslatef(offset, 0, offset);

        //  gl.glTranslatef(BoardRenderer.stone_size * 0.5f, y - 1.2f, BoardRenderer.stone_size * 0.5f);
          renderer.board.renderPlayerStone(gl, model.getPlayerColor(currentPlayer), s, alpha);
          gl.glPopMatrix();
        }
        
        gl.glRotatef(rotate, 0, 1, 0);
        gl.glTranslatef(offset, 0, offset);

        gl.glPushMatrix();
        renderer.board.renderShadow(gl, s, model.getPlayerColor(currentPlayer), y, 0, 0, 0, 0, 90 * model.board.centerPlayer, alpha, 1.0f);
        gl.glPopMatrix();

        gl.glTranslatef(0, y, 0);
        renderer.board.renderPlayerStone(gl, (s == highlightStone && s != model.currentStone.stone) ? 0 : model.getPlayerColor(currentPlayer), s, alpha);
        gl.glPopMatrix();
      }
    }
  }

  @Override
  public boolean execute(float elapsed) {
    final float EPSILON = 0.5f;
    if (status == Status.IDLE && (Math.abs(currentOffset - lastOffset) > EPSILON)) {
      final float ROTSPEED = 3.0f + (float)Math.pow(Math.abs(currentOffset - lastOffset), 0.65f) * 7.0f;

      if (!model.hasAnimations()) {
        currentOffset = lastOffset;
        return true;
      }
      if (currentOffset < lastOffset) {
        currentOffset += elapsed * ROTSPEED;
        if (currentOffset > lastOffset)
          currentOffset = lastOffset;
      } else {
        currentOffset -= elapsed * ROTSPEED;
        if (currentOffset < lastOffset)
          currentOffset = lastOffset;
      }
      return true;
    }
    if (status == Status.SPINNING) {
      flingSpeed *= 0.2f;
      flingSpeed += 0.90f * (currentOffset - lastFlingOffset) / elapsed;
      if (flingSpeed > MAX_FLING_SPEED) {
        flingSpeed = MAX_FLING_SPEED;
      }
      if (flingSpeed < -MAX_FLING_SPEED) {
        flingSpeed = -MAX_FLING_SPEED;
      }
      lastFlingOffset = currentOffset;
    }
    if (status == Status.FLINGING) {
      if (Math.abs(flingSpeed) < MIN_FLING_SPEED) {
        status = Status.IDLE;
        lastOffset = currentOffset;
        return true;
      }

      currentOffset += flingSpeed * elapsed;
      if (Math.abs(currentOffset - lastOffset) >= MAX_STONE_DRAG_DISTANCE) {
        highlightStone = null;
      }
      flingSpeed *= (float)Math.pow(0.05f, elapsed);
      if (currentOffset < 0) {
        currentOffset = 0.0f;
        /* bounce */
        flingSpeed *= -0.4f;
      }
      if (currentOffset > maxOffset) {
        currentOffset = maxOffset;
        /* bounce */
        flingSpeed *= -0.4f;
      }
      return true;
    }
    return false;
  }
}




Java Source Code List

com.google.example.games.basegameutils.BaseGameActivity.java
com.google.example.games.basegameutils.GameHelperUtils.java
com.google.example.games.basegameutils.GameHelper.java
de.saschahlusiak.freebloks.AboutActivity.java
de.saschahlusiak.freebloks.Global.java
de.saschahlusiak.freebloks.backup.FreebloksBackupAgent.java
de.saschahlusiak.freebloks.controller.GameMode.java
de.saschahlusiak.freebloks.controller.JNIServer.java
de.saschahlusiak.freebloks.controller.PlayerData.java
de.saschahlusiak.freebloks.controller.SpielClientInterface.java
de.saschahlusiak.freebloks.controller.SpielClient.java
de.saschahlusiak.freebloks.controller.Spielleiter.java
de.saschahlusiak.freebloks.database.FreebloksDBOpenHandler.java
de.saschahlusiak.freebloks.database.FreebloksDB.java
de.saschahlusiak.freebloks.database.HighscoreDB.java
de.saschahlusiak.freebloks.donate.DonateActivity.java
de.saschahlusiak.freebloks.game.ActivityInterface.java
de.saschahlusiak.freebloks.game.AddScoreTask.java
de.saschahlusiak.freebloks.game.CustomGameDialog.java
de.saschahlusiak.freebloks.game.FreebloksActivity.java
de.saschahlusiak.freebloks.game.GameFinishActivity.java
de.saschahlusiak.freebloks.game.GameMenu.java
de.saschahlusiak.freebloks.game.RateAppDialog.java
de.saschahlusiak.freebloks.game.RetainedConfig.java
de.saschahlusiak.freebloks.game.SpielClientThread.java
de.saschahlusiak.freebloks.lobby.ChatEntry.java
de.saschahlusiak.freebloks.lobby.ChatListAdapter.java
de.saschahlusiak.freebloks.lobby.ColorAdapter.java
de.saschahlusiak.freebloks.lobby.LobbyDialog.java
de.saschahlusiak.freebloks.model.Player.java
de.saschahlusiak.freebloks.model.Spiel.java
de.saschahlusiak.freebloks.model.Stone.java
de.saschahlusiak.freebloks.model.Turn.java
de.saschahlusiak.freebloks.model.Turnpool.java
de.saschahlusiak.freebloks.network.NET_CHAT.java
de.saschahlusiak.freebloks.network.NET_CURRENT_PLAYER.java
de.saschahlusiak.freebloks.network.NET_GAME_FINISH.java
de.saschahlusiak.freebloks.network.NET_GRANT_PLAYER.java
de.saschahlusiak.freebloks.network.NET_HEADER.java
de.saschahlusiak.freebloks.network.NET_REQUEST_GAME_MODE.java
de.saschahlusiak.freebloks.network.NET_REQUEST_HINT.java
de.saschahlusiak.freebloks.network.NET_REQUEST_PLAYER.java
de.saschahlusiak.freebloks.network.NET_REQUEST_UNDO.java
de.saschahlusiak.freebloks.network.NET_REVOKE_PLAYER.java
de.saschahlusiak.freebloks.network.NET_SERVER_STATUS.java
de.saschahlusiak.freebloks.network.NET_SET_STONE.java
de.saschahlusiak.freebloks.network.NET_START_GAME.java
de.saschahlusiak.freebloks.network.NET_UNDO_STONE.java
de.saschahlusiak.freebloks.network.Network.java
de.saschahlusiak.freebloks.preferences.AboutFragment.java
de.saschahlusiak.freebloks.preferences.DisplayFragment.java
de.saschahlusiak.freebloks.preferences.FreebloksPreferences.java
de.saschahlusiak.freebloks.preferences.InterfaceFragment.java
de.saschahlusiak.freebloks.preferences.MiscFragment.java
de.saschahlusiak.freebloks.preferences.StatisticsFragment.java
de.saschahlusiak.freebloks.preferences.ThemePreference.java
de.saschahlusiak.freebloks.stats.StatisticsActivity.java
de.saschahlusiak.freebloks.stats.StatisticsAdapter.java
de.saschahlusiak.freebloks.view.BackgroundRenderer.java
de.saschahlusiak.freebloks.view.BoardRenderer.java
de.saschahlusiak.freebloks.view.Freebloks3DView.java
de.saschahlusiak.freebloks.view.FreebloksRenderer.java
de.saschahlusiak.freebloks.view.SimpleModel.java
de.saschahlusiak.freebloks.view.effects.AbsEffect.java
de.saschahlusiak.freebloks.view.effects.AbsStoneEffect.java
de.saschahlusiak.freebloks.view.effects.BoardStoneGlowEffect.java
de.saschahlusiak.freebloks.view.effects.EffectSet.java
de.saschahlusiak.freebloks.view.effects.Effect.java
de.saschahlusiak.freebloks.view.effects.PhysicalStoneEffect.java
de.saschahlusiak.freebloks.view.effects.StoneFadeEffect.java
de.saschahlusiak.freebloks.view.effects.StoneRollEffect.java
de.saschahlusiak.freebloks.view.effects.StoneUndoEffect.java
de.saschahlusiak.freebloks.view.model.Board.java
de.saschahlusiak.freebloks.view.model.CurrentStone.java
de.saschahlusiak.freebloks.view.model.Intro.java
de.saschahlusiak.freebloks.view.model.Sounds.java
de.saschahlusiak.freebloks.view.model.Theme.java
de.saschahlusiak.freebloks.view.model.ViewElement.java
de.saschahlusiak.freebloks.view.model.ViewModel.java
de.saschahlusiak.freebloks.view.model.Wheel.java