arcanumcube 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -2
- package/dist/cjs/{arcanumcube.cjs → arcanumcube.js} +119 -29
- package/dist/cjs/core.js +733 -0
- package/dist/esm/arcanumcube.module.js +118 -29
- package/dist/esm/arcanumcube.module.min.js +4 -4
- package/dist/esm/core.module.js +686 -0
- package/dist/esm/core.module.min.js +4 -0
- package/dist/index.html +7 -7
- package/dist/types/core.d.ts +3 -0
- package/dist/types/webgl.d.ts +22 -6
- package/package.json +15 -4
package/README.md
CHANGED
|
@@ -1,8 +1,22 @@
|
|
|
1
1
|
# Arcanum Cube
|
|
2
2
|
|
|
3
|
-
Arcanum Cube is a cube puzzle module written in
|
|
3
|
+
Arcanum Cube Arcanum Cube is a WebGL cube puzzle module written in TypeScript. You can create Three.js meshes group and twist cube.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Demo Page
|
|
6
|
+
|
|
7
|
+
- [Example1](https://mawxiwtz.github.io/arcanumcube/) \
|
|
8
|
+
Rotation only
|
|
9
|
+
|
|
10
|
+
- [Example2](https://mawxiwtz.github.io/arcanumcube-demo/) \
|
|
11
|
+
Demo of playing and solving with AI
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
You can add arcanumcube as an npm dependency:
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
npm install arcanumcube
|
|
19
|
+
```
|
|
6
20
|
|
|
7
21
|
## Usage
|
|
8
22
|
|
|
@@ -16,11 +30,14 @@ import * as ARCCUBE from 'arcanumcube';
|
|
|
16
30
|
2. create a cube object
|
|
17
31
|
|
|
18
32
|
```
|
|
33
|
+
const scene = new THREE.Scene();
|
|
34
|
+
:
|
|
19
35
|
const arccube = new ARCCUBE.WebGLArcanumCube();
|
|
20
36
|
await arccube.init();
|
|
21
37
|
const arccubeGroup = arccube.getGroup();
|
|
22
38
|
arccubeGroup.position.set(0, 0, 0);
|
|
23
39
|
scene.add(arccubeGroup);
|
|
40
|
+
:
|
|
24
41
|
|
|
25
42
|
renderer.setAnimationLoop((time) => {
|
|
26
43
|
:
|
|
@@ -43,6 +60,10 @@ arccube.tweenTwist('U');
|
|
|
43
60
|
arccube.reset();
|
|
44
61
|
```
|
|
45
62
|
|
|
63
|
+
## Document
|
|
64
|
+
|
|
65
|
+
Currently under construction
|
|
66
|
+
|
|
46
67
|
## License
|
|
47
68
|
|
|
48
69
|
Released under the MIT license
|
|
@@ -43,6 +43,7 @@ __export(arcanumcube_exports, {
|
|
|
43
43
|
FACE: () => FACE,
|
|
44
44
|
GetSkinByName: () => GetSkinByName,
|
|
45
45
|
GetSkinNameList: () => GetSkinNameList,
|
|
46
|
+
MatchGoalState: () => MatchGoalState,
|
|
46
47
|
SIDE_MAX: () => SIDE_MAX,
|
|
47
48
|
SIDE_MIDDLE: () => SIDE_MIDDLE,
|
|
48
49
|
SIDE_MIN: () => SIDE_MIN,
|
|
@@ -329,6 +330,42 @@ function getRandomTwistList(steps = 0) {
|
|
|
329
330
|
}
|
|
330
331
|
return list;
|
|
331
332
|
}
|
|
333
|
+
var SIDE_FACES = Object.freeze([
|
|
334
|
+
[1, 2, 4, 5],
|
|
335
|
+
[2, 0, 5, 3],
|
|
336
|
+
[0, 1, 3, 4],
|
|
337
|
+
[2, 1, 5, 4],
|
|
338
|
+
[0, 2, 3, 5],
|
|
339
|
+
[1, 0, 4, 3]
|
|
340
|
+
]);
|
|
341
|
+
function getInitialState(up, front) {
|
|
342
|
+
const down = (up + 3) % 6;
|
|
343
|
+
const side = SIDE_FACES[up];
|
|
344
|
+
const state = new Array(CUBE_SIZE * CUBE_SIZE).fill(up);
|
|
345
|
+
for (let i = 0; i < 4; i++) {
|
|
346
|
+
if (i == 2) {
|
|
347
|
+
const downs = [...Array(CUBE_SIZE * CUBE_SIZE)].fill(down);
|
|
348
|
+
state.push(...downs);
|
|
349
|
+
}
|
|
350
|
+
const sides = [...Array(CUBE_SIZE * CUBE_SIZE)].fill(side[(front + i) % 4]);
|
|
351
|
+
state.push(...sides);
|
|
352
|
+
}
|
|
353
|
+
return state;
|
|
354
|
+
}
|
|
355
|
+
function isSameArrays(arr1, arr2) {
|
|
356
|
+
if (arr1.length !== arr2.length) return false;
|
|
357
|
+
return !arr1.some((v, i) => v !== arr2[i]);
|
|
358
|
+
}
|
|
359
|
+
var GOAL_STATE_LIST = [];
|
|
360
|
+
for (let up = 0; up < 6; up++) {
|
|
361
|
+
for (let front = 0; front < 4; front++) {
|
|
362
|
+
GOAL_STATE_LIST.push(getInitialState(up, front));
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
Object.freeze(GOAL_STATE_LIST);
|
|
366
|
+
function MatchGoalState(state) {
|
|
367
|
+
return GOAL_STATE_LIST.some((s) => isSameArrays(state, s));
|
|
368
|
+
}
|
|
332
369
|
var Cube = class {
|
|
333
370
|
type;
|
|
334
371
|
position;
|
|
@@ -473,6 +510,9 @@ var ArcanumCube = class {
|
|
|
473
510
|
const list = this.getUndoList(steps);
|
|
474
511
|
this.twist(list, true);
|
|
475
512
|
}
|
|
513
|
+
isSolved() {
|
|
514
|
+
return MatchGoalState(this.getStickerColors());
|
|
515
|
+
}
|
|
476
516
|
getHistory() {
|
|
477
517
|
return this._history;
|
|
478
518
|
}
|
|
@@ -716,7 +756,7 @@ var standardSkin = {
|
|
|
716
756
|
cube: {
|
|
717
757
|
material: () => {
|
|
718
758
|
return new THREE.MeshStandardMaterial({
|
|
719
|
-
color:
|
|
759
|
+
color: 3092271,
|
|
720
760
|
metalness: 0.8,
|
|
721
761
|
roughness: 0.4
|
|
722
762
|
});
|
|
@@ -1200,7 +1240,8 @@ var WebGLCube = class extends Cube {
|
|
|
1200
1240
|
gap: 0.01,
|
|
1201
1241
|
enableShadow: false,
|
|
1202
1242
|
skin: DefaultSkin,
|
|
1203
|
-
wireframe: false
|
|
1243
|
+
wireframe: false,
|
|
1244
|
+
wireframeColor: 32768
|
|
1204
1245
|
};
|
|
1205
1246
|
if (opts) {
|
|
1206
1247
|
Object.assign(this._config, opts);
|
|
@@ -1244,7 +1285,7 @@ var WebGLCube = class extends Cube {
|
|
|
1244
1285
|
}
|
|
1245
1286
|
if (config.wireframe) {
|
|
1246
1287
|
mat.wireframe = config.wireframe;
|
|
1247
|
-
mat.color = new THREE3.Color(
|
|
1288
|
+
mat.color = new THREE3.Color(config.wireframeColor);
|
|
1248
1289
|
}
|
|
1249
1290
|
const m = new THREE3.Mesh(geo, mat);
|
|
1250
1291
|
m.name = this.type;
|
|
@@ -1285,7 +1326,7 @@ var WebGLCube = class extends Cube {
|
|
|
1285
1326
|
}
|
|
1286
1327
|
if (config.wireframe) {
|
|
1287
1328
|
pmat.wireframe = config.wireframe;
|
|
1288
|
-
pmat.color = new THREE3.Color(
|
|
1329
|
+
pmat.color = new THREE3.Color(config.wireframeColor);
|
|
1289
1330
|
}
|
|
1290
1331
|
const pm = new THREE3.Mesh(pgeo, pmat);
|
|
1291
1332
|
pm.name = CUBE.STICKER;
|
|
@@ -1375,7 +1416,9 @@ var WebGLArcanumCube = class extends ArcanumCube {
|
|
|
1375
1416
|
/** tween group */
|
|
1376
1417
|
_tweens;
|
|
1377
1418
|
/** light at the center of cube */
|
|
1378
|
-
|
|
1419
|
+
_coreLights;
|
|
1420
|
+
/** status of locking the twist */
|
|
1421
|
+
_lockTwist;
|
|
1379
1422
|
constructor(options) {
|
|
1380
1423
|
super(options);
|
|
1381
1424
|
this._config = {
|
|
@@ -1387,8 +1430,12 @@ var WebGLArcanumCube = class extends ArcanumCube {
|
|
|
1387
1430
|
gap: 0.01,
|
|
1388
1431
|
enableShadow: false,
|
|
1389
1432
|
skin: DefaultSkin,
|
|
1390
|
-
|
|
1391
|
-
|
|
1433
|
+
enableCoreLight: false,
|
|
1434
|
+
coreLightColor: 33023,
|
|
1435
|
+
coreLightIntensity: 30,
|
|
1436
|
+
wireframe: false,
|
|
1437
|
+
wireframeColor: 32768,
|
|
1438
|
+
twistOptions: {}
|
|
1392
1439
|
};
|
|
1393
1440
|
this._matrix = [];
|
|
1394
1441
|
this._group = new THREE3.Group();
|
|
@@ -1396,7 +1443,8 @@ var WebGLArcanumCube = class extends ArcanumCube {
|
|
|
1396
1443
|
this._cubeMap = {};
|
|
1397
1444
|
this._cancelDragDeg = 15;
|
|
1398
1445
|
this._tweens = new TWEEN.Group();
|
|
1399
|
-
this.
|
|
1446
|
+
this._coreLights = [];
|
|
1447
|
+
this._lockTwist = false;
|
|
1400
1448
|
if (options) {
|
|
1401
1449
|
Object.assign(this._config, options);
|
|
1402
1450
|
}
|
|
@@ -1422,7 +1470,7 @@ var WebGLArcanumCube = class extends ArcanumCube {
|
|
|
1422
1470
|
this._cubeMap = {};
|
|
1423
1471
|
this._matrix = [];
|
|
1424
1472
|
this._history = [];
|
|
1425
|
-
this.
|
|
1473
|
+
this._coreLights = [];
|
|
1426
1474
|
const fixedGroups = new THREE3.Group();
|
|
1427
1475
|
const config = this._config;
|
|
1428
1476
|
const yarray = [];
|
|
@@ -1438,7 +1486,8 @@ var WebGLArcanumCube = class extends ArcanumCube {
|
|
|
1438
1486
|
enableShadow: config.enableShadow,
|
|
1439
1487
|
skin: config.skin,
|
|
1440
1488
|
envMap: config.envMap,
|
|
1441
|
-
wireframe: config.wireframe
|
|
1489
|
+
wireframe: config.wireframe,
|
|
1490
|
+
wireframeColor: config.wireframeColor
|
|
1442
1491
|
});
|
|
1443
1492
|
cube.init();
|
|
1444
1493
|
xarray.push(cube);
|
|
@@ -1446,18 +1495,18 @@ var WebGLArcanumCube = class extends ArcanumCube {
|
|
|
1446
1495
|
this._cubeObjectList.push(entityGroup);
|
|
1447
1496
|
this._cubeMap[entityGroup.id] = cube;
|
|
1448
1497
|
fixedGroups.add(cube.getGroup());
|
|
1449
|
-
if (config.
|
|
1498
|
+
if (config.enableCoreLight) {
|
|
1450
1499
|
if (x !== SIDE_MIN && y !== SIDE_MIN && z !== SIDE_MIN) {
|
|
1451
1500
|
const light = new THREE3.PointLight(
|
|
1452
|
-
config.wireframe ?
|
|
1453
|
-
|
|
1501
|
+
config.wireframe ? config.wireframeColor : config.coreLightColor,
|
|
1502
|
+
config.coreLightIntensity,
|
|
1454
1503
|
20,
|
|
1455
1504
|
0.1
|
|
1456
1505
|
);
|
|
1457
1506
|
light.position.x = (x - 1 / 2) * CUBE_SIDE_LEN * (1 + config.gap) * config.scale;
|
|
1458
1507
|
light.position.y = (y - 1 / 2) * CUBE_SIDE_LEN * (1 + config.gap) * config.scale;
|
|
1459
1508
|
light.position.z += (z - 1 / 2) * CUBE_SIDE_LEN * (1 + config.gap) * config.scale;
|
|
1460
|
-
this.
|
|
1509
|
+
this._coreLights.push(light);
|
|
1461
1510
|
}
|
|
1462
1511
|
}
|
|
1463
1512
|
}
|
|
@@ -1467,8 +1516,8 @@ var WebGLArcanumCube = class extends ArcanumCube {
|
|
|
1467
1516
|
}
|
|
1468
1517
|
this._matrix = yarray;
|
|
1469
1518
|
this._group.clear();
|
|
1470
|
-
if (config.
|
|
1471
|
-
this.
|
|
1519
|
+
if (config.enableCoreLight) {
|
|
1520
|
+
this._coreLights.forEach((light) => {
|
|
1472
1521
|
this._group.add(light);
|
|
1473
1522
|
});
|
|
1474
1523
|
}
|
|
@@ -1492,8 +1541,14 @@ var WebGLArcanumCube = class extends ArcanumCube {
|
|
|
1492
1541
|
}
|
|
1493
1542
|
await this.init();
|
|
1494
1543
|
}
|
|
1544
|
+
lockTwist(flag) {
|
|
1545
|
+
this._lockTwist = flag;
|
|
1546
|
+
}
|
|
1547
|
+
isTwisting() {
|
|
1548
|
+
return this._tweens.getAll().length > 0;
|
|
1549
|
+
}
|
|
1495
1550
|
reset(duration = 1800) {
|
|
1496
|
-
if (this.
|
|
1551
|
+
if (this._lockTwist || this.isTwisting()) return;
|
|
1497
1552
|
if (this._selectedCube) this.deselectCube();
|
|
1498
1553
|
if (this._selectedSticker) this.deselectSticker();
|
|
1499
1554
|
this._twistGroup = void 0;
|
|
@@ -1670,8 +1725,8 @@ var WebGLArcanumCube = class extends ArcanumCube {
|
|
|
1670
1725
|
}
|
|
1671
1726
|
}
|
|
1672
1727
|
this._group.clear();
|
|
1673
|
-
if (this._config.
|
|
1674
|
-
this.
|
|
1728
|
+
if (this._config.enableCoreLight) {
|
|
1729
|
+
this._coreLights.forEach((light) => {
|
|
1675
1730
|
this._group.add(light);
|
|
1676
1731
|
});
|
|
1677
1732
|
}
|
|
@@ -1680,7 +1735,7 @@ var WebGLArcanumCube = class extends ArcanumCube {
|
|
|
1680
1735
|
return twistGroup;
|
|
1681
1736
|
}
|
|
1682
1737
|
dragTwist(twist, rad) {
|
|
1683
|
-
if (this.
|
|
1738
|
+
if (this._lockTwist || this.isTwisting()) return;
|
|
1684
1739
|
if (!this._draggingTwist || this._draggingTwist.twist != twist) {
|
|
1685
1740
|
this._draggingTwist = {
|
|
1686
1741
|
twist,
|
|
@@ -1695,7 +1750,7 @@ var WebGLArcanumCube = class extends ArcanumCube {
|
|
|
1695
1750
|
this._draggingTwist.group.quaternion.copy(q);
|
|
1696
1751
|
}
|
|
1697
1752
|
dragTwistEnd() {
|
|
1698
|
-
if (this.
|
|
1753
|
+
if (this._lockTwist || this.isTwisting()) return;
|
|
1699
1754
|
if (this._draggingTwist) {
|
|
1700
1755
|
const deg = this._draggingTwist.rad * 180 / Math.PI;
|
|
1701
1756
|
if (deg > this._cancelDragDeg) {
|
|
@@ -1708,7 +1763,7 @@ var WebGLArcanumCube = class extends ArcanumCube {
|
|
|
1708
1763
|
// twist randomly several steps
|
|
1709
1764
|
scramble(steps = 0, duration = 3e3) {
|
|
1710
1765
|
const list = getRandomTwistList(steps);
|
|
1711
|
-
this.tweenTwist(list, false, duration);
|
|
1766
|
+
this.tweenTwist(list, false, duration, false);
|
|
1712
1767
|
}
|
|
1713
1768
|
undo(steps = 1, duration = 300) {
|
|
1714
1769
|
const list = this.getUndoList(steps);
|
|
@@ -1716,17 +1771,25 @@ var WebGLArcanumCube = class extends ArcanumCube {
|
|
|
1716
1771
|
}
|
|
1717
1772
|
// twisting(複数回対応)
|
|
1718
1773
|
// durationを0にするとTweenなしとなる
|
|
1719
|
-
tweenTwist(twist, reverse = false, duration = 500, cancel = false) {
|
|
1720
|
-
if (this.
|
|
1774
|
+
tweenTwist(twist, reverse = false, duration = 500, cancel = false, options) {
|
|
1775
|
+
if (this._lockTwist || this.isTwisting()) return;
|
|
1776
|
+
options = { ...this._config.twistOptions, ...options };
|
|
1721
1777
|
if (duration === 0) {
|
|
1722
1778
|
if (Array.isArray(twist)) {
|
|
1723
1779
|
if (twist.length == 0) return;
|
|
1724
|
-
|
|
1780
|
+
options?.onStart && options.onStart(this);
|
|
1781
|
+
const len = twist.length;
|
|
1782
|
+
for (let i = 0; i < len; i++) {
|
|
1783
|
+
const c = twist[i];
|
|
1725
1784
|
this._immediatelyTwist(c, reverse);
|
|
1785
|
+
options?.onTwisted && options.onTwisted(this, c, i + 1, len);
|
|
1726
1786
|
}
|
|
1727
1787
|
} else {
|
|
1788
|
+
options?.onStart && options.onStart(this);
|
|
1728
1789
|
this._immediatelyTwist(twist, reverse);
|
|
1790
|
+
options?.onTwisted && options.onTwisted(this, twist, 1, 1);
|
|
1729
1791
|
}
|
|
1792
|
+
options?.onComplete && options.onComplete(this);
|
|
1730
1793
|
return;
|
|
1731
1794
|
}
|
|
1732
1795
|
let firstTween = void 0;
|
|
@@ -1734,8 +1797,15 @@ var WebGLArcanumCube = class extends ArcanumCube {
|
|
|
1734
1797
|
if (Array.isArray(twist)) {
|
|
1735
1798
|
if (twist.length == 0) return;
|
|
1736
1799
|
const lap = duration / twist.length;
|
|
1737
|
-
|
|
1738
|
-
|
|
1800
|
+
const len = twist.length;
|
|
1801
|
+
for (let i = 0; i < len; i++) {
|
|
1802
|
+
const c = twist[i];
|
|
1803
|
+
const opts = {};
|
|
1804
|
+
const ontwisted = options?.onTwisted;
|
|
1805
|
+
if (ontwisted)
|
|
1806
|
+
opts.onTwisted = (self, twist2, n1, n2) => ontwisted(this, twist2, i + 1, len);
|
|
1807
|
+
if (i === len - 1 && options?.onComplete) opts.onComplete = options.onComplete;
|
|
1808
|
+
const t = this._tweenTwist(c, reverse, lap, cancel, opts);
|
|
1739
1809
|
this._tweens.add(t);
|
|
1740
1810
|
if (!tween) {
|
|
1741
1811
|
firstTween = tween = t;
|
|
@@ -1745,10 +1815,11 @@ var WebGLArcanumCube = class extends ArcanumCube {
|
|
|
1745
1815
|
}
|
|
1746
1816
|
}
|
|
1747
1817
|
} else {
|
|
1748
|
-
firstTween = this._tweenTwist(twist, reverse, duration, cancel);
|
|
1818
|
+
firstTween = this._tweenTwist(twist, reverse, duration, cancel, options);
|
|
1749
1819
|
this._tweens.add(firstTween);
|
|
1750
1820
|
}
|
|
1751
1821
|
if (firstTween) {
|
|
1822
|
+
options?.onStart && options.onStart(this);
|
|
1752
1823
|
firstTween.start();
|
|
1753
1824
|
}
|
|
1754
1825
|
}
|
|
@@ -1770,7 +1841,7 @@ var WebGLArcanumCube = class extends ArcanumCube {
|
|
|
1770
1841
|
super.twist(twist, reverse);
|
|
1771
1842
|
}
|
|
1772
1843
|
// twist with tween
|
|
1773
|
-
_tweenTwist(twist, reverse, duration, cancel) {
|
|
1844
|
+
_tweenTwist(twist, reverse, duration, cancel, options = {}) {
|
|
1774
1845
|
let qa;
|
|
1775
1846
|
if (this._draggingTwist) {
|
|
1776
1847
|
this._twistGroup = this._draggingTwist.group;
|
|
@@ -1807,12 +1878,30 @@ var WebGLArcanumCube = class extends ArcanumCube {
|
|
|
1807
1878
|
super.twist(twist, reverse);
|
|
1808
1879
|
}
|
|
1809
1880
|
this._tweens.remove(tween);
|
|
1881
|
+
options.onTwisted && options.onTwisted(this, twist, 1, 1);
|
|
1882
|
+
options.onComplete && options.onComplete(this);
|
|
1883
|
+
if (options.onSolved && this.isSolved()) {
|
|
1884
|
+
options.onSolved(this);
|
|
1885
|
+
}
|
|
1810
1886
|
});
|
|
1811
1887
|
return tween;
|
|
1812
1888
|
}
|
|
1813
1889
|
updateTweens() {
|
|
1814
1890
|
this._tweens.update();
|
|
1815
1891
|
}
|
|
1892
|
+
// set color of core lights
|
|
1893
|
+
setCoreLightColor(color) {
|
|
1894
|
+
const c = new THREE3.Color(color);
|
|
1895
|
+
this._coreLights.forEach((l) => {
|
|
1896
|
+
l.color = c;
|
|
1897
|
+
});
|
|
1898
|
+
}
|
|
1899
|
+
// change intensity of core lights
|
|
1900
|
+
setCoreLightIntensity(intensity) {
|
|
1901
|
+
this._coreLights.forEach((l) => {
|
|
1902
|
+
l.intensity = intensity;
|
|
1903
|
+
});
|
|
1904
|
+
}
|
|
1816
1905
|
};
|
|
1817
1906
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1818
1907
|
0 && (module.exports = {
|
|
@@ -1829,6 +1918,7 @@ var WebGLArcanumCube = class extends ArcanumCube {
|
|
|
1829
1918
|
FACE,
|
|
1830
1919
|
GetSkinByName,
|
|
1831
1920
|
GetSkinNameList,
|
|
1921
|
+
MatchGoalState,
|
|
1832
1922
|
SIDE_MAX,
|
|
1833
1923
|
SIDE_MIDDLE,
|
|
1834
1924
|
SIDE_MIN,
|