From f22037e54016cd0a1d5636ece395c97dfa9f5e66 Mon Sep 17 00:00:00 2001 From: Georgios Andreadis Date: Thu, 31 Aug 2017 22:03:58 +0200 Subject: Determine hover tile validity --- .../map/layers/HoverTileLayerComponent.js | 56 ++++++++++----- src/containers/map/layers/HoverTileLayer.js | 22 +++++- src/util/tile-calculations.js | 79 ++++++++++++++++++++++ 3 files changed, 138 insertions(+), 19 deletions(-) diff --git a/src/components/map/layers/HoverTileLayerComponent.js b/src/components/map/layers/HoverTileLayerComponent.js index 691b9733..a4d9446a 100644 --- a/src/components/map/layers/HoverTileLayerComponent.js +++ b/src/components/map/layers/HoverTileLayerComponent.js @@ -3,25 +3,45 @@ import {Layer} from "react-konva"; import HoverTile from "../elements/HoverTile"; import {TILE_SIZE_IN_PIXELS} from "../MapConstants"; -const HoverTileLayerComponent = ({mainGroupX, mainGroupY, mouseX, mouseY, currentRoomInConstruction, isValid, onClick}) => { - if (currentRoomInConstruction === -1) { - return +class HoverTileLayerComponent extends React.Component { + state = { + positionX: -1, + positionY: -1, + validity: false, + }; + + componentDidUpdate() { + if (this.props.currentRoomInConstruction === -1) { + return; + } + + const positionX = Math.floor((this.props.mouseX - this.props.mainGroupX) / TILE_SIZE_IN_PIXELS); + const positionY = Math.floor((this.props.mouseY - this.props.mainGroupY) / TILE_SIZE_IN_PIXELS); + + if (positionX !== this.state.positionX || positionY !== this.state.positionY) { + this.setState({positionX, positionY, validity: this.props.isValid(positionX, positionY)}); + } } - const positionX = Math.floor((mouseX - mainGroupX) / TILE_SIZE_IN_PIXELS); - const positionY = Math.floor((mouseY - mainGroupY) / TILE_SIZE_IN_PIXELS); - const pixelX = positionX * TILE_SIZE_IN_PIXELS + mainGroupX; - const pixelY = positionY * TILE_SIZE_IN_PIXELS + mainGroupY; - const validity = isValid(positionX, positionY); - - return ( - - onClick(positionX, positionY)} - /> - - ); -}; + render() { + if (this.props.currentRoomInConstruction === -1) { + return ; + } + + const positionX = Math.floor((this.props.mouseX - this.props.mainGroupX) / TILE_SIZE_IN_PIXELS); + const positionY = Math.floor((this.props.mouseY - this.props.mainGroupY) / TILE_SIZE_IN_PIXELS); + const pixelX = positionX * TILE_SIZE_IN_PIXELS + this.props.mainGroupX; + const pixelY = positionY * TILE_SIZE_IN_PIXELS + this.props.mainGroupY; + + return ( + + this.props.onClick(positionX, positionY)} + /> + + ); + } +} export default HoverTileLayerComponent; diff --git a/src/containers/map/layers/HoverTileLayer.js b/src/containers/map/layers/HoverTileLayer.js index b8868233..d8a1d983 100644 --- a/src/containers/map/layers/HoverTileLayer.js +++ b/src/containers/map/layers/HoverTileLayer.js @@ -1,11 +1,31 @@ import {connect} from "react-redux"; import {toggleTileAtLocation} from "../../../actions/topology"; import HoverTileLayerComponent from "../../../components/map/layers/HoverTileLayerComponent"; +import { + deriveValidNextTilePositions, + findPositionInPositions, + findPositionInRooms +} from "../../../util/tile-calculations"; const mapStateToProps = state => { return { currentRoomInConstruction: state.currentRoomInConstruction, - isValid: (x, y) => true, // TODO implement proper validation + isValid: (x, y) => { + const newRoom = Object.assign({}, state.objects.room[state.currentRoomInConstruction]); + const oldRooms = Object.keys(state.objects.room) + .map(id => Object.assign({}, state.objects.room[id])) + .filter(room => room.id !== state.currentRoomInConstruction); + + [...oldRooms, newRoom].forEach(room => { + room.tiles = room.tileIds.map(tileId => state.objects.tile[tileId]); + }); + if (newRoom.tileIds.length === 0) { + return findPositionInRooms(oldRooms, x, y) === -1; + } + + const validNextPositions = deriveValidNextTilePositions(oldRooms, newRoom.tiles); + return findPositionInPositions(validNextPositions, x, y) !== -1; + }, }; }; diff --git a/src/util/tile-calculations.js b/src/util/tile-calculations.js index 3050a404..4d81dd31 100644 --- a/src/util/tile-calculations.js +++ b/src/util/tile-calculations.js @@ -125,3 +125,82 @@ export function deriveWallLocations(tiles) { return result; } + +export function deriveValidNextTilePositions(rooms, selectedTiles) { + const result = [], newPosition = {x: 0, y: 0}; + let isSurroundingTile; + + selectedTiles.forEach((tile) => { + const x = tile.positionX; + const y = tile.positionY; + result.push({x, y}); + + for (let dX = -1; dX <= 1; dX++) { + for (let dY = -1; dY <= 1; dY++) { + if (Math.abs(dX) === Math.abs(dY)) { + continue; + } + + newPosition.x = x + dX; + newPosition.y = y + dY; + + isSurroundingTile = true; + for (let index in selectedTiles) { + if (selectedTiles[index].positionX === newPosition.x + && selectedTiles[index].positionY === newPosition.y) { + isSurroundingTile = false; + break; + } + } + + if (isSurroundingTile && findPositionInRooms(rooms, newPosition.x, newPosition.y) === -1) { + result.push({x: newPosition.x, y: newPosition.y}); + } + } + } + }); + + return result; +} + +export function findPositionInPositions(positions, positionX, positionY) { + let index = -1; + + for (let i = 0; i < positions.length; i++) { + const position = positions[i]; + if (positionX === position.x && positionY === position.y) { + index = i; + break; + } + } + + return index; +} + +export function findPositionInRooms(rooms, positionX, positionY) { + let index = -1; + + for (let i = 0; i < rooms.length; i++) { + const room = rooms[i]; + if (findPositionInTiles(room.tiles, positionX, positionY) !== -1) { + index = i; + break; + } + } + + return index; +} + +function findPositionInTiles(tiles, positionX, positionY) { + let index = -1; + + for (let i = 0; i < tiles.length; i++) { + const tile = tiles[i]; + if (positionX === tile.positionX && positionY === tile.positionY) { + index = i; + break; + } + } + + return index; +} -- cgit v1.2.3