fix: improve the terrible rasterization code

This commit is contained in:
punchready 2021-05-31 22:50:44 +02:00
parent 4b794e99e9
commit 1ba5410fd6

View File

@ -12,6 +12,7 @@ import uulm.teamname.marvelous.gamelibrary.requests.RequestType;
import java.awt.*;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.util.*;
/** Contains game logic handling. */
@ -97,24 +98,18 @@ class GameLogic {
}
case MindStone -> {
EntityType target = data.originEntity.type == EntityType.P1 ? EntityType.P2 : EntityType.P1;
Line2D line = new Line2D.Float(data.originField.getX(), data.originField.getY(), data.targetField.getX(), data.targetField.getY());
for(int i = data.originField.getX(); i <= data.targetField.getX(); i++) {
for(int j = data.originField.getY(); j <= data.targetField.getY(); j++) {
var cell = new Rectangle.Float(i - 0.5f, j - 0.5f, 1, 1);
if(line.intersects(cell)) {
for(Entity entity: state.entities.findByPosition(data.targetField)) {
for(IntVector2 pos: rasterize(data.originField, data.targetField)) {
for(Entity entity: state.entities.findByPosition(pos)) {
if(entity.id.isSameType(target)) {
result.add(new EventBuilder(EventType.TakenDamageEvent)
.withTargetEntity(entity.id)
.withTargetField(new IntVector2(i, j))
.withTargetField(pos)
.withAmount(data.value)
.buildEntityEvent());
}
}
}
}
}
}
case RealityStone -> {
if(data.originEntity == data.targetEntity) { // => place stone
result.add(new EventBuilder(EventType.SpawnEntityEvent)
@ -441,20 +436,11 @@ class GameLogic {
* @return Whether or not the light of sight exists
*/
private static boolean checkLineOfSight(GameState state, IntVector2 start, IntVector2 end) {
//naive code for the win!!! \o/
//at least its early exit and probably only O(ln(n*m))
//TODO: implement proper line rasterization algorithm in GameLogic.checkLineOfSight
Line2D line = new Line2D.Float(start.getX(), start.getY(), end.getX(), end.getY());
for(int i = start.getX(); i <= end.getX(); i++) {
for(int j = start.getY(); j <= end.getY(); j++) {
var cell = new Rectangle.Float(i - 0.5f, j - 0.5f, 1, 1);
if(line.intersects(cell)) {
if(state.entities.blocksVision(new IntVector2(i, j))) {
for(IntVector2 pos: rasterize(start, end)) {
if(state.entities.blocksVision(pos)) {
return false;
}
}
}
}
return true;
}
@ -866,4 +852,30 @@ class GameLogic {
return result;
}
/**
* Computes all fields which intersect the line between the center points of the given two fields.
* @return The list of intersecting positions
*/
public static ArrayList<IntVector2> rasterize(IntVector2 a, IntVector2 b) {
ArrayList<IntVector2> result = new ArrayList<>();
//TODO: implement proper line rasterization algorithm in GameLogic.rasterize
int x1 = Math.min(a.getX(), b.getX());
int x2 = Math.max(a.getX(), b.getX());
int y1 = Math.min(a.getY(), b.getY());
int y2 = Math.max(a.getY(), b.getY());
Line2D line = new Line2D.Float(x1 + 0.5f, y1 + 0.5f, x2 + 0.5f, y2 + 0.5f);
for(int i = x1; i <= x2; i++) {
for(int j = y1; j <= y2; j++) {
Rectangle2D cell = new Rectangle.Float(i, j, 1, 1);
if(line.intersects(cell)) {
result.add(new IntVector2(i, j));
}
}
}
return result;
}
}