Revision 7c969a6d
Added by Leszek Koltunski over 4 years ago
src/main/java/org/distorted/effects/scramble/ScrambleEffect.java | ||
---|---|---|
63 | 63 |
} |
64 | 64 |
} |
65 | 65 |
|
66 |
public static final int START_AXIS = -2; |
|
67 |
public static final int STOP_AXIS = -1; |
|
68 |
|
|
66 | 69 |
private RubikPreRender mPreRender; |
67 | 70 |
private int mEffectReturned; |
68 | 71 |
private int mNumDoubleScramblesLeft, mNumScramblesLeft; |
69 |
private int mLastVector;
|
|
72 |
private int mLastRotAxis, mLastRow;
|
|
70 | 73 |
private long mDurationSingleTurn; |
71 | 74 |
private Random mRnd; |
72 |
private int mNumAxis; |
|
73 | 75 |
private int mBasicAngle; |
74 |
private float[] mRowChances; |
|
75 | 76 |
|
76 | 77 |
RubikObject mObject; |
77 | 78 |
Effect[] mNodeEffects; |
... | ... | |
85 | 86 |
ScrambleEffect() |
86 | 87 |
{ |
87 | 88 |
mRnd = new Random( System.currentTimeMillis() ); |
88 |
mLastVector = -2;
|
|
89 |
mLastRotAxis = START_AXIS;
|
|
89 | 90 |
} |
90 | 91 |
|
91 | 92 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
98 | 99 |
// the time a single quarter-turn takes! |
99 | 100 |
// |
100 | 101 |
// Only works for |
102 |
// basicAngle==5, i.e. something whose rotations are by 72 degrees (Megaminx) or |
|
101 | 103 |
// basicAngle==4, i.e. something whose rotations are by 90 degrees (RubikCube) or |
102 |
// basicAngle==3, i.e. something whose rotations are by 120 degrees (a Pyramix) or
|
|
104 |
// basicAngle==3, i.e. something whose rotations are by 120 degrees (Pyramix) or |
|
103 | 105 |
// basicAngle==2, i.e. something whose rotations are by 180 degrees (e.g. a 3x2x1 'Bunny') |
104 | 106 |
|
105 | 107 |
private void createBaseEffects(int duration, int numScrambles) |
... | ... | |
110 | 112 |
|
111 | 113 |
if( mBasicAngle>=4 ) |
112 | 114 |
{ |
115 |
int chance = mBasicAngle==4 ? 3:2; |
|
116 |
|
|
113 | 117 |
for(int i=0; i<numScrambles; i++) |
114 | 118 |
{ |
115 |
if( (mRnd.nextInt() % 3) == 0 )
|
|
119 |
if( (mRnd.nextInt() % chance) == 0 )
|
|
116 | 120 |
{ |
117 | 121 |
mNumDoubleScramblesLeft++; |
118 | 122 |
} |
... | ... | |
125 | 129 |
} |
126 | 130 |
|
127 | 131 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
128 |
// only works if basicAngle<=4, i.e. won't work for something whose basic rotations are by less |
|
129 |
// than 90 degrees. |
|
132 |
// only works if basicAngle<=5 |
|
130 | 133 |
|
131 | 134 |
private void addNewScramble() |
132 | 135 |
{ |
133 | 136 |
if( mNumScramblesLeft>0 ) |
134 | 137 |
{ |
135 |
if( mLastVector == -2 ) |
|
136 |
{ |
|
137 |
mLastVector = mRnd.nextInt(mNumAxis); |
|
138 |
} |
|
139 |
else |
|
140 |
{ |
|
141 |
int newVector = mRnd.nextInt(mNumAxis-1); |
|
142 |
mLastVector = (newVector>=mLastVector ? newVector+1 : newVector); |
|
143 |
} |
|
144 |
|
|
145 |
int row=0; |
|
146 |
float rowFloat = mRnd.nextFloat(); |
|
147 |
|
|
148 |
for(int i=0; i<mRowChances.length; i++) |
|
149 |
{ |
|
150 |
if( rowFloat<=mRowChances[i] ) |
|
151 |
{ |
|
152 |
row=i; |
|
153 |
break; |
|
154 |
} |
|
155 |
} |
|
138 |
int lastRotAxis = mLastRotAxis; |
|
139 |
mLastRotAxis = mObject.randomizeNewRotAxis(mRnd,mLastRotAxis); |
|
140 |
mLastRow = mObject.randomizeNewRow(mRnd,lastRotAxis,mLastRow,mLastRotAxis); |
|
156 | 141 |
|
157 |
int rowBitmap = (1<<row);
|
|
142 |
int rowBitmap = (1<<mLastRow);
|
|
158 | 143 |
int angle= randomizeAngle(); |
159 | 144 |
int absAngle = (angle<0 ? -angle : angle); |
160 | 145 |
long durationMillis = absAngle*mDurationSingleTurn; |
... | ... | |
167 | 152 |
android.util.Log.e("effect", "ERROR: "+mNumDoubleScramblesLeft); |
168 | 153 |
} |
169 | 154 |
|
170 |
mPreRender.addRotation(this, mLastVector, rowBitmap, angle*(360/mBasicAngle), durationMillis);
|
|
155 |
mPreRender.addRotation(this, mLastRotAxis, rowBitmap, angle*(360/mBasicAngle), durationMillis);
|
|
171 | 156 |
} |
172 | 157 |
else |
173 | 158 |
{ |
174 |
mLastVector = -1;
|
|
159 |
mLastRotAxis = STOP_AXIS;
|
|
175 | 160 |
|
176 | 161 |
if( mEffectReturned == mCubeEffectNumber+mNodeEffectNumber ) |
177 | 162 |
{ |
... | ... | |
181 | 166 |
} |
182 | 167 |
|
183 | 168 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
184 |
// only works for basicAngle<=4.
|
|
169 |
// only works for basicAngle<=5.
|
|
185 | 170 |
|
186 | 171 |
private int randomizeAngle() |
187 | 172 |
{ |
... | ... | |
318 | 303 |
{ |
319 | 304 |
mObject = pre.getObject(); |
320 | 305 |
mPreRender = pre; |
321 |
mRowChances = mObject.getRowChances(); |
|
322 | 306 |
|
323 | 307 |
mObject.solve(); |
324 | 308 |
|
325 |
mNumAxis = mObject.getRotationAxis().length; |
|
326 | 309 |
mBasicAngle = mObject.getBasicAngle(); |
327 | 310 |
|
328 | 311 |
int numScrambles = pre.getNumScrambles(); |
src/main/java/org/distorted/objects/RubikCube.java | ||
---|---|---|
36 | 36 |
import org.distorted.library.type.Static3D; |
37 | 37 |
import org.distorted.library.type.Static4D; |
38 | 38 |
|
39 |
import java.util.Random; |
|
40 |
|
|
41 |
import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS; |
|
42 |
|
|
39 | 43 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
40 | 44 |
|
41 | 45 |
class RubikCube extends RubikObject |
... | ... | |
314 | 318 |
return getSize(); |
315 | 319 |
} |
316 | 320 |
|
321 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
322 |
|
|
323 |
float[] getRowChances() |
|
324 |
{ |
|
325 |
int size = getSize(); |
|
326 |
float[] chances = new float[size]; |
|
327 |
|
|
328 |
for(int i=0; i<size; i++) |
|
329 |
{ |
|
330 |
chances[i] = (i+1.0f) / size; |
|
331 |
} |
|
332 |
|
|
333 |
return chances; |
|
334 |
} |
|
335 |
|
|
317 | 336 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
318 | 337 |
// PUBLIC API |
319 | 338 |
|
... | ... | |
338 | 357 |
|
339 | 358 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
340 | 359 |
|
341 |
public float[] getRowChances()
|
|
360 |
public float returnRotationFactor(float offset)
|
|
342 | 361 |
{ |
343 |
int size = getSize();
|
|
344 |
float[] chances = new float[size];
|
|
362 |
return 1.0f;
|
|
363 |
}
|
|
345 | 364 |
|
346 |
for(int i=0; i<size; i++) |
|
365 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
366 |
|
|
367 |
public int randomizeNewRotAxis(Random rnd, int oldRotAxis) |
|
368 |
{ |
|
369 |
int numAxis = ROTATION_AXIS.length; |
|
370 |
|
|
371 |
if( oldRotAxis == START_AXIS ) |
|
347 | 372 |
{ |
348 |
chances[i] = (i+1.0f) / size; |
|
373 |
return rnd.nextInt(numAxis); |
|
374 |
} |
|
375 |
else |
|
376 |
{ |
|
377 |
int newVector = rnd.nextInt(numAxis-1); |
|
378 |
return (newVector>=oldRotAxis ? newVector+1 : newVector); |
|
349 | 379 |
} |
350 |
|
|
351 |
return chances; |
|
352 | 380 |
} |
353 | 381 |
|
354 | 382 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
355 | 383 |
|
356 |
public float returnRotationFactor(float offset)
|
|
384 |
public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
|
|
357 | 385 |
{ |
358 |
return 1.0f; |
|
386 |
float rowFloat = rnd.nextFloat(); |
|
387 |
|
|
388 |
for(int row=0; row<mRowChances.length; row++) |
|
389 |
{ |
|
390 |
if( rowFloat<=mRowChances[row] ) return row; |
|
391 |
} |
|
392 |
|
|
393 |
return 0; |
|
359 | 394 |
} |
360 | 395 |
|
361 | 396 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
src/main/java/org/distorted/objects/RubikDino.java | ||
---|---|---|
42 | 42 |
import org.distorted.library.type.Static3D; |
43 | 43 |
import org.distorted.library.type.Static4D; |
44 | 44 |
|
45 |
import java.util.Random; |
|
46 |
|
|
47 |
import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS; |
|
48 |
|
|
45 | 49 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
46 | 50 |
|
47 | 51 |
public class RubikDino extends RubikObject |
... | ... | |
338 | 342 |
return 2.0f; |
339 | 343 |
} |
340 | 344 |
|
345 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
346 |
|
|
347 |
float[] getRowChances() |
|
348 |
{ |
|
349 |
float[] chances = new float[3]; |
|
350 |
|
|
351 |
chances[0] = 0.5f; |
|
352 |
chances[1] = 0.5f; |
|
353 |
chances[2] = 1.0f; |
|
354 |
|
|
355 |
return chances; |
|
356 |
} |
|
357 |
|
|
341 | 358 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
342 | 359 |
// PUBLIC API |
343 | 360 |
|
... | ... | |
369 | 386 |
|
370 | 387 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
371 | 388 |
|
372 |
public float[] getRowChances()
|
|
389 |
public int randomizeNewRotAxis(Random rnd, int oldRotAxis)
|
|
373 | 390 |
{ |
374 |
float[] chances = new float[3];
|
|
391 |
int numAxis = ROTATION_AXIS.length;
|
|
375 | 392 |
|
376 |
chances[0] = 0.5f; |
|
377 |
chances[1] = 0.5f; |
|
378 |
chances[2] = 1.0f; |
|
393 |
if( oldRotAxis == START_AXIS ) |
|
394 |
{ |
|
395 |
return rnd.nextInt(numAxis); |
|
396 |
} |
|
397 |
else |
|
398 |
{ |
|
399 |
int newVector = rnd.nextInt(numAxis-1); |
|
400 |
return (newVector>=oldRotAxis ? newVector+1 : newVector); |
|
401 |
} |
|
402 |
} |
|
379 | 403 |
|
380 |
return chances; |
|
404 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
405 |
|
|
406 |
public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis) |
|
407 |
{ |
|
408 |
float rowFloat = rnd.nextFloat(); |
|
409 |
|
|
410 |
switch(oldRotAxis) |
|
411 |
{ |
|
412 |
case 0 : switch(newRotAxis) |
|
413 |
{ |
|
414 |
case 1: |
|
415 |
case 2: return oldRow; |
|
416 |
case 3: return 2-oldRow; |
|
417 |
default: android.util.Log.e("dino", "error: oldRotAxis="+oldRotAxis+" newRotAxis:"+newRotAxis); |
|
418 |
} |
|
419 |
case 1 : switch(newRotAxis) |
|
420 |
{ |
|
421 |
case 0: |
|
422 |
case 3: return oldRow; |
|
423 |
case 2: return 2-oldRow; |
|
424 |
default: android.util.Log.e("dino", "error: oldRotAxis="+oldRotAxis+" newRotAxis:"+newRotAxis); |
|
425 |
} |
|
426 |
case 2 : switch(newRotAxis) |
|
427 |
{ |
|
428 |
case 0: |
|
429 |
case 3: return oldRow; |
|
430 |
case 1: return 2-oldRow; |
|
431 |
default: android.util.Log.e("dino", "error: oldRotAxis="+oldRotAxis+" newRotAxis:"+newRotAxis); |
|
432 |
} |
|
433 |
case 3 : switch(newRotAxis) |
|
434 |
{ |
|
435 |
case 1: |
|
436 |
case 2: return oldRow; |
|
437 |
case 0: return 2-oldRow; |
|
438 |
default: android.util.Log.e("dino", "error: oldRotAxis="+oldRotAxis+" newRotAxis:"+newRotAxis); |
|
439 |
} |
|
440 |
default: return rowFloat<=0.5f ? 0:2; |
|
441 |
} |
|
381 | 442 |
} |
382 | 443 |
|
383 | 444 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
src/main/java/org/distorted/objects/RubikObject.java | ||
---|---|---|
49 | 49 |
import java.io.DataInputStream; |
50 | 50 |
import java.io.IOException; |
51 | 51 |
import java.io.InputStream; |
52 |
import java.util.Random; |
|
52 | 53 |
|
53 | 54 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
54 | 55 |
|
... | ... | |
90 | 91 |
private Static3D mObjectScale; |
91 | 92 |
|
92 | 93 |
float mStart, mStep; |
94 |
float[] mRowChances; |
|
93 | 95 |
|
94 | 96 |
Static1D mRotationAngleStatic, mRotationAngleMiddle, mRotationAngleFinal; |
95 | 97 |
DistortedTexture mTexture; |
... | ... | |
124 | 126 |
mNodeScale= new Static3D(1,NODE_RATIO,1); |
125 | 127 |
mQuat = quat; |
126 | 128 |
|
129 |
mRowChances = getRowChances(); |
|
130 |
|
|
127 | 131 |
mRotationAngle= new Dynamic1D(); |
128 | 132 |
mRotationAxis = new Static3D(1,0,0); |
129 | 133 |
mRotateEffect = new VertexEffectRotate(mRotationAngle, mRotationAxis, CENTER); |
... | ... | |
696 | 700 |
abstract void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top, int side); |
697 | 701 |
abstract int getFaceColor(int cubit, int cubitface, int size); |
698 | 702 |
abstract float returnMultiplier(); |
703 |
abstract float[] getRowChances(); |
|
704 |
|
|
699 | 705 |
public abstract Static3D[] getRotationAxis(); |
700 | 706 |
public abstract int getBasicAngle(); |
701 | 707 |
public abstract int computeRowFromOffset(float offset); |
702 | 708 |
public abstract float returnRotationFactor(float offset); |
703 | 709 |
public abstract String retObjectString(); |
704 |
public abstract float[] getRowChances(); |
|
710 |
public abstract int randomizeNewRotAxis(Random rnd, int oldRotAxis); |
|
711 |
public abstract int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis); |
|
705 | 712 |
} |
src/main/java/org/distorted/objects/RubikPyraminx.java | ||
---|---|---|
38 | 38 |
import org.distorted.library.type.Static3D; |
39 | 39 |
import org.distorted.library.type.Static4D; |
40 | 40 |
|
41 |
import java.util.Random; |
|
42 |
|
|
43 |
import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS; |
|
44 |
|
|
41 | 45 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
42 | 46 |
|
43 | 47 |
public class RubikPyraminx extends RubikObject |
... | ... | |
399 | 403 |
return getSize()/0.82f;//(SQ3/2); |
400 | 404 |
} |
401 | 405 |
|
406 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
407 |
|
|
408 |
float[] getRowChances() |
|
409 |
{ |
|
410 |
int size = getSize(); |
|
411 |
int total = size*(size+1)/2; |
|
412 |
float running=0.0f; |
|
413 |
float[] chances = new float[size]; |
|
414 |
|
|
415 |
for(int i=0; i<size; i++) |
|
416 |
{ |
|
417 |
running += (size-i); |
|
418 |
chances[i] = running / total; |
|
419 |
} |
|
420 |
|
|
421 |
return chances; |
|
422 |
} |
|
423 |
|
|
402 | 424 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
403 | 425 |
// PUBLIC API |
404 | 426 |
|
... | ... | |
424 | 446 |
|
425 | 447 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
426 | 448 |
|
427 |
public float[] getRowChances()
|
|
449 |
public float returnRotationFactor(float offset)
|
|
428 | 450 |
{ |
429 | 451 |
int size = getSize(); |
430 |
int total = size*(size+1)/2; |
|
431 |
float running=0.0f; |
|
432 |
float[] chances = new float[size]; |
|
452 |
int row = (int)(size*offset/(SQ3/2)); |
|
433 | 453 |
|
434 |
for(int i=0; i<size; i++) |
|
454 |
return ((float)size)/(size-row); |
|
455 |
} |
|
456 |
|
|
457 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
458 |
|
|
459 |
public int randomizeNewRotAxis(Random rnd, int oldRotAxis) |
|
460 |
{ |
|
461 |
int numAxis = ROTATION_AXIS.length; |
|
462 |
|
|
463 |
if( oldRotAxis == START_AXIS ) |
|
435 | 464 |
{ |
436 |
running += (size-i); |
|
437 |
chances[i] = running / total; |
|
465 |
return rnd.nextInt(numAxis); |
|
466 |
} |
|
467 |
else |
|
468 |
{ |
|
469 |
int newVector = rnd.nextInt(numAxis-1); |
|
470 |
return (newVector>=oldRotAxis ? newVector+1 : newVector); |
|
438 | 471 |
} |
439 |
|
|
440 |
return chances; |
|
441 | 472 |
} |
442 | 473 |
|
443 | 474 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
444 | 475 |
|
445 |
public float returnRotationFactor(float offset)
|
|
476 |
public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
|
|
446 | 477 |
{ |
447 |
int size = getSize(); |
|
448 |
int row = (int)(size*offset/(SQ3/2)); |
|
478 |
float rowFloat = rnd.nextFloat(); |
|
449 | 479 |
|
450 |
return ((float)size)/(size-row); |
|
480 |
for(int row=0; row<mRowChances.length; row++) |
|
481 |
{ |
|
482 |
if( rowFloat<=mRowChances[row] ) return row; |
|
483 |
} |
|
484 |
|
|
485 |
return 0; |
|
451 | 486 |
} |
452 | 487 |
|
453 | 488 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
Also available in: Unified diff
Adjust randomizing new rotations so that:
1) it works for basicAngle=5 (Megaminx) (so now basicAngle=2,3,4,5 supported)
2) it leaves the decision as to what can be the next rotation to the Object class, as in case of certain Objects (the Dino, or the Helicopter, the Megaminx) the next rotation doesn't have to 'intersect' the old rotation always when oldRotAxis != newRotAxis (that's so simple only in case of the Cube and - only partly - the Pyraminx!)