feat: add portal support

This commit is contained in:
punchready 2021-06-24 22:07:40 +02:00
parent 7b1ce8af8f
commit be7dd1ca94
10 changed files with 127 additions and 15 deletions

View File

@ -65,6 +65,9 @@ class Board {
Rock rock = (Rock)entity;
data[y][x] = new Piece(PieceType.Rock, entity.id, rock.getHp(), rock.maxHP);
}
case Portals -> {
data[y][x] = new Piece(PieceType.Portal, entity.id);
}
case InfinityStones -> {
InfinityStone stone = (InfinityStone)entity;
data[y][x] = new Piece(PieceType.InfinityStone, entity.id, stone.type);

View File

@ -28,6 +28,16 @@ class Piece {
this.stone = null;
}
public Piece(PieceType type, EntityID id) {
this.type = type;
this.id = id;
this.hp = null;
this.mp = null;
this.ap = null;
this.inventory = null;
this.stone = null;
}
public Piece(PieceType type, EntityID id, int hp, int maxHP) {
this.type = type;
this.id = id;

View File

@ -6,5 +6,6 @@ enum PieceType {
Character,
InfinityStone,
Thanos,
NPC
NPC,
Portal
}

View File

@ -6,4 +6,5 @@ package uulm.teamname.marvelous.gamelibrary.config;
public enum FieldType {
GRASS,
ROCK,
PORTAL
}

View File

@ -0,0 +1,46 @@
package uulm.teamname.marvelous.gamelibrary.entities;
import uulm.teamname.marvelous.gamelibrary.IntVector2;
import java.util.Objects;
/** Represents a portal on the map. */
public class Portal extends Entity {
/**
* Constructs a new {@link Portal}.
* @param id The {@link EntityID} of the portal
* @param position The position of the portal
*/
public Portal(EntityID id, IntVector2 position) {
super(id, position);
solid = false;
opaque = true;
}
@Override
public Portal clone() {
return new Portal(id, position);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
return super.equals(o);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode());
}
@Override
public String toString() {
return "Portal{" +
"position=" + position +
'}';
}
}

View File

@ -1,17 +1,14 @@
package uulm.teamname.marvelous.gamelibrary.gamelogic;
import uulm.teamname.marvelous.gamelibrary.IntVector2;
import uulm.teamname.marvelous.gamelibrary.entities.Entity;
import uulm.teamname.marvelous.gamelibrary.entities.EntityID;
import uulm.teamname.marvelous.gamelibrary.entities.EntityType;
import uulm.teamname.marvelous.gamelibrary.entities.Rock;
import uulm.teamname.marvelous.gamelibrary.entities.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
/** Represents a managed list of {@link Entity Entities}. */
public class EntityManager {
public class EntityManager implements Iterable<Entity> {
/** The internal collection of {@link Entity Entities} */
private final HashSet<Entity> entities = new HashSet<>();
@ -149,11 +146,9 @@ public class EntityManager {
return false;
}
/**
* Iterates over all entities inside the list.
* @return An iterator over every {@link Entity}
*/
public Iterator<Entity> getEntities() {
/** Iterates over all entities inside the list. */
@Override
public Iterator<Entity> iterator() {
return entities.iterator();
}

View File

@ -351,17 +351,49 @@ public class GameLogic {
.buildEntityEvent());
for(Entity entity: state.entities.findByPosition(data.targetField)) {
if(entity instanceof Character) {
result.add(new EventBuilder(EventType.MoveEvent)
.withOriginEntity(entity.id)
.withOriginField(data.targetField)
.withTargetField(data.originField)
.buildCharacterEvent());
break; //we should only have one entity per field anyways
}else if(entity instanceof InfinityStone) {
result.add(new EventBuilder(EventType.DestroyedEntityEvent)
.withTargetField(data.targetField)
.withTargetEntity(entity.id)
.buildEntityEvent());
break; //we should only have one entity per field anyways
}else if(entity instanceof Portal) {
List<Entity> targets = new ArrayList<>();
for(Entity e: state.entities) {
if(e.id.type == EntityType.Portals && !e.id.equals(entity.id)) {
targets.add(e);
}
}
if(targets.isEmpty()) {
break;
}
Entity target = targets.get(rand.nextInt(targets.size()));
List<IntVector2> fields = getFreeNeighbour(state, target.getPosition());
if(fields.isEmpty()) {
break;
}
IntVector2 field = fields.get(rand.nextInt(fields.size()));
result.add(new EventBuilder(EventType.TeleportedEvent)
.withTeleportedEntity(data.originEntity)
.withOriginField(data.targetField)
.withTargetField(field)
.withOriginPortal(entity.id)
.withTargetPortal(target.id)
.buildTeleportedEvent());
break; //we should only have one entity per field anyways
}
}
@ -596,6 +628,12 @@ public class GameLogic {
target.setPosition(data.targetField);
}
}
case TeleportedEvent -> {
TeleportedEvent data = (TeleportedEvent)event;
Character target = (Character)state.entities.findEntity(data.teleportedEntity);
target.setPosition(data.targetField);
}
case UseInfinityStoneEvent -> {
state.stoneCooldown.setCooldown(((CharacterEvent)event).stoneType);
}
@ -721,10 +759,13 @@ public class GameLogic {
ArrayList<IntVector2> free = new ArrayList<>();
int rockIndex = 0;
int portalIndex = 0;
for(int x = 0; x < state.mapSize.getX(); x++) {
for(int y = 0; y < state.mapSize.getY(); y++) {
if(state.scenarioConfig.scenario[y][x] == FieldType.ROCK) {
state.entities.addEntity(new Rock(new EntityID(EntityType.Rocks, rockIndex++), new IntVector2(x, y), 100));
}else if(state.scenarioConfig.scenario[y][x] == FieldType.PORTAL) {
state.entities.addEntity(new Portal(new EntityID(EntityType.Portals, portalIndex++), new IntVector2(x, y)));
}else {
free.add(new IntVector2(x, y));
}
@ -1062,6 +1103,15 @@ public class GameLogic {
.withEntity(thanosNPC)
.buildEntityEvent());
for(Entity e: state.entities) {
if(e.id.type == EntityType.Portals) {
result.add(new EventBuilder(EventType.DestroyedEntityEvent)
.withTargetEntity(e.id)
.withTargetField(e.getPosition())
.buildEntityEvent());
}
}
state.turnOrder.add(thanos);
state.entities.addEntity(thanosNPC);

View File

@ -153,6 +153,9 @@ class GameState {
sb.append(entities.get(0).id.equals(activeCharacter) ? "'" : " ");
}
case Rocks -> {
sb.append("M ");
}
case Portals -> {
sb.append("O ");
}
case InfinityStones -> {

View File

@ -36,7 +36,10 @@ public class BaseGameLogicTest {
scenarioConfig.scenario = new FieldType[20][20];
for(int x = 0; x < scenarioConfig.scenario[0].length; x++) {
for(int y = 0; y < scenarioConfig.scenario.length; y++) {
if(Math.abs(randomIntegers.next() % 100) < 10) {
int r = Math.abs(randomIntegers.next() % 100);
if(r < 2) {
scenarioConfig.scenario[y][x] = FieldType.PORTAL;
}else if(r < 10) {
scenarioConfig.scenario[y][x] = FieldType.ROCK;
}else {
scenarioConfig.scenario[y][x] = FieldType.GRASS;

View File

@ -83,10 +83,10 @@ class GameLogicTest extends BaseGameLogicTest {
snapshot.turnNumber = 10;
assertEquals(0, state.turnNumber, "Original's turn number should remain unchanged");
assertTrue(snapshot.entities.getEntities().hasNext(), "Snapshot should contain cloned entities");
assertTrue(snapshot.entities.iterator().hasNext(), "Snapshot should contain cloned entities");
((Rock)snapshot.entities.getEntities().next()).decreaseHp(5);
assertEquals(100, ((Rock)state.entities.getEntities().next()).getHp(), "Original's rock entity hp should remain unchanged");
((Rock)snapshot.entities.iterator().next()).decreaseHp(5);
assertEquals(100, ((Rock)state.entities.iterator().next()).getHp(), "Original's rock entity hp should remain unchanged");
}