GameLogic.re.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. import * as RE from 'rogue-engine'
  2. import * as THREE from 'three'
  3. import { TweenManager } from './Library/SimpleTweens'
  4. import Easing from './Library/Easings'
  5. import {LineMaterial} from '../manual_modules/threejs-jsm/lines/LineMaterial'
  6. import {LineGeometry} from '../manual_modules/threejs-jsm/lines/LineGeometry'
  7. import {Line2} from '../manual_modules/threejs-jsm/lines/Line2'
  8. import TileRaycastReceiver from './TileRaycastReceiver.re'
  9. import AsyncLoader from './Library/AsyncLoader';
  10. import GameData from './Library/GameDataPersistent';
  11. export default class GameLogic extends RE.Component {
  12. @RE.Prop("Object3D") playGrid
  13. @RE.Prop("Prefab") tile
  14. @RE.Prop("Material") hoverMaterial
  15. @RE.PropList("Material") tileMaterials = []
  16. @RE.Prop("Material") pickedMaterial
  17. @RE.Prop("Vector2") boardDimensions = new THREE.Vector2(8, 8)
  18. @RE.Prop("Number") maxColors = 5
  19. tweenManager = new TweenManager()
  20. loader = new AsyncLoader()
  21. selectedTiles = []
  22. movesRemaining = 3
  23. score = 0
  24. awake() {
  25. this.tweenManager.awake()
  26. }
  27. start() {
  28. let level = GameData.get("active-level") ?? 1
  29. this.levelData = GameData.get("level-data")[level] ?? {x: this.boardDimensions.x, y: this.boardDimensions.y, c: this.maxColors}
  30. this.score = this.levelData.g
  31. this.movesRemaining = 3
  32. this.loader.loadStaticText("gamehud.html").then(html => {
  33. RE.Runtime.uiContainer.innerHTML = html
  34. for(let i = 0; i < this.levelData.x * this.levelData.y; i++) {
  35. this.instantiateTile(
  36. new THREE.Vector2((i % this.levelData.x), Math.floor(i / this.levelData.x)),
  37. Math.floor(1500 * Math.random()) + 1800,
  38. )
  39. }
  40. this.movesDisplay = document.getElementById("moves")
  41. this.scoreDisplay = document.getElementById("score")
  42. })
  43. this.tweenManager.start()
  44. for(let child of this.playGrid.children) {
  45. setTimeout(() => {
  46. this.playGrid.remove(child)
  47. }, 0)
  48. }
  49. }
  50. instantiateTile(gridPosition, delay, startingY = 14, easingFunction = Easing.Elastic.EaseOut) {
  51. let tile = this.tile.instantiate(this.playGrid)
  52. let component = RE.getComponent(TileRaycastReceiver, tile)
  53. component.initialize(
  54. new THREE.Vector2(gridPosition.x, gridPosition.y),
  55. this.tileMaterials[Math.floor(Math.random() * Math.min(this.levelData.c, this.tileMaterials.length))],
  56. this.hoverMaterial,
  57. this.tweenManager,
  58. delay,
  59. startingY,
  60. easingFunction,
  61. )
  62. }
  63. update() {
  64. this.tweenManager.update()
  65. if(RE.Input.mouse.getButtonUp(0) || RE.Input.touch.endTouches.length > 0) {
  66. if(this.selectedTiles.length == 1) {
  67. this.selectedTiles.length = 0
  68. }
  69. if(this.selectedTiles.length > 1 && this.selectedTiles.length < 5) {
  70. this.movesRemaining--
  71. }
  72. if(this.selectedTiles.length >= 5) {
  73. this.movesRemaining += Math.floor((this.selectedTiles.length - 5) / 3)
  74. }
  75. this.movesDisplay.innerHTML = this.movesRemaining
  76. let moveScore = (this.selectedTiles.length * 10)
  77. this.selectedTiles.forEach(tileComponent => {
  78. moveScore *= Math.max(1, Math.floor(this.selectedTiles.indexOf(tileComponent) / 5))
  79. tileComponent.remove(this.tweenManager)
  80. this.instantiateTile(
  81. tileComponent.object3d.gridPosition,
  82. Math.floor(1500 * Math.random()) + 300,
  83. -12,
  84. Easing.Exponential.EaseOut,
  85. )
  86. })
  87. this.selectedTiles.length = 0
  88. this.score -= moveScore
  89. this.scoreDisplay.innerHTML = this.score
  90. }
  91. if(RE.Input.keyboard.getKeyUp("Escape")) {
  92. RE.App.loadScene("Main Menu")
  93. }
  94. if(this.movesRemaining == 0) {
  95. GameData.set('final-score', 1337)
  96. RE.App.loadScene("Game Over")
  97. }
  98. }
  99. buildLine() {
  100. let positions = []
  101. this.selectedTiles.forEach(tileComponent => {
  102. let position = tileComponent.getPosition()
  103. positions.push(new THREE.Vector3(position.x, 1.2, position.y))
  104. })
  105. this.lineGeometry = new LineGeometry()
  106. this.lineMaterial = new LineMaterial({
  107. color: 0xffffff,
  108. linewidth: 5, // in pixels
  109. vertexColors: true,
  110. //resolution: // to be set by renderer, eventually
  111. dashed: false
  112. });
  113. this.line = new Line2(this.lineGeometry, this.lineMaterial);
  114. this.line.computeLineDistances();
  115. this.line.scale.set(1, 1, 1);
  116. }
  117. addTile(tileComponent) {
  118. let isAdded = false
  119. if(this.selectedTiles.length == 0) {
  120. this.selectedTiles.push(tileComponent)
  121. isAdded = true
  122. return
  123. }
  124. if(this.isValidTileToSelect(tileComponent)) {
  125. this.selectedTiles.push(tileComponent)
  126. isAdded = true
  127. }
  128. return isAdded
  129. }
  130. isValidTileToSelect(tileComponent) {
  131. let lastAddedTile = this.selectedTiles[this.selectedTiles.length - 1]
  132. let initialColor = lastAddedTile.getOriginalMaterial().name
  133. return this.selectedTiles.indexOf(tileComponent) == -1 &&
  134. tileComponent.getOriginalMaterial().name == initialColor &&
  135. this.isNearbyTile(lastAddedTile.object3d.gridPosition, tileComponent.object3d.gridPosition)
  136. }
  137. isNearbyTile(startingPosition, newPosition) {
  138. return (newPosition.x == startingPosition.x - 1 ||
  139. newPosition.x == startingPosition.x ||
  140. newPosition.x == startingPosition.x + 1) &&
  141. (newPosition.y == startingPosition.y - 1 ||
  142. newPosition.y == startingPosition.y ||
  143. newPosition.y == startingPosition.y + 1)
  144. }
  145. }
  146. RE.registerComponent(GameLogic);