Project

General

Profile

Download (10.9 KB) Statistics
| Branch: | Tag: | Revision:

magiccube / src / main / java / org / distorted / effects / scramble / ScrambleEffect.java @ ac722a43

1 3b12e641 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2019 Leszek Koltunski                                                               //
3
//                                                                                               //
4 fdec60a3 Leszek Koltunski
// This file is part of Magic Cube.                                                              //
5 3b12e641 Leszek Koltunski
//                                                                                               //
6 fdec60a3 Leszek Koltunski
// Magic Cube is free software: you can redistribute it and/or modify                            //
7 3b12e641 Leszek Koltunski
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11 fdec60a3 Leszek Koltunski
// Magic Cube is distributed in the hope that it will be useful,                                 //
12 3b12e641 Leszek Koltunski
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17 fdec60a3 Leszek Koltunski
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18 3b12e641 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
19
20 1f9772f3 Leszek Koltunski
package org.distorted.effects.scramble;
21 3b12e641 Leszek Koltunski
22 1f9772f3 Leszek Koltunski
import org.distorted.effects.BaseEffect;
23 3b12e641 Leszek Koltunski
import org.distorted.library.effect.Effect;
24
import org.distorted.library.main.DistortedEffects;
25 8becce57 Leszek Koltunski
import org.distorted.library.main.DistortedScreen;
26 3b12e641 Leszek Koltunski
import org.distorted.library.message.EffectListener;
27 5a4d4fba Leszek Koltunski
import org.distorted.main.RubikPreRender;
28 9c2f0c91 Leszek Koltunski
import org.distorted.objects.TwistyObject;
29 3b12e641 Leszek Koltunski
30
import java.lang.reflect.Method;
31 e8764a49 Leszek Koltunski
import java.util.Random;
32 3b12e641 Leszek Koltunski
33
///////////////////////////////////////////////////////////////////////////////////////////////////
34
35 5a4d4fba Leszek Koltunski
public abstract class ScrambleEffect extends BaseEffect implements EffectListener, RubikPreRender.ActionFinishedListener
36 3b12e641 Leszek Koltunski
{
37
  public enum Type
38
    {
39
    NONE         (ScrambleEffectNone.class        ),
40 a62aa9d7 Leszek Koltunski
    ROTATIONS    (ScrambleEffectRotations.class   ),
41 3b12e641 Leszek Koltunski
    ;
42
43
    final Class<? extends ScrambleEffect> effect;
44
45
    Type(Class<? extends ScrambleEffect> effect)
46
      {
47
      this.effect= effect;
48
      }
49
    }
50
51
  private static int NUM_EFFECTS = Type.values().length;
52
  private static final int FAKE_EFFECT_ID  = -3;
53
  private static final Type[] types;
54
55
  static
56
    {
57
    int i=0;
58
    types = new Type[NUM_EFFECTS];
59
60
    for(Type type: Type.values())
61
      {
62
      types[i++] = type;
63
      }
64
    }
65
66 7c969a6d Leszek Koltunski
  public static final int START_AXIS = -2;
67
  public static final int STOP_AXIS  = -1;
68
69 5a4d4fba Leszek Koltunski
  private RubikPreRender mPreRender;
70 e8764a49 Leszek Koltunski
  private int mEffectReturned;
71
  private int mNumDoubleScramblesLeft, mNumScramblesLeft;
72 7c969a6d Leszek Koltunski
  private int mLastRotAxis, mLastRow;
73 e8764a49 Leszek Koltunski
  private long mDurationSingleTurn;
74
  private Random mRnd;
75 e844c116 Leszek Koltunski
  private int mBasicAngle;
76 3b12e641 Leszek Koltunski
77 9c2f0c91 Leszek Koltunski
  TwistyObject mObject;
78 e8764a49 Leszek Koltunski
  Effect[] mNodeEffects;
79
  int[] mNodeEffectPosition;
80
  Effect[] mCubeEffects;
81
  int[] mCubeEffectPosition;
82
  int mCubeEffectNumber, mNodeEffectNumber;
83 3b12e641 Leszek Koltunski
84
///////////////////////////////////////////////////////////////////////////////////////////////////
85
86
  ScrambleEffect()
87
    {
88 e8764a49 Leszek Koltunski
    mRnd = new Random( System.currentTimeMillis() );
89 7c969a6d Leszek Koltunski
    mLastRotAxis = START_AXIS;
90 3b12e641 Leszek Koltunski
    }
91
92
///////////////////////////////////////////////////////////////////////////////////////////////////
93
94 e4db5995 Leszek Koltunski
  abstract void createEffects(int duration, int numScrambles);
95 a62aa9d7 Leszek Koltunski
  abstract void effectFinishedPlugin(final long effectID);
96 3b12e641 Leszek Koltunski
97
///////////////////////////////////////////////////////////////////////////////////////////////////
98 47ba5ddc Leszek Koltunski
// first compute how many out of 'numScrambles' are double turns (this will matter when we compute
99
// the time a single quarter-turn takes!
100 e844c116 Leszek Koltunski
//
101
// Only works for
102 7c969a6d Leszek Koltunski
// basicAngle==5, i.e. something whose rotations are by  72 degrees (Megaminx) or
103 769d7b9f Leszek Koltunski
// basicAngle==4, i.e. something whose rotations are by  90 degrees (RubikCube) or
104 7c969a6d Leszek Koltunski
// basicAngle==3, i.e. something whose rotations are by 120 degrees (Pyramix) or
105 769d7b9f Leszek Koltunski
// basicAngle==2, i.e. something whose rotations are by 180 degrees (e.g. a 3x2x1 'Bunny')
106 e8764a49 Leszek Koltunski
107 a62aa9d7 Leszek Koltunski
  private void createBaseEffects(int duration, int numScrambles)
108 3b12e641 Leszek Koltunski
    {
109 e8764a49 Leszek Koltunski
    mNumScramblesLeft = numScrambles;
110
111
    mNumDoubleScramblesLeft=0;
112
113 e844c116 Leszek Koltunski
    if( mBasicAngle>=4 )
114 e8764a49 Leszek Koltunski
      {
115 7c969a6d Leszek Koltunski
      int chance = mBasicAngle==4 ? 3:2;
116
117 e844c116 Leszek Koltunski
      for(int i=0; i<numScrambles; i++)
118 e8764a49 Leszek Koltunski
        {
119 7c969a6d Leszek Koltunski
        if( (mRnd.nextInt() % chance) == 0 )
120 e844c116 Leszek Koltunski
          {
121
          mNumDoubleScramblesLeft++;
122
          }
123 e8764a49 Leszek Koltunski
        }
124
      }
125
126
    mDurationSingleTurn = duration/(mNumScramblesLeft+mNumDoubleScramblesLeft);
127
128
    addNewScramble();
129 a62aa9d7 Leszek Koltunski
    }
130 3b12e641 Leszek Koltunski
131 a62aa9d7 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
132 7c969a6d Leszek Koltunski
// only works if basicAngle<=5
133 3b12e641 Leszek Koltunski
134 e8764a49 Leszek Koltunski
  private void addNewScramble()
135 a62aa9d7 Leszek Koltunski
    {
136 e8764a49 Leszek Koltunski
    if( mNumScramblesLeft>0 )
137
      {
138 7c969a6d Leszek Koltunski
      int lastRotAxis = mLastRotAxis;
139
      mLastRotAxis = mObject.randomizeNewRotAxis(mRnd,mLastRotAxis);
140
      mLastRow = mObject.randomizeNewRow(mRnd,lastRotAxis,mLastRow,mLastRotAxis);
141 5cf34c5f Leszek Koltunski
142 7c969a6d Leszek Koltunski
      int rowBitmap  = (1<<mLastRow);
143 e8764a49 Leszek Koltunski
      int angle= randomizeAngle();
144
      int absAngle = (angle<0 ? -angle : angle);
145 5cf34c5f Leszek Koltunski
      long durationMillis = absAngle*mDurationSingleTurn;
146 e8764a49 Leszek Koltunski
147
      mNumScramblesLeft--;
148
      if( absAngle==2 ) mNumDoubleScramblesLeft--;
149 3b12e641 Leszek Koltunski
150 2ecf0c21 Leszek Koltunski
      if( mNumScramblesLeft==0 && mNumDoubleScramblesLeft!=0 )
151
        {
152
        android.util.Log.e("effect", "ERROR: "+mNumDoubleScramblesLeft);
153
        }
154
155 7c969a6d Leszek Koltunski
      mPreRender.addRotation(this, mLastRotAxis, rowBitmap, angle*(360/mBasicAngle), durationMillis);
156 e8764a49 Leszek Koltunski
      }
157
    else
158
      {
159 7c969a6d Leszek Koltunski
      mLastRotAxis = STOP_AXIS;
160 035fe333 Leszek Koltunski
161
      if( mEffectReturned == mCubeEffectNumber+mNodeEffectNumber )
162
        {
163 5a4d4fba Leszek Koltunski
        mPreRender.effectFinished(FAKE_EFFECT_ID);
164 035fe333 Leszek Koltunski
        }
165 e8764a49 Leszek Koltunski
      }
166
    }
167
168
///////////////////////////////////////////////////////////////////////////////////////////////////
169 7c969a6d Leszek Koltunski
// only works for basicAngle<=5.
170 e8764a49 Leszek Koltunski
171
  private int randomizeAngle()
172
    {
173 2ecf0c21 Leszek Koltunski
    int random = mRnd.nextInt(mNumScramblesLeft);
174
    int result = random<mNumDoubleScramblesLeft ? 2:1;
175
    int sign   = mRnd.nextInt(2);
176
177
    return sign==0 ? result : -result;
178 3b12e641 Leszek Koltunski
    }
179
180 47ba5ddc Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
181
182
  private void assignEffects()
183
    {
184
    for(int i=0; i<mCubeEffectNumber; i++)
185
      {
186 27a70eae Leszek Koltunski
      mObject.apply(mCubeEffects[i],mCubeEffectPosition[i]);
187 47ba5ddc Leszek Koltunski
      mCubeEffects[i].notifyWhenFinished(this);
188
      }
189
190 27a70eae Leszek Koltunski
    DistortedEffects nodeEffects = mObject.getEffects();
191 47ba5ddc Leszek Koltunski
192
    for(int i=0; i<mNodeEffectNumber; i++)
193
      {
194
      nodeEffects.apply(mNodeEffects[i],mNodeEffectPosition[i]);
195
      mNodeEffects[i].notifyWhenFinished(this);
196
      }
197
    }
198
199
///////////////////////////////////////////////////////////////////////////////////////////////////
200
201
  private void disassignEffects()
202
    {
203
    for(int i=0; i<mCubeEffectNumber; i++)
204
      {
205 27a70eae Leszek Koltunski
      mObject.remove(mCubeEffects[i].getID());
206 47ba5ddc Leszek Koltunski
      }
207
208 27a70eae Leszek Koltunski
    DistortedEffects nodeEffects = mObject.getEffects();
209 47ba5ddc Leszek Koltunski
210
    for(int i=0; i<mNodeEffectNumber; i++)
211
      {
212
      nodeEffects.abortById(mNodeEffects[i].getID());
213
      }
214
    }
215
216
///////////////////////////////////////////////////////////////////////////////////////////////////
217
// PUBLIC API
218
///////////////////////////////////////////////////////////////////////////////////////////////////
219
220
  @SuppressWarnings("unused")
221
  public static String[] getNames()
222
    {
223
    String[] names = new String[NUM_EFFECTS];
224
225
    for( int i=0; i<NUM_EFFECTS; i++)
226
      {
227
      names[i] = types[i].name();
228
      }
229
230
    return names;
231
    }
232
233
///////////////////////////////////////////////////////////////////////////////////////////////////
234
235
  @SuppressWarnings("unused")
236
  public static ScrambleEffect create(int ordinal) throws InstantiationException, IllegalAccessException
237
    {
238
    return types[ordinal].effect.newInstance();
239
    }
240
241 3b12e641 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
242
243 8becce57 Leszek Koltunski
  public void onActionFinished(final long effectID)
244 3b12e641 Leszek Koltunski
    {
245 8becce57 Leszek Koltunski
    addNewScramble();
246
    }
247 e8764a49 Leszek Koltunski
248 8becce57 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
249
250
  public void effectFinished(final long effectID)
251
    {
252 e8764a49 Leszek Koltunski
    for(int i=0; i<mCubeEffectNumber; i++)
253 3b12e641 Leszek Koltunski
      {
254 e8764a49 Leszek Koltunski
      long id = mCubeEffects[i].getID();
255
256
      if( effectID == id )
257 a62aa9d7 Leszek Koltunski
        {
258 e8764a49 Leszek Koltunski
        mEffectReturned++;
259
        effectFinishedPlugin(effectID);
260 a62aa9d7 Leszek Koltunski
261 e8764a49 Leszek Koltunski
        if( mEffectReturned == mCubeEffectNumber+mNodeEffectNumber )
262 a62aa9d7 Leszek Koltunski
          {
263 e8764a49 Leszek Koltunski
          disassignEffects();
264 035fe333 Leszek Koltunski
265
          if( mNumScramblesLeft==0 )
266
            {
267 5a4d4fba Leszek Koltunski
            mPreRender.effectFinished(FAKE_EFFECT_ID);
268 035fe333 Leszek Koltunski
            }
269 e8764a49 Leszek Koltunski
          }
270 a62aa9d7 Leszek Koltunski
271 e8764a49 Leszek Koltunski
        return;
272
        }
273
      }
274 a62aa9d7 Leszek Koltunski
275 e8764a49 Leszek Koltunski
    for(int i=0; i<mNodeEffectNumber; i++)
276
      {
277
      long id = mNodeEffects[i].getID();
278 a62aa9d7 Leszek Koltunski
279 e8764a49 Leszek Koltunski
      if( effectID == id )
280 a62aa9d7 Leszek Koltunski
        {
281 e8764a49 Leszek Koltunski
        mEffectReturned++;
282
        effectFinishedPlugin(effectID);
283 a62aa9d7 Leszek Koltunski
284 e8764a49 Leszek Koltunski
        if( mEffectReturned == mCubeEffectNumber+mNodeEffectNumber )
285 a62aa9d7 Leszek Koltunski
          {
286 e8764a49 Leszek Koltunski
          disassignEffects();
287 035fe333 Leszek Koltunski
288
          if( mNumScramblesLeft==0 )
289
            {
290 5a4d4fba Leszek Koltunski
            mPreRender.effectFinished(FAKE_EFFECT_ID);
291 035fe333 Leszek Koltunski
            }
292 a62aa9d7 Leszek Koltunski
          }
293 e8764a49 Leszek Koltunski
294
        return;
295 a62aa9d7 Leszek Koltunski
        }
296 3b12e641 Leszek Koltunski
      }
297
    }
298
299
///////////////////////////////////////////////////////////////////////////////////////////////////
300
301 47ba5ddc Leszek Koltunski
  @SuppressWarnings("unused")
302 5a4d4fba Leszek Koltunski
  public long start(int duration, DistortedScreen screen, RubikPreRender pre)
303 3b12e641 Leszek Koltunski
    {
304 5a4d4fba Leszek Koltunski
    mObject     = pre.getObject();
305
    mPreRender  = pre;
306 a62aa9d7 Leszek Koltunski
307 27a70eae Leszek Koltunski
    mObject.solve();
308 beb325a0 Leszek Koltunski
309 e844c116 Leszek Koltunski
    mBasicAngle = mObject.getBasicAngle();
310
311 5a4d4fba Leszek Koltunski
    int numScrambles = pre.getNumScrambles();
312 e4db5995 Leszek Koltunski
    int dura = (int)(duration*Math.pow(numScrambles,0.6f));
313
    createBaseEffects(dura,numScrambles);
314
    createEffects    (dura,numScrambles);
315 a62aa9d7 Leszek Koltunski
316 e8764a49 Leszek Koltunski
    if( mCubeEffectNumber==0 && mNodeEffectNumber==0 )
317 a62aa9d7 Leszek Koltunski
      {
318
      throw new RuntimeException("Cube and Node Plugin Effects not created!");
319
      }
320
321 e8764a49 Leszek Koltunski
    assignEffects();
322 3b12e641 Leszek Koltunski
323
    return FAKE_EFFECT_ID;
324
    }
325
326
///////////////////////////////////////////////////////////////////////////////////////////////////
327
328
  @SuppressWarnings("unused")
329
  public static void enableEffects()
330
    {
331
    Method method;
332
333
    for(Type type: Type.values())
334
      {
335
      try
336
        {
337
        method = type.effect.getDeclaredMethod("enable"); // enable not public, thus getDeclaredMethod
338
        }
339
      catch(NoSuchMethodException ex)
340
        {
341
        android.util.Log.e("ScrambleEffect", type.effect.getSimpleName()+": exception getting method: "+ex.getMessage());
342
        method = null;
343
        }
344
345
      try
346
        {
347
        if( method!=null ) method.invoke(null);
348
        }
349
      catch(Exception ex)
350
        {
351
        android.util.Log.e("ScrambleEffect", type.effect.getSimpleName()+": exception invoking method: "+ex.getMessage());
352
        }
353
      }
354
    }
355
}