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/209f25c781af4aa53a4011f522b5c2d9 to your computer and use it in GitHub Desktop.
Save Durisvk/209f25c781af4aa53a4011f522b5c2d9 to your computer and use it in GitHub Desktop.
package com.iddqd.doto.gamelogic.gameobject;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.iddqd.doto.gamelogic.GameLogicConstants;
import com.iddqd.doto.gamelogic.astar.AStar;
import com.iddqd.doto.gamelogic.astar.Path;
import com.iddqd.doto.gamelogic.astar.Spot;
import com.iddqd.doto.gamelogic.gameobject.actors.heroes.AbstractHero;
import com.iddqd.doto.gamelogic.math.geometry.CircleCollider;
import com.iddqd.doto.gamelogic.math.geometry.Point;
import com.iddqd.doto.gamelogic.math.geometry.Vector;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
/**
* Created by Ruza on 24.7.2017.
*/
public abstract class GameBodyObject extends GameObject {
private int width;
private int height;
private double rotation;
private Point position;
private boolean collidable = true;
private boolean isStatic = false;
private Path aStarPath = null;
private Spot current = null;
private double currentIndex = -1;
public GameBodyObject() {
this.width = 0;
this.height = 0;
this.rotation = 0;
this.position = new Point(0, 0);
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public double getRotation() {
return rotation;
}
public void setRotation(double rotation) {
this.rotation = rotation;
}
public Spot getCurrent() {
return current;
}
public boolean setRotationWithMaxRotation(double rotation, double maxRotation) {
if(Math.abs(getRotation() - rotation) < maxRotation) {
setRotation(rotation);
return true;
}
return false;
}
public Point getPosition() {
return position;
}
public void setPosition(Point position) {
this.position = position;
}
@JsonIgnore
public boolean isCollidable() {
return collidable;
}
public void setCollidable(boolean collidable) {
this.collidable = collidable;
}
public boolean isStatic() {
return isStatic;
}
public void setStatic(boolean aStatic) {
isStatic = aStatic;
}
public double getRadius() {
return Math.max(width, height) / 2;
}
public boolean checkCollision(GameBodyObject anotherObject) {
if(anotherObject.isStatic() && isStatic()) {
return false;
}
if(anotherObject instanceof AbstractHero && ((AbstractHero) anotherObject).isDead()) {
return false;
}
if(this instanceof AbstractHero && ((AbstractHero) this).isDead()) {
return false;
}
if(this.isCollidable() && anotherObject.isCollidable()) {
return CircleCollider.collide(getPosition(), getRadius(), anotherObject.getPosition(), anotherObject.getRadius());
}
return false;
}
@JsonIgnore
private Point lastPointToMove;
public void setLastPointToMove(Point lastPointToMove) {
this.lastPointToMove = lastPointToMove;
}
/**
*
* @param p
* @param stepSize
* @param minDistance
* @param shouldStepInto
* @return if it moved
*/
public boolean moveTowardsPoint(Point p, double stepSize, double minDistance, ArrayList<GameBodyObject> objects, boolean shouldStepInto, AStar astar) {
ArrayList<GameBodyObject> others = (ArrayList<GameBodyObject>) objects.clone();
others.remove(this);
if(aStarPath == null || !aStarPath.isSuccess() || astar.interruptedPath(aStarPath.getPath(), this) || lastPointToMove == null || !lastPointToMove.isAlmostTheSame(p, 0.01)) {
try {
//astar.getGrid().unsetObstacleForObject(this);
aStarPath = astar.process(this, p, objects);
currentIndex = 0;
current = null;
//astar.getGrid().reset();
} catch(Exception e) {
e.printStackTrace();
}
}
lastPointToMove = p.clone();
double dx = p.getX() - getPosition().getX();
double dy = p.getY() - getPosition().getY();
Point lastPosition = getPosition().clone();
boolean isClose = false;
double dist = Math.sqrt(dx * dx + dy * dy);
if (dist < Math.max(minDistance, stepSize)) {
isClose = true;
} else {
if (aStarPath.getPath().indexOf(current) >= aStarPath.getPath().size() - 1) {
if (shouldStepInto && dist <= stepSize) {
setPosition(p.clone());
}
} else {
if (aStarPath.isHit()) {
moveByAStar(stepSize);
} else {
moveByPoint(dx, dy, stepSize);
}
}
}
// -- A* --
// -- COLLISION AVOIDANCE -- //
/* double dx = p.getX() - getPosition().getX();
double dy = p.getY() - getPosition().getY();
boolean isClose = false;
Point lastPosition = getPosition().clone();
if (Math.sqrt(dx * dx + dy * dy) < Math.max(minDistance, stepSize)) {
isClose = true;
} else {
setRotation(Math.atan2(dy, dx));
// Though the sqrt is expensive operation
// We check first without using sqrt
if (shouldStepInto && Math.abs(dx) + Math.abs(dy) < stepSize) {
if (Math.sqrt(dx * dx + dy * dy) < stepSize) {
getPosition().setX(p.getX());
getPosition().setY(p.getY());
}
} else {
getPosition().setX(getPosition().getX() + (stepSize * Math.cos(getRotation())));
getPosition().setY(getPosition().getY() + (stepSize * Math.sin(getRotation())));
}
}
*/
/*GameBodyObject collider = null;
ArrayList<Double> movements = new ArrayList<>();
for (GameBodyObject obj : others) {
if (checkCollision(obj)) {
double distanceMoved = getPosition().distance(lastPosition);
if(!isStatic() && distanceMoved > 0.01) {
Vector v = new Vector(getPosition().getX() - obj.getPosition().getX(), getPosition().getY() - obj.getPosition().getY());
int av = (int)(v.getAngle() * 180 / Math.PI);
Vector n1 = v.getNormal(stepSize, 1);
int an1 = (int)(n1.getAngle() * 180 / Math.PI);
Vector n2 = v.getNormal(stepSize, -1);
int an2 = (int)(n2.getAngle() * 180 / Math.PI);
Point p1 = lastPosition.clone();
Point p2 = lastPosition.clone();
p1.moveByVector(n1);
p2.moveByVector(n2);
double dist1 = p1.distance(p);
double dist2 = p2.distance(p);
if (dist1 < dist2) {
Double angle = getAngleIfNotColliding(n1, p1, n2, p2, others);
if(angle != null) {
movements.add(angle);
}
} else {
Double angle = getAngleIfNotColliding(n2, p2, n1, p1, others);
if(angle != null) {
movements.add(angle);
}
}
};
}
}
movements.removeIf(Objects::isNull);
if(movements != null && !movements.isEmpty()) {
setPosition(lastPosition.clone());
double totalAngle = 0;
for (double angle : movements) {
totalAngle += angle;
}
Vector v = Vector.createFromLengthAndAngle(stepSize, totalAngle/movements.size());
Point newPos = getPosition().clone();
newPos.moveByVector(v);
setRotationWithMaxRotation(totalAngle/movements.size(), GameLogicConstants.MAX_ROTATION_ON_COLLISION);
getPosition().moveByVector(v);
}*/
return isClose;
}
public boolean moveTowardsPoint(Point p, double stepSize, double minDistance, ArrayList<GameBodyObject> objects, AStar astar) {
return moveTowardsPoint(p, stepSize, minDistance, objects, false, astar);
}
private boolean checkCollisionWithCircle(Point p, double radius, ArrayList<GameBodyObject> objects) {
for(GameBodyObject obj : objects) {
if(CircleCollider.collide(p, radius, obj.getPosition(), obj.getRadius())) {
double dx = obj.getPosition().getX() - p.getX();
double dy = obj.getPosition().getY() - p.getY();
return true;
}
}
return false;
}
private Double getAngleIfNotColliding(Vector n, Point p, Vector alternativeN, Point alternativeP, ArrayList<GameBodyObject> others) {
if (!checkCollisionWithCircle(p, getRadius(), others)) {
return n.getAngle();
} else {
if(!checkCollisionWithCircle(alternativeP, getRadius(), others)) {
return alternativeN.getAngle();
} else {
return null;
}
}
}
private void moveByAStar(double stepSize) {
if (aStarPath != null && aStarPath.getPath().size() > 0) {
if (current == null) {
currentIndex = 0;
current = aStarPath.getPath().get((int) currentIndex);
}
Spot c1 = aStarPath.getPath().get((int) currentIndex);
Spot c2 = aStarPath.getPath().get(Math.min((int) currentIndex + 1, aStarPath.getPath().size() - 1));
double angle = new Vector(c2.getX() - c1.getX(), c2.getY() - c1.getY()).getAngle();
double coef = Math.max(Math.abs(Math.cos(angle)), Math.abs(Math.sin(angle)));
double mss = stepSize / (current.getWidth() / coef);
Spot p2 = aStarPath.getPath().get(Math.min((int) Math.ceil(currentIndex + mss), aStarPath.getPath().size() - 1));
Spot p1 = current;
if (!p1.equals(p2)) {
Vector v = new Vector(p2.getX() - p1.getX(), p2.getY() - p1.getY()).normalize();
getPosition().moveByVector(v.mult(stepSize));
setRotation(v.getAngle());
}
currentIndex = Math.min(currentIndex + mss, aStarPath.getPath().size() - 1);
current = aStarPath.getPath().get((int) currentIndex);
}
}
private void moveByPoint(double dx, double dy, double stepSize) {
setRotation(Math.atan2(dy, dx));
setPosition(new Point(getPosition().getX() + stepSize * Math.cos(getRotation()), getPosition().getY() + stepSize * Math.sin(getRotation())));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment