Basic gameplay?

This commit is contained in:
2026-03-07 13:01:52 -03:00
parent 3074316606
commit 5218fab55a
15 changed files with 239 additions and 28 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 177 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 B

+5
View File
@@ -12,11 +12,15 @@ import { create_main_menu } from "./main_menu.ts";
import { ClickableSystem } from "./systems/clickable_system.ts";
import { start_game } from "./game.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 {
paused = false;
debugging = false;
dimension!: Dimension;
constructor() {
super("game");
@@ -43,6 +47,7 @@ export class ClientWorld extends World {
this.add_system(new PlayerControlsSystem(), "game");
this.add_system(new MovementSystem(), "game");
this.add_system(new CropSystem(), "game");
this.add_system(new DimensionLogicSystem(), "game");
// render systems
this.add_system(new RenderSystem(), "game");
+1 -1
View File
@@ -2,7 +2,7 @@ import { Component } from "$/common/ecs/mod.ts";
import { AssetManager } from "../assets.ts";
import { Texture } from "../renderer.ts";
interface Tile {
export interface Tile {
x: number;
y: number;
id: string;
+19 -1
View File
@@ -25,6 +25,9 @@ export class ContainerSlot {
}
set_item(item_stack: ItemStack | undefined) {
if ((item_stack?.amount ?? 0) <= 0) {
item_stack = undefined;
}
this.#item_stack = item_stack;
}
@@ -57,7 +60,18 @@ export class Container {
}
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) {
if (!slot.has_item()) {
slot.set_item(item_stack);
@@ -75,6 +89,10 @@ export class Container {
get_slot(slot: number): ContainerSlot {
return this.#slots[slot];
}
set_item(slot: number, item: ItemStack) {
this.#slots[slot].set_item(item);
}
}
export interface ContainerLayout {
+2 -23
View File
@@ -5,7 +5,6 @@ import { Dimension } from "./components/dimension.ts";
import { create_player } from "./player.ts";
import { UIButton } from "./components/ui_components.ts";
import { open_about } from "./about.ts";
import { create_crop_entity, Crop } from "./components/crop.ts";
import { generate } from "./generation.ts";
import { canvas } from "./renderer.ts";
@@ -14,7 +13,8 @@ export function start_game(world: ClientWorld) {
world.clear_entities();
const dimension = new Entity("dimension");
dimension.add(new Dimension([]));
world.dimension = new Dimension([]);
dimension.add(world.dimension);
world.add_entity(dimension);
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 UIButton("About", 320, 64, () => open_about()));
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"),
));
}
+4
View File
@@ -1,8 +1,12 @@
import { EverythingRegistry } from "../common/everything_registry.ts";
import { AssetManager } from "./assets.ts";
import { ClientWorld } from "./client_world.ts";
import { InputManager } from "./input_manager.ts";
import { begin_drawing, end_drawing, init_window } from "./renderer.ts";
EverythingRegistry.add_registry("tiles");
await import("./tiles/mod.ts");
export class ClientLoop {
running = false;
last_time = 0;
+3 -2
View File
@@ -34,11 +34,12 @@ export function create_player(world: ClientWorld) {
// TODO: actual player ids
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: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: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:tomato_seeds", 64));
player.add(new Camera(-100, -100));
world.add_entity(player);
+79
View File
@@ -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);
}
}
}*/
}
}
+78
View File
@@ -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);
}
},
});
+16
View File
@@ -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";
}
},
});
+3
View File
@@ -0,0 +1,3 @@
import "./grass.ts";
import "./dirt.ts";
import "./tree.ts";
+17
View File
@@ -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
View File
@@ -1,5 +1,5 @@
export const TEXTURE_SIZE = 16;
export const TILE_SIZE = 32;
export const TILE_SIZE = 48;
export const SLOT_SIZE = 18 * 3;
+11
View File
@@ -1,3 +1,6 @@
import { ClientWorld } from "../client/client_world.ts";
import { Tile } from "../client/components/dimension.ts";
export class EverythingRegistry {
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;
}
}
export interface TileRegistry {
texture_id: string;
has_collision: boolean;
on_click?(world: ClientWorld, tile: Tile): void;
on_interact?(world: ClientWorld, tile: Tile): void;
}