Project

General

Profile

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

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

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 3b12e641 Leszek Koltunski
75 9c2f0c91 Leszek Koltunski
  TwistyObject mObject;
76 e8764a49 Leszek Koltunski
  Effect[] mNodeEffects;
77
  int[] mNodeEffectPosition;
78
  Effect[] mCubeEffects;
79
  int[] mCubeEffectPosition;
80
  int mCubeEffectNumber, mNodeEffectNumber;
81 bbc6471c Leszek Koltunski
  int mNumScrambles;
82 5043d5d0 Leszek Koltunski
  int[][] mScrambles;
83 3b12e641 Leszek Koltunski
84
///////////////////////////////////////////////////////////////////////////////////////////////////
85
86
  ScrambleEffect()
87
    {
88 e8764a49 Leszek Koltunski
    mRnd = new Random( System.currentTimeMillis() );
89 5043d5d0 Leszek Koltunski
    mScrambles = new int[ObjectList.MAX_LEVEL][3];
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
    mNumDoubleScramblesLeft=0;
111
112 5043d5d0 Leszek Koltunski
    for(int scramble=0; scramble<mNumScramblesLeft; scramble++)
113 e8764a49 Leszek Koltunski
      {
114 5043d5d0 Leszek Koltunski
      mObject.randomizeNewScramble(mScrambles, mRnd, scramble);
115
      int angle = mScrambles[scramble][2];
116
      if( angle==2 || angle==-2 ) mNumDoubleScramblesLeft++;
117 e8764a49 Leszek Koltunski
      }
118
119
    mDurationSingleTurn = duration/(mNumScramblesLeft+mNumDoubleScramblesLeft);
120 bbc6471c Leszek Koltunski
    mNumScrambles = 0;
121 e8764a49 Leszek Koltunski
122
    addNewScramble();
123 a62aa9d7 Leszek Koltunski
    }
124 3b12e641 Leszek Koltunski
125 a62aa9d7 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
126 7c969a6d Leszek Koltunski
// only works if basicAngle<=5
127 3b12e641 Leszek Koltunski
128 e8764a49 Leszek Koltunski
  private void addNewScramble()
129 a62aa9d7 Leszek Koltunski
    {
130 e8764a49 Leszek Koltunski
    if( mNumScramblesLeft>0 )
131
      {
132 5043d5d0 Leszek Koltunski
      int axis = mScrambles[mNumScrambles][0];
133
      int row  = mScrambles[mNumScrambles][1];
134
      int angle= mScrambles[mNumScrambles][2];
135 5cf34c5f Leszek Koltunski
136 5043d5d0 Leszek Koltunski
      int rowBitmap  = (1<<row);
137 e8764a49 Leszek Koltunski
      int absAngle = (angle<0 ? -angle : angle);
138 5cf34c5f Leszek Koltunski
      long durationMillis = absAngle*mDurationSingleTurn;
139 e8764a49 Leszek Koltunski
140
      mNumScramblesLeft--;
141
      if( absAngle==2 ) mNumDoubleScramblesLeft--;
142 3b12e641 Leszek Koltunski
143 2ecf0c21 Leszek Koltunski
      if( mNumScramblesLeft==0 && mNumDoubleScramblesLeft!=0 )
144
        {
145
        android.util.Log.e("effect", "ERROR: "+mNumDoubleScramblesLeft);
146
        }
147
148 5043d5d0 Leszek Koltunski
      mController.addRotation(this, axis, rowBitmap, angle*(360/mBasicAngle), durationMillis);
149
150
      mNumScrambles++;
151 e8764a49 Leszek Koltunski
      }
152
    else
153
      {
154 035fe333 Leszek Koltunski
      if( mEffectReturned == mCubeEffectNumber+mNodeEffectNumber )
155
        {
156 af88bf2e Leszek Koltunski
        mController.effectFinished(FAKE_EFFECT_ID);
157 035fe333 Leszek Koltunski
        }
158 e8764a49 Leszek Koltunski
      }
159
    }
160
161 47ba5ddc Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
162
163
  private void assignEffects()
164
    {
165
    for(int i=0; i<mCubeEffectNumber; i++)
166
      {
167 27a70eae Leszek Koltunski
      mObject.apply(mCubeEffects[i],mCubeEffectPosition[i]);
168 47ba5ddc Leszek Koltunski
      mCubeEffects[i].notifyWhenFinished(this);
169
      }
170
171 27a70eae Leszek Koltunski
    DistortedEffects nodeEffects = mObject.getEffects();
172 47ba5ddc Leszek Koltunski
173
    for(int i=0; i<mNodeEffectNumber; i++)
174
      {
175
      nodeEffects.apply(mNodeEffects[i],mNodeEffectPosition[i]);
176
      mNodeEffects[i].notifyWhenFinished(this);
177
      }
178
    }
179
180
///////////////////////////////////////////////////////////////////////////////////////////////////
181
182
  private void disassignEffects()
183
    {
184
    for(int i=0; i<mCubeEffectNumber; i++)
185
      {
186 27a70eae Leszek Koltunski
      mObject.remove(mCubeEffects[i].getID());
187 47ba5ddc Leszek Koltunski
      }
188
189 27a70eae Leszek Koltunski
    DistortedEffects nodeEffects = mObject.getEffects();
190 47ba5ddc Leszek Koltunski
191
    for(int i=0; i<mNodeEffectNumber; i++)
192
      {
193
      nodeEffects.abortById(mNodeEffects[i].getID());
194
      }
195
    }
196
197
///////////////////////////////////////////////////////////////////////////////////////////////////
198
// PUBLIC API
199
///////////////////////////////////////////////////////////////////////////////////////////////////
200
201
  @SuppressWarnings("unused")
202
  public static String[] getNames()
203
    {
204
    String[] names = new String[NUM_EFFECTS];
205
206
    for( int i=0; i<NUM_EFFECTS; i++)
207
      {
208
      names[i] = types[i].name();
209
      }
210
211
    return names;
212
    }
213
214
///////////////////////////////////////////////////////////////////////////////////////////////////
215
216
  @SuppressWarnings("unused")
217
  public static ScrambleEffect create(int ordinal) throws InstantiationException, IllegalAccessException
218
    {
219
    return types[ordinal].effect.newInstance();
220
    }
221
222 3b12e641 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
223
224 8becce57 Leszek Koltunski
  public void onActionFinished(final long effectID)
225 3b12e641 Leszek Koltunski
    {
226 8becce57 Leszek Koltunski
    addNewScramble();
227
    }
228 e8764a49 Leszek Koltunski
229 8becce57 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
230
231
  public void effectFinished(final long effectID)
232
    {
233 e8764a49 Leszek Koltunski
    for(int i=0; i<mCubeEffectNumber; i++)
234 3b12e641 Leszek Koltunski
      {
235 e8764a49 Leszek Koltunski
      long id = mCubeEffects[i].getID();
236
237
      if( effectID == id )
238 a62aa9d7 Leszek Koltunski
        {
239 e8764a49 Leszek Koltunski
        mEffectReturned++;
240
        effectFinishedPlugin(effectID);
241 a62aa9d7 Leszek Koltunski
242 e8764a49 Leszek Koltunski
        if( mEffectReturned == mCubeEffectNumber+mNodeEffectNumber )
243 a62aa9d7 Leszek Koltunski
          {
244 e8764a49 Leszek Koltunski
          disassignEffects();
245 035fe333 Leszek Koltunski
246
          if( mNumScramblesLeft==0 )
247
            {
248 af88bf2e Leszek Koltunski
            mController.effectFinished(FAKE_EFFECT_ID);
249 035fe333 Leszek Koltunski
            }
250 e8764a49 Leszek Koltunski
          }
251 a62aa9d7 Leszek Koltunski
252 e8764a49 Leszek Koltunski
        return;
253
        }
254
      }
255 a62aa9d7 Leszek Koltunski
256 e8764a49 Leszek Koltunski
    for(int i=0; i<mNodeEffectNumber; i++)
257
      {
258
      long id = mNodeEffects[i].getID();
259 a62aa9d7 Leszek Koltunski
260 e8764a49 Leszek Koltunski
      if( effectID == id )
261 a62aa9d7 Leszek Koltunski
        {
262 e8764a49 Leszek Koltunski
        mEffectReturned++;
263
        effectFinishedPlugin(effectID);
264 a62aa9d7 Leszek Koltunski
265 e8764a49 Leszek Koltunski
        if( mEffectReturned == mCubeEffectNumber+mNodeEffectNumber )
266 a62aa9d7 Leszek Koltunski
          {
267 e8764a49 Leszek Koltunski
          disassignEffects();
268 035fe333 Leszek Koltunski
269
          if( mNumScramblesLeft==0 )
270
            {
271 af88bf2e Leszek Koltunski
            mController.effectFinished(FAKE_EFFECT_ID);
272 035fe333 Leszek Koltunski
            }
273 a62aa9d7 Leszek Koltunski
          }
274 e8764a49 Leszek Koltunski
275
        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
}