Project

General

Profile

Download (32.9 KB) Statistics
| Branch: | Revision:

sokoban / distorted-sokoban / src / main / java / org / distorted / sokoban / SokobanLevels.java @ 1f6d1786

1
package org.distorted.sokoban;
2

    
3
import android.graphics.Canvas;
4
import android.graphics.Bitmap;
5
import android.graphics.BitmapFactory;
6
import android.graphics.Paint;
7
import android.graphics.Region;
8
import android.graphics.Paint.Style;
9
import android.graphics.drawable.NinePatchDrawable;
10

    
11
import android.app.Activity;
12
import android.content.Context;
13
import android.content.res.Resources;
14

    
15
import android.util.Log;
16
import android.util.DisplayMetrics;
17

    
18
import java.util.Vector;
19

    
20
///////////////////////////////////////////////////////////////////////////////////////////////////
21

    
22
public class SokobanLevels
23
  {
24
  private static final String TAG_LEVELS = "SokobanLevels";
25
  
26
  public static final int COLOR_GREEN = 0xff6a7900;
27
  public static final int COLOR_BLACK = 0xff000000;
28
  public static final int COLOR_WHITE = 0xffffffff;
29
  public static final int COLOR_GRAY  = 0xff999999;
30
  private static final int COLOR_EMPT = 0xaaffffff;
31
 
32
  private static final int    SAMPLE_SIZE     =   5;
33
  private static final double SPRING_CONST    = 1.8;
34
  private static final int    MAX_SPRING_SPEED=   8;
35
  private static final int    MIN_CLICK_DIST  =   8;
36
  private static final int    PLAY_MIN_DIST   =  20;
37

    
38
  public static final int FLAG_H = 15;
39
  public static final int FLAG_W = 22;
40
  
41
  public static Bitmap emptyBig1 , packBig1, destBig1, dpckBig1, playBig1;
42
  public static Bitmap emptyBig2 , packBig2, destBig2, dpckBig2, playBig2;
43
  public static Bitmap backgroundSmall, destSmall, emptySmall, packSmall, playSmall, dpckSmall;
44
  public static Bitmap bkgClicked, bkgUnClick;
45
  public static Bitmap levelBig, levelInfo;
46
  
47
  private int levelHeight;
48

    
49
  public static int mGap;
50
  private int amountDrag = -1;
51
  
52
  private static boolean mVertical;
53
  private static SokobanTimer timer =null;
54
  private static SokobanLevels levels;
55
  private boolean mSpringing = false;
56
  private boolean canMove = false;
57
  private int cX, cY;
58
  private static int mNumLevels, clickedLevel=-1;
59
  private static int currLevel;
60
  private static int mScrollPos;
61
  private double mScrollSpeed;
62
  private static Vector<SokobanLevel> mLevels;
63
  private Paint mPaint;
64
  private double sample[];
65
  private int samplePtr;
66
  private boolean mDragging = false;
67
  private static int currTime;
68
  private static int currMoves;
69
  private static boolean timerRunning=false;
70
  
71
  public static int levelInfoH, levelInfoW, sCell ,levelBigH ,levelBigW ,bCell1 ,bCell2, backSmallH, backSmallW;
72
  public static int sMargin, bMargin;
73
  public static int bDrawnX1, bDrawnY1, bDrawnX2, bDrawnY2, sDrawnX, sDrawnY; 
74
  public static int mGapO, mGapI;
75
  public static int gapX1, gapY1, gapX2, gapY2;
76

    
77
  private static Resources res; 
78
  private static SokobanLevel created;
79
  private static int scrWidth, scrHeight;
80
  public  static SokobanLevelBuffer slBuffer;
81
  
82
  static class Flag
83
  {
84
      public Bitmap flag;
85
      public String name;
86

    
87
      Flag()
88
        {
89
        flag = null;
90
        name = null;
91
        }
92
      Flag(String n)
93
        {
94
        name = n;
95

    
96
        try
97
          {
98
          int resID = res.getIdentifier(name, "drawable", "org.distorted.sokoban");
99
          flag = BitmapFactory.decodeResource(res, resID!=0 ? resID:R.drawable.unk);  	
100
          }
101
        catch( Exception ex )
102
          {
103
          flag=null;
104
          }
105
        }
106
  }
107

    
108
  private static Vector<Flag> mFlags;
109

    
110
///////////////////////////////////////////////////////////////////////////////////////////////////
111

    
112
  private SokobanLevels(Context context)
113
  {
114
      mNumLevels = 0;
115
      mScrollPos = 0;
116
      mScrollSpeed=0;
117
      
118
      res = context.getResources();
119
      
120
      mVertical = (scrWidth<=scrHeight);
121
      mGap = scrHeight/6;
122
      levelHeight = (scrHeight-mGap)/3;
123
      
124
      if( levelHeight<120 ) levelHeight = 120;
125
      if( levelHeight>260 ) levelHeight = 260;
126
      
127
      sample = new double[SAMPLE_SIZE];
128
      samplePtr = -1;
129

    
130
      cX = -(MIN_CLICK_DIST+1);
131
      cY = -(MIN_CLICK_DIST+1);
132
      
133
      mPaint = new Paint();
134
      mPaint.setStyle(Style.FILL);
135
      
136
      mLevels = new Vector<>();
137
      mFlags  = new Vector<>();
138
      
139
      createImages();
140
      
141
      created = new SokobanLevel(context,scrWidth,scrHeight,mGap);
142
      slBuffer= new SokobanLevelBuffer(levelHeight,scrHeight);
143
  }
144

    
145
///////////////////////////////////////////////////////////////////////////////////////////////////
146

    
147
  public static void init(Activity act)
148
  {
149
	if( scrWidth<=0 || scrHeight<=0 )
150
		{
151
		DisplayMetrics dm = new DisplayMetrics();
152
		act.getWindowManager().getDefaultDisplay().getMetrics(dm);
153
		  
154
		scrWidth = Math.min(dm.widthPixels,dm.heightPixels);
155
		scrHeight= Math.max(dm.widthPixels,dm.heightPixels);
156
		}
157
		
158
    levels = new SokobanLevels((Context)act);
159
  }
160

    
161
///////////////////////////////////////////////////////////////////////////////////////////////////
162

    
163
  private void createImages()
164
  {
165
    NinePatchDrawable play,pack,dpck,levl, dpck_small, pack_small, dialog, dlgred;
166
	  Canvas c;
167
	  
168
    try
169
      {
170
    	  play = (NinePatchDrawable)res.getDrawable(R.drawable.play);
171
    	  pack = (NinePatchDrawable)res.getDrawable(R.drawable.pack);
172
    	  dpck = (NinePatchDrawable)res.getDrawable(R.drawable.dpck);
173
    	  levl = (NinePatchDrawable)res.getDrawable(R.drawable.level_info);
174
    	  
175
    	  pack_small = (NinePatchDrawable)res.getDrawable(R.drawable.pack_small);
176
    	  dpck_small = (NinePatchDrawable)res.getDrawable(R.drawable.dpck_small);
177
    	  
178
    	  dialog     = (NinePatchDrawable)res.getDrawable(R.drawable.dialog);
179
        dlgred     = (NinePatchDrawable)res.getDrawable(R.drawable.dialog_clicked);
180
      }
181
      catch( Exception ex ) { Log.e(TAG_LEVELS, "Failed to create 9Patches!"); return; }
182

    
183
      mGapO   = scrHeight/80;
184
      mGapI   = scrHeight/80;
185
      sDrawnX = 10;
186
      sDrawnY = 10;
187
      
188
      bDrawnX1= 12;
189
      bDrawnY1= (scrHeight-mGap)/(scrWidth/bDrawnX1);
190
      bDrawnY2= 18;
191
      bDrawnX2= scrWidth/((scrHeight-mGap)/bDrawnY2);
192
      
193
      sCell   = (levelHeight-mGapO-2*mGapI)/sDrawnX;
194
      bCell1  = scrWidth/bDrawnX1;
195
      bCell2  = (scrHeight-mGap)/bDrawnY2;
196
     
197
      sMargin = sCell /10;
198
      bMargin = bCell1/12;
199
      
200
      if( sMargin<=0 ) sMargin=1;
201
      if( bMargin<=0 ) bMargin=1;
202
      
203
      int sCross1  = (int)(sCell *0.42);
204
      int sCross2  = (int)(sCell *0.38);
205
      int bCross11 = (int)(bCell1*0.42);
206
      int bCross21 = (int)(bCell1*0.38);
207
      int bCross12 = (int)(bCell2*0.42);
208
      int bCross22 = (int)(bCell2*0.38);
209
      
210
      int sS  = sCell  - sMargin;
211
      int bS1 = bCell1 - bMargin;
212
      int bS2 = bCell2 - bMargin;
213

    
214
      int fB1 = bCell1/8;
215
      int fB2 = bCell2/8;
216
      int fS  = sCell /8;
217
      
218
      if( fB1<=0 ) fB1=1;
219
      if( fB2<=0 ) fB2=1;
220
      if( fS <=0 ) fS =1;
221
      
222
      backSmallW = sDrawnX*sCell + sMargin;
223
      backSmallH = sDrawnY*sCell + sMargin;
224
      
225
      mGapI = (levelHeight-mGapO-backSmallH)/2;
226
      
227
      levelInfoH = (backSmallH-2*mGapI)/3;
228
      levelInfoW = scrWidth-2*mGapO-3*mGapI-backSmallW+2;		  
229
      levelBigH  = backSmallH;
230
      levelBigW  = scrWidth-2*mGapO-3*mGapI-backSmallW+2;			  
231
     
232
      gapX1= (scrWidth      -bDrawnX1*bCell1-bMargin)/2;
233
      gapY1= (scrHeight-mGap-bDrawnY1*bCell1-bMargin)/2;
234
      
235
      gapX2= (scrWidth      -bDrawnX2*bCell2-bMargin)/2;
236
      gapY2= (scrHeight-mGap-bDrawnY2*bCell2-bMargin)/2;
237
     
238
      bkgClicked = Bitmap.createBitmap(scrWidth,levelHeight,  Bitmap.Config.ARGB_8888 );
239
      bkgUnClick = Bitmap.createBitmap(scrWidth,levelHeight,  Bitmap.Config.ARGB_8888 );
240
      
241
      backgroundSmall = Bitmap.createBitmap(backSmallW,backSmallH, Bitmap.Config.ARGB_8888);
242
      
243
      levelInfo = Bitmap.createBitmap(levelInfoW,levelInfoH, Bitmap.Config.ARGB_8888);
244
      levelBig  = Bitmap.createBitmap(levelBigW ,levelBigH , Bitmap.Config.ARGB_8888);
245
      
246
      emptySmall= Bitmap.createBitmap(sS ,sS , Bitmap.Config.ARGB_8888);
247
      packSmall = Bitmap.createBitmap(sS ,sS , Bitmap.Config.ARGB_8888);
248
      destSmall = Bitmap.createBitmap(sS ,sS , Bitmap.Config.ARGB_8888);
249
      dpckSmall = Bitmap.createBitmap(sS ,sS , Bitmap.Config.ARGB_8888);
250
      playSmall = Bitmap.createBitmap(sS ,sS , Bitmap.Config.ARGB_8888);
251
      
252
      emptyBig1 = Bitmap.createBitmap(bS1,bS1, Bitmap.Config.ARGB_8888);
253
      packBig1  = Bitmap.createBitmap(bS1,bS1, Bitmap.Config.ARGB_8888);
254
      destBig1  = Bitmap.createBitmap(bS1,bS1, Bitmap.Config.ARGB_8888);
255
      dpckBig1  = Bitmap.createBitmap(bS1,bS1, Bitmap.Config.ARGB_8888);
256
      playBig1  = Bitmap.createBitmap(bS1,bS1, Bitmap.Config.ARGB_8888);
257

    
258
      emptyBig2 = Bitmap.createBitmap(bS2,bS2, Bitmap.Config.ARGB_8888);
259
      packBig2  = Bitmap.createBitmap(bS2,bS2, Bitmap.Config.ARGB_8888);
260
      destBig2  = Bitmap.createBitmap(bS2,bS2, Bitmap.Config.ARGB_8888);
261
      dpckBig2  = Bitmap.createBitmap(bS2,bS2, Bitmap.Config.ARGB_8888);
262
      playBig2  = Bitmap.createBitmap(bS2,bS2, Bitmap.Config.ARGB_8888);
263

    
264
      // bkgClicked
265
      c = new Canvas(bkgClicked);
266
      mPaint.setColor(COLOR_BLACK);
267
      c.drawRect(0,0, scrWidth, levelHeight, mPaint);
268
      dlgred.setBounds(mGapO, mGapO/2, scrWidth-mGapO, levelHeight-mGapO/2);
269
	  dlgred.draw(c);
270
      
271
      // bkgUnClick
272
      c = new Canvas(bkgUnClick);
273
      mPaint.setColor(COLOR_BLACK);
274
      c.drawRect(0,0, scrWidth, levelHeight, mPaint);
275
      dialog.setBounds(mGapO, mGapO/2, scrWidth-mGapO, levelHeight-mGapO/2);
276
	  dialog.draw(c);
277

    
278
      // backgroundSmall
279
      c = new Canvas(backgroundSmall);
280
      mPaint.setColor(SokobanLevel.COLOR_BACK);
281
      c.drawRect(0,0, backSmallW, backSmallH, mPaint);
282
      mPaint.setColor(SokobanLevel.COLOR_GRID);
283
      
284
      for( int i=0; i<=sDrawnY; i++ ) c.drawRect(0, i*sCell, backSmallW, i*sCell+sMargin , mPaint);
285
      for( int i=0; i<=sDrawnX; i++ ) c.drawRect(i*sCell, 0, i*sCell+sMargin, backSmallH , mPaint);
286
  	  
287
      // levelInfo
288
      c = new Canvas(levelInfo);
289
      levelInfo.eraseColor(0);
290
      levl.setBounds(0,0,levelInfoW,levelInfoH);
291
      levl.draw(c);
292
      
293
      // levelBig
294
      c = new Canvas(levelBig);
295
      levelBig.eraseColor(0);
296
      levl.setBounds(0,0,levelBigW,levelBigH);
297
      levl.draw(c);
298
      
299
      //emptySmall
300
      emptySmall.eraseColor(COLOR_EMPT);
301
      
302
      //packSmall
303
      c = new Canvas(packSmall);
304
      packSmall.eraseColor(0);
305
      
306
      pack_small.setBounds( fS, fS, sS-fS, sS-fS );
307
      pack_small.draw(c);
308
      
309
      //destSmall
310
      c = new Canvas(destSmall);
311
      destSmall.eraseColor(COLOR_EMPT);
312
      
313
      mPaint.setColor(SokobanLevel.COLOR_CRES);
314
      c.drawRect( sCross2, sCross2, sS-sCross2, sS-sCross2 ,mPaint);
315
      c.drawRect( fS, sCross1, sS-fS, sS-sCross1 ,mPaint);
316
      c.drawRect( sCross1, fS, sS-sCross1, sS-fS ,mPaint);
317
      
318
      //dpckSmall
319
      c = new Canvas(dpckSmall);
320
      dpckSmall.eraseColor(0);
321
      
322
      dpck_small.setBounds( fS, fS, sS-fS, sS-fS );
323
      dpck_small.draw(c);
324
      
325
      //playSmall
326
      c = new Canvas(playSmall);
327
      playSmall.eraseColor(0);
328
      
329
      play.setBounds( fS, fS, sS-fS, sS-fS );
330
      play.draw(c);
331
      
332
      //emptyBig1
333
      emptyBig1.eraseColor(COLOR_EMPT);
334
      
335
      //emptyBig2
336
      emptyBig2.eraseColor(COLOR_EMPT);
337
      
338
      //packBig1
339
      c = new Canvas(packBig1);
340
      packBig1.eraseColor(0);
341
      
342
      pack.setBounds( fB1, fB1, bS1-fB1, bS1-fB1 );
343
      pack.draw(c);
344
      
345
      //packBig2
346
      c = new Canvas(packBig2);
347
      packBig2.eraseColor(0);
348
      
349
      pack.setBounds( fB2, fB2, bS2-fB2, bS2-fB2 );
350
      pack.draw(c);
351
      
352
      //destBig1
353
      c = new Canvas(destBig1);
354
      destBig1.eraseColor(COLOR_EMPT);
355
      
356
      mPaint.setColor(SokobanLevel.COLOR_CRES);
357
      c.drawRect( bCross21, bCross21, bS1-bCross21, bS1-bCross21 ,mPaint);
358
      c.drawRect( fB1, bCross11, bS1-fB1, bS1-bCross11 ,mPaint);
359
      c.drawRect( bCross11, fB1, bS1-bCross11, bS1-fB1 ,mPaint);
360
      
361
      //destBig2
362
      c = new Canvas(destBig2);
363
      destBig2.eraseColor(COLOR_EMPT);
364
      
365
      mPaint.setColor(SokobanLevel.COLOR_CRES);
366
      c.drawRect( bCross22, bCross22, bS2-bCross22, bS2-bCross22 ,mPaint);
367
      c.drawRect( fB2, bCross12, bS2-fB2, bS2-bCross12 ,mPaint);
368
      c.drawRect( bCross12, fB2, bS2-bCross12, bS2-fB2 ,mPaint);
369
      
370
      //dpckBig1
371
      c = new Canvas(dpckBig1);
372
      dpckBig1.eraseColor(0);
373
      
374
      dpck.setBounds( fB1, fB1, bS1-fB1, bS1-fB1 );
375
      dpck.draw(c);
376
      
377
      //dpckBig2
378
      c = new Canvas(dpckBig2);
379
      dpckBig2.eraseColor(0);
380
      
381
      dpck.setBounds( fB2, fB2, bS2-fB2, bS2-fB2 );
382
      dpck.draw(c);
383
      
384
      //playBig1
385
      c = new Canvas(playBig1);
386
      playBig1.eraseColor(0);
387
      
388
      play.setBounds( fB1, fB1, bS1-fB1, bS1-fB1 );
389
      play.draw(c);
390
      
391
      //playBig2
392
      c = new Canvas(playBig2);
393
      playBig2.eraseColor(0);
394
      
395
      play.setBounds( fB2, fB2, bS2-fB2, bS2-fB2 );
396
      play.draw(c);
397
  }
398
  
399
///////////////////////////////////////////////////////////////////////////////////////////////////
400
  
401
  public static SokobanLevels getInstance()
402
  {
403
      return levels;
404
  }
405

    
406
///////////////////////////////////////////////////////////////////////////////////////////////////
407

    
408
  public static SokobanLevel getLevel(int i)
409
  {
410
      if( i>=0 && i<mNumLevels ) return (SokobanLevel)mLevels.elementAt(i);
411

    
412
      return null;
413
  }
414

    
415
///////////////////////////////////////////////////////////////////////////////////////////////////
416

    
417
  public Bitmap getFlag(String s)
418
  {
419
      if( s==null ) return null;
420

    
421
      int size = mFlags.size();
422
      Flag tmp;
423

    
424
      for(int i=0; i<size; i++)
425
        {
426
        tmp = (Flag)mFlags.elementAt(i);
427
        if( tmp.name.equals(s) ) return tmp.flag;
428
        }
429

    
430
      tmp = new Flag(s);
431
      mFlags.addElement(tmp);
432

    
433
      return tmp.flag;
434
  }
435

    
436
///////////////////////////////////////////////////////////////////////////////////////////////////
437

    
438
  public void updateMyRecords(String n)
439
  {
440
      SokobanLevel sl;
441
      int move;
442

    
443
      for(int i=0; i<mNumLevels; i++)
444
        {
445
        sl = (SokobanLevel)mLevels.elementAt(i);
446
        if( sl==null ) continue;
447

    
448
        move = sl.getMyMoves();
449

    
450
        if( move<SokobanDatabase.INVALID ) sl.setName(n);
451
        }
452
  }
453

    
454
///////////////////////////////////////////////////////////////////////////////////////////////////
455

    
456
  public void resetCurrTime()
457
  {
458
      stopTimer();
459
      currTime = 0;
460
  }
461

    
462
///////////////////////////////////////////////////////////////////////////////////////////////////
463

    
464
  public void setScrDimensions(int w, int h)
465
  {
466
	  if( scrWidth!=w || scrHeight!=h )
467
        {
468
		Log.e(TAG_LEVELS, "Correcting SokobanLevels images!");  
469
		  
470
        scrWidth    = w;
471
        scrHeight   = h;
472
        mVertical   = (w<=h);
473
        
474
        levelHeight = (h-mGap)/3;
475
        
476
        if( levelHeight<120 ) levelHeight = 120;
477
        if( levelHeight>200 ) levelHeight = 200;
478
        
479
        createImages();
480
        SokobanLevelBuffer.allocate(levelHeight,scrHeight);
481
        created.allocate(scrWidth,scrHeight,mGap);
482
        }
483
  }
484

    
485
///////////////////////////////////////////////////////////////////////////////////////////////////
486

    
487
  public void scrollToEnd()
488
  {
489
      if( mVertical ) mScrollPos=mNumLevels*levelHeight-(scrHeight-mGap);
490
      else mScrollPos=mNumLevels*levelHeight-scrWidth;
491
  }
492

    
493
///////////////////////////////////////////////////////////////////////////////////////////////////
494

    
495
  public void setScroll(int s)
496
  {
497
      mScrollPos = s;
498

    
499
      if( mScrollPos<0 ) mScrollPos = 0;
500
      
501
      if( mVertical )
502
      {
503
    	  if( mScrollPos> mNumLevels*levelHeight-(scrHeight-mGap) )
504
    		  mScrollPos=mNumLevels*levelHeight-(scrHeight-mGap);
505
      }
506
      else
507
      {
508
    	  if( mScrollPos>mNumLevels*levelHeight-scrWidth )
509
    		  mScrollPos=mNumLevels*levelHeight-scrWidth;
510
      }
511
  }
512

    
513
///////////////////////////////////////////////////////////////////////////////////////////////////
514

    
515
  public static int getScroll()
516
  {
517
      return mScrollPos;
518
  }
519

    
520
///////////////////////////////////////////////////////////////////////////////////////////////////
521

    
522
  private void scroll()
523
  {
524
	  mScrollPos+=mScrollSpeed;
525

    
526
      if( mVertical )
527
        {
528
        if( mScrollPos<0 )
529
          {
530
          mSpringing = true;
531
          mScrollSpeed+=SPRING_CONST;
532
          if( mScrollSpeed<-MAX_SPRING_SPEED ) mScrollSpeed=-MAX_SPRING_SPEED;
533
          }
534
        else if( mScrollPos> mNumLevels*levelHeight-(scrHeight-mGap))
535
          {
536
          mSpringing = true;
537
          mScrollSpeed-=SPRING_CONST;
538
          if( mScrollSpeed> MAX_SPRING_SPEED ) mScrollSpeed= MAX_SPRING_SPEED;
539
          }
540
        else
541
          {
542
          if( mSpringing )
543
            {
544
            if( mScrollPos<mScrollSpeed ) mScrollPos = 0;
545
            else mScrollPos = mNumLevels*levelHeight-(scrHeight-mGap);
546

    
547
            mSpringing = false;
548
            mScrollSpeed = 0;
549
            }
550
          else
551
            {
552
        	     if( mScrollSpeed> 1 ) mScrollSpeed-=1;
553
        	else if( mScrollSpeed<-1 ) mScrollSpeed+=1;
554
        	else                       mScrollSpeed=0;     
555
            }
556
          }
557
        }
558
      else
559
        {
560
        if( mScrollPos<0 )
561
          {
562
          mSpringing = true;
563
          mScrollSpeed+=SPRING_CONST;
564
          if( mScrollSpeed<-MAX_SPRING_SPEED ) mScrollSpeed=-MAX_SPRING_SPEED;
565
          }
566
        else if( mScrollPos> mNumLevels*levelHeight-scrWidth )
567
          {
568
          mSpringing = true;
569
          mScrollSpeed-=SPRING_CONST;
570
          if( mScrollSpeed> MAX_SPRING_SPEED ) mScrollSpeed= MAX_SPRING_SPEED;
571
          }
572
        else
573
          {
574
          if( mSpringing )
575
            {
576
            if( mScrollPos<mScrollSpeed ) mScrollPos = 0;
577
            else mScrollPos = mNumLevels*levelHeight-scrWidth;
578

    
579
            mSpringing = false;
580
            mScrollSpeed = 0;
581
            }
582
          else
583
            {
584
        	     if( mScrollSpeed> 1 ) mScrollSpeed-=1;
585
            else if( mScrollSpeed<-1 ) mScrollSpeed+=1;
586
            else                       mScrollSpeed=0;     
587
            }
588
          }
589
        }
590
  }
591

    
592
///////////////////////////////////////////////////////////////////////////////////////////////////
593

    
594
  public static int getNumLevels()
595
  {
596
      return mNumLevels;
597
  }
598

    
599
///////////////////////////////////////////////////////////////////////////////////////////////////
600

    
601
  public static int getIntrinsic()
602
  {
603
      SokobanLevel sl= getLevel(mNumLevels-1);
604

    
605
      if( sl!=null ) return sl.getIntrinsicNum();
606

    
607
      return -1;
608
  }
609

    
610
///////////////////////////////////////////////////////////////////////////////////////////////////
611

    
612
  public void addLevel(SokobanLevel l, int num)
613
  {
614
      mLevels.addElement(l);
615
      mNumLevels++;
616
      l.setNum(mNumLevels);
617
      l.setIntrinsicNum(num);
618
      l.setRecordId(num+SokobanDatabase.BEGIN_LEVELS);
619
  }
620

    
621
///////////////////////////////////////////////////////////////////////////////////////////////////
622

    
623
  public void insertLevel(SokobanLevel l, int pos,int intrinsic, int recordid)
624
  {
625
      if( pos>=mNumLevels )
626
        {
627
        for(int i=mNumLevels; i<=pos; i++)
628
          {
629
          mLevels.addElement(null);
630
          }
631
     
632
        mNumLevels = pos+1;
633
        }
634

    
635
      mLevels.setElementAt(l, pos);
636
      l.setNum(pos+1);
637
      l.setIntrinsicNum(intrinsic);
638
      l.setRecordId(recordid);
639
  }
640

    
641
///////////////////////////////////////////////////////////////////////////////////////////////////
642

    
643
  public void render(int state, Canvas c)
644
  { 
645
      if( state==SokobanCanvas.STATE_MAIN ||
646
          state==SokobanCanvas.STATE_MENU ||
647
          state==SokobanCanvas.STATE_DOWN ||
648
          state==SokobanCanvas.STATE_DOWL ||
649
          state==SokobanCanvas.STATE_FAID ||
650
          state==SokobanCanvas.STATE_FAIE ||
651
          state==SokobanCanvas.STATE_SUCE ||
652
          state==SokobanCanvas.STATE_SUCD ||
653
          state==SokobanCanvas.STATE_HELP  )
654
        {
655
        if( (mScrollSpeed!=0 || mSpringing) && !mDragging )
656
          {
657
          scroll();
658
          SokobanCanvas.setRepaint();
659
          }
660

    
661
        int beg = Math.max(mScrollPos/levelHeight, 0);
662
        int end = Math.min(( mVertical ? (mScrollPos+scrHeight-mGap):(mScrollPos+scrWidth) )/levelHeight, mNumLevels-1);
663
        int height = mVertical ? (mGap/2-mScrollPos+(beg-1)*levelHeight):((beg-1)*levelHeight-mScrollPos);
664
        int begHeight = height+levelHeight;
665
        
666
        mPaint.setColor(COLOR_BLACK);
667
        c.drawRect(0, scrHeight-mGap/2-mGapO, scrWidth,scrHeight-mGap/2+7, mPaint);
668
        
669
        try
670
          {
671
          c.clipRect(0, mGap/2, scrWidth, scrHeight-mGap/2+6, Region.Op.INTERSECT);
672
        	
673
          for(int i=beg; i<=end; i++)
674
            {
675
            SokobanLevel sl = (SokobanLevel)mLevels.elementAt(i);
676
            height+=levelHeight;
677

    
678
            if( sl!=null && height+mGap/2+mGapO<scrHeight)
679
              {
680
              if( state!=SokobanCanvas.STATE_SUCD )
681
                sl.renderSmall(  c, height, i==clickedLevel);
682
              else
683
                sl.renderRecords(c, height );
684
              }
685
            }
686
          
687
          c.clipRect(0, 0, scrWidth, scrHeight, Region.Op.INTERSECT);
688
          }
689
        catch( ArrayIndexOutOfBoundsException aiofb ) { System.out.println("render1: level out of bounds??"); }
690

    
691
        if( begHeight>mGap/2-5 )
692
          {
693
          c.drawRect(0, mGap/2-5, scrWidth,begHeight, mPaint);
694
          }
695
        if( height+levelHeight<scrHeight-mGap/2-mGapO )
696
          {
697
          c.drawRect(0, height+levelHeight, scrWidth, scrHeight-mGap/2-mGapO, mPaint);
698
          }
699
        }
700
      else if( state==SokobanCanvas.STATE_PLAY ||
701
               state==SokobanCanvas.STATE_TIME ||
702
               state==SokobanCanvas.STATE_NEWR ||
703
               state==SokobanCanvas.STATE_NAME ||
704
               state==SokobanCanvas.STATE_EXIS ||
705
               state==SokobanCanvas.STATE_FAIL ||
706
               state==SokobanCanvas.STATE_RECO ||
707
               state==SokobanCanvas.STATE_SECU ||
708
               state==SokobanCanvas.STATE_SUBM  )
709
        {
710
        SokobanLevel sl;
711

    
712
        try
713
          {
714
          sl = (SokobanLevel)mLevels.elementAt(currLevel);
715
          }
716
        catch( ArrayIndexOutOfBoundsException aiofb ) { System.out.println("render2: level out of bounds??"); return; }
717

    
718
        sl.renderBig(c,0,mGap/2  );
719
        }
720
      else if( state==SokobanCanvas.STATE_CREA ||
721
               state==SokobanCanvas.STATE_CRED ||
722
               state==SokobanCanvas.STATE_CRES ||
723
               state==SokobanCanvas.STATE_SUBC  )
724
        {
725
        created.renderBig(c,0,mGap/2  );
726
        mPaint.setColor(COLOR_BLACK);
727
        c.drawRect(0, 0, scrWidth, 7, mPaint);
728
        }
729
  }
730

    
731
///////////////////////////////////////////////////////////////////////////////////////////////////
732

    
733
  public int stopTimer()
734
    {
735
    timerRunning = false;
736
    return timer!=null ? timer.stop() : -2;
737
    }
738

    
739
///////////////////////////////////////////////////////////////////////////////////////////////////
740

    
741
  public void startTimer(int time)
742
    {
743
    currTime = time/10;
744
    timerRunning= true;
745
    timer = SokobanTimer.getInstance();
746
    timer.start(time);
747
    }
748

    
749
///////////////////////////////////////////////////////////////////////////////////////////////////
750

    
751
  private int retClickedLevel(int x, int y)
752
  {
753
    int ret;
754

    
755
    if( mVertical ) ret =(y+mScrollPos-mGap/2)/levelHeight;
756
    else            ret =(x+mScrollPos       )/levelHeight;
757

    
758
    return ret>=mNumLevels ? mNumLevels-1:ret;
759
  }
760

    
761
///////////////////////////////////////////////////////////////////////////////////////////////////
762

    
763
  public static int getCurrLevel()
764
  {
765
    return currLevel;
766
  }
767

    
768
///////////////////////////////////////////////////////////////////////////////////////////////////
769

    
770
  public static int getCurrTime()
771
  {  
772
    return currTime;
773
  }
774

    
775
///////////////////////////////////////////////////////////////////////////////////////////////////
776

    
777
  public static int getCurrMoves()
778
  {
779
    return currMoves;
780
  }
781

    
782
///////////////////////////////////////////////////////////////////////////////////////////////////
783

    
784
  public static void setTime(int t)
785
  {
786
    currTime = t;
787
    if( currTime%100==0 ) SokobanCanvas.getMenu().updatePlayState();
788
    SokobanCanvas.setRepaint();
789
  }
790

    
791
///////////////////////////////////////////////////////////////////////////////////////////////////
792

    
793
  public void rollbackCreated()
794
  {
795
    created.rollback();
796
  }
797

    
798
///////////////////////////////////////////////////////////////////////////////////////////////////
799

    
800
  public void rollback()
801
  {
802
    SokobanLevel sl;
803

    
804
    try
805
      {
806
      sl = (SokobanLevel)mLevels.elementAt(currLevel);
807
      }
808
    catch( ArrayIndexOutOfBoundsException aiofb ) { System.out.println("rollback: level out of bounds??"); return; }
809

    
810
    currMoves = 0;
811
    sl.rollback();
812
  }
813

    
814
///////////////////////////////////////////////////////////////////////////////////////////////////
815

    
816
  public void withdrawCreated()
817
  {
818
    created.withdraw();
819
  }
820

    
821
///////////////////////////////////////////////////////////////////////////////////////////////////
822

    
823
  public void withdraw()
824
  {
825
    SokobanLevel sl;
826

    
827
    try
828
      {
829
      sl = (SokobanLevel)mLevels.elementAt(currLevel);
830
      }
831
    catch( ArrayIndexOutOfBoundsException aiofb ) { System.out.println("withdraw: level out of bounds??"); return; }
832

    
833
    if( sl.withdraw() ) currMoves--;
834
  }
835

    
836
///////////////////////////////////////////////////////////////////////////////////////////////////
837

    
838
  public static void resetCreated()
839
  {
840
    created.resetCreated();
841
  }
842

    
843
///////////////////////////////////////////////////////////////////////////////////////////////////
844

    
845
  public static void drop(int stuff)
846
  {
847
    created.drop(stuff);
848
  }
849

    
850
///////////////////////////////////////////////////////////////////////////////////////////////////
851

    
852
  public static int validate()
853
  {
854
    return created.validate();
855
  }
856

    
857
///////////////////////////////////////////////////////////////////////////////////////////////////
858

    
859
  public boolean canWithdrawCreated()
860
  {
861
    return created.canWithdraw();
862
  }
863

    
864
///////////////////////////////////////////////////////////////////////////////////////////////////
865

    
866
  public boolean canWithdraw()
867
  {
868
    SokobanLevel sl;
869

    
870
    try
871
      {
872
      sl = (SokobanLevel)mLevels.elementAt(currLevel);
873
      }
874
    catch( ArrayIndexOutOfBoundsException aiofb ) { System.out.println("withdraw: level out of bounds??"); return false; }
875

    
876
    return sl.canWithdraw();
877
  }
878

    
879
///////////////////////////////////////////////////////////////////////////////////////////////////
880

    
881
  public void click(int state,int x,int y)
882
    {
883
    if( y<mGap/2 || y>scrHeight-mGap/2 ) { clickedLevel=-1; return; }
884

    
885
    cX = x;
886
    cY = y;
887
    mDragging = true;
888

    
889
    if( state==SokobanCanvas.STATE_MAIN || state==SokobanCanvas.STATE_SUCD )
890
      {
891
      amountDrag = mVertical ? y:x;
892
      if( mScrollSpeed<=1 && mScrollSpeed>=-1 ) clickedLevel = retClickedLevel(x,y);
893
      else                                      clickedLevel = -1;
894
      samplePtr =-1;
895
      for(int i=0; i<SAMPLE_SIZE; i++) sample[i]=0;
896
      mScrollSpeed = 0;
897
      }
898
    else if( state==SokobanCanvas.STATE_PLAY || state==SokobanCanvas.STATE_CREA || state==SokobanCanvas.STATE_CRES )
899
      {
900
      canMove = true;
901
      }
902

    
903
    mScrollSpeed = 0;
904
    }
905

    
906
///////////////////////////////////////////////////////////////////////////////////////////////////
907

    
908
  public void unclick(int state,int x,int y)
909
    {
910
    if( y<mGap/2 || y>scrHeight-mGap/2 ) { clickedLevel=-1; mDragging=false; return; }
911

    
912
    int dx = cX-x;
913
    int dy = cY-y;
914
    mDragging = false;
915

    
916
    if( state==SokobanCanvas.STATE_MAIN || state==SokobanCanvas.STATE_SUCD )
917
      {
918
      if( state==SokobanCanvas.STATE_MAIN && clickedLevel>=0 && dx*dx+dy*dy<=MIN_CLICK_DIST*MIN_CLICK_DIST)
919
        {
920
        SokobanDatabase.getInstance().incNumPlayings();
921
        currLevel = clickedLevel;
922
        currMoves = 0;
923
        SokobanCanvas.getMenu().enterPlayState(currLevel);
924
        SokobanCanvas.setRepaint();
925
        }
926
      
927
      clickedLevel = -1;
928
      cX = -(MIN_CLICK_DIST+1);
929
      cY = -(MIN_CLICK_DIST+1);
930
      amountDrag = -1;
931

    
932
      mScrollSpeed=0;
933
      for(int i=0; i<SAMPLE_SIZE; i++) mScrollSpeed +=sample[i];
934
      mScrollSpeed/=SAMPLE_SIZE;
935
      }
936
    else if( state==SokobanCanvas.STATE_PLAY )
937
      {
938
      movePlayer(dx,dy);
939
      }
940
    else if( state==SokobanCanvas.STATE_CRES )
941
      {
942
      movePlayerCreated(dx,dy);
943
      }
944
    else if( state==SokobanCanvas.STATE_CREA )
945
      {
946
      movePlayerFreely(dx,dy);
947
      }
948
    }
949

    
950
///////////////////////////////////////////////////////////////////////////////////////////////////
951

    
952
  public void drag(int state,int x,int y)
953
    {
954
    if( y<mGap/2 || y>scrHeight-mGap/2 ) { clickedLevel=-1; return; }
955

    
956
    int dx = cX-x;
957
    int dy = cY-y;
958

    
959
    if( state==SokobanCanvas.STATE_MAIN || state==SokobanCanvas.STATE_SUCD )
960
      {
961
      int nDrag = mVertical ? y:x;
962
 
963
      if( mSpringing==false ) mScrollSpeed = amountDrag-nDrag;
964
      amountDrag = nDrag;
965
      
966
      scroll();
967

    
968
      if( samplePtr<0 )
969
        {
970
        samplePtr=0;
971
        for(int i=0; i<SAMPLE_SIZE; i++) sample[i] = mScrollSpeed;
972
        }
973
      else
974
        {
975
        samplePtr++;
976
        if( samplePtr>=SAMPLE_SIZE ) samplePtr=0;
977
        sample[samplePtr] = mScrollSpeed;
978
        }
979

    
980
      if( dx*dx+dy*dy>MIN_CLICK_DIST*MIN_CLICK_DIST)
981
        {
982
        clickedLevel= -1;
983
        }
984
      }
985
    else if( state==SokobanCanvas.STATE_PLAY )
986
      {
987
      movePlayer(dx,dy);
988
      }
989
    else if( state==SokobanCanvas.STATE_CRES )
990
      {
991
      movePlayerCreated(dx,dy);
992
      }
993
    else if( state==SokobanCanvas.STATE_CREA )
994
      {
995
      movePlayerFreely(dx,dy);
996
      }
997
    }
998

    
999
///////////////////////////////////////////////////////////////////////////////////////////////////
1000

    
1001
  public void setSubmitted(int lvl)
1002
    {
1003
    SokobanLevel sl;
1004

    
1005
    if( lvl>=0 )
1006
      {
1007
      sl = getLevel(lvl);
1008
      if( sl!=null ) sl.setSubmitted(true);
1009
      }
1010
    else
1011
      {
1012
      for(int i=0; ; i++)
1013
        {
1014
        sl = getLevel(i);
1015
        if( sl==null ) break;
1016
        sl.setSubmitted(true);
1017
        }
1018
      }
1019
    }
1020

    
1021
///////////////////////////////////////////////////////////////////////////////////////////////////
1022

    
1023
  public SokobanLevel getCreated()
1024
    {
1025
    return created;
1026
    }
1027

    
1028
///////////////////////////////////////////////////////////////////////////////////////////////////
1029

    
1030
  public void fillLevelInfo(int lvl, int moves, int time, int place, String name, String country)
1031
    {
1032
    SokobanLevel sl = getLevel(lvl);
1033
    if( sl!=null )
1034
      {
1035
      if( place==0 )
1036
        {
1037
        SokobanRecordInfo wr = sl.getRecordInfo(0);
1038
 
1039
        if( wr==null ) sl.setDirty();
1040
        else
1041
          {
1042
          int wm = wr.getMove();
1043
          if( moves<wm || (moves==wm && time<wr.getTime()) ) sl.setDirty();
1044
          }
1045
        }
1046
 
1047
      sl.addRecordInfo(moves,time,place,name,country);
1048
      }
1049
    }
1050

    
1051
///////////////////////////////////////////////////////////////////////////////////////////////////
1052

    
1053
  public void keyboardMovePlayer(int state, int dir)
1054
    {
1055
    int dx=0,dy=0;    
1056
      
1057
    switch(dir)    
1058
      {
1059
      case 1: canMove=true; dy= PLAY_MIN_DIST; break;
1060
      case 2: canMove=true; dx=-PLAY_MIN_DIST; break;
1061
      case 3: canMove=true; dy=-PLAY_MIN_DIST; break;
1062
      case 4: canMove=true; dx= PLAY_MIN_DIST; break;
1063
      default: return;   
1064
      }
1065
        
1066
    if( state==SokobanCanvas.STATE_PLAY )
1067
      {
1068
      movePlayer(dx,dy);
1069
      }
1070
    else if( state==SokobanCanvas.STATE_CRES )
1071
      {
1072
      movePlayerCreated(dx,dy);
1073
      }
1074
    else if( state==SokobanCanvas.STATE_CREA )
1075
      {
1076
      movePlayerFreely(dx,dy);
1077
      }    
1078
    }
1079
    
1080
///////////////////////////////////////////////////////////////////////////////////////////////////
1081

    
1082
  private void movePlayerFreely(int dx, int dy)
1083
    {
1084
    if( !canMove || dx*dx+dy*dy<PLAY_MIN_DIST*PLAY_MIN_DIST) return;
1085

    
1086
    canMove = false;
1087
    created.movePlayerFreely(dx,dy);
1088
    }
1089

    
1090
///////////////////////////////////////////////////////////////////////////////////////////////////
1091

    
1092
  private void movePlayerCreated(int dx, int dy)
1093
    {
1094
    if( !canMove || dx*dx+dy*dy<PLAY_MIN_DIST*PLAY_MIN_DIST) return;
1095

    
1096
    canMove = false;
1097

    
1098
    if( created.movePlayer(dx,dy) && created.isSolved() )
1099
      {
1100
      SokobanCanvas.setState(SokobanCanvas.STATE_SUBC);
1101
      }
1102
    }
1103

    
1104
///////////////////////////////////////////////////////////////////////////////////////////////////
1105

    
1106
  private void movePlayer(int dx, int dy)
1107
    {
1108
    if( !canMove || dx*dx+dy*dy<PLAY_MIN_DIST*PLAY_MIN_DIST) return;
1109

    
1110
    canMove = false;
1111
    SokobanLevel sl;
1112

    
1113
    try
1114
      {
1115
      sl = (SokobanLevel)mLevels.elementAt(currLevel);
1116
      }
1117
    catch( ArrayIndexOutOfBoundsException aiofb )
1118
      {
1119
      System.out.println("movePlayer: level out of bounds??");
1120
      return;
1121
      }
1122

    
1123
    if( sl.movePlayer(dx,dy) )
1124
      {
1125
      currMoves++;
1126

    
1127
      if( currMoves%100==0 ) SokobanCanvas.getMenu().updatePlayState();
1128

    
1129
      if( timerRunning==false ) startTimer(0);
1130

    
1131
      if( sl.isSolved() )
1132
        {
1133
        currTime = stopTimer()/10;
1134
        int m = sl.getMyMoves();
1135

    
1136
        if( currMoves < m || (currMoves==m && currTime<sl.getMyTime() ) )
1137
          {
1138
          SokobanDatabase db = SokobanDatabase.getInstance();
1139
          sl.setMyInfo(currMoves,currTime,db.getName(),db.getCountry());
1140
          sl.setDirty();
1141
          SokobanLevelBuffer.invalidateAllR();
1142
          SokobanCanvas.setState(SokobanCanvas.STATE_NEWR);
1143
          }
1144
        else
1145
          SokobanCanvas.setState(SokobanCanvas.STATE_TIME);
1146
        }
1147
      }
1148
    }
1149

    
1150
///////////////////////////////////////////////////////////////////////////////////////////////////
1151
// end of SokobanLevels class
1152
  }
(6-6/12)