Project

General

Profile

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

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

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 3f7a4363 Leszek Koltunski
import java.lang.reflect.Method;
23
import java.util.Random;
24
25 3b12e641 Leszek Koltunski
import org.distorted.library.effect.Effect;
26
import org.distorted.library.main.DistortedEffects;
27 8becce57 Leszek Koltunski
import org.distorted.library.main.DistortedScreen;
28 3b12e641 Leszek Koltunski
import org.distorted.library.message.EffectListener;
29
30 318c0a7d Leszek Koltunski
import org.distorted.objectlib.main.ObjectType;
31 3f7a4363 Leszek Koltunski
import org.distorted.objectlib.main.TwistyObject;
32
33
import org.distorted.effects.BaseEffect;
34
import org.distorted.effects.EffectController;
35 88a3e972 Leszek Koltunski
import org.distorted.objectlib.helpers.MovesFinished;
36 3b12e641 Leszek Koltunski
37
///////////////////////////////////////////////////////////////////////////////////////////////////
38
39 55e6be1d Leszek Koltunski
public abstract class ScrambleEffect extends BaseEffect implements EffectListener, MovesFinished
40 3b12e641 Leszek Koltunski
{
41
  public enum Type
42
    {
43
    NONE         (ScrambleEffectNone.class        ),
44 a62aa9d7 Leszek Koltunski
    ROTATIONS    (ScrambleEffectRotations.class   ),
45 3b12e641 Leszek Koltunski
    ;
46
47
    final Class<? extends ScrambleEffect> effect;
48
49
    Type(Class<? extends ScrambleEffect> effect)
50
      {
51
      this.effect= effect;
52
      }
53
    }
54
55 bbc6471c Leszek Koltunski
  private static final int NUM_EFFECTS = Type.values().length;
56 3b12e641 Leszek Koltunski
  private static final int FAKE_EFFECT_ID  = -3;
57
  private static final Type[] types;
58
59
  static
60
    {
61
    int i=0;
62
    types = new Type[NUM_EFFECTS];
63
64
    for(Type type: Type.values())
65
      {
66
      types[i++] = type;
67
      }
68
    }
69
70 af88bf2e Leszek Koltunski
  private EffectController mController;
71 e8764a49 Leszek Koltunski
  private int mEffectReturned;
72 542ec777 Leszek Koltunski
  private int mNumScramblesLeft;
73
  private long mDurationPerDegree;
74 bbc6471c Leszek Koltunski
  private final Random mRnd;
75 925ed78f Leszek Koltunski
  private int[] mBasicAngle;
76 20dea800 Leszek Koltunski
  private boolean mRotReady, mPluginReady;
77 3b12e641 Leszek Koltunski
78 9c2f0c91 Leszek Koltunski
  TwistyObject mObject;
79 e8764a49 Leszek Koltunski
  Effect[] mNodeEffects;
80
  int[] mNodeEffectPosition;
81
  Effect[] mCubeEffects;
82
  int[] mCubeEffectPosition;
83
  int mCubeEffectNumber, mNodeEffectNumber;
84 bbc6471c Leszek Koltunski
  int mNumScrambles;
85 5043d5d0 Leszek Koltunski
  int[][] mScrambles;
86 3b12e641 Leszek Koltunski
87
///////////////////////////////////////////////////////////////////////////////////////////////////
88
89
  ScrambleEffect()
90
    {
91 e8764a49 Leszek Koltunski
    mRnd = new Random( System.currentTimeMillis() );
92 318c0a7d Leszek Koltunski
    mScrambles = new int[ObjectType.MAX_SCRAMBLE][3];
93 3b12e641 Leszek Koltunski
    }
94
95
///////////////////////////////////////////////////////////////////////////////////////////////////
96
97 e4db5995 Leszek Koltunski
  abstract void createEffects(int duration, int numScrambles);
98 a62aa9d7 Leszek Koltunski
  abstract void effectFinishedPlugin(final long effectID);
99 3b12e641 Leszek Koltunski
100
///////////////////////////////////////////////////////////////////////////////////////////////////
101 e8764a49 Leszek Koltunski
102 a62aa9d7 Leszek Koltunski
  private void createBaseEffects(int duration, int numScrambles)
103 3b12e641 Leszek Koltunski
    {
104 e8764a49 Leszek Koltunski
    mNumScramblesLeft = numScrambles;
105 542ec777 Leszek Koltunski
    int absAngle, angle, axis, basicDegrees, totalDegrees = 0;
106 e8764a49 Leszek Koltunski
107 5043d5d0 Leszek Koltunski
    for(int scramble=0; scramble<mNumScramblesLeft; scramble++)
108 e8764a49 Leszek Koltunski
      {
109 9f171eba Leszek Koltunski
      mObject.randomizeNewScramble(mScrambles, mRnd, scramble, numScrambles);
110 542ec777 Leszek Koltunski
      axis  = mScrambles[scramble][0];
111
      angle = mScrambles[scramble][2];
112
      absAngle = (angle<0 ? -angle : angle);
113
      basicDegrees = 360/mBasicAngle[axis];
114
      totalDegrees += absAngle*basicDegrees;
115 e8764a49 Leszek Koltunski
      }
116
117 542ec777 Leszek Koltunski
    mDurationPerDegree = duration/totalDegrees;
118 bbc6471c Leszek Koltunski
    mNumScrambles = 0;
119 e8764a49 Leszek Koltunski
120 20dea800 Leszek Koltunski
    mRotReady    = false;
121
    mPluginReady = false;
122
123 e8764a49 Leszek Koltunski
    addNewScramble();
124 a62aa9d7 Leszek Koltunski
    }
125 3b12e641 Leszek Koltunski
126 a62aa9d7 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
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 542ec777 Leszek Koltunski
      int rowBitmap= (1<<row);
137 e8764a49 Leszek Koltunski
      int absAngle = (angle<0 ? -angle : angle);
138 542ec777 Leszek Koltunski
      int basicDegrees  = 360/mBasicAngle[axis];
139
      long durationMillis = absAngle*basicDegrees*mDurationPerDegree;
140 e8764a49 Leszek Koltunski
141
      mNumScramblesLeft--;
142 542ec777 Leszek Koltunski
      mController.addRotation(this, axis, rowBitmap, angle*basicDegrees, durationMillis);
143 5043d5d0 Leszek Koltunski
      mNumScrambles++;
144 e8764a49 Leszek Koltunski
      }
