Skip to content

Commit

Permalink
Create units via EntityRepository, and test spawning of explosions once
Browse files Browse the repository at this point in the history
a unit dies.
  • Loading branch information
stefanhendriks committed Oct 22, 2015
1 parent db4c42e commit 770de5c
Show file tree
Hide file tree
Showing 11 changed files with 118 additions and 115 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -107,40 +107,37 @@ public Entity placeOnMap(Vector2D absoluteMapCoordinates, EntityData entityData,
System.out.println("Placing " + entityData + " on map at " + absoluteMapCoordinates + " for " + player);
Entity createdEntity;
Image originalImage = entityData.image;
Image recoloredImage = originalImage;
SpriteSheet spriteSheet;

switch (entityData.type) {
case STRUCTURE:
recoloredImage = recolorer.recolorToFactionColor(originalImage, player.getFactionColor());
createdEntity = new Structure(absoluteMapCoordinates, recoloredImage, player, entityData, this);
addEntityToList(map.placeStructure((Structure) createdEntity));
break;
case UNIT:
recoloredImage = recolorer.recolorToFactionColor(originalImage, player.getFactionColor());
spriteSheet = new SpriteSheet(recoloredImage, entityData.width, entityData.height);
createdEntity = new Unit(map, absoluteMapCoordinates, spriteSheet, player, entityData, this);
addEntityToList(map.placeUnit((Unit) createdEntity));
break;
case PROJECTILE:
spriteSheet = new SpriteSheet(recoloredImage, entityData.width, entityData.height);
createdEntity = new Projectile(absoluteMapCoordinates, spriteSheet, player, entityData, this);
addEntityToList(map.placeProjectile((Projectile) createdEntity));
break;
case PARTICLE:
spriteSheet = new SpriteSheet(recoloredImage, entityData.width, entityData.height);
createdEntity = new Particle(absoluteMapCoordinates, spriteSheet, entityData, this);
addEntityToList(createdEntity);
break;
default:
throw new IllegalArgumentException("Unknown type " + entityData.type);

if (EntityType.STRUCTURE.equals(entityData.type)) {
Image recoloredImage = recolorer.recolorToFactionColor(originalImage, player.getFactionColor());
createdEntity = new Structure(absoluteMapCoordinates, recoloredImage, player, entityData, this);
return addEntityToList(map.placeStructure((Structure) createdEntity));
} else if (EntityType.UNIT.equals(entityData.type)) {
Image recoloredImage = recolorer.recolorToFactionColor(originalImage, player.getFactionColor());
SpriteSheet spriteSheet = makeSpriteSheet(entityData, recoloredImage);
createdEntity = new Unit(map, absoluteMapCoordinates, spriteSheet, player, entityData, this);
return addEntityToList(map.placeUnit((Unit) createdEntity));
} else if (EntityType.PROJECTILE.equals(entityData.type)) {
SpriteSheet spriteSheet = makeSpriteSheet(entityData, originalImage);
createdEntity = new Projectile(absoluteMapCoordinates, spriteSheet, player, entityData, this);
return addEntityToList(map.placeProjectile((Projectile) createdEntity));
} else if (EntityType.PARTICLE.equals(entityData.type)) {
SpriteSheet spriteSheet = makeSpriteSheet(entityData, originalImage);
createdEntity = new Particle(absoluteMapCoordinates, spriteSheet, entityData, this);
return addEntityToList(createdEntity);
} else {
throw new IllegalArgumentException("Unknown type " + entityData.type);
}
return createdEntity;
}

public void addEntityToList(Entity entity) {
public SpriteSheet makeSpriteSheet(EntityData entityData, Image recoloredImage) {
return new SpriteSheet(recoloredImage, entityData.width, entityData.height);
}

public Entity addEntityToList(Entity entity) {
lastCreatedEntity = entity;
entitiesSet.add(entity);
return entity;
}

public void removeEntities(Predicate predicate) {
Expand Down
41 changes: 13 additions & 28 deletions src/test/java/com/fundynamic/d2tm/game/AbstractD2TMTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -159,44 +159,24 @@ public Image getSprite() {
// UNIT
////////////////////////////////////////////////////////////////////////////////
public Unit makeUnit(UnitFacings facing, Vector2D unitAbsoluteMapCoordinates) {
return makeUnit(facing, unitAbsoluteMapCoordinates, Vector2D.zero(), 100);
return makeUnit(facing, unitAbsoluteMapCoordinates, Vector2D.zero());
}

public Unit makeUnit(UnitFacings facing, Vector2D unitAbsoluteMapCoordinates, Vector2D offset, int hitPoints) {
Unit unit = makeUnit(player, hitPoints, unitAbsoluteMapCoordinates);
public Unit makeUnit(UnitFacings facing, Vector2D unitAbsoluteMapCoordinates, Vector2D offset) {
Unit unit = makeUnit(player, unitAbsoluteMapCoordinates);
unit.setFacing(facing.getValue());
unit.setOffset(offset);
return unit;
}

public Unit makeUnit(Player player, int hitPoints) {
return makeUnit(player, hitPoints, Vector2D.zero());
public Unit makeUnit(Player player) {
return makeUnit(player, Vector2D.zero());
}

public Unit makeUnit(Player player, int hitPoints, Vector2D absoluteMapCoordinates) {
public Unit makeUnit(Player player, Vector2D absoluteMapCoordinates) {
if (entityRepository == null) throw new IllegalStateException("You forgot to set up the entityRepository, probably you need to do super.setUp()");
if (map == null) throw new IllegalStateException("You forgot to set up the map, probably you need to do super.setUp()");
EntityData entityData = new EntityData(32, 32, 2);
entityData.moveSpeed = 1; // 1 pixel per second
entityData.turnSpeed = 1; // 1 facing per second
entityData.hitPoints = hitPoints;
Unit unit = new Unit(
map,
absoluteMapCoordinates,
mock(SpriteSheet.class),
player,
entityData,
entityRepository) {
@Override
public boolean isDestroyed() {
// we do this so that we do not have to deal with spawning explosions (which is done in the
// update method of the 'original' unit.)
return super.hitPointBasedDestructibility.hasDied();
}
};
entityRepository.addEntityToList(unit);
map.placeUnit(unit);
return unit;
return (Unit) entityRepository.placeOnMap(absoluteMapCoordinates, EntityType.UNIT, "QUAD", player);
}

public EntityRepository getTestableEntityRepository() {
Expand All @@ -207,7 +187,12 @@ public EntityRepository makeTestableEntityRepository(final Map map, EntitiesData
Image image = mock(Image.class);
Recolorer recolorer = mock(Recolorer.class);
when(recolorer.recolorToFactionColor(any(Image.class), any(Recolorer.FactionColor.class))).thenReturn(image);
return new EntityRepository(map, recolorer, entitiesData);
return new EntityRepository(map, recolorer, entitiesData) {
@Override
public SpriteSheet makeSpriteSheet(EntityData entityData, Image recoloredImage) {
return mock(SpriteSheet.class);
}
};
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public void setUp() throws SlickException {

@Test
public void leftClickedSelectsUnitOnHoverCell() throws SlickException {
Unit unit = makeUnit(player, 100, Vector2D.create(32, 32));
Unit unit = makeUnit(player, Vector2D.create(32, 32));
assertThat(unit.isSelected(), is(false));

mouse.mouseMovedToCell(map.getCell(1, 1)); // equals 32, 32
Expand All @@ -37,7 +37,7 @@ public void leftClickedSelectsUnitOnHoverCell() throws SlickException {
@Test
public void movesSelectedUnitsToCellThatIsNotOccupiedByOtherCell() throws SlickException {

Unit unit = makeUnit(player, 100, Vector2D.create(32, 32));
Unit unit = makeUnit(player, Vector2D.create(32, 32));
unit.select();

// TODO: This is ugly because absolute coordinates are used here versus map coordinates above in test
Expand All @@ -54,11 +54,11 @@ public void movesSelectedUnitsToCellThatIsNotOccupiedByOtherCell() throws SlickE
@Test
public void attacksUnitOfOtherPlayer() {
// create player for unit and select it
Unit unit = makeUnit(player, 100, Vector2D.create(32, 32));
Unit unit = makeUnit(player, Vector2D.create(32, 32));
unit.select();

Player enemy = new Player("Enemy", Recolorer.FactionColor.RED);
Unit enemyUnit = makeUnit(enemy, 100, Vector2D.create(64, 64));
Unit enemyUnit = makeUnit(enemy, Vector2D.create(64, 64));
map.placeUnit(enemyUnit);

Cell cell = map.getCellByAbsoluteMapCoordinates(Vector2D.create(64, 64));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public void leftClickSelectsEntityOnHoverCell() throws SlickException {
mouse.setHoverCell(cell);

Vector2D coordinatesAsAbsoluteVector2D = cell.getCoordinatesAsAbsoluteVector2D();
Unit unit = makeUnit(player, 100, coordinatesAsAbsoluteVector2D);
Unit unit = makeUnit(player, coordinatesAsAbsoluteVector2D);
assertThat(unit.isSelected(), is(false));

// ACT: click left
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ public void setUp() throws SlickException {
Player playerTwo = new Player("Player two", Recolorer.FactionColor.RED);

// player one has 4 units and 2 structures
entitiesSet.add(makeUnit(player, 100, Vector2D.create(320, 320)));
entitiesSet.add(makeUnit(player, 200, Vector2D.create(384, 320)));
entitiesSet.add(makeUnit(player, 300, Vector2D.create(320, 384)));
entitiesSet.add(makeUnit(player, 200, Vector2D.create(960, 960)));
entitiesSet.add(makeUnit(player, Vector2D.create(320, 320)));
entitiesSet.add(makeUnit(player, Vector2D.create(384, 320)));
entitiesSet.add(makeUnit(player, Vector2D.create(320, 384)));
entitiesSet.add(makeUnit(player, Vector2D.create(960, 960)));
playerOneUnitCount = 4;
moveableUnitsOfPlayerOne = 4;
destroyers = 4;
Expand All @@ -52,9 +52,9 @@ public void setUp() throws SlickException {
playerOneStructureCount = 2;

// player two has 3 units and 3 structures
entitiesSet.add(makeUnit(playerTwo, 100));
entitiesSet.add(makeUnit(playerTwo, 200));
entitiesSet.add(makeUnit(playerTwo, 300));
entitiesSet.add(makeUnit(playerTwo));
entitiesSet.add(makeUnit(playerTwo));
entitiesSet.add(makeUnit(playerTwo));
destroyers += 3;

entitiesSet.add(makeStructure(playerTwo, 200));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class EntityRepositoryTest extends AbstractD2TMTest {

@Test
public void findsUnitAtVector() throws SlickException {
Unit unit = makeUnit(player, 100, Vector2D.create(100, 100));
Unit unit = makeUnit(player, Vector2D.create(100, 100));

// find at same position
EntitiesSet entities = entityRepository.findEntitiesOfTypeAtVector(Vector2D.create(100, 100), EntityType.UNIT);
Expand Down
11 changes: 8 additions & 3 deletions src/test/java/com/fundynamic/d2tm/game/entities/PlayerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.fundynamic.d2tm.game.AbstractD2TMTest;
import com.fundynamic.d2tm.game.entities.structures.Structure;
import com.fundynamic.d2tm.game.entities.units.Unit;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
Expand Down Expand Up @@ -30,14 +31,18 @@ public void hasNoAliveEntitiesWhenAddingStructureWithNotEnoughHitPoints() {

@Test
public void hasAliveEntitiesWhenAddingUnitWithEnoughHitPoints() {
player.addEntity(makeUnit(player, 100));
player.addEntity(makeUnit(player));

assertEquals(1, player.aliveEntities());
}

@Test
public void hasNoAliveEntitiesWhenAddingUnitWithNotEnoughHitPoints() {
player.addEntity(makeUnit(player, 0));
public void hasNoAliveEntitiesWhenUnitIsDestroyed() {
Unit unit = makeUnit(player);
unit.takeDamage(unit.getHitPoints()); // destroys unit
unit.update(1); // updates internal state so it really is marked destroyed

player.addEntity(unit);

assertEquals(0, player.aliveEntities());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

public class UnitFacingsTest {

Vector2D unitAbsoluteMapCoordinates = create(32, 32);
private Vector2D unitAbsoluteMapCoordinates = create(32, 32);

//////////////////////////////////
// Determine facing from A to B
Expand Down
91 changes: 53 additions & 38 deletions src/test/java/com/fundynamic/d2tm/game/entities/units/UnitTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

import com.fundynamic.d2tm.game.AbstractD2TMTest;
import com.fundynamic.d2tm.game.behaviors.FadingSelection;
import com.fundynamic.d2tm.game.behaviors.HitPointBasedDestructibility;
import com.fundynamic.d2tm.game.entities.Entity;
import com.fundynamic.d2tm.game.entities.EntityType;
import com.fundynamic.d2tm.game.entities.structures.Structure;
import com.fundynamic.d2tm.game.rendering.RenderQueue;
import com.fundynamic.d2tm.math.Vector2D;
import org.junit.Before;
import org.junit.Test;
Expand All @@ -11,6 +16,9 @@
import org.newdawn.slick.SlickException;
import org.newdawn.slick.SpriteSheet;

import java.util.List;

import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
Expand Down Expand Up @@ -45,7 +53,7 @@ public void rendersUnitOnExpectedCoordinates() {
int offsetY = 6;
Vector2D offset = Vector2D.create(offsetX, offsetY);

Unit unit = makeUnit(UnitFacings.DOWN, unitAbsoluteMapCoordinates, offset, 100);
Unit unit = makeUnit(UnitFacings.DOWN, unitAbsoluteMapCoordinates, offset);

// TODO: Resolve this quirky thing, because we pass here the coordinates to draw
// but isn't that basically the unit coordinates * tile size!?
Expand Down Expand Up @@ -73,16 +81,20 @@ public void aliveUnitUpdateCycleOfUnitThatIsNotSelected() {
}

@Test
public void deadUnitUpdateCycle() {
FadingSelection fadingSelection = mock(FadingSelection.class);
int hitPoints = 100;
Unit unit = makeUnit(UnitFacings.DOWN, unitAbsoluteMapCoordinates, Vector2D.zero(), hitPoints);
unit.setFadingSelection(fadingSelection);

unit.takeDamage(hitPoints);
public void whenUnitDiesItSpawnsAnExplosion() {
Unit unit = makeUnit(player);
unit.takeDamage(unit.getHitPoints());

unit.update(1);

Entity lastCreatedEntity = entityRepository.getLastCreatedEntity();
assertThat(lastCreatedEntity.getEntityType(), is(EntityType.PARTICLE));
assertThat(lastCreatedEntity.getEntityData().key, is(unit.getEntityData().getExplosionIdKey()));

// once dead, we don't expect any interactions
FadingSelection fadingSelection = mock(FadingSelection.class);
unit.setFadingSelection(fadingSelection);
unit.update(1);
verifyZeroInteractions(fadingSelection);
}

Expand All @@ -95,57 +107,60 @@ public void verifyUnitMovesToDesiredCellItWantsToMoveToDownRightCell() {

assertThat(unit.getAbsoluteCoordinates(), is(unitAbsoluteMapCoordinates));

// for facing
unit.update(1);
unit.update(0.5F); // decide next cell
unit.update(0.5F); // start turning

// 32 seconds
for (int tick = 0; tick < 32; tick++) {
unit.update(1);
}

// the unit is about to fully move onto new cell
assertThat(unit.getAbsoluteCoordinates(), is(unitAbsoluteMapCoordinates));
assertThat(unit.getOffset(), is(Vector2D.create(31, 31)));

// one more time
unit.update(1);
// a QUAD moves 2 squares for 1 second (see rules.ini)
unit.update(0.5F);

assertThat(unit.getAbsoluteCoordinates(), is(mapCoordinateToMoveTo));
assertThat(unit.getOffset(), is(Vector2D.create(0, 0)));
}

@Test
public void verifyUnitMovesToDesiredCellItWantsToMoveToUpperLeftCell() {
Unit unit = makeUnit(UnitFacings.DOWN, unitAbsoluteMapCoordinates);
Unit unit = makeUnit(UnitFacings.UP, unitAbsoluteMapCoordinates);

Vector2D mapCoordinateToMoveTo = unitAbsoluteMapCoordinates.min(Vector2D.create(32, 32)); // move to left-up
unit.moveTo(mapCoordinateToMoveTo); // move to left-up

assertThat(unit.getAbsoluteCoordinates(), is(unitAbsoluteMapCoordinates));

// for facing, coming from DOWN to LEFT_UP requires a minimum of 4 steps
unit.update(1); // first decide which cell
unit.update(1); // then start turning
unit.update(1); // until
unit.update(1); // we're
unit.update(1); // ready to move...
// for facing, coming from UP to LEFT_UP requires a 1 step
unit.update(1); // first decide which movecell, etc

// and move 32 steps (remember, a unit in a test has a moveSpeed of 1 pixel per 1 second)
for (int tick = 0; tick < 32; tick++) {
unit.update(1);
}
// we take 0.5F because turnSpeed is 2 'turns' per second. So half a second is 1 facing per update
unit.update(0.5F); // turn towards

// the unit is about to move, so do not expect it has been moved yet
assertThat(unit.getAbsoluteCoordinates(), is(unitAbsoluteMapCoordinates));
assertThat(unit.getOffset(), is(Vector2D.create(-31, -31)));

// one more time
unit.update(1);
// a QUAD moves 2 squares for 1 second (see rules.ini)
unit.update(0.5F);

assertThat(unit.getAbsoluteCoordinates(), is(mapCoordinateToMoveTo));
assertThat(unit.getOffset(), is(Vector2D.create(0, 0)));
}

@Test
public void selectedUnitPutsFadingSelectionAndHealthBarOnRenderQueue() {
Unit unit = makeUnit(player, Vector2D.create(48, 48));
unit.select();

Vector2D viewportVec = Vector2D.create(32, 32);
RenderQueue renderQueue = new RenderQueue(viewportVec);
unit.enrichRenderQueue(renderQueue);

List<RenderQueue.ThingToRender> thingsToRender = renderQueue.getThingsToRender(RenderQueue.ENTITY_GUI_LAYER);
assertThat(thingsToRender.size(), is(2));

RenderQueue.ThingToRender first = thingsToRender.get(0);
assertThat(first.renderable, is(instanceOf(HitPointBasedDestructibility.class)));
assertThat(first.x, is(16)); // unitX - viewportVecX
assertThat(first.y, is(16)); // unitY - viewportVecY

RenderQueue.ThingToRender second = thingsToRender.get(1);
assertThat(second.renderable, is(instanceOf(FadingSelection.class)));
assertThat(second.x, is(16)); // unitX - viewportVecX
assertThat(second.y, is(16)); // unitY - viewportVecY
}

public static SpriteSheet makeSpriteSheet() {
SpriteSheet spriteSheet = mock(SpriteSheet.class);
Expand Down

0 comments on commit 770de5c

Please sign in to comment.