import * as RE from 'rogue-engine' import * as THREE from 'three' import { TweenManager } from './Library/SimpleTweens' import Easing from './Library/Easings' import {LineMaterial} from '../manual_modules/threejs-jsm/lines/LineMaterial' import {LineGeometry} from '../manual_modules/threejs-jsm/lines/LineGeometry' import {Line2} from '../manual_modules/threejs-jsm/lines/Line2' import TileRaycastReceiver from './TileRaycastReceiver.re' import AsyncLoader from './Library/AsyncLoader'; import GameData from './Library/GameDataPersistent'; export default class GameLogic extends RE.Component { @RE.Prop("Object3D") playGrid @RE.Prop("Prefab") tile @RE.Prop("Material") hoverMaterial @RE.PropList("Material") tileMaterials = [] @RE.Prop("Material") pickedMaterial @RE.Prop("Vector2") boardDimensions = new THREE.Vector2(8, 8) @RE.Prop("Number") maxColors = 5 tweenManager = new TweenManager() loader = new AsyncLoader() selectedTiles = [] movesRemaining = 3 score = 0 awake() { this.tweenManager.awake() } start() { let level = GameData.get("active-level") ?? 1 this.levelData = GameData.get("level-data")[level] ?? {x: this.boardDimensions.x, y: this.boardDimensions.y, c: this.maxColors} this.score = this.levelData.g this.movesRemaining = 3 this.loader.loadStaticText("gamehud.html").then(html => { RE.Runtime.uiContainer.innerHTML = html for(let i = 0; i < this.levelData.x * this.levelData.y; i++) { this.instantiateTile( new THREE.Vector2((i % this.levelData.x), Math.floor(i / this.levelData.x)), Math.floor(1500 * Math.random()) + 1800, ) } this.movesDisplay = document.getElementById("moves") this.scoreDisplay = document.getElementById("score") }) this.tweenManager.start() for(let child of this.playGrid.children) { setTimeout(() => { this.playGrid.remove(child) }, 0) } } instantiateTile(gridPosition, delay, startingY = 14, easingFunction = Easing.Elastic.EaseOut) { let tile = this.tile.instantiate(this.playGrid) let component = RE.getComponent(TileRaycastReceiver, tile) component.initialize( new THREE.Vector2(gridPosition.x, gridPosition.y), this.tileMaterials[Math.floor(Math.random() * Math.min(this.levelData.c, this.tileMaterials.length))], this.hoverMaterial, this.tweenManager, delay, startingY, easingFunction, ) } update() { this.tweenManager.update() if(RE.Input.mouse.getButtonUp(0) || RE.Input.touch.endTouches.length > 0) { if(this.selectedTiles.length == 1) { this.selectedTiles.length = 0 } if(this.selectedTiles.length > 1 && this.selectedTiles.length < 5) { this.movesRemaining-- } if(this.selectedTiles.length >= 5) { this.movesRemaining += Math.floor((this.selectedTiles.length - 5) / 3) } this.movesDisplay.innerHTML = this.movesRemaining let moveScore = (this.selectedTiles.length * 10) this.selectedTiles.forEach(tileComponent => { moveScore *= Math.max(1, Math.floor(this.selectedTiles.indexOf(tileComponent) / 5)) tileComponent.remove(this.tweenManager) this.instantiateTile( tileComponent.object3d.gridPosition, Math.floor(1500 * Math.random()) + 300, -12, Easing.Exponential.EaseOut, ) }) this.selectedTiles.length = 0 this.score -= moveScore this.scoreDisplay.innerHTML = this.score } if(RE.Input.keyboard.getKeyUp("Escape")) { RE.App.loadScene("Main Menu") } if(this.movesRemaining == 0) { GameData.set('final-score', 1337) RE.App.loadScene("Game Over") } } buildLine() { let positions = [] this.selectedTiles.forEach(tileComponent => { let position = tileComponent.getPosition() positions.push(new THREE.Vector3(position.x, 1.2, position.y)) }) this.lineGeometry = new LineGeometry() this.lineMaterial = new LineMaterial({ color: 0xffffff, linewidth: 5, // in pixels vertexColors: true, //resolution: // to be set by renderer, eventually dashed: false }); this.line = new Line2(this.lineGeometry, this.lineMaterial); this.line.computeLineDistances(); this.line.scale.set(1, 1, 1); } addTile(tileComponent) { let isAdded = false if(this.selectedTiles.length == 0) { this.selectedTiles.push(tileComponent) isAdded = true return } if(this.isValidTileToSelect(tileComponent)) { this.selectedTiles.push(tileComponent) isAdded = true } return isAdded } isValidTileToSelect(tileComponent) { let lastAddedTile = this.selectedTiles[this.selectedTiles.length - 1] let initialColor = lastAddedTile.getOriginalMaterial().name return this.selectedTiles.indexOf(tileComponent) == -1 && tileComponent.getOriginalMaterial().name == initialColor && this.isNearbyTile(lastAddedTile.object3d.gridPosition, tileComponent.object3d.gridPosition) } isNearbyTile(startingPosition, newPosition) { return (newPosition.x == startingPosition.x - 1 || newPosition.x == startingPosition.x || newPosition.x == startingPosition.x + 1) && (newPosition.y == startingPosition.y - 1 || newPosition.y == startingPosition.y || newPosition.y == startingPosition.y + 1) } } RE.registerComponent(GameLogic);