X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/FreeShisen/blobdiff_plain/92b19250a620252d642c0abaf8dd3d733c299f3d..45abc54753baba4f2114c97cfd11a70058c2c6b6:/src/de/cwde/freeshisen/ShisenShoView.java diff --git a/src/de/cwde/freeshisen/ShisenShoView.java b/src/de/cwde/freeshisen/ShisenShoView.java index a4280b7..6f567ce 100644 --- a/src/de/cwde/freeshisen/ShisenShoView.java +++ b/src/de/cwde/freeshisen/ShisenShoView.java @@ -1,12 +1,15 @@ package de.cwde.freeshisen; +import java.lang.ref.WeakReference; import java.util.List; import java.util.Locale; import java.util.Timer; import java.util.TimerTask; import android.app.Activity; +import android.app.AlertDialog; import android.content.Context; +import android.content.SharedPreferences; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; @@ -21,6 +24,7 @@ import android.graphics.Rect; import android.graphics.Typeface; import android.os.Handler; import android.os.Message; +import android.preference.PreferenceManager; import android.view.MenuItem; import android.view.MotionEvent; import android.view.SurfaceHolder; @@ -28,6 +32,12 @@ import android.view.SurfaceView; class ShisenShoView extends SurfaceView implements SurfaceHolder.Callback { + private static final String INVALID_TIME = "9:99:99"; + private static final String COLOR_TEXT = "#FFFFFF"; + private static final String COLOR_TEXT_SHADOW = "#000000"; + private static final String COLOR_HINT = "#F0C000"; + private static final String COLOR_SELECTED = "#FF0000"; + private enum StatePlay { UNINITIALIZED, IDLE, SELECTED1, SELECTED2, GAMEOVER }; private enum StatePaint { BOARD, SELECTED1, SELECTED2, MATCHED, WIN, LOSE, HINT, TIME }; @@ -39,24 +49,42 @@ class ShisenShoView extends SurfaceView implements SurfaceHolder.Callback { private int tileWidth; private Bitmap bg; private Bitmap tile[]; - private int[] selection1=new int[2]; - private int[] selection2=new int[2]; - private List path=null; - private List pairs=null; + private Point selection1 = new Point(0, 0); + private Point selection2 = new Point(0, 0); + private List path = null; + private List pairs = null; private long startTime; private long playTime; private long baseTime; private Timer timer; - private static Handler timerHandler; - private boolean timerRegistered=false; + static class hHandler extends Handler { + private final WeakReference mTarget; + + hHandler(ShisenShoView target) { + mTarget = new WeakReference(target); + } + + @Override + public void handleMessage(Message msg) { + ShisenShoView target = mTarget.get(); + if (target != null) + target.onUpdateTime(); + } + } + + private Handler timerHandler = new hHandler(this); + + private boolean timerRegistered = false; private ShisenSho app; private StatePlay cstate; private StatePaint pstate; private Canvas canvas = null; private SurfaceHolder surfaceHolder = null; + private String time = INVALID_TIME; + public ShisenShoView(ShisenSho shishenSho) { - super((Context)shishenSho); + super((Context) shishenSho); this.app = shishenSho; cstate = StatePlay.UNINITIALIZED; surfaceHolder = getHolder(); @@ -64,8 +92,11 @@ class ShisenShoView extends SurfaceView implements SurfaceHolder.Callback { } public ShisenShoView(Context ctx) { - super((Context)ctx); - // silence lint? + super(ctx); + this.app = (ShisenSho) ctx; + cstate = StatePlay.UNINITIALIZED; + surfaceHolder = getHolder(); + surfaceHolder.addCallback(this); } private void paint(StatePaint pstate) { @@ -124,27 +155,23 @@ class ShisenShoView extends SurfaceView implements SurfaceHolder.Callback { } private void registerTimer() { - if (timer!=null) return; // Already registered - timerHandler = new Handler() { - public void handleMessage(Message msg) { - onUpdateTime(); - } - }; - timer=new Timer(); + if (timer != null) + return; // Already registered + timer = new Timer(); timer.scheduleAtFixedRate(new TimerTask() { public void run() { timerHandler.sendEmptyMessage(Activity.RESULT_OK); } }, 0, 1000); - timerRegistered=true; + timerRegistered = true; } private void unregisterTimer() { - if (timer==null) return; // Already unregistered + if (timer == null) + return; // Already unregistered timer.cancel(); timer = null; - timerHandler = null; - timerRegistered=false; + timerRegistered = false; } public void pauseTime() { @@ -177,7 +204,7 @@ class ShisenShoView extends SurfaceView implements SurfaceHolder.Callback { startTime=System.currentTimeMillis(); playTime=0; baseTime=0; - if (app.timeCounter && !timerRegistered) { + if (!timerRegistered) { registerTimer(); } pairs=app.board.getPairs(1); @@ -221,7 +248,7 @@ class ShisenShoView extends SurfaceView implements SurfaceHolder.Callback { private void onUndoActivate() { if (app.board.getCanUndo()) { - if (cstate==StatePlay.GAMEOVER && app.timeCounter && !timerRegistered) { + if (cstate==StatePlay.GAMEOVER && !timerRegistered) { // Reprogram the time update that had been // deactivated with the game over status registerTimer(); @@ -234,7 +261,7 @@ class ShisenShoView extends SurfaceView implements SurfaceHolder.Callback { } public void onTimeCounterActivate() { - if (app.timeCounter && cstate!=StatePlay.GAMEOVER && !timerRegistered) { + if (cstate!=StatePlay.GAMEOVER && !timerRegistered) { // Reprogram the time update that had been // deactivated with the time_counter=false registerTimer(); @@ -243,21 +270,24 @@ class ShisenShoView extends SurfaceView implements SurfaceHolder.Callback { private void onUpdateTime() { paint(pstate); - if (!(app.timeCounter && cstate!=StatePlay.GAMEOVER)) { + if (cstate==StatePlay.GAMEOVER) { unregisterTimer(); } } @SuppressWarnings("deprecation") - public void drawMessage(Canvas canvas, int x, int y, boolean centered, String message, String color, float textSize) { + public static void drawMessage(Canvas canvas, int x, int y, + boolean centered, String message, float textSize) { Paint paint = new Paint(); - paint.setColor(Color.parseColor(color)); paint.setLinearText(true); paint.setAntiAlias(true); - paint.setTextAlign(centered?Align.CENTER:Align.LEFT); + paint.setTextAlign(centered ? Align.CENTER : Align.LEFT); paint.setTypeface(Typeface.SANS_SERIF); paint.setFakeBoldText(true); paint.setTextSize(textSize); + paint.setColor(Color.parseColor(COLOR_TEXT_SHADOW)); + canvas.drawText(message, x + 1, y + 1, paint); + paint.setColor(Color.parseColor(COLOR_TEXT)); canvas.drawText(message, x, y, paint); } @@ -280,14 +310,8 @@ class ShisenShoView extends SurfaceView implements SurfaceHolder.Callback { protected void doDraw(Canvas canvas) { try { - // Double buffering - // Bitmap buffer = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888); - //Canvas cbuffer = new Canvas(buffer); - Canvas cbuffer = canvas; if (canvas == null) return; - //super.onDraw(canvas); - // Board upper left corner on screen int x0=0; int y0=0; @@ -297,10 +321,8 @@ class ShisenShoView extends SurfaceView implements SurfaceHolder.Callback { y0=(screenHeight-app.board.boardSize[0]*tileHeight)/2; } - int red = Color.parseColor("#FF0000"); - int orange = Color.parseColor("#F0C000"); - Paint paint = new Paint(); - paint.setFlags(Paint.ANTI_ALIAS_FLAG); + int selectcolor = Color.parseColor(COLOR_SELECTED); + int hintcolor = Color.parseColor(COLOR_HINT); // Background & board painting switch (pstate) { @@ -317,7 +339,7 @@ class ShisenShoView extends SurfaceView implements SurfaceHolder.Callback { int bgHeight = bg.getHeight(); for (int i=0; i0) { - Line pair=pairs.get(0); - Point a=pair.a; - Point b=pair.b; - path=app.board.getPath(a,b); - paint.setColor(orange); - paint.setStyle(Style.STROKE); - paint.setStrokeCap(Cap.ROUND); - paint.setStrokeJoin(Join.ROUND); - paint.setStrokeWidth(3); - - cbuffer.drawRect(new Rect( - x0+a.j*tileWidth-2, - y0+a.i*tileHeight-2, - x0+a.j*tileWidth-2+tileWidth+2*2, - y0+a.i*tileHeight-2+tileHeight+2*2), - paint); - - if (path!=null) { - Point p0=null; + if (pairs != null && pairs.size() > 0) { + Line pair = pairs.get(0); + Point a = pair.a; + Point b = pair.b; + path = app.board.getPath(a, b); + + highlightTile(canvas, x0, y0, a, hintcolor); + + if (path != null) { + Point p0 = null; for (Point p1 : path) { - if (p0!=null) { - cbuffer.drawLine( - x0+p0.j*tileWidth-2+(tileWidth/2), - y0+p0.i*tileHeight-2+(tileHeight/2), - x0+p1.j*tileWidth-2+(tileWidth/2), - y0+p1.i*tileHeight-2+(tileHeight/2), - paint); + if (p0 != null) { + drawLine(canvas, x0, y0, p0, p1, hintcolor); } - p0=p1; + p0 = p1; } - path=null; + path = null; } - cbuffer.drawRect(new Rect( - x0+b.j*tileWidth-2, - y0+b.i*tileHeight-2, - x0+b.j*tileWidth-2+tileWidth+2*2, - y0+b.i*tileHeight-2+tileHeight+2*2), - paint); + highlightTile(canvas, x0, y0, b, hintcolor); } break; } @@ -450,14 +421,16 @@ class ShisenShoView extends SurfaceView implements SurfaceHolder.Callback { // Win & loose notifications switch (pstate) { case WIN: - drawMessage(cbuffer, screenWidth/2,screenHeight/2,true,"You Win!", "#FFFFFF", 100); + drawMessage(canvas, screenWidth / 2, screenHeight / 2, true, + "You Win!", 100); break; case LOSE: - drawMessage(cbuffer, screenWidth/2,screenHeight/2,true,"Game Over", "#FFFFFF", 100); + drawMessage(canvas, screenWidth / 2, screenHeight / 2, true, + "Game Over", 100); break; } - if (app.timeCounter) switch (pstate) { + switch (pstate) { case BOARD: case SELECTED1: case SELECTED2: @@ -467,34 +440,24 @@ class ShisenShoView extends SurfaceView implements SurfaceHolder.Callback { case HINT: case TIME: updateTime(); - int hours=(int)(playTime/(60*60)); - int minutes=(int)((playTime/60)%60); - int seconds=(int)(playTime%60); - String time=String.format(Locale.US, "%01d:%02d:%02d", hours, minutes, seconds); + int hours = (int) (playTime / (60 * 60)); + int minutes = (int) ((playTime / 60) % 60); + int seconds = (int) (playTime % 60); + if (hours < 10) { + time = String.format(Locale.US, "%01d:%02d:%02d", + hours, minutes, seconds); + } else { + time = INVALID_TIME; + } int timePosX=screenWidth-120; int timePosY=screenHeight-10; - - drawMessage(cbuffer, timePosX+1,timePosY+1,false,time,"#000000",30); - drawMessage(cbuffer, timePosX,timePosY,false,time,"#FFFFFF",30); - break; - } - - // Debug messages - /* - debugMessage="StatePlay: "+cstate+"\n"+"StatePaint: "+pstate; - if (debugMessage!=null && debugMessage.length()>0) { - int l = 20; - String lines[] = debugMessage.split("\n"); - for (int i=0; i=0 && - i=0 && j= 0 && i < app.board.boardSize[0] && j >= 0 + && j < app.board.boardSize[1] + && app.board.board[i][j] != 0) { + selection1.set(i, j); paint(StatePaint.SELECTED1); control(StatePlay.SELECTED1); } break; case SELECTED1: - if (i>=0 && i=0 && j= 0 && i < app.board.boardSize[0] && j >= 0 + && j < app.board.boardSize[1] + && app.board.board[i][j] != 0) { + if (selection1.equals(i, j)) { paint(StatePaint.BOARD); control(StatePlay.IDLE); } else { - selection2[0]=i; - selection2[1]=j; + selection2.set(i, j); paint(StatePaint.SELECTED2); - Point a=new Point(selection1[0],selection1[1]); - Point b=new Point(selection2[0],selection2[1]); - path=app.board.getPath(a,b); + Point a = selection1.copy(); + Point b = selection2.copy(); + path = app.board.getPath(a, b); paint(StatePaint.MATCHED); app.sleep(2); paint(StatePaint.BOARD); - if (path.size()>0) { - app.board.play(a,b); + if (path.size() > 0) { + app.board.play(a, b); } - path=null; + path = null; paint(StatePaint.BOARD); - pairs=app.board.getPairs(1); - if (pairs.size()==0) { - if (app.board.getNumPieces()==0) { + pairs = app.board.getPairs(1); + if (pairs.size() == 0) { + if (app.board.getNumPieces() == 0) { paint(StatePaint.WIN); + checkforhiscore(); } else { paint(StatePaint.LOSE); } @@ -576,10 +568,44 @@ class ShisenShoView extends SurfaceView implements SurfaceHolder.Callback { } } + private void checkforhiscore() { + if (timerRegistered) { + unregisterTimer(); + } + final String[] sizes = { "S", "M", "L" }; + final String[] diffs = { "E", "H" }; + String prefname1 = "hiscore_" + diffs[app.difficulty-1] + sizes[app.size-1] + "1"; + String prefname2 = "hiscore_" + diffs[app.difficulty-1] + sizes[app.size-1] + "2"; + // get hiscores for current size/difficulty + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(app); + String besttime1 = sp.getString(prefname1, INVALID_TIME); + String besttime2 = sp.getString(prefname2, INVALID_TIME); + // did we win something? + if (time.compareTo(besttime2) < 0) { + // score! + new AlertDialog.Builder(app.activity) + .setTitle("Hiscore!") + .setCancelable(true) + .setIcon(R.drawable.icon) + .setPositiveButton(app.getString(android.R.string.ok), null) + .setMessage("You've made the highscore list!").create() // FIXME: hardcoded string + .show(); + + SharedPreferences.Editor editor = sp.edit(); + if (time.compareTo(besttime1) < 0) { + editor.putString(prefname1, time); + editor.putString(prefname2, besttime1); + } else { + editor.putString(prefname2, time); + } + editor.commit(); + } + } + public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { surfaceHolder = holder; - if (cstate!=StatePlay.GAMEOVER && app.timeCounter && !timerRegistered) { + if (cstate!=StatePlay.GAMEOVER && !timerRegistered) { registerTimer(); } repaint(); @@ -596,87 +622,4 @@ class ShisenShoView extends SurfaceView implements SurfaceHolder.Callback { unregisterTimer(); } } - - /* - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - - if (!initialized) initialize(); - - long currTime = System.currentTimeMillis(); - - a = (float)(currTime - startTime) / (float)duration; - if (a > (float)1.0) a = (float)1.0; - - x = Math.round(nextx*a + prevx*(1-a)); - y = Math.round(nexty*a + prevy*(1-a)); - - if (a == (float)1.0) computeNextTarget(); - - int bgWidth = bg.getWidth(); - int bgHeight = bg.getHeight(); - for (int i=0; i