/* * Copyright (c) 2012. HappyDroids LLC, All rights reserved. */ package com.happydroids.droidtowers.grid; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; import com.google.common.eventbus.Subscribe; import com.happydroids.droidtowers.TowerConsts; import com.happydroids.droidtowers.entities.GridObject; import com.happydroids.droidtowers.events.GameGridResizeEvent; import com.happydroids.droidtowers.events.GridObjectBoundsChangeEvent; import com.happydroids.droidtowers.events.GridObjectPlacedEvent; import com.happydroids.droidtowers.events.GridObjectRemovedEvent; import com.happydroids.droidtowers.math.GridPoint; public class GridPositionCache { private GridPosition[][] gridPositions; private GridPoint gridSize; private final GameGrid gameGrid; private float[][] noiseLevels; public GridPositionCache(GameGrid gameGrid) { this.gameGrid = gameGrid; this.gameGrid.events().register(this); } @Subscribe public void handleGameGridResizeEvent(GameGridResizeEvent event) { if (gridSize != null && gridSize.equals(gameGrid.getGridSize())) { return; } boolean copyExisting = false; GridPosition[][] oldPositions = null; if (event.copyGridPositions) { if (gridSize != null && gridPositions != null) { oldPositions = gridPositions; copyExisting = true; } } gridSize = gameGrid.getGridSize().cpy(); gridPositions = new GridPosition[gridSize.x + 1][gridSize.y + 1]; if (copyExisting) { for (int x = 0; x < oldPositions.length; x++) { System.arraycopy(oldPositions[x], 0, gridPositions[x], 0, oldPositions[x].length); } } for (short x = 0; x <= gridSize.x; x++) { for (short y = 0; y <= gridSize.y; y++) { if (gridPositions[x][y] == null) { gridPositions[x][y] = new GridPosition(x, y); } } } } private void addGridObjectToPosition(GridObject gridObject) { for (int x = gridObject.getPosition().x; x < gridObject.getPosition().x + gridObject.getSize().x; x++) { for (int y = gridObject.getPosition().y; y < gridObject.getPosition().y + gridObject.getSize().y; y++) { GridPosition gridPosition = getPosition(x, y); if (gridPosition != null) { getPosition(x, y).add(gridObject); } } } } private void removeGridObjectFromPosition(GridObject gridObject, GridPoint position, GridPoint size) { for (int x = position.x; x < position.x + size.x; x++) { for (int y = position.y; y < position.y + size.y; y++) { GridPosition gridPosition = getPosition(x, y); if (gridPosition != null) { gridPosition.remove(gridObject); } } } } @Subscribe public void GameGrid_onGridObjectPlaced(GridObjectPlacedEvent event) { GridObject gridObject = event.getGridObject(); if (!gridObject.isPlaced()) { return; } addGridObjectToPosition(gridObject); } @Subscribe public void GameGrid_onGridObjectBoundsChange(GridObjectBoundsChangeEvent event) { GridObject gridObject = event.getGridObject(); if (!gridObject.isPlaced()) { return; } removeGridObjectFromPosition(gridObject, event.getPrevPosition(), event.getPrevSize()); addGridObjectToPosition(gridObject); } @Subscribe public void GameGrid_onGridObjectRemoved(GridObjectRemovedEvent event) { removeGridObjectFromPosition(event.getGridObject(), event.getGridObject().getPosition(), event.getGridObject() .getSize()); } private GridPosition getObjectSetForPosition(GridPoint gridPoint) { return !checkBounds(gridPoint.x, gridPoint.y) ? null : gridPositions[gridPoint.x][gridPoint.y]; } public Array<GridObject> getObjectsAt(GridPoint position, GridPoint size, GridObject... gridObjectsToIgnore) { Array<GridObject> objects = new Array<GridObject>(); int maxX = Math.min(gridSize.x, position.x + size.x); int maxY = Math.min(gridSize.y, position.y + size.y); GridPoint currentPos = position.cpy(); for (int x = position.x; x < maxX; x++) { for (int y = position.y; y < maxY; y++) { currentPos.set(x, y); GridPosition forPosition = getObjectSetForPosition(currentPos); if (forPosition != null) { for (GridObject object : forPosition.getObjects()) { if (!objects.contains(object, false)) { objects.add(object); } } } } } if (gridObjectsToIgnore != null && gridObjectsToIgnore.length > 0) { for (GridObject gridObject : gridObjectsToIgnore) { objects.removeValue(gridObject, false); } } return objects; } public Array<GridObject> getObjectsAt(GridPoint gridPoint) { GridPosition objectsAt = getObjectSetForPosition(gridPoint); if (objectsAt != null) { return objectsAt.getObjects(); } return null; } public GridPosition getPosition(GridPoint gridPoint) { return getPosition(gridPoint.x, gridPoint.y); } public GridPosition getPosition(int x, int y) { return !checkBounds(x, y) ? null : gridPositions[x][y]; } private boolean checkBounds(int x, int y) { if (x >= gridPositions.length || x < 0) { return false; } else if (y >= gridPositions[x].length || y < 0) { return false; } return true; } public GridPosition[][] getPositions() { return gridPositions; } public void updateNoiseLevels() { for (GridPosition[] row : gridPositions) { for (GridPosition position : row) { position.findMaxValues(); } } for (GridPosition[] row : gridPositions) { for (GridPosition position : row) { position.calculateValuesForPosition(gridPositions); } } } public void normalizeTransitDistances() { float minVal = Float.MAX_VALUE; float maxVal = Float.MIN_VALUE; for (GridPosition[] row : gridPositions) { for (GridPosition position : row) { minVal = Math.min(position.distanceFromTransit, minVal); maxVal = Math.max(position.distanceFromTransit, maxVal); } } if (maxVal != Float.MIN_VALUE) { for (GridPosition[] row : gridPositions) { for (GridPosition position : row) { if (position.distanceFromTransit > 5) { position.normalizedDistanceFromTransit = position.distanceFromTransit / maxVal; } else { position.normalizedDistanceFromTransit = 0f; } } } } } public void normalizeSecurityDistances() { float minVal = Float.MAX_VALUE; float maxVal = Float.MIN_VALUE; for (GridPosition[] row : gridPositions) { for (GridPosition position : row) { minVal = Math.min(position.distanceFromSecurity, minVal); maxVal = Math.max(position.distanceFromSecurity, maxVal); } } if (maxVal != Float.MIN_VALUE) { for (GridPosition[] row : gridPositions) { for (GridPosition position : row) { if (position.distanceFromSecurity > 5) { position.normalizedDistanceFromSecurity = position.distanceFromSecurity / maxVal; } else { position.normalizedDistanceFromSecurity = 0f; } } } } } public GridPosition getPosition(Vector2 worldPoint) { return getPosition((int) worldPoint.x / TowerConsts.GRID_UNIT_SIZE, (int) worldPoint.y / TowerConsts.GRID_UNIT_SIZE); } }