Project

General

Profile

Download (8.27 KB) Statistics
| Branch: | Revision:

distorted-objectlib / src / main / java / org / distorted / objectlib / effects / fastscramble / FastScrambleEffect.java @ c0266cb1

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2022 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is proprietary software licensed under an EULA which you should have received      //
7
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
8
///////////////////////////////////////////////////////////////////////////////////////////////////
9

    
10
package org.distorted.objectlib.effects.fastscramble;
11

    
12
import java.lang.reflect.Method;
13
import java.util.Random;
14

    
15
import org.distorted.library.effect.Effect;
16
import org.distorted.library.main.DistortedEffects;
17
import org.distorted.library.message.EffectListener;
18

    
19
import org.distorted.objectlib.main.ObjectPreRender;
20
import org.distorted.objectlib.main.TwistyObject;
21

    
22
import org.distorted.objectlib.effects.BaseEffect;
23
import org.distorted.objectlib.main.TwistyObjectNode;
24

    
25
///////////////////////////////////////////////////////////////////////////////////////////////////
26

    
27
public abstract class FastScrambleEffect extends BaseEffect implements EffectListener
28
{
29
  public enum Type
30
    {
31
    SPIN   (FastScrambleEffectSpin.class),
32
    ;
33

    
34
    final Class<? extends FastScrambleEffect> effect;
35

    
36
    Type(Class<? extends FastScrambleEffect> effect)
37
      {
38
      this.effect = effect;
39
      }
40
    }
41

    
42
  private static final int NUM_EFFECTS = Type.values().length;
43
  private static final int NUM_PHASES  = 2;
44
  private static final int FAKE_EFFECT_ID = -5;
45
  private static final Type[] types;
46

    
47
  static
48
    {
49
    int i=0;
50
    types = new Type[NUM_EFFECTS];
51

    
52
    for(Type type: Type.values())
53
      {
54
      types[i++] = type;
55
      }
56
    }
57

    
58
  private int mDuration;
59
  private int mEffectReturned;
60
  private final int[] mCubeEffectNumber, mNodeEffectNumber;
61
  private int mPhase;
62
  private final Random mRnd;
63
  private final Object mLock;
64
  int mNumScrambles;
65
  int[][] mScrambles;
66

    
67
  ObjectPreRender mPre;
68
  TwistyObject mObject;
69
  TwistyObjectNode mObjectNode;
70
  Effect[][] mCubeEffects;
71
  int[][] mCubeEffectPosition;
72
  Effect[][] mNodeEffects;
73
  int[][] mNodeEffectPosition;
74

    
75
///////////////////////////////////////////////////////////////////////////////////////////////////
76

    
77
  FastScrambleEffect()
78
    {
79
    mLock = new Object();
80
    mRnd = new Random( System.currentTimeMillis() );
81

    
82
    mPhase= 0;
83

    
84
    mCubeEffectNumber   = new int[NUM_PHASES];
85
    mNodeEffectNumber   = new int[NUM_PHASES];
86
    mCubeEffectPosition = new int[NUM_PHASES][];
87
    mNodeEffectPosition = new int[NUM_PHASES][];
88
    mCubeEffects        = new Effect[NUM_PHASES][];
89
    mNodeEffects        = new Effect[NUM_PHASES][];
90
    }
91

    
92
///////////////////////////////////////////////////////////////////////////////////////////////////
93

    
94
  abstract void createEffectsPhase0(int duration);
95
  abstract void createEffectsPhase1(int duration);
96

    
97
///////////////////////////////////////////////////////////////////////////////////////////////////
98

    
99
  private void createScrambles()
100
    {
101
    mScrambles = new int[mNumScrambles][3];
102

    
103
    if( mObject!=null )
104
      {
105
      synchronized(mLock)
106
        {
107
        for(int scramble=0; scramble<mNumScrambles; scramble++)
108
          {
109
          mObject.randomizeNewScramble(mScrambles, mRnd, scramble, mNumScrambles);
110
          }
111
        }
112

    
113
      for(int scramble=0; scramble<mNumScrambles; scramble++)
114
        {
115
        int row = mScrambles[scramble][1];
116
        mScrambles[scramble][1] = (1<<row);
117
        }
118
      }
119
    }
120

    
121
///////////////////////////////////////////////////////////////////////////////////////////////////
122

    
123
  private void assignEffects(int phase)
124
    {
125
    mCubeEffectNumber[phase] = ( mCubeEffects[phase]!=null ) ? mCubeEffects[phase].length : 0;
126
    mNodeEffectNumber[phase] = ( mNodeEffects[phase]!=null ) ? mNodeEffects[phase].length : 0;
127

    
128
    if( mCubeEffectNumber[phase]==0 && mNodeEffectNumber[phase]==0 )
129
      {
130
      throw new RuntimeException("Cube and Node Effects ("+phase+" phase) both not created!");
131
      }
132

    
133
    for(int i=0; i<mCubeEffectNumber[phase]; i++)
134
      {
135
      mObject.applyEffect(mCubeEffects[phase][i],mCubeEffectPosition[phase][i]);
136
      mCubeEffects[phase][i].notifyWhenFinished(this);
137
      }
138

    
139
    DistortedEffects nodeEffects = mObjectNode.getEffects();
140

    
141
    for(int i=0; i<mNodeEffectNumber[phase]; i++)
142
      {
143
      nodeEffects.apply(mNodeEffects[phase][i],mNodeEffectPosition[phase][i]);
144
      mNodeEffects[phase][i].notifyWhenFinished(this);
145
      }
146
    }
147

    
148
///////////////////////////////////////////////////////////////////////////////////////////////////
149

    
150
  private void effectAction(int phase)
151
    {
152
    switch(phase)
153
      {
154
      case 0: mEffectReturned = 0;
155
              mPhase          = 1;
156

    
157
              // do not start initializing the Object until we have finished creating moves!
158
              synchronized(mLock)
159
                {
160
                mPre.applyScrambles(mScrambles);
161
                }
162

    
163
              createEffectsPhase1(mDuration);
164
              assignEffects(mPhase);
165
              break;
166
      case 1: mPre.effectFinished(FAKE_EFFECT_ID);
167
              break;
168
      }
169
    }
170

    
171
///////////////////////////////////////////////////////////////////////////////////////////////////
172
// PUBLIC API
173
///////////////////////////////////////////////////////////////////////////////////////////////////
174

    
175
  @SuppressWarnings("unused")
176
  public static String[] getNames()
177
    {
178
    String[] names = new String[NUM_EFFECTS];
179

    
180
    for( int i=0; i<NUM_EFFECTS; i++)
181
      {
182
      names[i] = types[i].name();
183
      }
184

    
185
    return names;
186
    }
187

    
188
///////////////////////////////////////////////////////////////////////////////////////////////////
189

    
190
  @SuppressWarnings("unused")
191
  public static FastScrambleEffect create(int ordinal) throws InstantiationException, IllegalAccessException
192
    {
193
    return types[ordinal].effect.newInstance();
194
    }
195

    
196
///////////////////////////////////////////////////////////////////////////////////////////////////
197

    
198
  public void effectFinished(final long effectID)
199
    {
200
    int total = mCubeEffectNumber[mPhase]+mNodeEffectNumber[mPhase];
201

    
202
    for(int i=0; i<mCubeEffectNumber[mPhase]; i++)
203
      {
204
      long id = mCubeEffects[mPhase][i].getID();
205

    
206
      if( effectID == id )
207
        {
208
        if( ++mEffectReturned == total ) effectAction(mPhase);
209
        mObject.removeEffect(id);
210
        return;
211
        }
212
      }
213
    for(int i=0; i<mNodeEffectNumber[mPhase]; i++)
214
      {
215
      long id = mNodeEffects[mPhase][i].getID();
216

    
217
      if( effectID == id )
218
        {
219
        if( ++mEffectReturned == total ) effectAction(mPhase);
220
        mObjectNode.getEffects().abortById(id);
221
        return;
222
        }
223
      }
224
    }
225

    
226
///////////////////////////////////////////////////////////////////////////////////////////////////
227

    
228
  @SuppressWarnings("unused")
229
  public long start(int duration, ObjectPreRender pre)
230
    {
231
    mObject       = pre.getObject();
232
    mObjectNode   = pre.getObjectNode();
233
    mPre          = pre;
234
    mDuration     = duration;
235
    mNumScrambles = pre.getNumScrambles();
236

    
237
    Thread thread = new Thread()
238
      {
239
      public void run()
240
        {
241
        createScrambles();
242
        }
243
      };
244

    
245
    thread.start();
246

    
247
    createEffectsPhase0(mDuration);
248
    assignEffects(mPhase);
249

    
250
    return FAKE_EFFECT_ID;
251
    }
252

    
253
///////////////////////////////////////////////////////////////////////////////////////////////////
254

    
255
  @SuppressWarnings("unused")
256
  public static void enableEffects()
257
    {
258
    Method method;
259

    
260
    for(Type type: Type.values())
261
      {
262
      try
263
        {
264
        method = type.effect.getDeclaredMethod("enable"); // enable not public, thus getDeclaredMethod
265
        }
266
      catch(NoSuchMethodException ex)
267
        {
268
        android.util.Log.e("FastScrambleEffect", type.effect.getSimpleName()+": exception getting method: "+ex.getMessage());
269
        method = null;
270
        }
271

    
272
      try
273
        {
274
        if( method!=null ) method.invoke(null);
275
        }
276
      catch(Exception ex)
277
        {
278
        android.util.Log.e("FastScrambleEffect", type.effect.getSimpleName()+": exception invoking method: "+ex.getMessage());
279
        }
280
      }
281
    }
282
}
(1-1/2)