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 CHANGED
@@ -1,8 +1,22 @@
1
1
  # Arcanum Cube
2
2
 
3
- Arcanum Cube is a cube puzzle module written in Typescript. Supports creation and manipulation of WebGL mesh groups.
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
- [Demo Page](https://mawxiwtz.github.io/arcanumcube/)
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: 1118481,
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("#080");
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("#080");
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
- _pointLights;
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
- enableLight: false,
1391
- wireframe: false
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._pointLights = [];
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._pointLights = [];
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.enableLight) {
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 ? 32768 : 33023,
1453
- 30,
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._pointLights.push(light);
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.enableLight) {
1471
- this._pointLights.forEach((light) => {
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._tweens.getAll().length > 0) return;
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.enableLight) {
1674
- this._pointLights.forEach((light) => {
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._tweens.getAll().length > 0) return;
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._tweens.getAll().length > 0) return;
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._tweens.getAll().length > 0) return;
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
- for (const c of twist) {
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
- for (const c of twist) {
1738
- const t = this._tweenTwist(c, reverse, lap, cancel);
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,