Add inventory
This commit is contained in:
parent
548fb99c8b
commit
469121e18a
8 changed files with 200 additions and 22 deletions
|
@ -2,13 +2,15 @@ import * as input from '../input.mjs';
|
||||||
import * as events from './events.mjs';
|
import * as events from './events.mjs';
|
||||||
import * as player from './player.mjs';
|
import * as player from './player.mjs';
|
||||||
import * as graphics from '../graphics/index.mjs';
|
import * as graphics from '../graphics/index.mjs';
|
||||||
|
import * as inventory from './inventory.mjs';
|
||||||
import {state} from './index.mjs';
|
import {state} from './index.mjs';
|
||||||
|
|
||||||
export const mapping = {
|
export const mapping = {
|
||||||
thrust: 'KeyW',
|
thrust: 'KeyW',
|
||||||
left: 'KeyA',
|
left: 'KeyA',
|
||||||
right: 'KeyD',
|
right: 'KeyD',
|
||||||
exitEdit: 'Escape'
|
exitEdit: 'Escape',
|
||||||
|
inventory: 'KeyE',
|
||||||
};
|
};
|
||||||
|
|
||||||
let held, pressed;
|
let held, pressed;
|
||||||
|
@ -42,6 +44,10 @@ function tickPlaying() {
|
||||||
if (held[mapping.right]) {
|
if (held[mapping.right]) {
|
||||||
player.ship.applyThrust({ turnRight: 1 });
|
player.ship.applyThrust({ turnRight: 1 });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pressed[mapping.inventory]) {
|
||||||
|
state.inventory = !state.inventory;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function tickEditing() {
|
function tickEditing() {
|
||||||
|
|
|
@ -23,12 +23,14 @@ export function launchShip() {
|
||||||
|
|
||||||
export function editShip() {
|
export function editShip() {
|
||||||
game.state.editing = true;
|
game.state.editing = true;
|
||||||
|
game.state.inventory = true;
|
||||||
edit.init();
|
edit.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function endEditing() {
|
export function endEditing() {
|
||||||
graphics.changePerspective('universe');
|
graphics.changePerspective('universe');
|
||||||
game.state.editing = false;
|
game.state.editing = false;
|
||||||
|
game.state.inventory = false;
|
||||||
edit.end();
|
edit.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ import * as graphics from '../graphics/index.mjs';
|
||||||
import * as gui from '../gui/index.mjs';
|
import * as gui from '../gui/index.mjs';
|
||||||
import * as assets from '../assets.mjs';
|
import * as assets from '../assets.mjs';
|
||||||
import * as input from '../input.mjs';
|
import * as input from '../input.mjs';
|
||||||
|
import * as inventory from './inventory.mjs';
|
||||||
import * as world from '../world/index.mjs';
|
import * as world from '../world/index.mjs';
|
||||||
import * as events from './events.mjs';
|
import * as events from './events.mjs';
|
||||||
import * as control from './control.mjs';
|
import * as control from './control.mjs';
|
||||||
|
@ -15,7 +16,8 @@ export async function init() {
|
||||||
view: 'menu',
|
view: 'menu',
|
||||||
playing: false,
|
playing: false,
|
||||||
editing: false,
|
editing: false,
|
||||||
paused: false
|
paused: false,
|
||||||
|
inventory: false
|
||||||
};
|
};
|
||||||
|
|
||||||
graphics.init();
|
graphics.init();
|
||||||
|
@ -29,7 +31,7 @@ export async function init() {
|
||||||
|
|
||||||
// Recursive `requestAnimationFrame` can cause problems with Parcel.
|
// Recursive `requestAnimationFrame` can cause problems with Parcel.
|
||||||
while(true) {
|
while(true) {
|
||||||
await tick();
|
tick();
|
||||||
await new Promise(res => requestAnimationFrame(res));
|
await new Promise(res => requestAnimationFrame(res));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,10 +46,11 @@ export function changeView(view) {
|
||||||
state.paused = false;
|
state.paused = false;
|
||||||
world.init();
|
world.init();
|
||||||
player.init();
|
player.init();
|
||||||
|
inventory.init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function tick() {
|
function tick() {
|
||||||
if (state.view == 'game') {
|
if (state.view == 'game') {
|
||||||
world.tick();
|
world.tick();
|
||||||
control.tick();
|
control.tick();
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
import {modules} from '../data.mjs';
|
||||||
|
import {images as assets} from '../assets.mjs';
|
||||||
|
|
||||||
|
export const items = new Map();
|
||||||
|
export let currentItem = null;
|
||||||
|
|
||||||
|
export function init() {
|
||||||
|
items.clear();
|
||||||
|
addItem('capsule', 'small');
|
||||||
|
addItem('thruster', 'light');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTiles() {
|
||||||
|
let list = Array.from(items.values());
|
||||||
|
list.sort((a, b) => toId(...a.ident) < toId(...b.ident));
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function addItem(type, id) {
|
||||||
|
let mapId = toId(type, id);
|
||||||
|
if (!items.has(mapId)) items.set(mapId, new Tile(type, id));
|
||||||
|
let tile = items.get(mapId);
|
||||||
|
tile.increase();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function removeItem(type, id) {
|
||||||
|
let mapId = toId(type, id);
|
||||||
|
if (!items.has(mapId)) return;
|
||||||
|
let tile = items.get(mapId);
|
||||||
|
tile.decrease();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectItem(type, id) {
|
||||||
|
currentItem = items.get(toId(type, id));
|
||||||
|
}
|
||||||
|
|
||||||
|
function toId(type, id) {
|
||||||
|
return `${type}.${id}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Tile {
|
||||||
|
constructor(type, id, q = 0) {
|
||||||
|
this.type = type;
|
||||||
|
this.id = id;
|
||||||
|
this.mapId = toId(type, id);
|
||||||
|
this.quantity = q;
|
||||||
|
this.image = assets.modules[type][id];
|
||||||
|
if (type === 'thruster') this.image = this.image.off;
|
||||||
|
}
|
||||||
|
|
||||||
|
get ident() {
|
||||||
|
return [this.type, this.id];
|
||||||
|
}
|
||||||
|
|
||||||
|
increase() {
|
||||||
|
this.quantity++;
|
||||||
|
}
|
||||||
|
|
||||||
|
decrease() {
|
||||||
|
this.quantity = Math.max(0, this.quantity - 1);
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,6 +14,7 @@ function renderElement(element) {
|
||||||
if (element.type == 'button') renderButton(element);
|
if (element.type == 'button') renderButton(element);
|
||||||
if (element.type == 'edit') renderEdit(element);
|
if (element.type == 'edit') renderEdit(element);
|
||||||
if (element.type == 'itemButton') renderItemButton(element);
|
if (element.type == 'itemButton') renderItemButton(element);
|
||||||
|
if (element.type == 'inventory') renderInventory(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (element.options.drawChildren)
|
if (element.options.drawChildren)
|
||||||
|
@ -56,30 +57,32 @@ function renderItemButton(element) {
|
||||||
}
|
}
|
||||||
|
|
||||||
context.fillRect(...element.shape);
|
context.fillRect(...element.shape);
|
||||||
|
if (element.selected) {
|
||||||
|
context.strokeStyle = '#fff';
|
||||||
|
context.lineWidth = 2;
|
||||||
|
} else {
|
||||||
context.strokeStyle = '#333';
|
context.strokeStyle = '#333';
|
||||||
context.strokeWidth = 4;
|
context.lineWidth = 1;
|
||||||
|
}
|
||||||
context.strokeRect(...element.shape);
|
context.strokeRect(...element.shape);
|
||||||
context.globalAlpha = 1;
|
context.globalAlpha = 1;
|
||||||
|
|
||||||
if (element.image) {
|
if (element.image) {
|
||||||
context.drawImage(element.image, ...element.shape);
|
let p = element.padding;
|
||||||
|
let ox = element.x + (p / 2 * element.w);
|
||||||
|
let oy = element.y + (p / 2 * element.h);
|
||||||
|
let [dw, dh] = [element.w * (1 - p), element.h * (1 - p)];
|
||||||
|
context.drawImage(element.image, ox, oy, dw, dh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderEdit(element) {
|
function renderEdit(element) {
|
||||||
/*
|
|
||||||
element.tiles.forEach(t => {
|
|
||||||
let tile = edit.getTile(x, y);
|
|
||||||
let [dx, dy] = tile.drawPos;
|
|
||||||
context.globalAlpha = 0.5;
|
|
||||||
context.fillStyle = '#000';
|
|
||||||
context.fillRect(dx, dy, 1, 1);
|
|
||||||
context.globalAlpha = 1;
|
|
||||||
|
|
||||||
let module = tile.module;
|
}
|
||||||
if (module !== null) {
|
|
||||||
context.drawImage(module.currentImage, dx, dy, 1, 1);
|
function renderInventory(element) {
|
||||||
}
|
context.globalAlpha = 0.1;
|
||||||
});
|
context.fillStyle = '#541';
|
||||||
*/
|
context.fillRect(...element.shape);
|
||||||
|
context.globalAlpha = 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
import * as gui from './index.mjs';
|
||||||
|
import GuiElement from './element.mjs';
|
||||||
|
import GuiItemButton from './item.mjs';
|
||||||
|
import {state} from '../game/index.mjs';
|
||||||
|
import * as inventory from '../game/inventory.mjs';
|
||||||
|
|
||||||
|
export default class GuiInventory extends GuiElement {
|
||||||
|
constructor(x, y, w = 100, h = 30) {
|
||||||
|
super(x, y, w, h);
|
||||||
|
this.type = 'inventory';
|
||||||
|
this.tileWidth = 4;
|
||||||
|
this.tileHeight = 5;
|
||||||
|
this.currentPage = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateTiles() {
|
||||||
|
this.children.clear();
|
||||||
|
|
||||||
|
let tileRatio = this.tileWidth / this.tileHeight;
|
||||||
|
let rectRatio = this.w / this.h;
|
||||||
|
let tileSize;
|
||||||
|
let [ox, oy] = [0, 0];
|
||||||
|
|
||||||
|
if (tileRatio < rectRatio) {
|
||||||
|
tileSize = this.h / this.tileHeight;
|
||||||
|
ox = (this.w - (tileSize * this.tileWidth)) / 2;
|
||||||
|
} else {
|
||||||
|
tileSize = this.w / this.tileWidth;
|
||||||
|
oy = (this.h - (tileSize * this.tileHeight)) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
let spacing = 0.15 * tileSize;
|
||||||
|
let pageSize = this.tileWidth * this.tileHeight;
|
||||||
|
let offset = pageSize * this.currentPage;
|
||||||
|
let tiles = inventory.getTiles().slice(offset);
|
||||||
|
let tile;
|
||||||
|
|
||||||
|
for (let y = 0; y < this.tileHeight; y++)
|
||||||
|
for (let x = 0; x < this.tileWidth && tiles.length; x++) {
|
||||||
|
let i = y * this.tileWidth + (x % this.tileWidth) + offset;
|
||||||
|
tile = tiles.shift();
|
||||||
|
|
||||||
|
let ex = x * tileSize + spacing / 2 + ox + this.x;
|
||||||
|
let ey = y * tileSize + spacing / 2 + oy + this.y;
|
||||||
|
let [ew, eh] = [tileSize - spacing, tileSize - spacing];
|
||||||
|
|
||||||
|
let ident = tile.ident;
|
||||||
|
|
||||||
|
let onclick = (button) => {
|
||||||
|
this.tileClicked(...ident, button);
|
||||||
|
};
|
||||||
|
|
||||||
|
let cur = inventory.currentItem;
|
||||||
|
let selected = cur !== null && tile.type === cur.type
|
||||||
|
&& tile.id === cur.id;
|
||||||
|
|
||||||
|
let el = new GuiItemButton(tile, onclick, ex, ey, ew, eh, {
|
||||||
|
padding: 0.1,
|
||||||
|
selected: selected
|
||||||
|
});
|
||||||
|
|
||||||
|
this.append(el);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tick() {
|
||||||
|
if (state.inventory && !this.active) this.updateTiles();
|
||||||
|
this.active = state.inventory;
|
||||||
|
this.options.draw = this.options.drawChildren = this.active;
|
||||||
|
if (!this.active) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
getTile(x, y) {
|
||||||
|
return this.getTile(x + px, y + py);
|
||||||
|
}
|
||||||
|
|
||||||
|
tileClicked(type, id, button) {
|
||||||
|
if (button == 'left') inventory.selectItem(type, id);
|
||||||
|
|
||||||
|
if (!state.editing) {
|
||||||
|
if (button == 'left') {
|
||||||
|
inventory.addItem(type, id);
|
||||||
|
} else if (button == 'right') {
|
||||||
|
inventory.removeitem(type, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateTiles();
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,11 +2,16 @@ import * as gui from './index.mjs';
|
||||||
import GuiButton from './button.mjs';
|
import GuiButton from './button.mjs';
|
||||||
|
|
||||||
export default class GuiItemButton extends GuiButton {
|
export default class GuiItemButton extends GuiButton {
|
||||||
constructor(tile, onclick, x, y, w = 50, h = 50) {
|
constructor(tile, onclick, x, y, w = 50, h = 50, { padding, selected } = {
|
||||||
|
padding: 0,
|
||||||
|
selected: false
|
||||||
|
}) {
|
||||||
super(null, onclick, x, y, w, h);
|
super(null, onclick, x, y, w, h);
|
||||||
this.module = tile.module;
|
this.module = tile.module;
|
||||||
this.image = tile.image;
|
this.image = tile.image;
|
||||||
this.type = 'itemButton';
|
this.type = 'itemButton';
|
||||||
|
this.padding = padding;
|
||||||
|
this.selected = selected;
|
||||||
}
|
}
|
||||||
|
|
||||||
click() {
|
click() {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import GuiFrame from './frame.mjs';
|
||||||
import GuiImage from './image.mjs';
|
import GuiImage from './image.mjs';
|
||||||
import GuiButton from './button.mjs';
|
import GuiButton from './button.mjs';
|
||||||
import GuiEdit from './edit.mjs';
|
import GuiEdit from './edit.mjs';
|
||||||
|
import GuiInventory from './inventory.mjs';
|
||||||
import * as events from '../game/events.mjs';
|
import * as events from '../game/events.mjs';
|
||||||
import {state} from '../game/index.mjs';
|
import {state} from '../game/index.mjs';
|
||||||
|
|
||||||
|
@ -53,5 +54,11 @@ export function game() {
|
||||||
edit.x -= 10;
|
edit.x -= 10;
|
||||||
edit.y += 10;
|
edit.y += 10;
|
||||||
|
|
||||||
|
let inventory = new GuiInventory(0, 0, 0, 0);
|
||||||
|
shadow.append(inventory);
|
||||||
|
inventory.posRelative({x: 0, y: 0, w: 0.4, h: 0.6});
|
||||||
|
inventory.x += 10;
|
||||||
|
inventory.y += 10;
|
||||||
|
|
||||||
return shadow;
|
return shadow;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue