Rooms, items and some player stuff
This commit is contained in:
46
src/engine/builders/item.js
Normal file
46
src/engine/builders/item.js
Normal file
@@ -0,0 +1,46 @@
|
||||
import Item from '../item';
|
||||
|
||||
export default class ItemBuilder {
|
||||
constructor() {
|
||||
this.item = new Item();
|
||||
}
|
||||
|
||||
withID(ID) {
|
||||
this.item.id = ID;
|
||||
return this;
|
||||
}
|
||||
|
||||
withName(name) {
|
||||
this.item.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
withDescription(description) {
|
||||
this.item.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
isUsable(value) {
|
||||
this.item.usable = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
isTakeable(value) {
|
||||
this.item.takeable = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
withUseCallback(callback) {
|
||||
this.item.useCallback = callback;
|
||||
return this;
|
||||
}
|
||||
|
||||
withTakeCallback(callback) {
|
||||
this.item.takeCallback = callback;
|
||||
return this;
|
||||
}
|
||||
|
||||
create() {
|
||||
return this.item;
|
||||
}
|
||||
}
|
66
src/engine/builders/room.js
Normal file
66
src/engine/builders/room.js
Normal file
@@ -0,0 +1,66 @@
|
||||
import Room from '../room';
|
||||
|
||||
export default class RoomBuilder {
|
||||
constructor() {
|
||||
this.room = new Room();
|
||||
}
|
||||
|
||||
withID(ID) {
|
||||
this.room.id = ID;
|
||||
return this;
|
||||
}
|
||||
|
||||
withTitle(title) {
|
||||
this.room.title = title;
|
||||
return this;
|
||||
}
|
||||
|
||||
withFirstDescription(description) {
|
||||
this.room.firstDescription = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
withDescription(description) {
|
||||
this.room.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
withExit(direction, roomID) {
|
||||
this.room.addExit(direction, roomID);
|
||||
return this;
|
||||
}
|
||||
|
||||
withItem(itemID) {
|
||||
this.room.addItem(itemID);
|
||||
return this;
|
||||
}
|
||||
|
||||
withEnterCallback(callback) {
|
||||
this.room.addEnterCallback(callback);
|
||||
return this;
|
||||
}
|
||||
|
||||
withExitCallback(callback) {
|
||||
this.room.addExitCallback(callback);
|
||||
return this;
|
||||
}
|
||||
|
||||
withEnterLogic(func) {
|
||||
this.room.addEnterLogic(func);
|
||||
return this;
|
||||
}
|
||||
|
||||
withExitLogic(func) {
|
||||
this.room.addExitLogic(func);
|
||||
return this;
|
||||
}
|
||||
|
||||
withTick(func) {
|
||||
this.room.addTickCallback(func);
|
||||
return this;
|
||||
}
|
||||
|
||||
create() {
|
||||
return this.room;
|
||||
}
|
||||
}
|
43
src/engine/commands.js
Normal file
43
src/engine/commands.js
Normal file
@@ -0,0 +1,43 @@
|
||||
import LookCommand from "./commands/look";
|
||||
import UseCommand from "./commands/use";
|
||||
const defaultCommands = [
|
||||
[["look", "l"], LookCommand],
|
||||
[["use", "interact"], UseCommand]
|
||||
];
|
||||
|
||||
export default class Commands {
|
||||
constructor(context, commands) {
|
||||
this.context = context;
|
||||
this.commands = commands || new Map();
|
||||
this.addDefaultCommands();
|
||||
}
|
||||
|
||||
doCommand(str) {
|
||||
const room = this.context.getRoom(this.context.player.currentRoom);
|
||||
const split = str.split(" ");
|
||||
if (this.commands.get(split[0])) {
|
||||
this.commands.get(split[0])(split, this.context);
|
||||
}
|
||||
if (room.getExit(split[0])) {
|
||||
this.context.move(room.getExit(split[0]));
|
||||
}
|
||||
}
|
||||
|
||||
addCommand(name, func) {
|
||||
if (Array.isArray(name)) {
|
||||
name.forEach((command) => this.commands.set(command, func));
|
||||
} else {
|
||||
this.commands.set(name, func);
|
||||
}
|
||||
}
|
||||
|
||||
addCommands(commands) {
|
||||
commands.forEach((command) => {
|
||||
this.addCommand(command[0], command[1]);
|
||||
});
|
||||
}
|
||||
|
||||
addDefaultCommands() {
|
||||
this.addCommands(defaultCommands);
|
||||
}
|
||||
}
|
21
src/engine/commands/look.js
Normal file
21
src/engine/commands/look.js
Normal file
@@ -0,0 +1,21 @@
|
||||
export default function LookCommand(args, context) {
|
||||
if (args.length == 0) {
|
||||
context.examineRoom();
|
||||
} else {
|
||||
const room = context.getRoom(context.player.currentRoom);
|
||||
const items = room.getItems();
|
||||
let item = null;
|
||||
for (let i of items) {
|
||||
if (i.name.includes(args[1])) {
|
||||
item = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!item) {
|
||||
context.output.say(`I could not find a ${args[1]}`);
|
||||
} else {
|
||||
context.output.say(item.name);
|
||||
context.output.say(item.description);
|
||||
}
|
||||
}
|
||||
}
|
0
src/engine/commands/take.js
Normal file
0
src/engine/commands/take.js
Normal file
16
src/engine/commands/use.js
Normal file
16
src/engine/commands/use.js
Normal file
@@ -0,0 +1,16 @@
|
||||
export default async function UseCommand(args, context) {
|
||||
const room = context.getRoom(context.player.currentRoom);
|
||||
const items = room.getItems();
|
||||
let item = null;
|
||||
for (let i of items) {
|
||||
if (i.name.includes(args[1])) {
|
||||
item = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!item) {
|
||||
context.output.say(`I could not find a ${args[1]}`);
|
||||
} else {
|
||||
await item.onUse();
|
||||
}
|
||||
}
|
92
src/engine/index.js
Normal file
92
src/engine/index.js
Normal file
@@ -0,0 +1,92 @@
|
||||
import State from './state';
|
||||
import Room from './room';
|
||||
import Player from './player';
|
||||
import Output from './output';
|
||||
import Input from './input';
|
||||
import Commands from './commands';
|
||||
|
||||
export default class Game {
|
||||
constructor() {
|
||||
this.player = new Player();
|
||||
this.state = State;
|
||||
this.rooms = [];
|
||||
this.items = [];
|
||||
this.output = new Output();
|
||||
this.commandHandler = new Commands(this);
|
||||
this.input = new Input(this.commandHandler);
|
||||
this.visitedRooms = new Map();
|
||||
}
|
||||
|
||||
print(string) {
|
||||
this.output.say(string);
|
||||
}
|
||||
|
||||
init(data) {
|
||||
console.log(data);
|
||||
this.rooms = data.rooms.map((room) => {
|
||||
room.context = this;
|
||||
return room;
|
||||
});
|
||||
this.items = data.items.map((item) => {
|
||||
item.context = this;
|
||||
return item;
|
||||
});
|
||||
this.state = data.state;
|
||||
this.commandHandler.addCommands(data.commands);
|
||||
this.player = new Player();
|
||||
this.move(this.player.currentRoom);
|
||||
}
|
||||
|
||||
examineRoom() {
|
||||
const room = this.getRoom(this.player.currentRoom);
|
||||
this.output.say(room.title);
|
||||
if (!this.visitedRooms.get(this.player.currentRoom) && room.firstDescription != "") {
|
||||
this.output.say(room.firstDescription);
|
||||
} else {
|
||||
this.output.say(room.description);
|
||||
}
|
||||
this.examineItems();
|
||||
this.examineExits();
|
||||
}
|
||||
|
||||
examineItems() {
|
||||
const room = this.getRoom(this.player.currentRoom);
|
||||
const items = room.getItems();
|
||||
items.forEach((item) => this.output.say(item.name));
|
||||
}
|
||||
|
||||
examineExits() {
|
||||
const room = this.getRoom(this.player.currentRoom);
|
||||
let exitDescription = "You can go ";
|
||||
for (let exit of room.exits.keys()) {
|
||||
exitDescription += " " + exit;
|
||||
}
|
||||
this.output.say(exitDescription);
|
||||
}
|
||||
|
||||
getRoom(id) {
|
||||
return this.rooms.find((room) => room.id == id);
|
||||
}
|
||||
|
||||
getItem(id) {
|
||||
return this.items.find((item) => item.id == id);
|
||||
}
|
||||
|
||||
wait(ms) {
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(resolve, ms);
|
||||
});
|
||||
}
|
||||
|
||||
async move(roomID) {
|
||||
const currentRoom = this.getRoom(this.player.currentRoom);
|
||||
const newRoom = this.getRoom(roomID);
|
||||
if (currentRoom.canExit() && newRoom.canEnter()) {
|
||||
await currentRoom.onExit();
|
||||
await newRoom.onEnter();
|
||||
this.player.currentRoom = roomID;
|
||||
this.examineRoom();
|
||||
this.visitedRooms.set(roomID, true);
|
||||
}
|
||||
}
|
||||
}
|
17
src/engine/input.js
Normal file
17
src/engine/input.js
Normal file
@@ -0,0 +1,17 @@
|
||||
export default class Input {
|
||||
constructor(commandHandler) {
|
||||
this.handler = commandHandler;
|
||||
this.inputField = document.getElementById("input-area");
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
this.inputField.addEventListener("keydown", (e) => {
|
||||
if (e.which == 13) {
|
||||
const val = this.inputField.value;
|
||||
this.inputField.value = "";
|
||||
this.handler.doCommand(val);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
20
src/engine/item.js
Normal file
20
src/engine/item.js
Normal file
@@ -0,0 +1,20 @@
|
||||
export default class Item {
|
||||
constructor() {
|
||||
this.id = "item";
|
||||
this.name = "An item";
|
||||
this.description = "You see nothing special about this item";
|
||||
this.usable = true;
|
||||
this.takeable = true;
|
||||
this.useCallback = null;
|
||||
this.takeCallback = null;
|
||||
this.context = null;
|
||||
}
|
||||
|
||||
async onUse() {
|
||||
if (this.useCallback) return this.useCallback(this.context);
|
||||
}
|
||||
|
||||
async onTake() {
|
||||
if (this.takeCallback) return this.takeCallback();
|
||||
}
|
||||
}
|
16
src/engine/output.js
Normal file
16
src/engine/output.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import { TTS } from '../framework/tts';
|
||||
import { AriaOutput } from '../framework/tts/outputs/aria';
|
||||
|
||||
export default class Output {
|
||||
constructor() {
|
||||
this.tts = new TTS(new AriaOutput());
|
||||
this.history = document.getElementById("output-area");
|
||||
}
|
||||
|
||||
say(string) {
|
||||
const node = document.createElement("p");
|
||||
node.appendChild(document.createTextNode(string));
|
||||
this.history.appendChild(node);
|
||||
// this.tts.speak(string);
|
||||
}
|
||||
}
|
6
src/engine/player.js
Normal file
6
src/engine/player.js
Normal file
@@ -0,0 +1,6 @@
|
||||
export default class Player {
|
||||
constructor() {
|
||||
this.inventory = [];
|
||||
this.currentRoom = "start";
|
||||
}
|
||||
}
|
75
src/engine/room.js
Normal file
75
src/engine/room.js
Normal file
@@ -0,0 +1,75 @@
|
||||
export default class Room {
|
||||
constructor() {
|
||||
this.id = "room";
|
||||
this.title = "A room";
|
||||
this.description = "You see nothing special";
|
||||
this.firstDescription = "As you walk into the room, you notice nothing special";
|
||||
this.objects = [];
|
||||
this.exits = new Map();
|
||||
this.enterCallback = null;
|
||||
this.exitCallback = null;
|
||||
this.canEnterLogic = null;
|
||||
this.canExitLogic = null;
|
||||
this.tickCallback = null;
|
||||
this.context = null;
|
||||
}
|
||||
|
||||
async onEnter() {
|
||||
if (this.enterCallback) return this.enterCallback(this.context);
|
||||
}
|
||||
|
||||
async onExit() {
|
||||
if (this.exitCallback) return this.exitCallback(this.context);
|
||||
}
|
||||
|
||||
canEnter() {
|
||||
if (this.canEnterLogic) {
|
||||
return this.canEnterLogic(this.context);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
canExit() {
|
||||
if (this.canExitLogic) {
|
||||
return this.canExitLogic(this.context);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
addExit(direction, roomID) {
|
||||
this.exits.set(direction, roomID);
|
||||
return this;
|
||||
}
|
||||
|
||||
getExit(direction) {
|
||||
return this.exits.get(direction);
|
||||
}
|
||||
|
||||
addItem(item) {
|
||||
this.objects.push(item);
|
||||
}
|
||||
|
||||
addEnterCallback(callback) {
|
||||
this.enterCallback = callback;
|
||||
}
|
||||
|
||||
addExitCallback(callback) {
|
||||
this.exitCallback = callback;
|
||||
}
|
||||
|
||||
addEnterLogic(func) {
|
||||
this.canEnterLogic = func;
|
||||
}
|
||||
|
||||
addExitLogic(func) {
|
||||
this.canExitLogic = func;
|
||||
}
|
||||
|
||||
addTickCallback(callback) {
|
||||
this.tickCallback = callback;
|
||||
}
|
||||
|
||||
getItems() {
|
||||
return this.objects.map((item) => this.context.getItem(item));
|
||||
}
|
||||
}
|
15
src/engine/state.js
Normal file
15
src/engine/state.js
Normal file
@@ -0,0 +1,15 @@
|
||||
class State {
|
||||
constructor() {
|
||||
this.states = new Map();
|
||||
}
|
||||
|
||||
get(key) {
|
||||
return this.states.get(key);
|
||||
}
|
||||
|
||||
set(key, value) {
|
||||
return this.states.set(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
export default new State();
|
Reference in New Issue
Block a user