Skip to content

Instantly share code, notes, and snippets.

@Durisvk
Created August 9, 2017 18:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Durisvk/4de2d7e2e0a229a6cfd4bb9cc7203996 to your computer and use it in GitHub Desktop.
Save Durisvk/4de2d7e2e0a229a6cfd4bb9cc7203996 to your computer and use it in GitHub Desktop.
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