Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Player can move units #62

Merged
merged 20 commits into from Mar 31, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
8c0651b
implement crude way of distinguishing if we should 'move' or 'place' …
stefanhendriks Mar 12, 2015
4904fbc
move unit to given destination (but does not reveal shroud)
stefanhendriks Mar 12, 2015
e0f1bee
when moving unit to other cell reveal shroud on map
stefanhendriks Mar 12, 2015
aaff66b
instead of jumping to target, just do a very naive decision what the …
stefanhendriks Mar 12, 2015
5a845fc
determine facing (8 sides only) when moving to cell.
stefanhendriks Mar 12, 2015
cace1c0
move unit pixel by pixel at a random pace
stefanhendriks Mar 15, 2015
748a65d
first accumulate all possible vector changes before applying them - t…
stefanhendriks Mar 15, 2015
3120e22
player can only move its own units
stefanhendriks Mar 16, 2015
116cf7a
make sure you move onto next cell before going to a new one so that a…
stefanhendriks Mar 16, 2015
ba6d60e
rename to controllingPlayer because that sounds less booleanish
stefanhendriks Mar 18, 2015
cae5010
provide moveSpeed upon construction on Unit, so it is configurable
stefanhendriks Mar 18, 2015
7d4a510
select unit - even when mouse is already moving cursor
stefanhendriks Mar 18, 2015
eac454d
refactor mouse logic into behavior classes - todo: write tests as the…
stefanhendriks Mar 18, 2015
f0c0ca1
render debug info for cells + make controllingPlayer part of the Mous…
stefanhendriks Mar 19, 2015
869d7dd
render mouse using png's and change rendering depending on mouse beha…
stefanhendriks Mar 19, 2015
364aba9
show debug cell info only when toggled
stefanhendriks Mar 19, 2015
fa1e02c
ignore graphics/ folder which I have locally with temp stuff
stefanhendriks Mar 19, 2015
febb9aa
fix broken tests
stefanhendriks Mar 19, 2015
193da35
remove 'public' keyword because it is obselete in an interface
stefanhendriks Mar 24, 2015
35a28ef
Claim cell before moving to it. Also make sure collision detection skips
stefanhendriks Mar 24, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -14,6 +14,7 @@ engine/target
game/target
d2tm/target
target
graphics/

# Eclipse files
engine/.classpath
Expand Down
@@ -0,0 +1,9 @@
package com.fundynamic.d2tm.game.behaviors;

import com.fundynamic.d2tm.math.Vector2D;

public interface Moveable {

void moveTo(Vector2D target);

}
@@ -0,0 +1,18 @@
package com.fundynamic.d2tm.game.controls;


import com.fundynamic.d2tm.game.map.Cell;

public abstract class AbstractMouseBehavior implements MouseBehavior {
protected final Mouse mouse;

public AbstractMouseBehavior(Mouse mouse) {
this.mouse = mouse;
}

public abstract void leftClicked();

public abstract void rightClicked();

public abstract void mouseMovedToCell(Cell cell);
}
117 changes: 76 additions & 41 deletions src/main/java/com/fundynamic/d2tm/game/controls/Mouse.java
@@ -1,73 +1,108 @@
package com.fundynamic.d2tm.game.controls;

import com.fundynamic.d2tm.game.behaviors.Selectable;
import com.fundynamic.d2tm.game.entities.Entity;
import com.fundynamic.d2tm.game.entities.Player;
import com.fundynamic.d2tm.game.map.Cell;
import com.fundynamic.d2tm.math.Vector2D;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Image;
import org.newdawn.slick.SlickException;

import java.util.HashMap;
import java.util.Map;


