Project

General

Profile

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

magiccube / src / main / java / org / distorted / effect / scramble / ScrambleEffect.java @ 27a70eae

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 64975793 Leszek Koltunski
package org.distorted.effect.scramble;
21 3b12e641 Leszek Koltunski
22 64975793 Leszek Koltunski
import org.distorted.effect.BaseEffect;
23 3b12e641 Leszek Koltunski
import org.distorted.library.effect.Effect;
24
import org.distorted.library.main.DistortedEffects;
25
import org.distorted.library.message.EffectListener;
26 64975793 Leszek Koltunski
import org.distorted.magic.RubikRenderer;
27 27a70eae Leszek Koltunski
import org.distorted.object.RubikObject;
28 3b12e641 Leszek Koltunski
29
import java.lang.reflect.Method;
30 e8764a49 Leszek Koltunski
import java.util.Random;
31 3b12e641 Leszek Koltunski
32 27a70eae Leszek Koltunski
import static org.distorted.object.RubikObjectList.VECTX;
33
import static org.distorted.object.RubikObjectList.VECTY;
34
import static org.distorted.object.RubikObjectList.VECTZ;
35
36 3b12e641 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
37
38 64975793 Leszek Koltunski
public abstract class ScrambleEffect extends BaseEffect implements EffectListener
39 3b12e641 Leszek Koltunski
{
40
  public enum Type
41
    {
42
    NONE         (ScrambleEffectNone.class        ),
43 a62aa9d7 Leszek Koltunski
    ROTATIONS    (ScrambleEffectRotations.class   ),
44 3b12e641 Leszek Koltunski
    ;
45
46
    final Class<? extends ScrambleEffect> effect;
47
48
    Type(Class<? extends ScrambleEffect> effect)
49
      {
50
      this.effect= effect;
51
      }
52
    }
53
54
  private static int NUM_EFFECTS = Type.values().length;
55
  private static final int FAKE_EFFECT_ID  = -3;
56
  private static final Type[] types;
57
58
  static
59
    {
60
    int i=0;
61
    types = new Type[NUM_EFFECTS];
62
63
    for(Type type: Type.values())
64
      {
65
      types[i++] = type;
66
      }
67
    }
68
69
  private EffectListener mListener;
70 e8764a49 Leszek Koltunski
  private int mEffectReturned;
71
  private long mCurrentBaseEffectID;
72
  private int mNumDoubleScramblesLeft, mNumScramblesLeft;
73
  private int mLastVector;
74
  private long mDurationSingleTurn;
75
  private Random mRnd;
76 27a70eae Leszek Koltunski
  private RubikObject mObject;
77 3b12e641 Leszek Koltunski
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
    mLastVector = -1;
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 e8764a49 Leszek Koltunski
101 a62aa9d7 Leszek Koltunski
  private void createBaseEffects(int duration, int numScrambles)
102 3b12e641 Leszek Koltunski
    {
103 e8764a49 Leszek Koltunski
    mNumScramblesLeft = numScrambles;
104
105
    mNumDoubleScramblesLeft=0;
106
107
    for(int i=0; i<numScrambles; i++)
108
      {
109
      if( (mRnd.nextInt() % 3) == 0 )
110
        {
111
        mNumDoubleScramblesLeft++;
112
        }
113
      }
114
115
    mDurationSingleTurn = duration/(mNumScramblesLeft+mNumDoubleScramblesLeft);
116
117
    addNewScramble();
118 a62aa9d7 Leszek Koltunski
    }
119 3b12e641 Leszek Koltunski
120 a62aa9d7 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
121 3b12e641 Leszek Koltunski
122 e8764a49 Leszek Koltunski
  private void addNewScramble()
123 a62aa9d7 Leszek Koltunski
    {
124 e8764a49 Leszek Koltunski
    if( mNumScramblesLeft>0 )
125
      {
126
      if( mLastVector == -1 )
127
        {
128
        switch(mRnd.nextInt(3))
129
          {
130 27a70eae Leszek Koltunski
          case 0: mLastVector = VECTX; break;
131
          case 1: mLastVector = VECTY; break;
132
          case 2: mLastVector = VECTZ; break;
133 e8764a49 Leszek Koltunski
          }
134
        }
135
      else
136
        {
137
        int newVector = mRnd.nextInt(2);
138
139
        switch(mLastVector)
140
          {
141 27a70eae Leszek Koltunski
          case VECTX: mLastVector = (newVector==0 ? VECTY: VECTZ); break;
142
          case VECTY: mLastVector = (newVector==0 ? VECTX: VECTZ); break;
143
          case VECTZ: mLastVector = (newVector==0 ? VECTX: VECTY); break;
144 e8764a49 Leszek Koltunski
          }
145
        }
146
147 27a70eae Leszek Koltunski
      int row  = mRnd.nextInt(mObject.getSize());
148 e8764a49 Leszek Koltunski
      int angle= randomizeAngle();
149
      int absAngle = (angle<0 ? -angle : angle);
150
      long durationMillis =  absAngle*mDurationSingleTurn;
151
152
      mNumScramblesLeft--;
153
      if( absAngle==2 ) mNumDoubleScramblesLeft--;
154 3b12e641 Leszek Koltunski
155 2ecf0c21 Leszek Koltunski
      if( mNumScramblesLeft==0 && mNumDoubleScramblesLeft!=0 )
156
        {
157
        android.util.Log.e("effect", "ERROR: "+mNumDoubleScramblesLeft);
158
        }
159
160 27a70eae Leszek Koltunski
      mCurrentBaseEffectID = mObject.addNewRotation(mLastVector, row, angle*90, durationMillis, this );
161 e8764a49 Leszek Koltunski
      }
162
    else
163
      {
164
      mLastVector = -1;
165 035fe333 Leszek Koltunski
166
      if( mEffectReturned == mCubeEffectNumber+mNodeEffectNumber )
167
        {
168
        mListener.effectFinished(FAKE_EFFECT_ID);
169
        }
170 e8764a49 Leszek Koltunski
      }
171
    }
172
173
///////////////////////////////////////////////////////////////////////////////////////////////////
174
175
  private int randomizeAngle()
176
    {
177 2ecf0c21 Leszek Koltunski
    int random = mRnd.nextInt(mNumScramblesLeft);
178
    int result = random<mNumDoubleScramblesLeft ? 2:1;
179
    int sign   = mRnd.nextInt(2);
180
181
    return sign==0 ? result : -result;
182 3b12e641 Leszek Koltunski
    }
183
184 47ba5ddc Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
185
186
  private void assignEffects()
187
    {
188
    for(int i=0; i<mCubeEffectNumber; i++)
189
      {
190 27a70eae Leszek Koltunski
      mObject.apply(mCubeEffects[i],mCubeEffectPosition[i]);
191 47ba5ddc Leszek Koltunski
      mCubeEffects[i].notifyWhenFinished(this);
192
      }
193
194 27a70eae Leszek Koltunski
    DistortedEffects nodeEffects = mObject.getEffects();
195 47ba5ddc Leszek Koltunski
196
    for(int i=0; i<mNodeEffectNumber; i++)
197
      {
198
      nodeEffects.apply(mNodeEffects[i],mNodeEffectPosition[i]);
199
      mNodeEffects[i].notifyWhenFinished(this);
200
      }
201
    }
202
203
///////////////////////////////////////////////////////////////////////////////////////////////////
204
205
  private void disassignEffects()
206
    {
207
    for(int i=0; i<mCubeEffectNumber; i++)
208
      {
209 27a70eae Leszek Koltunski
      mObject.remove(mCubeEffects[i].getID());
210 47ba5ddc Leszek Koltunski
      }
211
212 27a70eae Leszek Koltunski
    DistortedEffects nodeEffects = mObject.getEffects();
213 47ba5ddc Leszek Koltunski
214
    for(int i=0; i<mNodeEffectNumber; i++)
215
      {
216
      nodeEffects.abortById(mNodeEffects[i].getID());
217
      }
218
    }
219
220
///////////////////////////////////////////////////////////////////////////////////////////////////
221
// PUBLIC API
222
///////////////////////////////////////////////////////////////////////////////////////////////////
223
224
  @SuppressWarnings("unused")
225
  public static String[] getNames()
226
    {
227
    String[] names = new String[NUM_EFFECTS];
228
229
    for( int i=0; i<NUM_EFFECTS; i++)
230
      {
231
      names[i] = types[i].name();
232
      }
233
234
    return names;
235
    }
236
237
///////////////////////////////////////////////////////////////////////////////////////////////////
238
239
  @SuppressWarnings("unused")
240
  public static ScrambleEffect create(int ordinal) throws InstantiationException, IllegalAccessException
241
    {
242
    return types[ordinal].effect.newInstance();
243
    }
244
245 3b12e641 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
246
247 a62aa9d7 Leszek Koltunski
  public void effectFinished(final long effectID)
248 3b12e641 Leszek Koltunski
    {
249 e8764a49 Leszek Koltunski
    if( effectID == mCurrentBaseEffectID )
250
      {
251 27a70eae Leszek Koltunski
      mObject.removeRotationNow();
252 e8764a49 Leszek Koltunski
      addNewScramble();
253
      return;
254
      }
255
256
    for(int i=0; i<mCubeEffectNumber; i++)
257 3b12e641 Leszek Koltunski
      {
258 e8764a49 Leszek Koltunski
      long id = mCubeEffects[i].getID();
259
260
      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
            mListener.effectFinished(FAKE_EFFECT_ID);
272
            }
273 e8764a49 Leszek Koltunski
          }
274 a62aa9d7 Leszek Koltunski
275 e8764a49 Leszek Koltunski
        return;
276
        }
