[Add] NPC class.

This commit is contained in:
Ritchie Cunningham 2022-03-10 22:57:15 +00:00
parent 35468417a4
commit 8ac22505e3
14 changed files with 191 additions and 54 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
bin/tfg/NPC.class Normal file

Binary file not shown.

Binary file not shown.

View File

@ -53,6 +53,7 @@ public class AnimatedSprite {
public AnimatedSprite(Sprite s, Location l) {
animatedSprite = s;
entityLoc = l;
updatePosition(l);
}
/**

View File

@ -1,14 +1,25 @@
package tfg;
import org.jsfml.graphics.Drawable;
import org.jsfml.graphics.RenderStates;
import org.jsfml.graphics.RenderTarget;
/**
* The base class for all players, NPCs, Monsters, items etc.
*/
public class Entity {
public abstract class Entity implements Drawable, Comparable<Entity> {
/**
* The entity location.
*/
protected Location entityLoc;
/**
* The animated sprite representing the entity.
*/
protected AnimatedSprite entitySprite;
protected Map parentMap;
/**
* Get the entity location.
* @return Entity location.
@ -24,4 +35,31 @@ public class Entity {
public void setLocation(Location l) {
entityLoc = l;
}
/**
* Draw the animated sprite.
*/
public void draw(RenderTarget target, RenderStates states) {
entitySprite.getSprite().draw(target, states);
}
/**
* Update all entity logic on fixed timestep.
*/
public void update() {
/* Update animation, ignored if no animation. */
entitySprite.animate();
}
public void setParentMap(Map m) {
parentMap = m;
}
public Map getParentMap() {
return parentMap;
}
public int compareTo(Entity e) {
return entityLoc.compareTo(e.getLocation());
}
}

View File

@ -47,6 +47,8 @@ public class Game {
* Allows the window to shift focus.
*/
private Camera camera;
private Map currentMap;
/**
@ -64,7 +66,10 @@ public class Game {
public void handleInitialization() {
window.create(new VideoMode(windowDimensions.x, windowDimensions.y),
windowTitle);
player.changeMap(new Map(10, 10, Tile.SAND));
currentMap = new Map(10, 10, Tile.SAND);
currentMap.addEntity(player);
currentMap.addEntity(new NPC(1, 0, "Clefty", "npc1"));
currentMap.addEntity(new NPC(3, 2, "Clefty2", "npc2"));
camera = new Camera(window);
// window.setFramerateLimit(60);
}
@ -120,6 +125,16 @@ public class Game {
break;
case LOST_FOCUS:
windowFocus = false;
break;
case KEY_PRESSED:
switch(event.asKeyEvent().key) {
case E:
player.interact();
break;
default:
break;
}
break;
default:
break;
}
@ -148,7 +163,7 @@ public class Game {
* Update at a fixed rate (20Hz).
*/
public void handleLogic() {
player.update();
currentMap.updateAllEntities();
}
/**
@ -159,8 +174,8 @@ public class Game {
window.clear();
/* Draw each object like layers, background to foreground. */
camera.centerOn(player.getAnimatedSprite());
window.draw(player.getMap());
window.draw(player);
window.draw(currentMap);
currentMap.drawAllEntities(window);
camera.centerOnDefault();
window.draw(fpsUI);
window.display();

View File

@ -7,7 +7,7 @@ import org.jsfml.system.Vector2i;
* Contains a position and direction.
* @author Ritchie Cunningham
*/
public class Location implements Cloneable {
public class Location implements Cloneable, Comparable<Location> {
/**
* Vector position (x,y).
*/
@ -160,4 +160,16 @@ public class Location implements Cloneable {
protected Location clone() throws CloneNotSupportedException {
return (Location) super.clone();
}
public boolean equals(Location l) {
return locPosition.equals(l.getPosition());
}
public String toString() {
return "[" + locPosition.x + ", " + locPosition.y + "] Facing: " + locDirection;
}
public int compareTo(Location l) {
return locPosition.y - l.getPosition().y;
}
}

View File

@ -4,6 +4,7 @@ import org.jsfml.graphics.Drawable;
import org.jsfml.graphics.PrimitiveType;
import org.jsfml.graphics.RenderStates;
import org.jsfml.graphics.RenderTarget;
import org.jsfml.graphics.RenderWindow;
import org.jsfml.graphics.Texture;
import org.jsfml.graphics.Vertex;
import org.jsfml.graphics.VertexArray;
@ -12,7 +13,10 @@ import org.jsfml.system.Vector2i;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
/**
* A map or level for the player to interact in. Can be created
@ -35,6 +39,8 @@ public class Map implements Drawable {
*/
private VertexArray vertexArray = new VertexArray();
private final ArrayList<Entity> entitiesOnMap = new ArrayList<Entity>();
/**
* Create a new map of specified size and tile type.
* @param l Map length.
@ -141,7 +147,39 @@ public class Map implements Drawable {
/* Return true if the location is greater than 0. */
return ((coordinates.x >= 0) && (coordinates.y >=0) &&
(coordinates.x < dimensions.x) &&
(coordinates.y < dimensions.y) && Tile.getCanWalkOn(getTile(l)));
(coordinates.y < dimensions.y) &&
Tile.getCanWalkOn(getTile(l)) &&
(getEntityatLocation(l) == null));
}
public Entity getEntityatLocation(Location l) {
Iterator<Entity> it = entitiesOnMap.iterator();
while(it.hasNext()) {
Entity e = it.next();
if(e.getLocation().equals(1)) {
return e;
}
}
return null;
}
public void addEntity(Entity e) {
if(getEntityatLocation(e.getLocation()) == null) {
e.setParentMap(this);
entitiesOnMap.add(e);
}
}
public void drawAllEntities(RenderWindow w) {
for(Entity e : entitiesOnMap) {
w.draw(e);
}
}
public void updateAllEntities() {
Collections.sort(entitiesOnMap);
for(Entity e : entitiesOnMap) {
e.update();
}
}
}

57
src/tfg/NPC.java Normal file
View File

@ -0,0 +1,57 @@
package tfg;
import org.jsfml.audio.SoundSource;
import org.jsfml.graphics.RenderStates;
import org.jsfml.graphics.RenderTarget;
import org.jsfml.graphics.Sprite;
import org.jsfml.graphics.Texture;
import java.io.IOException;
import java.nio.file.Paths;
/**
* NPC class for interactive non-player characters.
* @author Ritchie Cunningham.
*/
public class NPC extends Entity {
private final Texture entitySpriteshTexture = new Texture();
private boolean moving = false;
private String name;
public NPC(int x, int y, String n, String spritesheet) {
entityLoc = new Location(x,y);
try {
entitySpriteshTexture.loadFromFile(Paths.get("res/"+spritesheet+".png"));
} catch(IOException ex) {
ex.printStackTrace();
}
Sprite sprite = new Sprite();
sprite.setTexture(entitySpriteshTexture);
entitySprite = new AnimatedSprite(sprite, entityLoc);
name = n;
}
public void move(Direction d) {
if(!moving && entitySprite.finishedAnimating()) {
Location newLoc = entityLoc.getRelativeLocation(d);
entityLoc.setDirection(d);
if(parentMap.isValidLocation(newLoc)) {
moving = true;
entitySprite.startAnimation(AnimationType.WALKING);
} else {
entitySprite.startAnimation(AnimationType.STATIONARY_WALK);
}
}
}
public void update() {
if(moving) {
if(entitySprite.finishedAnimating()) {
moving = false;
entityLoc = entityLoc.getRelativeLocation(entityLoc.getDirection());
entitySprite.updatePosition(entityLoc);
}
}
entitySprite.animate();
}
}

View File

@ -3,9 +3,6 @@ package tfg;
import org.jsfml.audio.Sound;
import org.jsfml.audio.SoundBuffer;
import org.jsfml.audio.SoundSource;
import org.jsfml.graphics.Drawable;
import org.jsfml.graphics.RenderStates;
import org.jsfml.graphics.RenderTarget;
import org.jsfml.graphics.Sprite;
import org.jsfml.graphics.Texture;
@ -16,19 +13,12 @@ import java.nio.file.Paths;
* Holds everything that pertains to the player (you?).
* @author Ritchie Cunningham
*/
public class Player extends Entity implements Drawable {
public class Player extends Entity {
/**
* The texture for the sprite.
*/
private Texture playerSpritesheetTexture = new Texture();
/**
* The player sprite that supports animation.
*/
private final AnimatedSprite playerSprite;
/**
* The map the player is currently on.
*/
private Map currentMap;
private final Texture entitySpritesheetTexture = new Texture();
/**
* The action the player is currently performing.
*/
@ -51,15 +41,15 @@ public class Player extends Entity implements Drawable {
entityLoc = new Location(x, y);
/* Load sprite texture and 'stuck' sound. */
try {
playerSpritesheetTexture.loadFromFile(Paths.get("res/player.png"));
entitySpritesheetTexture.loadFromFile(Paths.get("res/player.png"));
cannotMoveBuffer.loadFromFile(Paths.get("res/stuck.wav"));
} catch(IOException ex) {
ex.printStackTrace();
}
Sprite sprite = new Sprite(); /* Create a new regular sprite. */
sprite.setTexture(playerSpritesheetTexture);
sprite.setTexture(entitySpritesheetTexture);
/* Create a new animated sprite from the regular sprite. */
playerSprite = new AnimatedSprite(sprite, entityLoc);
entitySprite = new AnimatedSprite(sprite, entityLoc);
cannotMove.setBuffer(cannotMoveBuffer);
}
@ -70,43 +60,27 @@ public class Player extends Entity implements Drawable {
this(0,0);
}
/**
* Change the map the is on.
* @param m New map.
*/
public void changeMap(Map m) {
currentMap = m;
}
/**
* Get the map the player is currently on.
* @return Map player is currently on.
*/
public Map getMap() {
return currentMap;
}
/**
* Move the player in the specified direction.
* @param d Direction to move the player.
*/
public void move(Direction d) {
if(currentAction == PlayerAction.NONE) {
if(currentAction == PlayerAction.NONE && entitySprite.finishedAnimating()) {
/*
* Get the location relative to the current location.
* e.g. NORTH would return the location above the current location.
*/
Location newLoc = entityLoc.getRelativeLocation(d);
entityLoc.setDirection(d);
if(currentMap.isValidLocation(newLoc)) {
if(parentMap.isValidLocation(newLoc)) {
currentAction = PlayerAction.MOVING;
playerSprite.startAnimation(AnimationType.WALKING);
entitySprite.startAnimation(AnimationType.WALKING);
} else if(cannotMove.getStatus() == SoundSource.Status.STOPPED) {
/*
* Play the stationary walk animation.
* It appears like the player is trying to move, but can't.
*/
playerSprite.startAnimation(AnimationType.STATIONARY_WALK);
entitySprite.startAnimation(AnimationType.STATIONARY_WALK);
/* Play an annoying sound. */
cannotMove.play();
}
@ -119,16 +93,16 @@ public class Player extends Entity implements Drawable {
*/
public void update() {
if(currentAction == PlayerAction.MOVING) {
if(playerSprite.finishedAnimating()) {
if(entitySprite.finishedAnimating()) {
currentAction = PlayerAction.NONE;
/* Actually move the location. */
entityLoc = entityLoc.getRelativeLocation(entityLoc.getDirection());
/* Update the sprite with new location. */
playerSprite.updatePosition(entityLoc);
entitySprite.updatePosition(entityLoc);
}
}
/* Update the animation, if there is no current animation, ignore. */
playerSprite.animate();
entitySprite.animate();
}
/**
@ -136,14 +110,16 @@ public class Player extends Entity implements Drawable {
* @return Animated sprite.
*/
public AnimatedSprite getAnimatedSprite() {
return playerSprite;
return entitySprite;
}
/**
* Draw the player on screen.
*/
public void draw(RenderTarget target, RenderStates states) {
/* Get the animated sprite and draw it. */
playerSprite.getSprite().draw(target, states);
public void interact() {
Location interactLoc = entityLoc.getRelativeLocation(entityLoc.getDirection());
Entity e = parentMap.getEntityatLocation(interactLoc);
if(e != null && e instanceof NPC) {
System.out.println("'Sup Nerd!");
NPC npc = (NPC)e;
npc.move(Direction.SOUTH);
}
}
}