Basic gameplay?
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 177 B |
Binary file not shown.
|
After Width: | Height: | Size: 177 B |
@@ -12,11 +12,15 @@ import { create_main_menu } from "./main_menu.ts";
|
|||||||
import { ClickableSystem } from "./systems/clickable_system.ts";
|
import { ClickableSystem } from "./systems/clickable_system.ts";
|
||||||
import { start_game } from "./game.ts";
|
import { start_game } from "./game.ts";
|
||||||
import { canvas, resize_canvas } from "./renderer.ts";
|
import { canvas, resize_canvas } from "./renderer.ts";
|
||||||
|
import { DimensionLogicSystem } from "./systems/dimension_logic.ts";
|
||||||
|
import { Dimension } from "./components/dimension.ts";
|
||||||
|
|
||||||
export class ClientWorld extends World {
|
export class ClientWorld extends World {
|
||||||
paused = false;
|
paused = false;
|
||||||
debugging = false;
|
debugging = false;
|
||||||
|
|
||||||
|
dimension!: Dimension;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super("game");
|
super("game");
|
||||||
|
|
||||||
@@ -43,6 +47,7 @@ export class ClientWorld extends World {
|
|||||||
this.add_system(new PlayerControlsSystem(), "game");
|
this.add_system(new PlayerControlsSystem(), "game");
|
||||||
this.add_system(new MovementSystem(), "game");
|
this.add_system(new MovementSystem(), "game");
|
||||||
this.add_system(new CropSystem(), "game");
|
this.add_system(new CropSystem(), "game");
|
||||||
|
this.add_system(new DimensionLogicSystem(), "game");
|
||||||
|
|
||||||
// render systems
|
// render systems
|
||||||
this.add_system(new RenderSystem(), "game");
|
this.add_system(new RenderSystem(), "game");
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Component } from "$/common/ecs/mod.ts";
|
|||||||
import { AssetManager } from "../assets.ts";
|
import { AssetManager } from "../assets.ts";
|
||||||
import { Texture } from "../renderer.ts";
|
import { Texture } from "../renderer.ts";
|
||||||
|
|
||||||
interface Tile {
|
export interface Tile {
|
||||||
x: number;
|
x: number;
|
||||||
y: number;
|
y: number;
|
||||||
id: string;
|
id: string;
|
||||||
|
|||||||
@@ -25,6 +25,9 @@ export class ContainerSlot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
set_item(item_stack: ItemStack | undefined) {
|
set_item(item_stack: ItemStack | undefined) {
|
||||||
|
if ((item_stack?.amount ?? 0) <= 0) {
|
||||||
|
item_stack = undefined;
|
||||||
|
}
|
||||||
this.#item_stack = item_stack;
|
this.#item_stack = item_stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +60,18 @@ export class Container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
add_item(item_stack: ItemStack) {
|
add_item(item_stack: ItemStack) {
|
||||||
// TODO: merge stacks
|
for (const slot of this.#slots.filter((slot) => slot.has_item())) {
|
||||||
|
const slot_item = slot.get_item()!;
|
||||||
|
if (slot_item.type_id === item_stack.type_id) {
|
||||||
|
const missing = slot_item.max_amount - slot_item.amount;
|
||||||
|
const adding = Math.min(missing, item_stack.amount);
|
||||||
|
slot_item.amount += adding;
|
||||||
|
item_stack.amount -= adding;
|
||||||
|
if (item_stack.amount === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
for (const slot of this.#slots) {
|
for (const slot of this.#slots) {
|
||||||
if (!slot.has_item()) {
|
if (!slot.has_item()) {
|
||||||
slot.set_item(item_stack);
|
slot.set_item(item_stack);
|
||||||
@@ -75,6 +89,10 @@ export class Container {
|
|||||||
get_slot(slot: number): ContainerSlot {
|
get_slot(slot: number): ContainerSlot {
|
||||||
return this.#slots[slot];
|
return this.#slots[slot];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set_item(slot: number, item: ItemStack) {
|
||||||
|
this.#slots[slot].set_item(item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ContainerLayout {
|
export interface ContainerLayout {
|
||||||
|
|||||||
+2
-23
@@ -5,7 +5,6 @@ import { Dimension } from "./components/dimension.ts";
|
|||||||
import { create_player } from "./player.ts";
|
import { create_player } from "./player.ts";
|
||||||
import { UIButton } from "./components/ui_components.ts";
|
import { UIButton } from "./components/ui_components.ts";
|
||||||
import { open_about } from "./about.ts";
|
import { open_about } from "./about.ts";
|
||||||
import { create_crop_entity, Crop } from "./components/crop.ts";
|
|
||||||
import { generate } from "./generation.ts";
|
import { generate } from "./generation.ts";
|
||||||
import { canvas } from "./renderer.ts";
|
import { canvas } from "./renderer.ts";
|
||||||
|
|
||||||
@@ -14,7 +13,8 @@ export function start_game(world: ClientWorld) {
|
|||||||
world.clear_entities();
|
world.clear_entities();
|
||||||
|
|
||||||
const dimension = new Entity("dimension");
|
const dimension = new Entity("dimension");
|
||||||
dimension.add(new Dimension([]));
|
world.dimension = new Dimension([]);
|
||||||
|
dimension.add(world.dimension);
|
||||||
world.add_entity(dimension);
|
world.add_entity(dimension);
|
||||||
generate(dimension.get(Dimension)!, 100, 100);
|
generate(dimension.get(Dimension)!, 100, 100);
|
||||||
|
|
||||||
@@ -30,25 +30,4 @@ export function start_game(world: ClientWorld) {
|
|||||||
about_button.add(new Position(canvas.width / 2 - 150, canvas.height / 2 + 80));
|
about_button.add(new Position(canvas.width / 2 - 150, canvas.height / 2 + 80));
|
||||||
about_button.add(new UIButton("About", 320, 64, () => open_about()));
|
about_button.add(new UIButton("About", 320, 64, () => open_about()));
|
||||||
world.add_entity(about_button);
|
world.add_entity(about_button);
|
||||||
|
|
||||||
world.add_entity(create_crop_entity(
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
new Crop("bworld:potato"),
|
|
||||||
));
|
|
||||||
world.add_entity(create_crop_entity(
|
|
||||||
32,
|
|
||||||
0,
|
|
||||||
new Crop("bworld:carrot"),
|
|
||||||
));
|
|
||||||
world.add_entity(create_crop_entity(
|
|
||||||
0,
|
|
||||||
32,
|
|
||||||
new Crop("bworld:pumpkin"),
|
|
||||||
));
|
|
||||||
world.add_entity(create_crop_entity(
|
|
||||||
32,
|
|
||||||
32,
|
|
||||||
new Crop("bworld:tomato"),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
|
import { EverythingRegistry } from "../common/everything_registry.ts";
|
||||||
import { AssetManager } from "./assets.ts";
|
import { AssetManager } from "./assets.ts";
|
||||||
import { ClientWorld } from "./client_world.ts";
|
import { ClientWorld } from "./client_world.ts";
|
||||||
import { InputManager } from "./input_manager.ts";
|
import { InputManager } from "./input_manager.ts";
|
||||||
import { begin_drawing, end_drawing, init_window } from "./renderer.ts";
|
import { begin_drawing, end_drawing, init_window } from "./renderer.ts";
|
||||||
|
|
||||||
|
EverythingRegistry.add_registry("tiles");
|
||||||
|
await import("./tiles/mod.ts");
|
||||||
|
|
||||||
export class ClientLoop {
|
export class ClientLoop {
|
||||||
running = false;
|
running = false;
|
||||||
last_time = 0;
|
last_time = 0;
|
||||||
|
|||||||
+3
-2
@@ -34,11 +34,12 @@ export function create_player(world: ClientWorld) {
|
|||||||
// TODO: actual player ids
|
// TODO: actual player ids
|
||||||
player.add(new PlayerInventory(player.id));
|
player.add(new PlayerInventory(player.id));
|
||||||
player.get(PlayerInventory)!.container.add_item(new ItemStack("bworld:pickaxe", 1, 1));
|
player.get(PlayerInventory)!.container.add_item(new ItemStack("bworld:pickaxe", 1, 1));
|
||||||
player.get(PlayerInventory)!.container.add_item(new ItemStack("bworld:sword", 1, 1));
|
|
||||||
player.get(PlayerInventory)!.container.add_item(new ItemStack("bworld:axe", 1, 1));
|
|
||||||
player.get(PlayerInventory)!.container.add_item(new ItemStack("bworld:hoe", 1, 1));
|
player.get(PlayerInventory)!.container.add_item(new ItemStack("bworld:hoe", 1, 1));
|
||||||
player.get(PlayerInventory)!.container.add_item(new ItemStack("bworld:watering_can", 1, 1));
|
player.get(PlayerInventory)!.container.add_item(new ItemStack("bworld:watering_can", 1, 1));
|
||||||
|
player.get(PlayerInventory)!.container.add_item(new ItemStack("bworld:axe", 1, 1));
|
||||||
|
player.get(PlayerInventory)!.container.add_item(new ItemStack("bworld:sword", 1, 1));
|
||||||
player.get(PlayerInventory)!.container.add_item(new ItemStack("bworld:bomb", 64));
|
player.get(PlayerInventory)!.container.add_item(new ItemStack("bworld:bomb", 64));
|
||||||
|
player.get(PlayerInventory)!.container.add_item(new ItemStack("bworld:tomato_seeds", 64));
|
||||||
player.add(new Camera(-100, -100));
|
player.add(new Camera(-100, -100));
|
||||||
|
|
||||||
world.add_entity(player);
|
world.add_entity(player);
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
import { System } from "$/common/ecs/mod.ts";
|
||||||
|
import { ClientWorld } from "../client_world.ts";
|
||||||
|
import { Dimension } from "../components/dimension.ts";
|
||||||
|
import { Camera, screen_to_world } from "../components/camera.ts";
|
||||||
|
import { InputManager } from "../input_manager.ts";
|
||||||
|
import { canvas } from "../renderer.ts";
|
||||||
|
import { TILE_SIZE } from "$/common/constants.ts";
|
||||||
|
import { EverythingRegistry, TileRegistry } from "$/common/everything_registry.ts";
|
||||||
|
|
||||||
|
export class DimensionLogicSystem extends System {
|
||||||
|
update(world: ClientWorld, _delta: number): void {
|
||||||
|
const dimension_entity = world.get_entities().values().find((ent) => ent.get(Dimension));
|
||||||
|
const dimension = dimension_entity!.get(Dimension)!;
|
||||||
|
|
||||||
|
const [player] = world.get_tag("player")!;
|
||||||
|
const camera = player.get(Camera)!;
|
||||||
|
|
||||||
|
const mouse = InputManager.get_mouse_position();
|
||||||
|
|
||||||
|
const world_mouse = screen_to_world(
|
||||||
|
mouse.x,
|
||||||
|
mouse.y,
|
||||||
|
camera,
|
||||||
|
canvas.width,
|
||||||
|
canvas.height,
|
||||||
|
);
|
||||||
|
|
||||||
|
const tile_x = Math.floor(world_mouse.x / TILE_SIZE);
|
||||||
|
const tile_y = Math.floor(world_mouse.y / TILE_SIZE);
|
||||||
|
|
||||||
|
const tile = dimension.tiles.findLast((tile) => tile.x === tile_x && tile.y === tile_y);
|
||||||
|
|
||||||
|
if (tile) {
|
||||||
|
const tile_info = EverythingRegistry.get<TileRegistry>("tiles", tile.id);
|
||||||
|
|
||||||
|
if (!tile_info) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tile_info.on_interact || tile_info.on_click) {
|
||||||
|
if (tile_info.on_interact && InputManager.is_mouse_pressed(2)) {
|
||||||
|
InputManager.consume_mouse(2);
|
||||||
|
tile_info.on_interact(world, tile);
|
||||||
|
}
|
||||||
|
if (tile_info.on_click && InputManager.is_mouse_pressed(0)) {
|
||||||
|
InputManager.consume_mouse(0);
|
||||||
|
tile_info.on_click(world, tile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*for (const tile of dimension.tiles) {
|
||||||
|
const tile_info = EverythingRegistry.get<TileRegistry>("tiles", tile.id);
|
||||||
|
if (!tile_info) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tile_info.on_interact || tile_info.on_click) {
|
||||||
|
console.log(tile_info);
|
||||||
|
const hovered = point_inside_rec(
|
||||||
|
world_mouse.x,
|
||||||
|
world_mouse.y,
|
||||||
|
tile.x * TILE_SIZE,
|
||||||
|
tile.y * TILE_SIZE,
|
||||||
|
TILE_SIZE,
|
||||||
|
TILE_SIZE,
|
||||||
|
);
|
||||||
|
if (tile_info.on_interact && hovered && InputManager.is_mouse_pressed(2)) {
|
||||||
|
InputManager.consume_mouse(2);
|
||||||
|
tile_info.on_interact(world, tile);
|
||||||
|
}
|
||||||
|
if (tile_info.on_click && hovered && InputManager.is_mouse_pressed(0)) {
|
||||||
|
InputManager.consume_mouse(0);
|
||||||
|
tile_info.on_click(world, tile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
import { EverythingRegistry, TileRegistry } from "$/common/everything_registry.ts";
|
||||||
|
import { PlayerInventory } from "../components/inventory.ts";
|
||||||
|
|
||||||
|
EverythingRegistry.register<TileRegistry>("tiles", "bworld:dirt", {
|
||||||
|
texture_id: "bworld:dirt",
|
||||||
|
has_collision: false,
|
||||||
|
|
||||||
|
on_interact(world, tile) {
|
||||||
|
const [player] = world.get_tag("player")!;
|
||||||
|
const player_inventory = player.get(PlayerInventory)!;
|
||||||
|
const maybe_item = player_inventory.container.get_item(player_inventory.hotbar_selected);
|
||||||
|
if (maybe_item && maybe_item.type_id === "bworld:hoe") {
|
||||||
|
tile.id = "bworld:hoed_dirt";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
EverythingRegistry.register<TileRegistry>("tiles", "bworld:hoed_dirt", {
|
||||||
|
texture_id: "bworld:hoed_dirt",
|
||||||
|
has_collision: false,
|
||||||
|
|
||||||
|
on_click(world, tile) {
|
||||||
|
const [player] = world.get_tag("player")!;
|
||||||
|
const player_inventory = player.get(PlayerInventory)!;
|
||||||
|
const item = player_inventory.container.get_item(player_inventory.hotbar_selected);
|
||||||
|
if (!item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.type_id === "bworld:pickaxe") {
|
||||||
|
tile.id = "bworld:dirt";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
on_interact(world, tile) {
|
||||||
|
const [player] = world.get_tag("player")!;
|
||||||
|
const player_inventory = player.get(PlayerInventory)!;
|
||||||
|
const item = player_inventory.container.get_item(player_inventory.hotbar_selected);
|
||||||
|
if (!item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.type_id === "bworld:watering_can") {
|
||||||
|
tile.id = "bworld:hoed_watered_dirt";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
EverythingRegistry.register<TileRegistry>("tiles", "bworld:hoed_watered_dirt", {
|
||||||
|
texture_id: "bworld:hoed_watered_dirt",
|
||||||
|
has_collision: false,
|
||||||
|
|
||||||
|
on_click(world, tile) {
|
||||||
|
const [player] = world.get_tag("player")!;
|
||||||
|
const player_inventory = player.get(PlayerInventory)!;
|
||||||
|
const item = player_inventory.container.get_item(player_inventory.hotbar_selected);
|
||||||
|
if (!item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.type_id === "bworld:pickaxe") {
|
||||||
|
tile.id = "bworld:dirt";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
on_interact(world, tile) {
|
||||||
|
const [player] = world.get_tag("player")!;
|
||||||
|
const player_inventory = player.get(PlayerInventory)!;
|
||||||
|
const item = player_inventory.container.get_item(player_inventory.hotbar_selected);
|
||||||
|
if (!item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.type_id === "bworld:tomato_seeds") {
|
||||||
|
world.dimension.tiles.push({ x: tile.x, y: tile.y, id: "bworld:tomato_seeds" });
|
||||||
|
item.amount -= 1;
|
||||||
|
player_inventory.container.set_item(player_inventory.hotbar_selected, item);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { EverythingRegistry, TileRegistry } from "$/common/everything_registry.ts";
|
||||||
|
import { PlayerInventory } from "../components/inventory.ts";
|
||||||
|
|
||||||
|
EverythingRegistry.register<TileRegistry>("tiles", "bworld:grass", {
|
||||||
|
texture_id: "bworld:grass",
|
||||||
|
has_collision: false,
|
||||||
|
|
||||||
|
on_interact(world, tile) {
|
||||||
|
const [player] = world.get_tag("player")!;
|
||||||
|
const player_inventory = player.get(PlayerInventory)!;
|
||||||
|
const maybe_item = player_inventory.container.get_item(player_inventory.hotbar_selected);
|
||||||
|
if (maybe_item && maybe_item.type_id === "bworld:hoe") {
|
||||||
|
tile.id = "bworld:hoed_dirt";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import "./grass.ts";
|
||||||
|
import "./dirt.ts";
|
||||||
|
import "./tree.ts";
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { EverythingRegistry, TileRegistry } from "$/common/everything_registry.ts";
|
||||||
|
import { ItemStack, PlayerInventory } from "../components/inventory.ts";
|
||||||
|
|
||||||
|
EverythingRegistry.register<TileRegistry>("tiles", "bworld:tree", {
|
||||||
|
texture_id: "bworld:tree",
|
||||||
|
has_collision: false,
|
||||||
|
|
||||||
|
on_click(world, tile) {
|
||||||
|
const [player] = world.get_tag("player")!;
|
||||||
|
const player_inventory = player.get(PlayerInventory)!;
|
||||||
|
const maybe_item = player_inventory.container.get_item(player_inventory.hotbar_selected);
|
||||||
|
if (maybe_item && maybe_item.type_id === "bworld:axe") {
|
||||||
|
tile.id = "bworld:grass";
|
||||||
|
player_inventory.container.add_item(new ItemStack("bworld:log", 7));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
export const TEXTURE_SIZE = 16;
|
export const TEXTURE_SIZE = 16;
|
||||||
export const TILE_SIZE = 32;
|
export const TILE_SIZE = 48;
|
||||||
|
|
||||||
export const SLOT_SIZE = 18 * 3;
|
export const SLOT_SIZE = 18 * 3;
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
import { ClientWorld } from "../client/client_world.ts";
|
||||||
|
import { Tile } from "../client/components/dimension.ts";
|
||||||
|
|
||||||
export class EverythingRegistry {
|
export class EverythingRegistry {
|
||||||
static #registries = new Map<string, Map<string, unknown>>();
|
static #registries = new Map<string, Map<string, unknown>>();
|
||||||
|
|
||||||
@@ -13,3 +16,11 @@ export class EverythingRegistry {
|
|||||||
return this.#registries.get(registry_name)?.get(key) as T;
|
return this.#registries.get(registry_name)?.get(key) as T;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface TileRegistry {
|
||||||
|
texture_id: string;
|
||||||
|
has_collision: boolean;
|
||||||
|
|
||||||
|
on_click?(world: ClientWorld, tile: Tile): void;
|
||||||
|
on_interact?(world: ClientWorld, tile: Tile): void;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user