277
      }
278 a62aa9d7 Leszek Koltunski
279 e8764a49 Leszek Koltunski
    for(int i=0; i<mNodeEffectNumber; i++)
280
      {
281
      long id = mNodeEffects[i].getID();
282 a62aa9d7 Leszek Koltunski
283 e8764a49 Leszek Koltunski
      if( effectID == id )
284 a62aa9d7 Leszek Koltunski
        {
285 e8764a49 Leszek Koltunski
        mEffectReturned++;
286
        effectFinishedPlugin(effectID);
287 a62aa9d7 Leszek Koltunski
288 e8764a49 Leszek Koltunski
        if( mEffectReturned == mCubeEffectNumber+mNodeEffectNumber )
289 a62aa9d7 Leszek Koltunski
          {
290 e8764a49 Leszek Koltunski
          disassignEffects();
291 035fe333 Leszek Koltunski
292
          if( mNumScramblesLeft==0 )
293
            {
294
            mListener.effectFinished(FAKE_EFFECT_ID);
295
            }
296 a62aa9d7 Leszek Koltunski
          }
297 e8764a49 Leszek Koltunski
298
        return;
299 a62aa9d7 Leszek Koltunski
        }
300 3b12e641 Leszek Koltunski
      }
301
    }
302
303
///////////////////////////////////////////////////////////////////////////////////////////////////
304
305 47ba5ddc Leszek Koltunski
  @SuppressWarnings("unused")
