Created
August 9, 2017 18:00
-
-
Save Durisvk/4de2d7e2e0a229a6cfd4bb9cc7203996 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.iddqd.doto.gamelogic.astar; | |
import com.iddqd.doto.config.Constants; | |
import com.iddqd.doto.gamelogic.GameLogicConstants; | |
import com.iddqd.doto.gamelogic.gameobject.GameBodyObject; | |
import java.util.ArrayList; | |
import java.util.List; | |
public class Grid { | |
private List<List<Spot>> grid = null; | |
private int cols = 5; | |
private int rows = 5; | |
private double spotSize = 1; | |
private List<Spot> obstacles = new ArrayList<>(); | |
public Grid(double spotSize) { | |
this.spotSize = Math.max(1, spotSize); | |
cols = (int)(Constants.MAP_WIDTH / this.spotSize) + 1; | |
rows = (int)(Constants.MAP_HEIGHT / this.spotSize) + 1; | |
grid = new ArrayList<>(cols); | |
for(int x = 0; x < cols; x++) { | |
List<Spot> r = new ArrayList<>(rows); | |
grid.add(r); | |
for(int y = 0; y < rows; y++) { | |
r.add(new Spot(x, y, this.spotSize)); | |
} | |
} | |
for(int x = 0; x < cols; x++) { | |
for(int y = 0; y < rows; y++) { | |
grid.get(x).get(y).addNeighbors(this); | |
} | |
} | |
} | |
public int getMaxSize() { | |
return cols * rows; | |
} | |
public Spot getSpotAtPosition(double x, double y) { | |
int i = (int)(x / spotSize); | |
int j = (int)(y / spotSize); | |
if(i >= 0 && j >= 0 && i < cols && j < rows) { | |
return grid.get(i).get(j); | |
} | |
return null; | |
} | |
public Spot getSpotAtIndex(int x, int y) { | |
return grid.get(x).get(y); | |
} | |
public List<Spot> getObstacles() { | |
return obstacles; | |
} | |
public int getCols() { | |
return cols; | |
} | |
public int getRows() { | |
return rows; | |
} | |
public double getSpotWidth() { | |
return spotSize; | |
} | |
public void recalculateObstacles(List<GameBodyObject> objects) { | |
for(int i = 0; i < cols; i++) { | |
for(int j = 0; j < rows; j++) { | |
grid.get(i).get(j).setObstacle(false); | |
} | |
} | |
obstacles = new ArrayList<>(); | |
for(GameBodyObject obj : objects) { | |
List<Spot> spots = getIntersectsSpotsWithPosition(obj.getPosition().getX(), obj.getPosition().getY(), obj.getRadius()); | |
for(Spot s : spots) { | |
s.setObstacle(true); | |
obstacles.add(s); | |
} | |
} | |
} | |
public List<Spot> getIntersectsSpotsWithPosition(double x, double y, double r) { | |
int x0 = (int)(Math.round(x / spotSize)); | |
int y0 = (int)(Math.round(y / spotSize)); | |
int r0 = (int)(Math.round(r / spotSize)); | |
return getIntersectsSpotsWithIndex(x0, y0, r0); | |
} | |
public List<Spot> getIntersectsSpotsWithIndex(int x, int y, int r) { | |
List<Spot> result = new ArrayList<Spot>(); | |
double rr = r * r; | |
int lj = Integer.MAX_VALUE; | |
for(int i = -r; i <= 0; i++) { | |
if(x + i < 0 || x + i > grid.size() - 1) { | |
continue; | |
} | |
double ii = i * i; | |
int j = (int)(Math.round(Math.sqrt(rr - ii))); | |
if(x + i >= 0 && x + i < grid.size()) { | |
if(y - j >= 0 && y - j < grid.get(x + i).size()) { | |
result.add(grid.get(x + i).get(y - j)); | |
if(i != 0 && x - i >= 0 && x - i < grid.size()) { | |
result.add(grid.get(x - i).get(y - j)); | |
} | |
if (lj != Integer.MAX_VALUE) { | |
int jj = j - lj; | |
while (jj > 0) { | |
int minusY = y - j + jj; | |
int plusY = y + j - jj; | |
if(minusY < grid.get(x + i).size() - 1 && minusY >= 0) { | |
result.add(grid.get(x + i - 1).get(minusY)); | |
if(i != 0 && x - i >= 0 && x - i < grid.size() - 1) { | |
result.add(grid.get(x - i + 1).get(minusY)); | |
} | |
} | |
if(plusY < grid.get(x + i).size() - 1 && plusY >= 0) { | |
result.add(grid.get(x + i - 1).get(plusY)); | |
if(i != 0 && x - i >= 0 && x - i < grid.size() - 1) { | |
result.add(grid.get(x - i + 1).get(plusY)); | |
} | |
} | |
jj--; | |
} | |
} | |
lj = j; | |
} | |
if(j != 0 && y + j >= 0 && y + j < grid.get(x + i).size() - 1) { | |
result.add(grid.get(x + i).get(y + j)); | |
if(x - i < grid.size() && x - i >= 0) { | |
result.add(grid.get(x - i).get(y + j)); | |
} | |
} | |
} | |
} | |
return result; | |
} | |
private int sign(int val) { | |
return val < 0 ? -1 : 1; | |
} | |
public boolean isCollidingWithObstacle(Spot s, double radius) { | |
int r0 = (int)(radius / spotSize); | |
for(Spot sp : getIntersectsSpotsWithIndex(s.getX(), s.getY(), r0)) { | |
if(sp.isObstacle()) { | |
return true; | |
} | |
} | |
return false; | |
} | |
private List<Spot> tempObstacles = new ArrayList<>(); | |
public void unsetObstacleForObject(GameBodyObject object) { | |
tempObstacles = getIntersectsSpotsWithPosition(object.getPosition().getX(), object.getPosition().getY(), object.getRadius()); | |
for(Spot obstacle : tempObstacles) { | |
obstacle.setObstacle(false); | |
} | |
} | |
public void resetObstacles() { | |
for(Spot obstacle : tempObstacles) { | |
obstacle.setObstacle(true); | |
} | |
tempObstacles = new ArrayList<>(); | |
} | |
public void reset() { | |
for(int i = 0; i < cols; i++) { | |
for(int j = 0; j < rows; j++) { | |
grid.get(i).get(j).setPrevious(null); | |
} | |
} | |
resetObstacles(); | |
} | |
public Spot moveSpotSoThatItDoesntCollide(Spot s, double radius) { | |
return moveSpotSoThatItDoesntCollide(s, radius, new ArrayList<>()); | |
} | |
public Spot moveSpotSoThatItDoesntCollide(Spot s, double radius, List<Spot> closed) { | |
if(!isCollidingWithObstacle(s, radius)) { | |
return s; | |
} | |
closed.add(s); | |
ArrayList<Spot> spots = new ArrayList<>(); | |
for(Spot neighbor : s.getNeighbors()) { | |
if(!isCollidingWithObstacle(neighbor, radius)) { | |
spots.add(neighbor); | |
} else { | |
if(closed.size() < 6 && neighbor != null && !closed.contains(neighbor)) { | |
Spot spot = moveSpotSoThatItDoesntCollide(neighbor, radius, closed); | |
if(spot != null) { | |
spots.add(spot); | |
} | |
} else if(closed.size() >= 20) { | |
closed.clear(); | |
} | |
} | |
} | |
int minDist = Integer.MAX_VALUE; | |
Spot closest = null; | |
for(Spot spot : spots) { | |
int dx = spot.getX() - s.getX(); | |
int dy = spot.getY() - s.getY(); | |
int manhattanDistance = Math.abs(dx) + Math.abs(dy); | |
if(manhattanDistance < minDist) { | |
closest = spot; | |
minDist = manhattanDistance; | |
} | |
} | |
return closest; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment