Project

General

Profile

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

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

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 af88bf2e Leszek Koltunski
import org.distorted.effects.EffectController;
29 5043d5d0 Leszek Koltunski
import org.distorted.objects.ObjectList;
30 9c2f0c91 Leszek Koltunski
import org.distorted.objects.TwistyObject;
31 3b12e641 Leszek Koltunski
32
import java.lang.reflect.Method;
33 e8764a49 Leszek Koltunski
import java.util.Random;
34 3b12e641 Leszek Koltunski
35
///////////////////////////////////////////////////////////////////////////////////////////////////
36
37 5a4d4fba Leszek Koltunski
public abstract class ScrambleEffect extends BaseEffect implements EffectListener, RubikPreRender.ActionFinishedListener
38 3b12e641 Leszek Koltunski
{
39
  public enum Type
40
    {
41
    NONE         (ScrambleEffectNone.class        ),
42 a62aa9d7 Leszek Koltunski
    ROTATIONS    (ScrambleEffectRotations.class   ),
43 3b12e641 Leszek Koltunski
    ;
44
45
    final Class<? extends ScrambleEffect> effect;
46
47
    Type(Class<? extends ScrambleEffect> effect)
48
      {
49
      this.effect= effect;
50
      }
51
    }
52
53 bbc6471c Leszek Koltunski
  private static final int NUM_EFFECTS = Type.values().length;
54 3b12e641 Leszek Koltunski
  private static final int FAKE_EFFECT_ID  = -3;
55
  private static final Type[] types;
56
57
  static
58
    {
59
    int i=0;
60
    types = new Type[NUM_EFFECTS];
61
62
    for(Type type: Type.values())
63
      {
64
      types[i++] = type;
65
      }
66
    }
67
68 af88bf2e Leszek Koltunski
  private EffectController mController;
69 e8764a49 Leszek Koltunski
  private int mEffectReturned;
70
  private int mNumDoubleScramblesLeft, mNumScramblesLeft;
71
  private long mDurationSingleTurn;
72 bbc6471c Leszek Koltunski
  private final Random mRnd;
73 e844c116 Leszek Koltunski
  private int mBasicAngle;
74 20dea800 Leszek Koltunski
  private boolean mRotReady, mPluginReady;
75 3b12e641 Leszek Koltunski
76 9c2f0c91 Leszek Koltunski
  TwistyObject mObject;
77 e8764a49 Leszek Koltunski
  Effect[] mNodeEffects;
78
  int[] mNodeEffectPosition;
79
  Effect[] mCubeEffects;
80
  int[] mCubeEffectPosition;
81
  int mCubeEffectNumber, mNodeEffectNumber;
82 bbc6471c Leszek Koltunski
  int mNumScrambles;
83 5043d5d0 Leszek Koltunski
  int[][] mScrambles;
84 3b12e641 Leszek Koltunski
85
///////////////////////////////////////////////////////////////////////////////////////////////////
86
87
  ScrambleEffect()
88
    {
89 e8764a49 Leszek Koltunski
    mRnd = new Random( System.currentTimeMillis() );
90 5043d5d0 Leszek Koltunski
    mScrambles = new int[ObjectList.MAX_LEVEL][3];
91 3b12e641 Leszek Koltunski
    }
92
93
///////////////////////////////////////////////////////////////////////////////////////////////////
94
95 e4db5995 Leszek Koltunski
  abstract void createEffects(int duration, int numScrambles);
96 a62aa9d7 Leszek Koltunski
  abstract void effectFinishedPlugin(final long effectID);
97 3b12e641 Leszek Koltunski
98
///////////////////////////////////////////////////////////////////////////////////////////////////
99 47ba5ddc Leszek Koltunski
// first compute how many out of 'numScrambles' are double turns (this will matter when we compute
100
// the time a single quarter-turn takes!
101 e844c116 Leszek Koltunski
//
102
// Only works for
103 7c969a6d Leszek Koltunski
// basicAngle==5, i.e. something whose rotations are by  72 degrees (Megaminx) or
104 769d7b9f Leszek Koltunski
// basicAngle==4, i.e. something whose rotations are by  90 degrees (RubikCube) or
105 7c969a6d Leszek Koltunski
// basicAngle==3, i.e. something whose rotations are by 120 degrees (Pyramix) or
106 769d7b9f Leszek Koltunski
// basicAngle==2, i.e. something whose rotations are by 180 degrees (e.g. a 3x2x1 'Bunny')
107 e8764a49 Leszek Koltunski
108 a62aa9d7 Leszek Koltunski
  private void createBaseEffects(int duration, int numScrambles)
109 3b12e641 Leszek Koltunski
    {
110 e8764a49 Leszek Koltunski
    mNumScramblesLeft = numScrambles;
111
    mNumDoubleScramblesLeft=0;
112
113 5043d5d0 Leszek Koltunski
    for(int scramble=0; scramble<mNumScramblesLeft; scramble++)
114 e8764a49 Leszek Koltunski
      {
115 5043d5d0 Leszek Koltunski
      mObject.randomizeNewScramble(mScrambles, mRnd, scramble);
116
      int angle = mScrambles[scramble][2];
117
      if( angle==2 || angle==-2 ) mNumDoubleScramblesLeft++;
118 e8764a49 Leszek Koltunski
      }
119
120
    mDurationSingleTurn = duration/(mNumScramblesLeft+mNumDoubleScramblesLeft);
121 bbc6471c Leszek Koltunski
    mNumScrambles = 0;
122 e8764a49 Leszek Koltunski
123 20dea800 Leszek Koltunski
    mRotReady    = false;
124
    mPluginReady = false;
125
126 e8764a49 Leszek Koltunski
    addNewScramble();
127 a62aa9d7 Leszek Koltunski
    }
128 3b12e641 Leszek Koltunski
129 a62aa9d7 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
130 7c969a6d Leszek Koltunski
// only works if basicAngle<=5
131 3b12e641 Leszek Koltunski
132 e8764a49 Leszek Koltunski
  private void addNewScramble()
133 a62aa9d7 Leszek Koltunski
    {
134 e8764a49 Leszek Koltunski
    if( mNumScramblesLeft>0 )
135
      {
136 5043d5d0 Leszek Koltunski
      int axis = mScrambles[mNumScrambles][0];
137
      int row  = mScrambles[mNumScrambles][1];
138
      int angle= mScrambles[mNumScrambles][2];
139 5cf34c5f Leszek Koltunski
140 5043d5d0 Leszek Koltunski
      int rowBitmap  = (1<<row);
141 e8764a49 Leszek Koltunski
      int absAngle = (angle<0 ? -angle : angle);
142 5cf34c5f Leszek Koltunski
      long durationMillis = absAngle*mDurationSingleTurn;
143 e8764a49 Leszek Koltunski
144
      mNumScramblesLeft--;
145
      if( absAngle==2 ) mNumDoubleScramblesLeft--;
146 3b12e641 Leszek Koltunski
147 2ecf0c21 Leszek Koltunski
      if( mNumScramblesLeft==0 && mNumDoubleScramblesLeft!=0 )
148
        {
149
        android.util.Log.e("effect", "ERROR: "+mNumDoubleScramblesLeft);
150
        }
151
152 5043d5d0 Leszek Koltunski
      mController.addRotation(this, axis, rowBitmap, angle*(360/mBasicAngle), durationMillis);
153
154
      mNumScrambles++;
155 e8764a49 Leszek Koltunski
      }
156
    else
157
      {
158 035fe333 Leszek Koltunski
      if( mEffectReturned == mCubeEffectNumber+mNodeEffectNumber )
159
        {
160 20dea800 Leszek Koltunski
        mRotReady = true;
161
        if( mPluginReady ) mController.effectFinished(FAKE_EFFECT_ID);
162 035fe333 Leszek Koltunski
        }
163 e8764a49 Leszek Koltunski
      }
164
    }
165
166 47ba5ddc Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
167
168
  private void assignEffects()
169
    {
170
    for(int i=0; i<mCubeEffectNumber; i++)
171
      {
172 27a70eae Leszek Koltunski
      mObject.apply(mCubeEffects[i],mCubeEffectPosition[i]);
173 47ba5ddc Leszek Koltunski
      mCubeEffects[i].notifyWhenFinished(this);
174
      }
175
176 27a70eae Leszek Koltunski
    DistortedEffects nodeEffects = mObject.getEffects();
177 47ba5ddc Leszek Koltunski
178
    for(int i=0; i<mNodeEffectNumber; i++)
179
      {
180
      nodeEffects.apply(mNodeEffects[i],mNodeEffectPosition[i]);
181
      mNodeEffects[i].notifyWhenFinished(this);
182
      }
183
    }
184
185
///////////////////////////////////////////////////////////////////////////////////////////////////
186
187
  private void disassignEffects()
188
    {
189
    for(int i=0; i<mCubeEffectNumber; i++)
190
      {
191 27a70eae Leszek Koltunski
      mObject.remove(mCubeEffects[i].getID());
192 47ba5ddc Leszek Koltunski
      }
193
194 27a70eae Leszek Koltunski
    DistortedEffects nodeEffects = mObject.getEffects();
195 47ba5ddc Leszek Koltunski
196
    for(int i=0; i<mNodeEffectNumber; i++)
197
      {
198
      nodeEffects.abortById(mNodeEffects[i].getID());
199
      }
200
    }
201
202
///////////////////////////////////////////////////////////////////////////////////////////////////
203
// PUBLIC API
204
///////////////////////////////////////////////////////////////////////////////////////////////////
205
206
  @SuppressWarnings("unused")
207
  public static String[] getNames()
208
    {
209
    String[] names = new String[NUM_EFFECTS];
210
211
    for( int i=0; i<NUM_EFFECTS; i++)
212
      {
213
      names[i] = types[i].name();
214
      }
215
216
    return names;
217
    }
218
219
///////////////////////////////////////////////////////////////////////////////////////////////////
220
221
  @SuppressWarnings("unused")
222
  public static ScrambleEffect create(int ordinal) throws InstantiationException, IllegalAccessException
223
    {
224
    return types[ordinal].effect.newInstance();
225
    }
226
227 3b12e641 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
228
229 8becce57 Leszek Koltunski
  public void onActionFinished(final long effectID)
230 3b12e641 Leszek Koltunski
    {
231 8becce57 Leszek Koltunski
    addNewScramble();
232
    }
233 e8764a49 Leszek Koltunski
234 20dea800 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
235
236
  private void effectFinishedAction(final long effectID, final long id)
237
    {
238
    mEffectReturned++;
239
    effectFinishedPlugin(effectID);
240
241
    if( mEffectReturned == mCubeEffectNumber+mNodeEffectNumber )
242
      {
243
      disassignEffects();
244
245
      if( mNumScramblesLeft==0 )
246
        {
247
        mPluginReady = true;
248
        if( mRotReady ) mController.effectFinished(FAKE_EFFECT_ID);
249
        }
250
      }
251
    }
252
253 8becce57 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
254
255
  public void effectFinished(final long effectID)
256
    {
257 e8764a49 Leszek Koltunski
    for(int i=0; i<mCubeEffectNumber; i++)
258 3b12e641 Leszek Koltunski
      {
259 e8764a49 Leszek Koltunski
      long id = mCubeEffects[i].getID();
260
261
      if( effectID == id )
262 a62aa9d7 Leszek Koltunski
        {
263 20dea800 Leszek Koltunski
        effectFinishedAction(effectID,id);
264 e8764a49 Leszek Koltunski
        return;
265
        }
266
      }
267 a62aa9d7 Leszek Koltunski
268 e8764a49 Leszek Koltunski
    for(int i=0; i<mNodeEffectNumber; i++)
269
      {
270
      long id = mNodeEffects[i].getID();
271 a62aa9d7 Leszek Koltunski
272 e8764a49 Leszek Koltunski
      if( effectID == id )
273 a62aa9d7 Leszek Koltunski
        {
274 20dea800 Leszek Koltunski
        effectFinishedAction(effectID,id);
275 e8764a49 Leszek Koltunski
        return;
276 a62aa9d7 Leszek Koltunski
        }
277 3b12e641 Leszek Koltunski
      }
278
    }
279
280
///////////////////////////////////////////////////////////////////////////////////////////////////
281
282 47ba5ddc Leszek Koltunski
  @SuppressWarnings("unused")
283 af88bf2e Leszek Koltunski
  public long start(int duration, DistortedScreen screen, EffectController cont)
284 3b12e641 Leszek Koltunski
    {
285 af88bf2e Leszek Koltunski
    mObject    = cont.getObject();
286
    mController= cont;
287 a62aa9d7 Leszek Koltunski
288 27a70eae Leszek Koltunski
    mObject.solve();
289 beb325a0 Leszek Koltunski
290 e844c116 Leszek Koltunski
    mBasicAngle = mObject.getBasicAngle();
291
292 af88bf2e Leszek Koltunski
    int numScrambles = cont.getNumScrambles();
293 e4db5995 Leszek Koltunski
    int dura = (int)(duration*Math.pow(numScrambles,0.6f));
294
    createBaseEffects(dura,numScrambles);
295
    createEffects    (dura,numScrambles);
296 a62aa9d7 Leszek Koltunski
297 e8764a49 Leszek Koltunski
    if( mCubeEffectNumber==0 && mNodeEffectNumber==0 )
298 a62aa9d7 Leszek Koltunski
      {
299
      throw new RuntimeException("Cube and Node Plugin Effects not created!");
300
      }
301
302 e8764a49 Leszek Koltunski
    assignEffects();
303 3b12e641 Leszek Koltunski
304
    return FAKE_EFFECT_ID;
305
    }
306
307
///////////////////////////////////////////////////////////////////////////////////////////////////
308
309
  @SuppressWarnings("unused")
310
  public static void enableEffects()
311
    {
312
    Method method;
313
314
    for(Type type: Type.values())
315
      {
316
      try
317
        {
318
        method = type.effect.getDeclaredMethod("enable"); // enable not public, thus getDeclaredMethod
319
        }
320
      catch(NoSuchMethodException ex)
321
        {
322
        android.util.Log.e("ScrambleEffect", type.effect.getSimpleName()+": exception getting method: "+ex.getMessage());
323
        method = null;
324
        }
325
326
      try
327
        {
328
        if( method!=null ) method.invoke(null);
329
        }
330
      catch(Exception ex)
331
        {
332
        android.util.Log.e("ScrambleEffect", type.effect.getSimpleName()+": exception invoking method: "+ex.getMessage());
333
        }
334
      }
335
    }
336
}