306 64975793 Leszek Koltunski
  public long start(int duration, RubikRenderer renderer)
307 3b12e641 Leszek Koltunski
    {
308 27a70eae Leszek Koltunski
    mObject   = renderer.getObject();
309 64975793 Leszek Koltunski
    mListener = renderer;
310 a62aa9d7 Leszek Koltunski
311 27a70eae Leszek Koltunski
    mObject.solve();
312 beb325a0 Leszek Koltunski
313 64975793 Leszek Koltunski
    int numScrambles = renderer.getNumScrambles();
314 e4db5995 Leszek Koltunski
    int dura = (int)(duration*Math.pow(numScrambles,0.6f));
315
    createBaseEffects(dura,numScrambles);
316
    createEffects    (dura,numScrambles);
317 a62aa9d7 Leszek Koltunski
318 e8764a49 Leszek Koltunski
    if( mCubeEffectNumber==0 && mNodeEffectNumber==0 )
319 a62aa9d7 Leszek Koltunski
      {
320
      throw new RuntimeException("Cube and Node Plugin Effects not created!");
321
      }
322
323 e8764a49 Leszek Koltunski
    assignEffects();
324 3b12e641 Leszek Koltunski
325
    return FAKE_EFFECT_ID;
326
    }
327
328
///////////////////////////////////////////////////////////////////////////////////////////////////
329
330
  @SuppressWarnings("unused")
331
  public static void enableEffects()
332
    {
333
    Method method;
334
335
    for(Type type: Type.values())
336
      {
337
      try
338
        {
339
        method = type.effect.getDeclaredMethod("enable"); // enable not public, thus getDeclaredMethod
340
        }
341
      catch(NoSuchMethodException ex)
342
        {
343
        android.util.Log.e("ScrambleEffect", type.effect.getSimpleName()+": exception getting method: "+ex.getMessage());
344
        method = null;
345
        }
346
347
      try
348
        {
349
        if( method!=null ) method.invoke(null);
350
        }
351
      catch(Exception ex)
352
        {
353
        android.util.Log.e("ScrambleEffect", type.effect.getSimpleName()+": exception invoking method: "+ex.getMessage());
354
        }
355
      }
356
    }
357
}