145
    else
146
      {
147 542ec777 Leszek Koltunski
      mRotReady = true;
148
      if( mPluginReady ) mController.effectFinished(FAKE_EFFECT_ID);
149 e8764a49 Leszek Koltunski
      }
150
    }
151
152 47ba5ddc Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
153
154
  private void assignEffects()
155
    {
156
    for(int i=0; i<mCubeEffectNumber; i++)
157
      {
158 27a70eae Leszek Koltunski
      mObject.apply(mCubeEffects[i],mCubeEffectPosition[i]);
159 47ba5ddc Leszek Koltunski
      mCubeEffects[i].notifyWhenFinished(this);
160
      }
161
162 27a70eae Leszek Koltunski
    DistortedEffects nodeEffects = mObject.getEffects();
163 47ba5ddc Leszek Koltunski
164
    for(int i=0; i<mNodeEffectNumber; i++)
165
      {
166
      nodeEffects.apply(mNodeEffects[i],mNodeEffectPosition[i]);
167
      mNodeEffects[i].notifyWhenFinished(this);
168
      }
169
    }
170
171
///////////////////////////////////////////////////////////////////////////////////////////////////
172
173
  private void disassignEffects()
174
    {
175
    for(int i=0; i<mCubeEffectNumber; i++)
176
      {
177 27a70eae Leszek Koltunski
      mObject.remove(mCubeEffects[i].getID());
178 47ba5ddc Leszek Koltunski
      }
179
180 27a70eae Leszek Koltunski
    DistortedEffects nodeEffects = mObject.getEffects();
181 47ba5ddc Leszek Koltunski
182
    for(int i=0; i<mNodeEffectNumber; i++)
183
      {
184
      nodeEffects.abortById(mNodeEffects[i].getID());
185
      }
186
    }
187
188
///////////////////////////////////////////////////////////////////////////////////////////////////
189
// PUBLIC API
190
///////////////////////////////////////////////////////////////////////////////////////////////////
191
192
  @SuppressWarnings("unused")
193
  public static String[] getNames()
194
    {
195
    String[] names = new String[NUM_EFFECTS];
196
197
    for( int i=0; i<NUM_EFFECTS; i++)
198
      {
199
      names[i] = types[i].name();
200
      }
201
202
    return names;
203
    }
204
205
///////////////////////////////////////////////////////////////////////////////////////////////////
206
207
  @SuppressWarnings("unused")
208
  public static ScrambleEffect create(int ordinal) throws InstantiationException, IllegalAccessException
209
    {
210
    return types[ordinal].effect.newInstance();
211
    }
212
213 3b12e641 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
214
215 8becce57 Leszek Koltunski
  public void onActionFinished(final long effectID)
216 3b12e641 Leszek Koltunski
    {
217 8becce57 Leszek Koltunski
    addNewScramble();
218
    }
