package com.kkp.Activity;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import com.kkp.Activity.R;
import com.kkp.domain.Coordinate;
import com.kkp.domain.Shape;
import android.content.Context;
import android.content.res.Resources;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.View;
import android.widget.TextView;
public class DiamondView extends TileView {
//The current game mode, default is READY
private int mMode = READY;
//The game mode.
public static final int READY = 1;
public static final int RUNNING = 2;
public static final int LOSE = 3;
//The resource ID
public static final int RED_STAR = 1;
public static final int YELLOW_STAR = 2;
public static final int GREEN_STAR = 3;
//your score
private long mScore = 0;
//the speed of the diamond move
private long mMoveDelay;
private long mLastMove;
//about the brief information of game
TextView mStatusText;
//display your current score
TextView mScoreText;
//the current diamond
private Shape mShape;
//when the diamond stops on the screen, this container should append it
private List<Coordinate> mSpaceList = new ArrayList<Coordinate>();
private static final Random RAN = new Random();
private RefreshHandler mRefreshHandler = new RefreshHandler();
class RefreshHandler extends Handler{
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
DiamondView.this.update();
DiamondView.this.invalidate();
}
public void sleep(long time){
this.removeMessages(0);
sendMessageDelayed(obtainMessage(0), time);
}
}
/**
*This is the constructor
* @param context
* @param attrs
*/
public DiamondView(Context context, AttributeSet attrs) {
super(context, attrs);
initDiamondView();
}
/**
* This method will initialize the resource about the diamond view
*/
private void initDiamondView() {
setFocusable(true);
Resources r = getResources();
//set the size of the title
resetTiles(4);
//get the resource ,and set each of them a tag
loadTile(RED_STAR, r.getDrawable(R.drawable.redstar));
loadTile(YELLOW_STAR, r.getDrawable(R.drawable.yellowstar));
loadTile(GREEN_STAR, r.getDrawable(R.drawable.wall));
}
/**
* Game Start!
*/
private void initNewGame() {
//find the middle of the top screen
Shape.mMidWidth = (int) mXTileCount/2;
//don't take your old things on your new start
mSpaceList.clear();
if(mShape != null){
mShape.erase();
}
initNewShape();
//dare to set it to zero?
mMoveDelay = 300;
//if you are a the next rich generation, you can set it as you want
mScore = 0;
}
/**
* This method will create the diamond
*/
private void initNewShape() {
if(mShape != null){
mShape.erase();
}
mShape = Shape.createShape(RAN.nextInt(Shape.SHAPE_NUM));
mShape.draw();
}
/**
* This method is the way you talk with your computer
*/
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
//if you enter the "up", the game starts whose state is not running,
// otherwise,it will make your current diamond change the shape.
if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
if (mMode == READY || mMode == LOSE) {
initNewGame();
setMode(RUNNING);
update();
}
else if(mMode == RUNNING){
//save the shape list before change ,and restore it to original when clash happens
List<Coordinate> originalList = new ArrayList<Coordinate>();
originalList.addAll(mShape.getmShapeList());
mShape.change(mShape.getmShapeList().get(0));
if(isChangeCollide(mShape.getmShapeList())){
mShape.erase();
mShape.setmShapeList(originalList);
mShape.returnOrignalState();
}
}
return true;
}
//check if it is able to move right when we press the "Right" key.
if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
if(!isRightSide() && canMoveRight()){
mShape.moveRight();
}
return true;
}
//left
if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
if(!isLeftSide() && canMoveLeft()){
mShape.moveLeft();
}
return true;
}
//down
if(keyCode == KeyEvent.KEYCODE_DPAD_DOWN){
if(!isBottom() && canMoveDown()){
mShape.moveDown();
}
return true;
}
return super.onKeyDown(keyCode, event);
}
/**
* this method will do as whether it collides when the shape changes
* @param shapeList
* @return
*/
private boolean isChangeCollide(List<Coordinate> shapeList) {
for(Coordinate c : shapeList){
//if it is on the top,bottom,right,left side , it collides.
if(c.x < 1 || c.x > mXTileCount-2 || c.y < 1 || c.y > mYTileCount - 2){
return true;
}
//if it coincides with the space coordinates ,it collides
for(Coordinate c2 : mSpaceList){
if(c.equals(c2)){
return true;
}
}
}
return false;
}
public void setmStatusText(TextView mStatusText) {
this.mStatusText = mStatusText;
}
public void setmScoreText(TextView mScoreText) {
this.mScoreText = mScoreText;
}
/**
* this method will set your game current state, also providing some information for you
* @param mode
*/
public void setMode(int mode) {
int oldMode = mMode;
mMode = mode;
if(mode == RUNNING && oldMode != RUNNING){
mStatusText.setVisibility(View.INVISIBLE);
update();
return;
}
CharSequence str="";
if(mode == READY){
str="Please enter the up key to start";
}
if(mode == LOSE){
str="You lose, your total score is :" + mScore;
}
mStatusText.setText(str);
mStatusText.setVisibility(View.VISIBLE);
}
/**
* Updating the screen
*/
public void update() {
if(mMode == RUNNING){
long now = System.currentTimeMillis();
if(now - mLastMove > mMoveDelay){
clearTiles();
updateSpace();
updateShape();
updateWalls();
mLastMove = now;
}
mRefreshHandler.sleep(mMoveDelay);
}
}
/**
* Updating the space list
*/
private void updateSpace() {
List<Coordinate> shapeList = mShape.getmShapeList();
//if the shape touch the bottom or the coordinates of the space list,it should decide if it can remove rows
if (isStop()) {
int minY = shapeList.get(0).y;
int maxY = shapeList.get(0).y;
//get the max y and min y of the shape
for (Coordinate c : shapeList) {
if(c.y < minY){
minY = c.y;
}
if(c.y > maxY){
maxY = c.y;
}
mSpaceList.add(c);
}
int numX; //the number of coordinates in every row of space list.
int removeNum = 0;// the number of remove lines
//check from bottom to top of the shape
for (int i = minY; i <= maxY; i++) {
numX = 0;
for(Coordinate c : mSpaceList){
if(c.y == i){
numX++;
}
}
//start to remove line
if(numX == mXTileCount - 2){
removeNum++;
Iterator<Coordinate> it = mSpaceList.iterator();
while(it.hasNext()){
Coordinate c = it.next();
if(c.y == i){
it.remove();
}
//let the above lines move down
if(c.y < i){
c.y = c.y + 1;
}
}
}
}
//get the score
achieveScore(removeNum);
//Game Over
for(Coordinate c : mSpaceList){
if(c.y <= 1){
setMode(LOSE);
return;
}
}
initNewShape();
}
for (Coordinate c : mSpaceList) {
setTile(YELLOW_STAR, c.x, c.y);
}
}
/**
* calculate the score
* @param removeNum
*/
private void achieveScore(int removeNum) {
switch (removeNum) {
case 1:
mScore += 100;
break;
case 2:
mScore += 300;
break;
case 3:
mScore += 500;