Project

General

Profile

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

magiccube / src / main / java / org / distorted / effect / ScrambleEffect.java @ 42772cff

1 3b12e641 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2019 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// Distorted is free software: you can redistribute it and/or modify                             //
7
// 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
// Distorted is distributed in the hope that it will be useful,                                  //
12
// 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
// along with Distorted.  If not, see <http://www.gnu.org/licenses/>.                            //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19
20
package org.distorted.effect;
21
22
import org.distorted.library.effect.Effect;
23
import org.distorted.library.main.DistortedEffects;
24
import org.distorted.library.message.EffectListener;
25
import org.distorted.magic.RubikCube;
26
27
import java.lang.reflect.Method;
28 e8764a49 Leszek Koltunski
import java.util.Random;
29 3b12e641 Leszek Koltunski
30
///////////////////////////////////////////////////////////////////////////////////////////////////
31
32
public abstract class ScrambleEffect implements EffectListener
33
{
34
  public enum Type
35
    {
36
    NONE         (ScrambleEffectNone.class        ),
37 a62aa9d7 Leszek Koltunski
    ROTATIONS    (ScrambleEffectRotations.class   ),
38 3b12e641 Leszek Koltunski
    ;
39
40
    final Class<? extends ScrambleEffect> effect;
41
42
    Type(Class<? extends ScrambleEffect> effect)
43
      {
44
      this.effect= effect;
45
      }
46
    }
47
48
  private static int NUM_EFFECTS = Type.values().length;
49
  private static final int FAKE_EFFECT_ID  = -3;
50
  private static final Type[] types;
51
52
  static
53
    {
54
    int i=0;
55
    types = new Type[NUM_EFFECTS];
56
57
    for(Type type: Type.values())
58
      {
59
      types[i++] = type;
60
      }
61
    }
62
63
  private EffectListener mListener;
64 e8764a49 Leszek Koltunski
  private int mEffectReturned;
65
  private long mCurrentBaseEffectID;
66
  private int mNumDoubleScramblesLeft, mNumScramblesLeft;
67
  private int mLastVector;
68
  private long mDurationSingleTurn;
69
  private Random mRnd;
70 3b12e641 Leszek Koltunski
  private RubikCube mCube;
71
72 e8764a49 Leszek Koltunski
  Effect[] mNodeEffects;
73
  int[] mNodeEffectPosition;
74
  Effect[] mCubeEffects;
75
  int[] mCubeEffectPosition;
76
  int mCubeEffectNumber, mNodeEffectNumber;
77 3b12e641 Leszek Koltunski
78
///////////////////////////////////////////////////////////////////////////////////////////////////
79
80
  ScrambleEffect()
81
    {
82 e8764a49 Leszek Koltunski
    mRnd = new Random( System.currentTimeMillis() );
83
    mLastVector = -1;
84 3b12e641 Leszek Koltunski
    }
85
86
///////////////////////////////////////////////////////////////////////////////////////////////////
87
88
  public static String[] getNames()
89
    {
90
    String[] names = new String[NUM_EFFECTS];
91
92
    for( int i=0; i<NUM_EFFECTS; i++)
93
      {
94
      names[i] = types[i].name();
95
      }
96
97
    return names;
98
    }
99
100
///////////////////////////////////////////////////////////////////////////////////////////////////
101
102 42772cff Leszek Koltunski
  public static ScrambleEffect create(int ordinal) throws InstantiationException, IllegalAccessException
103 3b12e641 Leszek Koltunski
    {
104 42772cff Leszek Koltunski
    return types[ordinal].effect.newInstance();
105 3b12e641 Leszek Koltunski
    }
106
107
///////////////////////////////////////////////////////////////////////////////////////////////////
108
109 a62aa9d7 Leszek Koltunski
  abstract void createEffects(int duration);
110
  abstract void effectFinishedPlugin(final long effectID);
111 3b12e641 Leszek Koltunski
112
///////////////////////////////////////////////////////////////////////////////////////////////////
113 e8764a49 Leszek Koltunski
114 a62aa9d7 Leszek Koltunski
  private void createBaseEffects(int duration, int numScrambles)
115 3b12e641 Leszek Koltunski
    {
116 e8764a49 Leszek Koltunski
    mNumScramblesLeft = numScrambles;
117
118
    // compute how many out of 'numScrambles' are double turns.
119
    mNumDoubleScramblesLeft=0;
120
121
    for(int i=0; i<numScrambles; i++)
122
      {
123
      if( (mRnd.nextInt() % 3) == 0 )
124
        {
125
        mNumDoubleScramblesLeft++;
126
        }
127
      }
128
129
    mDurationSingleTurn = duration/(mNumScramblesLeft+mNumDoubleScramblesLeft);
130
131
    addNewScramble();
132 a62aa9d7 Leszek Koltunski
    }
133 3b12e641 Leszek Koltunski
134 a62aa9d7 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
135 3b12e641 Leszek Koltunski
136 e8764a49 Leszek Koltunski
  private void addNewScramble()
137 a62aa9d7 Leszek Koltunski
    {
138 e8764a49 Leszek Koltunski
    if( mNumScramblesLeft>0 )
139
      {
140
      if( mLastVector == -1 )
141
        {
142
        switch(mRnd.nextInt(3))
143
          {
144
          case 0: mLastVector = RubikCube.VECTX; break;
145
          case 1: mLastVector = RubikCube.VECTY; break;
146
          case 2: mLastVector = RubikCube.VECTZ; break;
147
          }
148
        }
149
      else
150
        {
151
        int newVector = mRnd.nextInt(2);
152
153
        switch(mLastVector)
154
          {
155
          case RubikCube.VECTX: mLastVector = (newVector==0 ? RubikCube.VECTY: RubikCube.VECTZ); break;
156
          case RubikCube.VECTY: mLastVector = (newVector==0 ? RubikCube.VECTX: RubikCube.VECTZ); break;
157
          case RubikCube.VECTZ: mLastVector = (newVector==0 ? RubikCube.VECTX: RubikCube.VECTY); break;
158
          }
159
        }
160
161
      int row  = mRnd.nextInt(mCube.getSize());
162
      int angle= randomizeAngle();
163
      int absAngle = (angle<0 ? -angle : angle);
164
      long durationMillis =  absAngle*mDurationSingleTurn;
165
166
      mNumScramblesLeft--;
167
      if( absAngle==2 ) mNumDoubleScramblesLeft--;
168 3b12e641 Leszek Koltunski
169 2ecf0c21 Leszek Koltunski
      if( mNumScramblesLeft==0 && mNumDoubleScramblesLeft!=0 )
170
        {
171
        android.util.Log.e("effect", "ERROR: "+mNumDoubleScramblesLeft);
172
        }
173
174 e8764a49 Leszek Koltunski
      mCurrentBaseEffectID = mCube.addNewRotation(mLastVector, row, angle*90, durationMillis, this );
175
      }
176
    else
177
      {
178
      mLastVector = -1;
179 035fe333 Leszek Koltunski
180
      if( mEffectReturned == mCubeEffectNumber+mNodeEffectNumber )
181
        {
182
        mListener.effectFinished(FAKE_EFFECT_ID);
183
        }
184 e8764a49 Leszek Koltunski
      }
185
    }
186
187
///////////////////////////////////////////////////////////////////////////////////////////////////
188
189
  private int randomizeAngle()
190
    {
191 2ecf0c21 Leszek Koltunski
    int random = mRnd.nextInt(mNumScramblesLeft);
192
    int result = random<mNumDoubleScramblesLeft ? 2:1;
193
    int sign   = mRnd.nextInt(2);
194
195
    return sign==0 ? result : -result;
196 3b12e641 Leszek Koltunski
    }
197
198
///////////////////////////////////////////////////////////////////////////////////////////////////
199
200 a62aa9d7 Leszek Koltunski
  public void effectFinished(final long effectID)
201 3b12e641 Leszek Koltunski
    {
202 e8764a49 Leszek Koltunski
    if( effectID == mCurrentBaseEffectID )
203
      {
204
      mCube.removeRotationNow();
205
      addNewScramble();
206
      return;
207
      }
208
209
    for(int i=0; i<mCubeEffectNumber; i++)
210 3b12e641 Leszek Koltunski
      {
211 e8764a49 Leszek Koltunski
      long id = mCubeEffects[i].getID();
212
213
      if( effectID == id )
214 a62aa9d7 Leszek Koltunski
        {
215 e8764a49 Leszek Koltunski
        mEffectReturned++;
216
        effectFinishedPlugin(effectID);
217 a62aa9d7 Leszek Koltunski
218 e8764a49 Leszek Koltunski
        if( mEffectReturned == mCubeEffectNumber+mNodeEffectNumber )
219 a62aa9d7 Leszek Koltunski
          {
220 e8764a49 Leszek Koltunski
          disassignEffects();
221 035fe333 Leszek Koltunski
222
          if( mNumScramblesLeft==0 )
223
            {
224
            mListener.effectFinished(FAKE_EFFECT_ID);
225
            }
226 e8764a49 Leszek Koltunski
          }
227 a62aa9d7 Leszek Koltunski
228 e8764a49 Leszek Koltunski
        return;
229
        }
230
      }
231 a62aa9d7 Leszek Koltunski
232 e8764a49 Leszek Koltunski
    for(int i=0; i<mNodeEffectNumber; i++)
233
      {
234
      long id = mNodeEffects[i].getID();
235 a62aa9d7 Leszek Koltunski
236 e8764a49 Leszek Koltunski
      if( effectID == id )
237 a62aa9d7 Leszek Koltunski
        {
238 e8764a49 Leszek Koltunski
        mEffectReturned++;
239
        effectFinishedPlugin(effectID);
240 a62aa9d7 Leszek Koltunski
241 e8764a49 Leszek Koltunski
        if( mEffectReturned == mCubeEffectNumber+mNodeEffectNumber )
242 a62aa9d7 Leszek Koltunski
          {
243 e8764a49 Leszek Koltunski
          disassignEffects();
244 035fe333 Leszek Koltunski
245
          if( mNumScramblesLeft==0 )
246
            {
247
            mListener.effectFinished(FAKE_EFFECT_ID);
248
            }
249 a62aa9d7 Leszek Koltunski
          }
250 e8764a49 Leszek Koltunski
251
        return;
252 a62aa9d7 Leszek Koltunski
        }
253 3b12e641 Leszek Koltunski
      }
254
    }
255
256
///////////////////////////////////////////////////////////////////////////////////////////////////
257
258 e8764a49 Leszek Koltunski
  public long start(int duration, RubikCube cube, int numScrambles, EffectListener listener)
259 3b12e641 Leszek Koltunski
    {
260
    mCube     = cube;
261
    mListener = listener;
262 a62aa9d7 Leszek Koltunski
263 e8764a49 Leszek Koltunski
    createBaseEffects(duration, numScrambles);
264
    createEffects(duration);
265 a62aa9d7 Leszek Koltunski
266 e8764a49 Leszek Koltunski
    if( mCubeEffectNumber==0 && mNodeEffectNumber==0 )
267 a62aa9d7 Leszek Koltunski
      {
268
      throw new RuntimeException("Cube and Node Plugin Effects not created!");
269
      }
270
271 e8764a49 Leszek Koltunski
    assignEffects();
272 3b12e641 Leszek Koltunski
273
    return FAKE_EFFECT_ID;
274
    }
275
276
///////////////////////////////////////////////////////////////////////////////////////////////////
277
278 e8764a49 Leszek Koltunski
  private void assignEffects()
279 3b12e641 Leszek Koltunski
    {
280 e8764a49 Leszek Koltunski
    for(int i=0; i<mCubeEffectNumber; i++)
281 a62aa9d7 Leszek Koltunski
      {
282 e8764a49 Leszek Koltunski
      mCube.apply(mCubeEffects[i],mCubeEffectPosition[i]);
283
      mCubeEffects[i].notifyWhenFinished(this);
284 a62aa9d7 Leszek Koltunski
      }
285
286
    DistortedEffects nodeEffects = mCube.getEffects();
287 3b12e641 Leszek Koltunski
288 e8764a49 Leszek Koltunski
    for(int i=0; i<mNodeEffectNumber; i++)
289 3b12e641 Leszek Koltunski
      {
290 e8764a49 Leszek Koltunski
      nodeEffects.apply(mNodeEffects[i],mNodeEffectPosition[i]);
291
      mNodeEffects[i].notifyWhenFinished(this);
292 3b12e641 Leszek Koltunski
      }
293 a62aa9d7 Leszek Koltunski
    }
294
295
///////////////////////////////////////////////////////////////////////////////////////////////////
296 3b12e641 Leszek Koltunski
297 e8764a49 Leszek Koltunski
  private void disassignEffects()
298 a62aa9d7 Leszek Koltunski
    {
299 e8764a49 Leszek Koltunski
    for(int i=0; i<mCubeEffectNumber; i++)
300 3b12e641 Leszek Koltunski
      {
301 e8764a49 Leszek Koltunski
      mCube.remove(mCubeEffects[i].getID());
302 3b12e641 Leszek Koltunski
      }
303
304
    DistortedEffects nodeEffects = mCube.getEffects();
305
306 e8764a49 Leszek Koltunski
    for(int i=0; i<mNodeEffectNumber; i++)
307 a62aa9d7 Leszek Koltunski
      {
308 e8764a49 Leszek Koltunski
      nodeEffects.abortById(mNodeEffects[i].getID());
309 a62aa9d7 Leszek Koltunski
      }
310 3b12e641 Leszek Koltunski
    }
311
312
///////////////////////////////////////////////////////////////////////////////////////////////////
313
314
  @SuppressWarnings("unused")
315
  public static void enableEffects()
316
    {
317
    Method method;
318
319
    for(Type type: Type.values())
320
      {
321
      try
322
        {
323
        method = type.effect.getDeclaredMethod("enable"); // enable not public, thus getDeclaredMethod
324
        }
325
      catch(NoSuchMethodException ex)
326
        {
327
        android.util.Log.e("ScrambleEffect", type.effect.getSimpleName()+": exception getting method: "+ex.getMessage());
328
        method = null;
329
        }
330
331
      try
332
        {
333
        if( method!=null ) method.invoke(null);
334
        }
335
      catch(Exception ex)
336
        {
337
        android.util.Log.e("ScrambleEffect", type.effect.getSimpleName()+": exception invoking method: "+ex.getMessage());
338
        }
339
      }
340
    }
341
}