219 e8764a49 Leszek Koltunski
220 20dea800 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
221
222
  private void effectFinishedAction(final long effectID, final long id)
223
    {
224
    mEffectReturned++;
225
    effectFinishedPlugin(effectID);
226
227
    if( mEffectReturned == mCubeEffectNumber+mNodeEffectNumber )
228
      {
229
      disassignEffects();
230
231 916f5dda Leszek Koltunski
      mPluginReady = true;
232
      if( mRotReady ) mController.effectFinished(FAKE_EFFECT_ID);
233 20dea800 Leszek Koltunski
      }
234
    }
235
236 8becce57 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
237
238
  public void effectFinished(final long effectID)
239
    {
240 e8764a49 Leszek Koltunski
    for(int i=0; i<mCubeEffectNumber; i++)
241 3b12e641 Leszek Koltunski
      {
242 e8764a49 Leszek Koltunski
      long id = mCubeEffects[i].getID();
243
244
      if( effectID == id )
245 a62aa9d7 Leszek Koltunski
        {
246 20dea800 Leszek Koltunski
        effectFinishedAction(effectID,id);
247 e8764a49 Leszek Koltunski
        return;
248
        }
249
      }
250 a62aa9d7 Leszek Koltunski
251 e8764a49 Leszek Koltunski
    for(int i=0; i<mNodeEffectNumber; i++)
252
      {
253
      long id = mNodeEffects[i].getID();
254 a62aa9d7 Leszek Koltunski
255 e8764a49 Leszek Koltunski
      if( effectID == id )
256 a62aa9d7 Leszek Koltunski
        {
257 20dea800 Leszek Koltunski
        effectFinishedAction(effectID,id);
258 e8764a49 Leszek Koltunski
        return;
259 a62aa9d7 Leszek Koltunski
        }
260 3b12e641 Leszek Koltunski
      }
261
    }
262
263
///////////////////////////////////////////////////////////////////////////////////////////////////
264
265 47ba5ddc Leszek Koltunski
  @SuppressWarnings("unused")
266 af88bf2e Leszek Koltunski
  public long start(int duration, DistortedScreen screen, EffectController cont)
267 3b12e641 Leszek Koltunski
    {
268 af88bf2e Leszek Koltunski
    mObject    = cont.getObject();
269
    mController= cont;
270 a62aa9d7 Leszek Koltunski
271 d13df23d Leszek Koltunski
    // NOT mController.solve() !! This would be a very subtle bug. We need to do this immediately,
272
    // because here we are already inside the mController.preRender() function (doing 'scrambleObjectNow')
273
    // and doing a delayed 'solve()' here would mean we'd be sometimes first doing the first rotation,
274
    // and only after it - the solve.
275
    mObject.solve();
276 beb325a0 Leszek Koltunski
277 e844c116 Leszek Koltunski
    mBasicAngle = mObject.getBasicAngle();
278
279 af88bf2e Leszek Koltunski
    int numScrambles = cont.getNumScrambles();
280 3ca97293 Leszek Koltunski
    int dura = (int)(duration*Math.pow(numScrambles,0.66f));
281 e4db5995 Leszek Koltunski
    createBaseEffects(dura,numScrambles);
282
    createEffects    (dura,numScrambles);
283 a62aa9d7 Leszek Koltunski
284 e8764a49 Leszek Koltunski
    if( mCubeEffectNumber==0 && mNodeEffectNumber==0 )
285 a62aa9d7 Leszek Koltunski
      {
286
      throw new RuntimeException("Cube and Node Plugin Effects not created!");
287
      }
288
289 e8764a49 Leszek Koltunski
    assignEffects();
290 3b12e641 Leszek Koltunski
291
    return FAKE_EFFECT_ID;
292
    }
293
294
///////////////////////////////////////////////////////////////////////////////////////////////////
295
296
  @SuppressWarnings("unused")
297
  public static void enableEffects()
298
    {
299
    Method method;
300
301
    for(Type type: Type.values())
302
      {
303
      try
304
        {
305
        method = type.effect.getDeclaredMethod("enable"); // enable not public, thus getDeclaredMethod
306
        }
307
      catch(NoSuchMethodException ex)
308
        {
309
        android.util.Log.e("ScrambleEffect", type.effect.getSimpleName()+": exception getting method: "+ex.getMessage());
310
        method = null;
311
        }
312
313
      try
314
        {
315
        if( method!=null ) method.invoke(null);
316
        }
317
      catch(Exception ex)
318
        {
319
        android.util.Log.e("ScrambleEffect", type.effect.getSimpleName()+": exception invoking method: "+ex.getMessage());
320
        }
321
      }
322
    }
323
}