/**
* This class represents the state of the mouse. This is not about coordinates (we can get these via Slick listeners)
* but about what structure is selected, the type of mouse being rendered (ie moving? attacking? placing structure? or
* 'normal' ?)
*/
public class Mouse {

private Cell hoverCell;
public enum MouseImages {
NORMAL, HOVER_OVER_SELECTABLE_ENTITY, MOVE, ATTACK, CUSTOM
}

private final Player controllingPlayer;
private final GameContainer gameContainer;

private MouseBehavior mouseBehavior;
private Entity lastSelectedEntity;
private Cell hoverCell;
private MouseImages currentImage = null;

public Mouse(){}
private Map<MouseImages, Image> mouseImages;

public Mouse(Cell hoverCell) {
this.hoverCell = hoverCell;
public Mouse(Player controllingPlayer, GameContainer gameContainer) {
this.controllingPlayer = controllingPlayer;
this.mouseBehavior = null;
this.hoverCell = null;
this.gameContainer = gameContainer;
this.mouseImages = new HashMap<>();
}

public void setHoverCell(Cell cell) {
if (cell == null) throw new IllegalArgumentException("argument cell may not be null");
this.hoverCell = cell;
public void init() {
this.mouseBehavior = new NormalMouse(this);
this.hoverCell = null;
}

public Cell getHoverCell() {
return hoverCell;
public void leftClicked() {
mouseBehavior.leftClicked();
}

public Vector2D getHoverCellMapVector() {
return hoverCell.getCoordinatesAsVector2D();
public void rightClicked() {
mouseBehavior.rightClicked();
}

/**
* When a structure is bound to a cell, this method makes sure that is the only selected structure.
* If there is no structure bound to the cell then this automatically deselects the structure.
*/
public void selectEntity() {
if (hoverCell == null) return;
Entity entity = hoverCell.getEntity();
if (entity == null) return;
if (!entity.isSelectable()) return;
lastSelectedEntity = entity;
((Selectable)lastSelectedEntity).select();
public void mouseMovedToCell(Cell cell) {
mouseBehavior.mouseMovedToCell(cell);
}

public boolean hasAnyEntitySelected() {
return this.lastSelectedEntity != null;
public void setMouseBehavior(MouseBehavior mouseBehavior) {
if (mouseBehavior == null) throw new IllegalArgumentException("MouseBehavior argument may not be null!");
System.out.println("Mouse behavior changed into " + mouseBehavior);
this.mouseBehavior = mouseBehavior;
}

public Entity getLastSelectedEntity() {
return lastSelectedEntity;
}

public void deselectEntity() {
if (lastSelectedEntity != null) {
if (lastSelectedEntity.isSelectable()) {
((Selectable) lastSelectedEntity).deselect();
}
public void setLastSelectedEntity(Entity lastSelectedEntity) {
this.lastSelectedEntity = lastSelectedEntity;
}

public Cell getHoverCell() {
return hoverCell;
}

public void setHoverCell(Cell hoverCell) {
this.hoverCell = hoverCell;
}

public Player getControllingPlayer() {
return controllingPlayer;
}

public void setMouseImage(Image image, int hotSpotX, int hotSpotY) {
if (image == null) throw new IllegalArgumentException("Image to set for mouse cursor may not be null!");
if (!mouseImages.containsValue(image)) {
this.currentImage = MouseImages.CUSTOM;
}
try {
gameContainer.setMouseCursor(image, hotSpotX, hotSpotY);
} catch (SlickException e) {
e.printStackTrace();
}
lastSelectedEntity = null;
}

public boolean hoversOverSelectableEntity() {
Entity entity = hoverCell.getEntity();
if (entity == null) return false;
return entity.isSelectable();
public void setMouseImage(MouseImages key, int hotSpotX, int hotSpotY) {
if (key.equals(this.currentImage)) return;
this.currentImage = key;
setMouseImage(mouseImages.get(key), hotSpotX, hotSpotY);
}

public void addMouseImage(MouseImages key, Image image) {
if (image == null) throw new IllegalArgumentException("Image for mouse images cannot be null!");
this.mouseImages.put(key, image);
}

public MouseBehavior getMouseBehavior() {
return this.mouseBehavior;
}

}
14 changes: 14 additions & 0 deletions src/main/java/com/fundynamic/d2tm/game/controls/MouseBehavior.java
@@ -0,0 +1,14 @@
package com.fundynamic.d2tm.game.controls;


import com.fundynamic.d2tm.game.map.Cell;

public interface MouseBehavior {

void leftClicked();

void rightClicked();

void mouseMovedToCell(Cell cell);

}
@@ -0,0 +1,48 @@
package com.fundynamic.d2tm.game.controls;


import com.fundynamic.d2tm.game.behaviors.Moveable;
import com.fundynamic.d2tm.game.entities.Entity;
import com.fundynamic.d2tm.game.map.Cell;

public class MovableSelectedMouse extends NormalMouse {

public MovableSelectedMouse(Mouse mouse) {
super(mouse);
mouse.setMouseImage(Mouse.MouseImages.MOVE, 16, 16);
}

@Override
public void leftClicked() {
Entity entity = hoveringOverSelectableEntity();
if (entity != null) {
deselectCurrentlySelectedEntity();
selectEntity(entity);
} else {
if (selectedEntityBelongsToControllingPlayer() && selectedEntityIsMovable()) {
((Moveable) mouse.getLastSelectedEntity()).moveTo(mouse.getHoverCell().getCoordinatesAsVector2D());
}
}
}

@Override
public void mouseMovedToCell(Cell cell) {
if (cell == null) throw new IllegalArgumentException("argument cell may not be null");
mouse.setHoverCell(cell);
Entity entity = hoveringOverSelectableEntity();
if (entity == null) {
mouse.setMouseImage(Mouse.MouseImages.MOVE, 16, 16);
return;
}
if (entity.belongsToPlayer(mouse.getControllingPlayer())) {
mouse.setMouseImage(Mouse.MouseImages.HOVER_OVER_SELECTABLE_ENTITY, 16, 16);
} else {
mouse.setMouseImage(Mouse.MouseImages.ATTACK, 16, 16);
}
}

@Override
public void rightClicked() {
super.rightClicked();
}
}
89 changes: 89 additions & 0 deletions src/main/java/com/fundynamic/d2tm/game/controls/NormalMouse.java
@@ -0,0 +1,89 @@
package com.fundynamic.d2tm.game.controls;


import com.fundynamic.d2tm.game.behaviors.Selectable;
import com.fundynamic.d2tm.game.entities.Entity;
import com.fundynamic.d2tm.game.entities.Player;
import com.fundynamic.d2tm.game.map.Cell;


public class NormalMouse extends AbstractMouseBehavior {

public NormalMouse(Mouse mouse) {
super(mouse);
mouse.setMouseImage(Mouse.MouseImages.NORMAL, 0, 0);
}

@Override
public void leftClicked() {
Entity entity = hoveringOverSelectableEntity();
if (entity == null) return;

selectEntity(entity);

if (selectedEntityBelongsToControllingPlayer() && selectedEntityIsMovable()) {
mouse.setMouseBehavior(new MovableSelectedMouse(mouse));
}
}

protected void selectEntity(Entity entity) {
deselectCurrentlySelectedEntity();
mouse.setLastSelectedEntity(entity);
((Selectable) entity).select();
}

protected Entity hoveringOverSelectableEntity() {
Cell hoverCell = mouse.getHoverCell();
if (hoverCell == null) return null;
Entity entity = hoverCell.getEntity();
if (entity == null) return null;
if (!entity.isSelectable()) return null;
return entity;
}

@Override
public void rightClicked() {
deselectCurrentlySelectedEntity();
if (selectedEntityBelongsToControllingPlayer()) {
mouse.setMouseBehavior(new NormalMouse(mouse));
}
mouse.setLastSelectedEntity(null);
}

protected void deselectCurrentlySelectedEntity() {
Entity lastSelectedEntity = mouse.getLastSelectedEntity();
if (lastSelectedEntity != null) {
if (lastSelectedEntity.isSelectable()) {
((Selectable) lastSelectedEntity).deselect();
}
}
mouse.setMouseImage(Mouse.MouseImages.NORMAL, 0, 0);
}

@Override
public void mouseMovedToCell(Cell cell) {
if (cell == null) throw new IllegalArgumentException("argument cell may not be null");
mouse.setHoverCell(cell);
Entity entity = hoveringOverSelectableEntity();
if (entity != null && entity.belongsToPlayer(mouse.getControllingPlayer())) {
mouse.setMouseImage(Mouse.MouseImages.HOVER_OVER_SELECTABLE_ENTITY, 16, 16);
} else {
mouse.setMouseImage(Mouse.MouseImages.NORMAL, 0, 0);
}
}

protected boolean selectedEntityBelongsToControllingPlayer() {
Entity lastSelectedEntity = mouse.getLastSelectedEntity();
if (lastSelectedEntity == null) return false;
Player controllingPlayer = mouse.getControllingPlayer();
if (controllingPlayer == null) return false;
return lastSelectedEntity.getPlayer().equals(controllingPlayer);
}


protected boolean selectedEntityIsMovable() {
Entity lastSelectedEntity = mouse.getLastSelectedEntity();
return lastSelectedEntity.isMovable();
}

}
@@ -0,0 +1,49 @@
package com.fundynamic.d2tm.game.controls;


import com.fundynamic.d2tm.game.entities.EntityRepository;
import com.fundynamic.d2tm.game.map.Cell;
import com.fundynamic.d2tm.math.Random;
import org.newdawn.slick.Color;
import org.newdawn.slick.Graphics;

public class PlacingStructureMouse extends AbstractMouseBehavior {

private final EntityRepository entityRepository;
private EntityRepository.EntityData entityToPlace;

public PlacingStructureMouse(Mouse mouse, EntityRepository entityRepository) {
super(mouse);
this.entityRepository = entityRepository;
selectRandomlySomethingToPlace();
}

@Override
public void leftClicked() {
Cell hoverCell = mouse.getHoverCell();
entityRepository.placeOnMap(hoverCell.getCoordinatesAsVector2D(), entityToPlace, mouse.getControllingPlayer());
selectRandomlySomethingToPlace();
}

@Override
public void rightClicked() {
mouse.setMouseBehavior(new NormalMouse(mouse));
}

@Override
public void mouseMovedToCell(Cell cell) {
mouse.setHoverCell(cell);
}

public void render(Graphics graphics, int x, int y) {
graphics.setColor(Color.green);
graphics.setLineWidth(1.1f);
graphics.drawRect(x, y, entityToPlace.width, entityToPlace.height);
}

private void selectRandomlySomethingToPlace() {
entityToPlace = entityRepository.getEntityData(EntityRepository.EntityType.STRUCTURE, Random.getRandomBetween(0, 2));
mouse.setMouseImage(entityToPlace.getFirstImage(), 16, 16);
}

}