39 Commits
v0.4 ... master

Author SHA1 Message Date
cf0df54548 Update map assets references in project.json
Because BASE Editor is reusing binary deserializer for JSON serializer,
the map assets 'source' property in project.json points to binary files
with ".dat" extension. It does not impact on how the editor works
because the asset sources are recreated when importing using UIDs, so
just to be consistent all the .json file references were replaced with
the .dat ones.
2025-07-11 15:06:08 +02:00
e8cc766ded Improve support for Nix dev shell 2025-07-11 14:41:10 +02:00
2e4459b92c Change initial world time 2025-07-11 14:30:14 +02:00
d66aabd58a Use BASE editor CLI interface to build app seamlessly 2025-07-11 10:09:47 +02:00
1e8ff04930 Improve Nix derivation 2025-07-10 15:12:16 +02:00
8edbc48ff1 Migrate Nix shell config to Flake 2023-12-09 22:34:56 +01:00
9d42bb8ee3 Enable BASE on NixOS platform 2023-12-07 22:48:42 +01:00
d08ba8eb5a Fix missing Forrest tileset 2023-11-16 14:17:59 +01:00
990ad6519e Improve the game start with some simple Grandma dialog 2023-11-16 14:17:59 +01:00
0be7b2fa43 Remove non-existing assets from project.json 2023-11-16 11:11:40 +01:00
356f792523 Implement day-night cycle | put some lights to the maps 2023-11-07 19:27:15 +01:00
e9ee8f7541 Migrate to new JSON format 2023-11-04 14:46:58 +01:00
eaa5f5d547 Implement some sample dialogs | apply BASE engine updates 2023-11-02 16:02:03 +01:00
3b99bc561a Apply BASE new MapLabels feature 2023-11-01 16:59:50 +01:00
f74548713d Apply BASE editor's SQL database format 2023-10-27 13:54:51 +02:00
898582fdb1 Apply BASE attribute methods improvements 2022-11-23 16:31:19 +01:00
6fefa32c7d Create new Forrest map 2022-09-06 15:37:00 +02:00
1d5afb0530 Add support for throwing weapon 2022-09-03 00:12:26 +02:00
a8f4679ee6 Extract game start point configuration to database 2022-09-02 22:25:28 +02:00
4357c631be Remove FPS profiler from DemoRunner 2022-09-02 22:14:25 +02:00
c967562498 Improve enemy loot generation 2022-09-02 22:10:44 +02:00
181061eb64 Enable displaying the FPS graph in HUD 2022-09-02 01:16:15 +02:00
f5790df5aa Fix HUD positioning issue 2022-09-01 15:08:35 +02:00
b051f20bd7 Add "Equipment" button to Game Menu 2022-09-01 13:33:47 +02:00
796c0ec9b0 Improve "New game" action after game over 2022-09-01 13:30:30 +02:00
25c9abd427 Use BASE API utility MapObject class 2022-09-01 11:38:17 +02:00
6678c352bb Improve MapObject to support CompletableFuture actions 2022-09-01 00:02:11 +02:00
5d9c7e6de2 Fix Escape key handling 2022-08-31 23:54:46 +02:00
8c4d114dad Simplify input handler 2022-08-31 23:54:46 +02:00
9bf75a8458 Replace Context's globals with DemoRunner field references 2022-08-31 23:54:46 +02:00
bf19c7bcf4 Add basic support for creature dialogs 2022-08-31 11:59:06 +02:00
3cdec6b303 Refactor MenuManager to GuiManager 2022-08-31 11:57:16 +02:00
fd5610fca0 Refactor stackable items codebase 2022-08-31 11:55:45 +02:00
92c2f3347a Increase player equipment size to 6x6 2022-08-31 01:05:56 +02:00
9ff0d6c99d Enable disarming already armed equipment 2022-08-31 01:01:04 +02:00
76264407f4 Add support for medicaments 2022-08-30 22:49:48 +02:00
5cf94454cf Import some assets and create maps in new format 2022-08-30 21:22:32 +02:00
c86f042cf8 Apply BASE API improvements 2022-08-30 19:14:33 +02:00
18883b66c2 Apply new map binary format | remove old maps 2022-08-26 17:31:50 +02:00
89 changed files with 2615 additions and 589 deletions

1
.envrc Normal file
View File

@@ -0,0 +1 @@
use flake

3
.gitignore vendored
View File

@@ -1,2 +1,5 @@
.direnv
build/ build/
data.trace.db data.trace.db
*.jar
result

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

184
data.sql Normal file
View File

@@ -0,0 +1,184 @@
SET DB_CLOSE_DELAY -1;
;
CREATE USER IF NOT EXISTS "" SALT '' HASH '' ADMIN;
CREATE SEQUENCE "PUBLIC"."SYSTEM_SEQUENCE_CE051218_6282_4D4E_BC8B_083D4B720B25" START WITH 13 BELONGS_TO_TABLE;
CREATE SEQUENCE "PUBLIC"."SYSTEM_SEQUENCE_704587BB_DC0E_44AB_A7F0_3DE0CA44FE3F" START WITH 2 BELONGS_TO_TABLE;
CREATE MEMORY TABLE "PUBLIC"."RANGED_WEAPON"(
"ID" VARCHAR NOT NULL,
"NAME" VARCHAR NOT NULL,
"TYPE" VARCHAR NOT NULL,
"COOLDOWN" INT NOT NULL,
"DAMAGE" VARCHAR NOT NULL,
"ANIMATION" VARCHAR NOT NULL,
"SOUND" VARCHAR NOT NULL,
"RANGE" VARCHAR NOT NULL,
"PUNCH_ANIMATION" VARCHAR NOT NULL,
"PUNCH_SOUND" VARCHAR NOT NULL,
"MISS_ANIMATION" VARCHAR NOT NULL,
"MISS_SOUND" VARCHAR NOT NULL,
"ICON" VARCHAR NOT NULL
);
ALTER TABLE "PUBLIC"."RANGED_WEAPON" ADD CONSTRAINT "PUBLIC"."CONSTRAINT_4" PRIMARY KEY("ID");
-- 2 +/- SELECT COUNT(*) FROM PUBLIC.RANGED_WEAPON;
INSERT INTO "PUBLIC"."RANGED_WEAPON" VALUES
('wooden_bow', 'Wooden Bow', 'bow', 1000, '1d6+1', 'Arrow', 'Arrow', '5d4', 'Punch', 'Arrow punch', 'Poof', 'Arrow punch', 'Generic,12,11'),
('iron_bow', 'Iron Bow', 'bow', 700, '2d6+2', 'Arrow', 'Arrow', '6d4', 'Punch', 'Arrow punch', 'Poof', 'Arrow punch', 'Generic,12,10');
CREATE MEMORY TABLE "PUBLIC"."AMMUNITION"(
"ID" VARCHAR NOT NULL,
"NAME" VARCHAR NOT NULL,
"APPLIES_TO" VARCHAR NOT NULL,
"DAMAGE" VARCHAR NOT NULL,
"ICON" VARCHAR NOT NULL
);
ALTER TABLE "PUBLIC"."AMMUNITION" ADD CONSTRAINT "PUBLIC"."CONSTRAINT_F" PRIMARY KEY("ID");
-- 1 +/- SELECT COUNT(*) FROM PUBLIC.AMMUNITION;
INSERT INTO "PUBLIC"."AMMUNITION" VALUES
('wooden_arrow', 'Wooden Arrow', 'bow', '1', 'Generic,8,10');
CREATE MEMORY TABLE "PUBLIC"."MELEE_WEAPON"(
"ID" VARCHAR NOT NULL,
"NAME" VARCHAR NOT NULL,
"COOLDOWN" INT NOT NULL,
"DAMAGE" VARCHAR NOT NULL,
"ANIMATION" VARCHAR NOT NULL,
"SOUND" VARCHAR,
"ICON" VARCHAR NOT NULL
);
ALTER TABLE "PUBLIC"."MELEE_WEAPON" ADD CONSTRAINT "PUBLIC"."CONSTRAINT_2" PRIMARY KEY("ID");
-- 2 +/- SELECT COUNT(*) FROM PUBLIC.MELEE_WEAPON;
INSERT INTO "PUBLIC"."MELEE_WEAPON" VALUES
('wooden_sword', 'Wooden Sword', 1000, '1d4+1', 'Slash', 'Sword slash', 'Generic,5,10'),
('wooden_dagger', 'Wooden Dagger', 300, '1d2', 'Slash', 'Sword slash', 'Generic,7,1');
CREATE MEMORY TABLE "PUBLIC"."OBJECT"(
"ID" VARCHAR NOT NULL,
"NAME" VARCHAR NOT NULL,
"CHARSET" VARCHAR NOT NULL,
"FRAME" SMALLINT,
"INTERACT_SOUND" VARCHAR
);
ALTER TABLE "PUBLIC"."OBJECT" ADD CONSTRAINT "PUBLIC"."CONSTRAINT_C" PRIMARY KEY("ID");
-- 3 +/- SELECT COUNT(*) FROM PUBLIC.OBJECT;
INSERT INTO "PUBLIC"."OBJECT" VALUES
('black_fsm_right_doors', 'Doors', 'FSM Doors', 0, 'Arrow punch'),
('enforced_chest_left', 'Enforced Chest', 'Chests', 3, 'Arrow punch'),
('plain_chest_down', 'Plain Chest', 'Chests', 0, 'Arrow punch');
CREATE MEMORY TABLE "PUBLIC"."JUNK"(
"ID" VARCHAR NOT NULL,
"NAME" VARCHAR NOT NULL,
"ICON" VARCHAR NOT NULL
);
ALTER TABLE "PUBLIC"."JUNK" ADD CONSTRAINT "PUBLIC"."CONSTRAINT_22" PRIMARY KEY("ID");
-- 4 +/- SELECT COUNT(*) FROM PUBLIC.JUNK;
INSERT INTO "PUBLIC"."JUNK" VALUES
('bone', 'Bone', 'Generic,21,2'),
('eye', 'Eye', 'Generic,21,3'),
('tooth', 'Tooth', 'Generic,21,5'),
('fur', 'Fur', 'Generic,21,6');
CREATE MEMORY TABLE "PUBLIC"."MEDICAMENTS"(
"ID" VARCHAR NOT NULL,
"NAME" VARCHAR NOT NULL,
"ICON" VARCHAR NOT NULL,
"HP" VARCHAR NOT NULL,
"ANIMATION" VARCHAR NOT NULL,
"SOUND" VARCHAR NOT NULL
);
ALTER TABLE "PUBLIC"."MEDICAMENTS" ADD CONSTRAINT "PUBLIC"."CONSTRAINT_E" PRIMARY KEY("ID");
-- 1 +/- SELECT COUNT(*) FROM PUBLIC.MEDICAMENTS;
INSERT INTO "PUBLIC"."MEDICAMENTS" VALUES
('small_life_potion', 'Small life potion', 'Generic,2,11', '2d4+2', 'Poof', 'Arrow punch');
CREATE MEMORY TABLE "PUBLIC"."ENEMY_DROP"(
"ID" INT DEFAULT NEXT VALUE FOR "PUBLIC"."SYSTEM_SEQUENCE_CE051218_6282_4D4E_BC8B_083D4B720B25" NOT NULL NULL_TO_DEFAULT SEQUENCE "PUBLIC"."SYSTEM_SEQUENCE_CE051218_6282_4D4E_BC8B_083D4B720B25",
"ENEMY" VARCHAR NOT NULL,
"ITEM" VARCHAR NOT NULL,
"CHANCE" DECIMAL NOT NULL,
"AMOUNT" VARCHAR NOT NULL
);
ALTER TABLE "PUBLIC"."ENEMY_DROP" ADD CONSTRAINT "PUBLIC"."CONSTRAINT_8" PRIMARY KEY("ID");
-- 7 +/- SELECT COUNT(*) FROM PUBLIC.ENEMY_DROP;
INSERT INTO "PUBLIC"."ENEMY_DROP" VALUES
(1, 'deku', 'throwing:deku_arrow', 0.8, '2d4+5'),
(6, 'skeleton', 'junk:bone', 0.7, '1'),
(7, 'skeleton_archer', 'junk:bone', 0.7, '1'),
(8, 'skeleton', 'melee:wooden_sword', 0.5, '1'),
(9, 'skeleton_archer', 'ranged:wooden_bow', 0.3, '1'),
(10, 'skeleton_archer', 'ammo:wooden_arrow', 0.7, '1d4+3'),
(11, 'deku', 'junk:eye', 0.7, '1d2');
CREATE MEMORY TABLE "PUBLIC"."CONFIG"(
"KEY" VARCHAR NOT NULL,
"VALUE" VARCHAR
);
ALTER TABLE "PUBLIC"."CONFIG" ADD CONSTRAINT "PUBLIC"."CONSTRAINT_7" PRIMARY KEY("KEY");
-- 5 +/- SELECT COUNT(*) FROM PUBLIC.CONFIG;
INSERT INTO "PUBLIC"."CONFIG" VALUES
('start_game', 'Hero Home,Main,Start'),
('screen', '1000x800'),
('camera_scale', '2'),
('full_day_duration', '600'),
('initial_time', '08:30');
CREATE MEMORY TABLE "PUBLIC"."LEVELS"(
"LEVEL" INT DEFAULT NEXT VALUE FOR "PUBLIC"."SYSTEM_SEQUENCE_704587BB_DC0E_44AB_A7F0_3DE0CA44FE3F" NOT NULL NULL_TO_DEFAULT SEQUENCE "PUBLIC"."SYSTEM_SEQUENCE_704587BB_DC0E_44AB_A7F0_3DE0CA44FE3F",
"MAX_HP" VARCHAR NOT NULL
);
ALTER TABLE "PUBLIC"."LEVELS" ADD CONSTRAINT "PUBLIC"."CONSTRAINT_85" PRIMARY KEY("LEVEL");
-- 1 +/- SELECT COUNT(*) FROM PUBLIC.LEVELS;
INSERT INTO "PUBLIC"."LEVELS" VALUES
(1, '3000');
CREATE MEMORY TABLE "PUBLIC"."THROWING_WEAPON"(
"ID" VARCHAR NOT NULL,
"NAME" VARCHAR NOT NULL,
"COOLDOWN" INT NOT NULL,
"DAMAGE" VARCHAR NOT NULL,
"ANIMATION" VARCHAR NOT NULL,
"SOUND" VARCHAR NOT NULL,
"RANGE" VARCHAR NOT NULL,
"PUNCH_ANIMATION" VARCHAR NOT NULL,
"PUNCH_SOUND" VARCHAR NOT NULL,
"MISS_ANIMATION" VARCHAR NOT NULL,
"MISS_SOUND" VARCHAR NOT NULL,
"ICON" VARCHAR NOT NULL
);
ALTER TABLE "PUBLIC"."THROWING_WEAPON" ADD CONSTRAINT "PUBLIC"."CONSTRAINT_40" PRIMARY KEY("ID");
-- 2 +/- SELECT COUNT(*) FROM PUBLIC.THROWING_WEAPON;
INSERT INTO "PUBLIC"."THROWING_WEAPON" VALUES
('deku_arrow', 'Deku''s arrow', 500, '2d4', 'Arrow', 'Arrow', '5d4', 'Punch', 'Arrow punch', 'Poof', 'Arrow punch', 'Generic,8,10'),
('shuriken', 'Shuriken', 100, '3d6', 'Shuriken', 'Arrow', '5d4', 'Punch', 'Arrow punch', 'Poof', 'Arrow punch', 'Generic,9,2');
CREATE MEMORY TABLE "PUBLIC"."ENEMY"(
"ID" VARCHAR NOT NULL,
"NAME" VARCHAR NOT NULL,
"CHARSET" VARCHAR NOT NULL,
"DEAD_CHARSET" VARCHAR,
"HP" VARCHAR NOT NULL,
"SPEED" VARCHAR NOT NULL,
"BLOCKING" BOOL NOT NULL,
"MELEE_WEAPON" VARCHAR,
"RANGED_WEAPON" VARCHAR,
"THROWING_WEAPON" VARCHAR,
"DIE_ANIMATION" VARCHAR NOT NULL,
"DIE_SOUND" VARCHAR NOT NULL
);
ALTER TABLE "PUBLIC"."ENEMY" ADD CONSTRAINT "PUBLIC"."CONSTRAINT_3" PRIMARY KEY("ID");
-- 8 +/- SELECT COUNT(*) FROM PUBLIC.ENEMY;
INSERT INTO "PUBLIC"."ENEMY" VALUES
('deku', 'Deku', 'Deku', 'Corpse', '2d4', '10d2', TRUE, NULL, NULL, 'deku_arrow,1d4+2', 'Poof', 'Deku death'),
('garo', 'Garo', 'Garo', 'Corpse', '7d4', '10d2', TRUE, 'wooden_sword', NULL, NULL, 'Poof', 'Deku death'),
('blanca', 'Blanca', 'Blanca', 'Corpse', '10d4', '10d2', TRUE, 'wooden_sword', NULL, NULL, 'Poof', 'Deku death'),
('turtle', 'Turtle', 'Turtle', 'Corpse', '5d4', '10d2', TRUE, 'wooden_sword', NULL, NULL, 'Poof', 'Deku death'),
('silver_bat', 'Silver Bat', 'Silver Bat', 'Corpse', '1d4+2', '10d2', TRUE, 'wooden_sword', NULL, NULL, 'Poof', 'Deku death'),
('eagle', 'Eagle', 'Eagle', 'Corpse', '2d4+2', '10d2', TRUE, 'wooden_sword', NULL, NULL, 'Poof', 'Deku death'),
('skeleton', 'Skeleton', 'Skeleton', 'Corpse', '2d6+2', '10d2', TRUE, 'wooden_sword', NULL, NULL, 'Poof', 'Deku death'),
('skeleton_archer', 'Skeleton Archer', 'Skeleton', 'Corpse', '2d6+2', '10d2', TRUE, 'wooden_dagger', 'wooden_bow,wooden_arrow,2d4+3', NULL, 'Poof', 'Deku death');
CREATE MEMORY TABLE "PUBLIC"."FRIEND"(
"ID" VARCHAR NOT NULL,
"NAME" VARCHAR NOT NULL,
"CHARSET" VARCHAR NOT NULL,
"SPEED" VARCHAR NOT NULL,
"BLOCKING" BOOLEAN DEFAULT FALSE NOT NULL,
"DIALOG_COLOR" VARCHAR DEFAULT '0xFFFFFF' NOT NULL
);
ALTER TABLE "PUBLIC"."FRIEND" ADD CONSTRAINT "PUBLIC"."CONSTRAINT_7C" PRIMARY KEY("ID");
-- 3 +/- SELECT COUNT(*) FROM PUBLIC.FRIEND;
INSERT INTO "PUBLIC"."FRIEND" VALUES
('turtle', 'Turtle', 'Turtle', '10d2', TRUE, 'AA00DD'),
('neko', 'Neko', 'Neko', '14', TRUE, 'AA00DD'),
('grandma', 'Grandma', 'Grandma', '7', TRUE, 'DD00AA');
ALTER TABLE "PUBLIC"."ENEMY_DROP" ADD CONSTRAINT "PUBLIC"."CONSTRAINT_8A" FOREIGN KEY("ENEMY") REFERENCES "PUBLIC"."ENEMY"("ID") NOCHECK;
ALTER TABLE "PUBLIC"."ENEMY" ADD CONSTRAINT "PUBLIC"."CONSTRAINT_3F" FOREIGN KEY("MELEE_WEAPON") REFERENCES "PUBLIC"."MELEE_WEAPON"("ID") NOCHECK;

111
flake.lock generated Normal file
View File

@@ -0,0 +1,111 @@
{
"nodes": {
"base": {
"inputs": {
"flake-utils": [
"flake-utils"
],
"gradle2nix": "gradle2nix",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1752221128,
"narHash": "sha256-dFWsRVenkLOtbBx67JfAjVD5PyiKJY4TMCbXbf7bGT4=",
"ref": "refs/heads/master",
"rev": "41cc804cc3855553587eafd13597054d93097972",
"revCount": 600,
"type": "git",
"url": "https://git.orleander.pl/bartek/base.git"
},
"original": {
"type": "git",
"url": "https://git.orleander.pl/bartek/base.git"
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"gradle2nix": {
"inputs": {
"flake-utils": [
"base",
"flake-utils"
],
"nixpkgs": [
"base",
"nixpkgs"
]
},
"locked": {
"lastModified": 1743629487,
"narHash": "sha256-MjnEgT9MhO2HknLhrx7GvBRVxdOzSKydIJMyzawe2Fk=",
"owner": "tadfisher",
"repo": "gradle2nix",
"rev": "293ecbdc10d32d9d4bdc2d23213b9be09ce247ee",
"type": "github"
},
"original": {
"owner": "tadfisher",
"ref": "v2",
"repo": "gradle2nix",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1751943650,
"narHash": "sha256-7orTnNqkGGru8Je6Un6mq1T8YVVU/O5kyW4+f9C1mZQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "88983d4b665fb491861005137ce2b11a9f89f203",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-25.05",
"type": "indirect"
}
},
"root": {
"inputs": {
"base": "base",
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

30
flake.nix Normal file
View File

@@ -0,0 +1,30 @@
{
description = "The BASE engine demo game";
inputs = {
nixpkgs.url = "nixpkgs/nixos-25.05";
flake-utils.url = "github:numtide/flake-utils";
base.url = "git+https://git.orleander.pl/bartek/base.git";
base.inputs.nixpkgs.follows = "nixpkgs";
base.inputs.flake-utils.follows = "flake-utils";
};
outputs = inputs @ {
self,
nixpkgs,
flake-utils,
...
}:
flake-utils.lib.eachDefaultSystem (system: let
pkgs = import nixpkgs {inherit system;};
in {
packages = rec {
game = pkgs.callPackage ./game.nix (inputs // {inherit system;});
default = game;
};
devShells.default = pkgs.callPackage ./shell.nix {inherit system;};
});
}

44
game.nix Normal file
View File

@@ -0,0 +1,44 @@
{
pkgs,
base,
lib,
stdenv,
system,
makeWrapper,
jdk17,
xorg,
openjfx17,
glib,
alsa-lib,
libGL,
gtk3,
...
}:
stdenv.mkDerivation rec {
pname = "base-demo";
version = "0.0.1";
src = ./.;
nativeBuildInputs = [base.packages.${system}.default makeWrapper];
buildPhase = ''
base-editor -bHp $src/project.json -o build
'';
installPhase = ''
mkdir -p $out/bin
mkdir -p $out/share/java
cp build/out/game.jar $out/share/java/base-demo-game.jar
makeWrapper "${jdk17}/bin/java" $out/bin/base-demo \
--add-flags "-jar $out/share/java/base-demo-game.jar" \
--prefix LD_LIBRARY_PATH : "${xorg.libXtst}/lib" \
--prefix LD_LIBRARY_PATH : "${openjfx17}/lib" \
--prefix LD_LIBRARY_PATH : "${glib.out}/lib" \
--prefix LD_LIBRARY_PATH : "${alsa-lib}/lib" \
--prefix LD_LIBRARY_PATH : "${libGL}/lib" \
--prefix LD_LIBRARY_PATH : "${gtk3}/lib"
'';
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,140 @@
{
"uid": "d1b85d85-c52a-46f5-b81e-444847f8ddae",
"rows": 17,
"columns": 20,
"tileWidth": 32,
"tileHeight": 32,
"layers": [{
"name": "All Lights",
"objectLayer": {
"passageMap": ["ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW"],
"objects": [{
"x": 6,
"y": 1,
"code": "/* \n * Following final parameters are available to use:\n * here: MapPin - the composite object containing current map UID, \n * layer\u0027s index and x,y coordinates of the current tile \n * x: int - the x coordinate of the current tile\n * y: int - the y coordinate of the current tile \n * layer: ObjectLayer - current object layer\n * map: GameMap - current map \n * handler: HeroHomeHandler - current map handler\n * runner: DemoRunner - the game runner of the project\n * context: Context - the game context\n */\ntorch(here);"
}, {
"x": 5,
"y": 7,
"code": "/* \n * Following final parameters are available to use:\n * here: MapPin - the composite object containing current map UID, \n * layer\u0027s index and x,y coordinates of the current tile \n * x: int - the x coordinate of the current tile\n * y: int - the y coordinate of the current tile \n * layer: ObjectLayer - current object layer\n * map: GameMap - current map \n * handler: HeroHomeHandler - current map handler\n * runner: DemoRunner - the game runner of the project\n * context: Context - the game context\n */\ntorch(here);"
}, {
"x": 13,
"y": 12,
"code": "/* \n * Following final parameters are available to use:\n * here: MapPin - the composite object containing current map UID, \n * layer\u0027s index and x,y coordinates of the current tile \n * x: int - the x coordinate of the current tile\n * y: int - the y coordinate of the current tile \n * layer: ObjectLayer - current object layer\n * map: GameMap - current map \n * handler: HeroHomeHandler - current map handler\n * runner: DemoRunner - the game runner of the project\n * context: Context - the game context\n */\ntorch(here);"
}, {
"x": 17,
"y": 7,
"code": "/* \n * Following final parameters are available to use:\n * here: MapPin - the composite object containing current map UID, \n * layer\u0027s index and x,y coordinates of the current tile \n * x: int - the x coordinate of the current tile\n * y: int - the y coordinate of the current tile \n * layer: ObjectLayer - current object layer\n * map: GameMap - current map \n * handler: HeroHomeHandler - current map handler\n * runner: DemoRunner - the game runner of the project\n * context: Context - the game context\n */\ntorch(here);"
}, {
"x": 15,
"y": 7,
"code": "/* \n * Following final parameters are available to use:\n * here: MapPin - the composite object containing current map UID, \n * layer\u0027s index and x,y coordinates of the current tile \n * x: int - the x coordinate of the current tile\n * y: int - the y coordinate of the current tile \n * layer: ObjectLayer - current object layer\n * map: GameMap - current map \n * handler: HeroHomeHandler - current map handler\n * runner: DemoRunner - the game runner of the project\n * context: Context - the game context\n */\ntorch(here);"
}, {
"x": 10,
"y": 2,
"code": "/* \n * Following final parameters are available to use:\n * here: MapPin - the composite object containing current map UID, \n * layer\u0027s index and x,y coordinates of the current tile \n * x: int - the x coordinate of the current tile\n * y: int - the y coordinate of the current tile \n * layer: ObjectLayer - current object layer\n * map: GameMap - current map \n * handler: HeroHomeHandler - current map handler\n * runner: DemoRunner - the game runner of the project\n * context: Context - the game context\n */\nlight(here);"
}, {
"x": 11,
"y": 2,
"code": "/* \n * Following final parameters are available to use:\n * here: MapPin - the composite object containing current map UID, \n * layer\u0027s index and x,y coordinates of the current tile \n * x: int - the x coordinate of the current tile\n * y: int - the y coordinate of the current tile \n * layer: ObjectLayer - current object layer\n * map: GameMap - current map \n * handler: HeroHomeHandler - current map handler\n * runner: DemoRunner - the game runner of the project\n * context: Context - the game context\n */\ntorch(here);"
}, {
"x": 2,
"y": 1,
"code": "/* \n * Following final parameters are available to use:\n * here: MapPin - the composite object containing current map UID, \n * layer\u0027s index and x,y coordinates of the current tile \n * x: int - the x coordinate of the current tile\n * y: int - the y coordinate of the current tile \n * layer: ObjectLayer - current object layer\n * map: GameMap - current map \n * handler: HeroHomeHandler - current map handler\n * runner: DemoRunner - the game runner of the project\n * context: Context - the game context\n */\nvar light \u003d light(here);\nlight.setPositionOffset(0, 15f);"
}, {
"x": 5,
"y": 1,
"code": "/* \n * Following final parameters are available to use:\n * here: MapPin - the composite object containing current map UID, \n * layer\u0027s index and x,y coordinates of the current tile \n * x: int - the x coordinate of the current tile\n * y: int - the y coordinate of the current tile \n * layer: ObjectLayer - current object layer\n * map: GameMap - current map \n * handler: HeroHomeHandler - current map handler\n * runner: DemoRunner - the game runner of the project\n * context: Context - the game context\n */\nvar light \u003d light(here);\nlight.setPositionOffset(0, 15f);"
}]
}
}, {
"name": "Floor",
"tileLayer": {
"tilesetUID": "eb5bbf17-efaa-4213-90c3-2785a32f3c37",
"tiles": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 33, 33, 33, 33, 33, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 33, 33, 33, 33, 33, 33, 0, 34, 34, 34, 34, 34, 0, 0, 0, 0, 0, 0, 0, 33, 33, 33, 33, 33, 33, 33, 0, 34, 34, 34, 34, 34, 0, 0, 0, 0, 0, 0, 0, 34, 34, 34, 0, 0, 0, 0, 0, 34, 34, 34, 34, 34, 0, 0, 0, 0, 0, 0, 0, 34, 34, 34, 0, 0, 0, 0, 0, 34, 34, 34, 34, 34, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 34, 34, 34, 34, 34, 0, 0, 0, 0, 0, 0, 0, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 0, 0, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 34, 0, 0, 0, 34, 34, 34, 34, 34, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
}
}, {
"name": "Carpets",
"autoTileLayer": {
"autotileUID": "f6bcd0ea-f293-4864-bd13-d1c4e8b79080",
"tiles": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 0, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"animated": false,
"animationDuration": 1.0,
"connect": false
}
}, {
"name": "Walls",
"autoTileLayer": {
"autotileUID": "b475367a-7bf8-44ee-b916-6e81a78f97d9",
"tiles": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"animated": false,
"animationDuration": 1.0,
"connect": false
}
}, {
"name": "Floor objects",
"tileLayer": {
"tilesetUID": "60362451-85ed-4bbe-8ac1-225056f48b40",
"tiles": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 52, 162, 163, 52, 215, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 68, 178, 179, 68, 10, 10, 0, 0, 81, 215, 141, 0, 0, 0, 0, 0, 0, 0, 0, 184, 147, 194, 195, 148, 26, 26, 0, 38, 6, 8, 45, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 132, 0, 0, 0, 0, 23, 22, 24, 61, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 212, 145, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 145, 244, 145, 0, 0, 0, 0, 0, 0, 0, 0, 35, 0, 0, 142, 215, 0, 0, 0, 0, 0, 0, 0, 167, 0, 215, 126, 215, 0, 0, 0, 0, 12, 11, 13, 14, 13, 0, 170, 0, 0, 0, 0, 183, 0, 0, 0, 0, 168, 0, 0, 0, 28, 27, 29, 29, 29, 0, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 0, 32, 215, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 77, 0, 0, 0, 0, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 58, 0, 0, 93, 0, 0, 0, 0, 137, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
}
}, {
"name": "Main",
"objectLayer": {
"passageMap": ["ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "BLOCK", "ALLOW", "ALLOW", "BLOCK", "BLOCK", "ALLOW", "ALLOW", "ALLOW", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "BLOCK", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "BLOCK", "ALLOW", "ALLOW", "BLOCK", "ALLOW", "ALLOW", "BLOCK", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "BLOCK", "ALLOW", "BLOCK", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "BLOCK", "BLOCK", "ALLOW", "ALLOW", "BLOCK", "ALLOW", "ALLOW", "BLOCK", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "BLOCK", "ALLOW", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "ALLOW", "BLOCK", "ALLOW", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "ALLOW", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "ALLOW", "BLOCK", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "BLOCK", "BLOCK", "BLOCK", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "BLOCK", "ALLOW", "ALLOW", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "ALLOW", "ALLOW", "ALLOW", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "ALLOW", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "BLOCK", "ALLOW", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "ALLOW", "ALLOW", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "BLOCK", "ALLOW", "ALLOW", "ALLOW", "BLOCK", "BLOCK", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "BLOCK", "BLOCK", "ALLOW", "ALLOW", "ALLOW", "BLOCK", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "BLOCK", "BLOCK", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "BLOCK", "ALLOW", "BLOCK", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "BLOCK", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "BLOCK", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "ALLOW", "BLOCK"],
"objects": [{
"x": 3,
"y": 12,
"code": "/* \n * Following final parameters are available to use:\n * x: int - the x coordinate of tile the object has been created on\n * y: int - the y coordinate of tile the object has been created on \n * layer: ObjectLayer - current object layer\n * map: GameMap - current map\n */\nwarp(here, A.maps.hero_house.main.home);"
}, {
"x": 5,
"y": 4,
"code": "/* \n * Following final parameters are available to use:\n * here: MapPin - the composite object containing current map UID, \n * layer\u0027s index and x,y coordinates of the current tile \n * x: int - the x coordinate of the current tile\n * y: int - the y coordinate of the current tile \n * layer: ObjectLayer - current object layer\n * map: GameMap - current map\n */\nfriend(here, \"neko\")\n\t.randomMovementAI(4f)\n\t.interaction(this::triggerNekoDialog);"
}, {
"x": 7,
"y": 9,
"code": "/* \n * Following final parameters are available to use:\n * x: int - the x coordinate of tile the object has been created on\n * y: int - the y coordinate of tile the object has been created on \n * layer: ObjectLayer - current object layer\n * map: GameMap - current map\n * handler: HeroHomeHandler - current map handler\n * runner: DemoRunner - the game runner of the project\n * context: Context - the game context\n */\nchest(here, \"plain_chest_down\")\n\t.addItem(new MeleeWeapon(\"wooden_sword\"))\n\t.addItem(new Medicament(\"small_life_potion\", 4))\n\t.shuffle();"
}, {
"x": 18,
"y": 12,
"code": "/* \n * Following final parameters are available to use:\n * here: MapPin - the composite object containing current map UID, \n * layer\u0027s index and x,y coordinates of the current tile \n * x: int - the x coordinate of the current tile\n * y: int - the y coordinate of the current tile \n * layer: ObjectLayer - current object layer\n * map: GameMap - current map \n * handler: HeroHomeHandler - current map handler\n * runner: DemoRunner - the game runner of the project\n * context: Context - the game context\n */\nchest(here, \"enforced_chest_left\")\n\t.addItem(new MeleeWeapon(\"wooden_sword\"))\n\t.addItem(new Medicament(\"small_life_potion\", 4))\n\t.shuffle();"
}, {
"x": 13,
"y": 15,
"code": "/* \n * Following final parameters are available to use:\n * here: MapPin - the composite object containing current map UID, \n * layer\u0027s index and x,y coordinates of the current tile \n * x: int - the x coordinate of the current tile\n * y: int - the y coordinate of the current tile \n * layer: ObjectLayer - current object layer\n * map: GameMap - current map\n */\nfriend(here, \"grandma\")\n\t.followPath(this::grandmaPath)\n\t.interaction(this::triggerGrandmaDialog);"
}],
"labels": [{
"label": "entry",
"x": 3,
"y": 11
}, {
"label": "Start",
"x": 10,
"y": 14
}, {
"label": "Grandma Waking",
"x": 11,
"y": 14
}, {
"label": "Grandma Origin",
"x": 11,
"y": 7
}]
}
}, {
"name": "Objects above",
"tileLayer": {
"tilesetUID": "60362451-85ed-4bbe-8ac1-225056f48b40",
"tiles": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 0, 0, 0, 0, 168, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 13, 0, 0, 13, 13, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
}
}, {
"name": "Ceiling",
"autoTileLayer": {
"autotileUID": "6584a279-e937-497e-a056-b1e77bff2439",
"tiles": [10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 10, 0, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 10, 0, 0, 10, 10, 10, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10],
"animated": false,
"animationDuration": 1.0,
"connect": false
}
}],
"handler": "com.bartlomiejpluta.demo.map.HeroHomeHandler",
"javaImports": "import com.bartlomiejpluta.demo.world.weapon.*;\nimport com.bartlomiejpluta.demo.world.potion.*;\nimport com.bartlomiejpluta.base.lib.animation.*;"
}

View File

@@ -1,34 +0,0 @@
BASE Demo*com.bartlomiejpluta.demo.runner.DemoRunner`
$f845355e-b9ad-4884-a217-dd3a4c18a3fa(f845355e-b9ad-4884-a217-dd3a4c18a3fa.datForrest TempleY
$551e1afc-9cda-4d9f-8817-bfd831fc0a75(551e1afc-9cda-4d9f-8817-bfd831fc0a75.datForrest"d
$d314b030-f865-432e-a356-3845f8aac7bc(d314b030-f865-432e-a356-3845f8aac7bc.pngForrest Temple ](2Z
$0dcbaf26-d634-4ca8-9691-7a8ff966f702(0dcbaf26-d634-4ca8-9691-7a8ff966f702.pngGaro (2\
$61393836-8127-4277-853f-87b48022ae43(61393836-8127-4277-853f-87b48022ae43.pngCorpse (2^
$e605b2b1-3cab-499f-882d-160ab65b49d8(e605b2b1-3cab-499f-882d-160ab65b49d8.pngSkeleton (2Z
$0ea0fe55-53b2-4eea-8fab-2011e694127b(0ea0fe55-53b2-4eea-8fab-2011e694127b.pngLuna (2\
$92ac46ff-8cf2-4748-907f-873030c8e378(92ac46ff-8cf2-4748-907f-873030c8e378.pngChests (2\
$fbea4628-e1d3-4acc-800a-ed54c1bb51b6(fbea4628-e1d3-4acc-800a-ed54c1bb51b6.pngBlanca (2[
$7a723b64-e54a-4fff-852d-108349133111(7a723b64-e54a-4fff-852d-108349133111.pngEagle (2\
$c7ec2341-e5fc-4285-9ecb-a2dfc8a0ed67(c7ec2341-e5fc-4285-9ecb-a2dfc8a0ed67.pngTurtle (2`
$f1113db3-4a6c-4a07-9b64-32ba8e653e4f(f1113db3-4a6c-4a07-9b64-32ba8e653e4f.png
Silver Bat (2Z
$1779ae2b-474a-4599-8fc3-be34f7d66965(1779ae2b-474a-4599-8fc3-be34f7d66965.pngDeku (:`
$2261c04f-b02e-4486-b388-8a0fa41622e9(2261c04f-b02e-4486-b388-8a0fa41622e9.ttfRoboto RegularB\
$ab9d40b4-eb28-45d7-bff2-9432a05eb41a(ab9d40b4-eb28-45d7-bff2-9432a05eb41a.xml
Start MenuB[
$56ca6b39-f949-4212-9c23-312db25887e0(56ca6b39-f949-4212-9c23-312db25887e0.xml Game MenuBU
$00bd0625-b3b8-4abf-97b7-91f42bce28ec(00bd0625-b3b8-4abf-97b7-91f42bce28ec.xmlHUDB[
$c473a91a-ff25-4e71-9bec-b35e48102aeb(c473a91a-ff25-4e71-9bec-b35e48102aeb.xml EquipmentB^
$53ca3e54-0f8d-44fa-8281-acd9c5bba743(53ca3e54-0f8d-44fa-8281-acd9c5bba743.xml Eq Item MenuB[
$d78413cd-0dad-4b51-8dd1-54e33535fe53(d78413cd-0dad-4b51-8dd1-54e33535fe53.xml Loot MenuJZ
$e6f067f1-eba0-4e62-99c3-2fd867e6f142(e6f067f1-eba0-4e62-99c3-2fd867e6f142.pngPoof (J[
$312cc4e6-8c44-43e7-828a-e7e2a77836f3(312cc4e6-8c44-43e7-828a-e7e2a77836f3.pngArrow (J[
$54f657bd-8108-464c-9bbe-63944fc14f6b(54f657bd-8108-464c-9bbe-63944fc14f6b.pngPunch (J[
$0ddac391-4086-4e9c-8310-59db649419ff(0ddac391-4086-4e9c-8310-59db649419ff.pngSlash (R]
$1311327d-4b74-4252-94da-23ee4129e357(1311327d-4b74-4252-94da-23ee4129e357.ogg Sword slashR\
$e452e215-f581-40fe-a5cf-f555d3db83b8(e452e215-f581-40fe-a5cf-f555d3db83b8.ogg
Deku deathRW
$cd8a40f2-1e2e-4e1d-a13f-b4fe210a04df(cd8a40f2-1e2e-4e1d-a13f-b4fe210a04df.oggArrowR]
$7c33cfee-e6a8-42b8-8b1d-c801b242dcf0(7c33cfee-e6a8-42b8-8b1d-c801b242dcf0.ogg Arrow punchZ]
$ddc1e14f-0d1f-4291-a29d-0dc5d8e9242b(ddc1e14f-0d1f-4291-a29d-0dc5d8e9242b.pngGeneric #(

287
project.json Normal file
View File

@@ -0,0 +1,287 @@
{
"name": "BASE Demo",
"runner": "com.bartlomiejpluta.demo.runner.DemoRunner",
"maps": [{
"uid": "d1b85d85-c52a-46f5-b81e-444847f8ddae",
"source": "d1b85d85-c52a-46f5-b81e-444847f8ddae.dat",
"name": "Hero Home"
}, {
"uid": "b602601a-e9b0-44bf-bc0d-5f31c9964ba1",
"source": "b602601a-e9b0-44bf-bc0d-5f31c9964ba1.dat",
"name": "Hero House"
}, {
"uid": "8fbb151f-682a-4357-ba92-157e4097898f",
"source": "8fbb151f-682a-4357-ba92-157e4097898f.dat",
"name": "Forrest"
}],
"tileSets": [{
"uid": "eb5bbf17-efaa-4213-90c3-2785a32f3c37",
"source": "eb5bbf17-efaa-4213-90c3-2785a32f3c37.png",
"name": "FSM 1",
"rows": 16,
"columns": 8
}, {
"uid": "bf5a8b2c-4635-4433-8781-d8fed02c7197",
"source": "bf5a8b2c-4635-4433-8781-d8fed02c7197.png",
"name": "FSM 2",
"rows": 16,
"columns": 16
}, {
"uid": "fa940a9c-aa18-4037-9c20-ca660182d5f4",
"source": "fa940a9c-aa18-4037-9c20-ca660182d5f4.png",
"name": "FSM 3",
"rows": 16,
"columns": 16
}, {
"uid": "60362451-85ed-4bbe-8ac1-225056f48b40",
"source": "60362451-85ed-4bbe-8ac1-225056f48b40.png",
"name": "FSM 4",
"rows": 16,
"columns": 16
}, {
"uid": "6d5672b0-64e6-48a7-8b48-bf73d37ca7d2",
"source": "6d5672b0-64e6-48a7-8b48-bf73d37ca7d2.png",
"name": "FSM 5",
"rows": 16,
"columns": 16
}, {
"uid": "413e09cf-ba41-4fe8-ac47-9697b5ad0245",
"source": "413e09cf-ba41-4fe8-ac47-9697b5ad0245.png",
"name": "Forrest",
"rows": 35,
"columns": 16
}],
"characterSets": [{
"uid": "0dcbaf26-d634-4ca8-9691-7a8ff966f702",
"source": "0dcbaf26-d634-4ca8-9691-7a8ff966f702.png",
"name": "Garo",
"rows": 4,
"columns": 4
}, {
"uid": "61393836-8127-4277-853f-87b48022ae43",
"source": "61393836-8127-4277-853f-87b48022ae43.png",
"name": "Corpse",
"rows": 4,
"columns": 4
}, {
"uid": "e605b2b1-3cab-499f-882d-160ab65b49d8",
"source": "e605b2b1-3cab-499f-882d-160ab65b49d8.png",
"name": "Skeleton",
"rows": 4,
"columns": 4
}, {
"uid": "0ea0fe55-53b2-4eea-8fab-2011e694127b",
"source": "0ea0fe55-53b2-4eea-8fab-2011e694127b.png",
"name": "Luna",
"rows": 4,
"columns": 4
}, {
"uid": "92ac46ff-8cf2-4748-907f-873030c8e378",
"source": "92ac46ff-8cf2-4748-907f-873030c8e378.png",
"name": "Chests2",
"rows": 4,
"columns": 4
}, {
"uid": "fbea4628-e1d3-4acc-800a-ed54c1bb51b6",
"source": "fbea4628-e1d3-4acc-800a-ed54c1bb51b6.png",
"name": "Blanca",
"rows": 4,
"columns": 4
}, {
"uid": "7a723b64-e54a-4fff-852d-108349133111",
"source": "7a723b64-e54a-4fff-852d-108349133111.png",
"name": "Eagle2",
"rows": 4,
"columns": 4
}, {
"uid": "c7ec2341-e5fc-4285-9ecb-a2dfc8a0ed67",
"source": "c7ec2341-e5fc-4285-9ecb-a2dfc8a0ed67.png",
"name": "Turtle",
"rows": 4,
"columns": 4
}, {
"uid": "f1113db3-4a6c-4a07-9b64-32ba8e653e4f",
"source": "f1113db3-4a6c-4a07-9b64-32ba8e653e4f.png",
"name": "Silver Bat",
"rows": 4,
"columns": 4
}, {
"uid": "1779ae2b-474a-4599-8fc3-be34f7d66965",
"source": "1779ae2b-474a-4599-8fc3-be34f7d66965.png",
"name": "Deku",
"rows": 4,
"columns": 4
}, {
"uid": "a6863639-d563-4d88-af8e-c6d087ee2ffb",
"source": "a6863639-d563-4d88-af8e-c6d087ee2ffb.png",
"name": "FSM Doors",
"rows": 4,
"columns": 4
}, {
"uid": "35f770a6-5d94-4ddf-a132-dc3788a3adaf",
"source": "35f770a6-5d94-4ddf-a132-dc3788a3adaf.png",
"name": "Neko",
"rows": 4,
"columns": 4
}, {
"uid": "4a636044-2dbd-4ef3-8bdf-b63501c85ae3",
"source": "4a636044-2dbd-4ef3-8bdf-b63501c85ae3.png",
"name": "Grandma",
"rows": 4,
"columns": 4
}, {
"uid": "f529cbfc-c29d-470b-8804-e50d6a1efc98",
"source": "f529cbfc-c29d-470b-8804-e50d6a1efc98.png",
"name": "Chests",
"rows": 4,
"columns": 16
}],
"fonts": [{
"uid": "2261c04f-b02e-4486-b388-8a0fa41622e9",
"source": "2261c04f-b02e-4486-b388-8a0fa41622e9.ttf",
"name": "Roboto Regular"
}],
"widgets": [{
"uid": "ab9d40b4-eb28-45d7-bff2-9432a05eb41a",
"source": "ab9d40b4-eb28-45d7-bff2-9432a05eb41a.xml",
"name": "Start Menu"
}, {
"uid": "56ca6b39-f949-4212-9c23-312db25887e0",
"source": "56ca6b39-f949-4212-9c23-312db25887e0.xml",
"name": "Game Menu"
}, {
"uid": "00bd0625-b3b8-4abf-97b7-91f42bce28ec",
"source": "00bd0625-b3b8-4abf-97b7-91f42bce28ec.xml",
"name": "HUD"
}, {
"uid": "c473a91a-ff25-4e71-9bec-b35e48102aeb",
"source": "c473a91a-ff25-4e71-9bec-b35e48102aeb.xml",
"name": "Equipment"
}, {
"uid": "53ca3e54-0f8d-44fa-8281-acd9c5bba743",
"source": "53ca3e54-0f8d-44fa-8281-acd9c5bba743.xml",
"name": "Eq Item Menu"
}, {
"uid": "d78413cd-0dad-4b51-8dd1-54e33535fe53",
"source": "d78413cd-0dad-4b51-8dd1-54e33535fe53.xml",
"name": "Loot Menu"
}, {
"uid": "1c2b2ba2-66bf-40ee-97bf-6e5065b7b420",
"source": "1c2b2ba2-66bf-40ee-97bf-6e5065b7b420.xml",
"name": "Dialog"
}, {
"uid": "5a5aea0a-8c8b-4730-8e45-9ec6ccc5c4f6",
"source": "5a5aea0a-8c8b-4730-8e45-9ec6ccc5c4f6.xml",
"name": "Dialog Choice"
}],
"animations": [{
"uid": "e6f067f1-eba0-4e62-99c3-2fd867e6f142",
"source": "e6f067f1-eba0-4e62-99c3-2fd867e6f142.png",
"name": "Poof",
"rows": 4,
"columns": 5
}, {
"uid": "312cc4e6-8c44-43e7-828a-e7e2a77836f3",
"source": "312cc4e6-8c44-43e7-828a-e7e2a77836f3.png",
"name": "Arrow",
"rows": 2,
"columns": 2
}, {
"uid": "54f657bd-8108-464c-9bbe-63944fc14f6b",
"source": "54f657bd-8108-464c-9bbe-63944fc14f6b.png",
"name": "Punch",
"rows": 3,
"columns": 5
}, {
"uid": "0ddac391-4086-4e9c-8310-59db649419ff",
"source": "0ddac391-4086-4e9c-8310-59db649419ff.png",
"name": "Slash",
"rows": 2,
"columns": 5
}, {
"uid": "c8883e76-ae93-4673-8893-d2ec72c1e199",
"source": "c8883e76-ae93-4673-8893-d2ec72c1e199.png",
"name": "Shuriken",
"rows": 2,
"columns": 3
}, {
"uid": "aeb17449-c342-4dab-9057-5fb05183fd03",
"source": "aeb17449-c342-4dab-9057-5fb05183fd03.png",
"name": "Heart Emoji",
"rows": 6,
"columns": 4
}, {
"uid": "78563669-8a6c-4024-82c8-7e4da5b76edd",
"source": "78563669-8a6c-4024-82c8-7e4da5b76edd.png",
"name": "Zzz",
"rows": 7,
"columns": 4
}],
"sounds": [{
"uid": "1311327d-4b74-4252-94da-23ee4129e357",
"source": "1311327d-4b74-4252-94da-23ee4129e357.ogg",
"name": "Sword slash"
}, {
"uid": "e452e215-f581-40fe-a5cf-f555d3db83b8",
"source": "e452e215-f581-40fe-a5cf-f555d3db83b8.ogg",
"name": "Deku death"
}, {
"uid": "cd8a40f2-1e2e-4e1d-a13f-b4fe210a04df",
"source": "cd8a40f2-1e2e-4e1d-a13f-b4fe210a04df.ogg",
"name": "Arrow"
}, {
"uid": "7c33cfee-e6a8-42b8-8b1d-c801b242dcf0",
"source": "7c33cfee-e6a8-42b8-8b1d-c801b242dcf0.ogg",
"name": "Arrow punch"
}],
"iconSets": [{
"uid": "ddc1e14f-0d1f-4291-a29d-0dc5d8e9242b",
"source": "ddc1e14f-0d1f-4291-a29d-0dc5d8e9242b.png",
"name": "Generic",
"rows": 35,
"columns": 12
}],
"autoTiles": [{
"uid": "f6bcd0ea-f293-4864-bd13-d1c4e8b79080",
"source": "f6bcd0ea-f293-4864-bd13-d1c4e8b79080.png",
"name": "FSM 1",
"rows": 4,
"columns": 8,
"layout": "LAYOUT_2X3"
}, {
"uid": "88042125-4c6d-4dfa-ad1d-8e78b6df9ee9",
"source": "88042125-4c6d-4dfa-ad1d-8e78b6df9ee9.png",
"name": "FSM 2",
"rows": 4,
"columns": 8,
"layout": "LAYOUT_2X2"
}, {
"uid": "6584a279-e937-497e-a056-b1e77bff2439",
"source": "6584a279-e937-497e-a056-b1e77bff2439.png",
"name": "FSM 3",
"rows": 3,
"columns": 8,
"layout": "LAYOUT_2X3"
}, {
"uid": "b475367a-7bf8-44ee-b916-6e81a78f97d9",
"source": "b475367a-7bf8-44ee-b916-6e81a78f97d9.png",
"name": "FSM 4",
"rows": 3,
"columns": 8,
"layout": "LAYOUT_2X2"
}, {
"uid": "04ac5ad8-4100-4016-97b3-a51a728ca49d",
"source": "04ac5ad8-4100-4016-97b3-a51a728ca49d.png",
"name": "Candacis Spring 1",
"rows": 3,
"columns": 2,
"layout": "LAYOUT_2X3"
}, {
"uid": "fc294b9e-105a-4120-8caa-393d78fdf414",
"source": "fc294b9e-105a-4120-8caa-393d78fdf414.png",
"name": "Candacis Spring 2",
"rows": 1,
"columns": 3,
"layout": "LAYOUT_2X3"
}]
}

6
shell.nix Normal file
View File

@@ -0,0 +1,6 @@
{pkgs, ...}:
pkgs.mkShell {
name = "base-demo-game-development-shell";
LD_LIBRARY_PATH = with pkgs; "${xorg.libXtst}/lib:${openjfx17}/lib:${glib.out}/lib:${alsa-lib}/lib:${libGL}/lib:${gtk3}/lib";
}

View File

@@ -6,11 +6,10 @@ import com.bartlomiejpluta.base.api.move.MoveEvent;
import com.bartlomiejpluta.base.lib.ai.RunawayAI; import com.bartlomiejpluta.base.lib.ai.RunawayAI;
import com.bartlomiejpluta.demo.entity.Creature; import com.bartlomiejpluta.demo.entity.Creature;
import com.bartlomiejpluta.demo.entity.Enemy; import com.bartlomiejpluta.demo.entity.Enemy;
import com.bartlomiejpluta.demo.world.weapon.MeleeWeapon;
import lombok.NonNull; import lombok.NonNull;
public class WeaponBasedAI implements AI { public class WeaponBasedAI implements AI {
private static final int RANGE = 10; private static final int RANGE = 20;
private static final int MIN_RANGE = 3; private static final int MIN_RANGE = 3;
private static final int MAX_RANGE = 12; private static final int MAX_RANGE = 12;
private final Enemy enemy; private final Enemy enemy;
@@ -54,23 +53,32 @@ public class WeaponBasedAI implements AI {
var meleeWeapon = enemy.getMeleeWeapon(); var meleeWeapon = enemy.getMeleeWeapon();
var rangedWeapon = enemy.getRangedWeapon(); var rangedWeapon = enemy.getRangedWeapon();
var throwingWeapon = enemy.getThrowingWeapon();
if (meleeWeapon == null && rangedWeapon == null) { if (meleeWeapon == null && rangedWeapon == null && throwingWeapon == null) {
runawayAI.nextActivity(layer, dt); runawayAI.nextActivity(layer, dt);
return; return;
} }
if (rangedWeapon == null || enemy.manhattanDistance(target) == 1 || enemy.getAmmunition() == null) { if ((rangedWeapon == null && throwingWeapon == null) || (rangedWeapon != null && enemy.getAmmunition() == null && throwingWeapon == null) || enemy.manhattanDistance(target) == 1) {
enemy.setWeapon(meleeWeapon); enemy.setWeapon(meleeWeapon);
meleeAI.nextActivity(layer, dt); meleeAI.nextActivity(layer, dt);
return; return;
} }
if (enemy.getWeapon() instanceof MeleeWeapon) { if (throwingWeapon != null) {
meleeAI.nextActivity(layer, dt); enemy.setWeapon(throwingWeapon);
archerAI.nextActivity(layer, dt);
return;
} }
enemy.setWeapon(rangedWeapon); enemy.setWeapon(rangedWeapon);
archerAI.nextActivity(layer, dt); archerAI.nextActivity(layer, dt);
// if (enemy.getWeapon() instanceof MeleeWeapon) {
// meleeAI.nextActivity(layer, dt);
// }
} }
} }

View File

@@ -1,32 +1,25 @@
package com.bartlomiejpluta.demo.entity; package com.bartlomiejpluta.demo.entity;
import com.bartlomiejpluta.base.api.context.ContextHolder;
import com.bartlomiejpluta.demo.runner.DemoRunner;
import com.bartlomiejpluta.demo.world.item.Item; import com.bartlomiejpluta.demo.world.item.Item;
import lombok.Getter; import lombok.Getter;
import lombok.NonNull; import lombok.NonNull;
public class Chest extends MapObject { import java.util.Arrays;
private final DemoRunner runner; import java.util.Collection;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
public class Chest extends MapObject {
@Getter @Getter
private final Item[] content = new Item[Enemy.MAX_LOOT]; private final Item[] content = new Item[Enemy.MAX_LOOT];
public Chest(@NonNull String id) { public Chest(@NonNull String id) {
super(id); super(id);
runner = ((DemoRunner) ContextHolder.INSTANCE.getContext().getGameRunner());
} }
@Override @Override
public void interact(Creature creature) { protected CompletableFuture<?> interact() {
super.interact(creature); return runner.getGuiManager().openChestWindow(this);
runner.openChestWindow(this);
}
@Override
protected boolean shouldGoFurther(MapObject object) {
return runner.openedWindows() == 0;
} }
public Chest addItem(Item item) { public Chest addItem(Item item) {
@@ -39,4 +32,30 @@ public class Chest extends MapObject {
throw new IllegalStateException("Chest is full!"); throw new IllegalStateException("Chest is full!");
} }
public Chest addItem(Item item, int slot) {
if(slot >= content.length) {
throw new IllegalStateException("The [" + slot + "] slot exceeds the chest size (" + content.length + ")!");
}
if (content[slot] != null) {
throw new IllegalStateException("The [" + slot + "] slot is already filled!");
}
content[slot] = item;
return this;
}
public Chest shuffle() {
var random = new Random();
for(int i = content.length - 1; i > 0; --i) {
var index = random.nextInt(i + 1);
var tmp = content[index];
content[index] = content[i];
content[i] = tmp;
}
return this;
}
} }

View File

@@ -1,6 +1,8 @@
package com.bartlomiejpluta.demo.entity; package com.bartlomiejpluta.demo.entity;
import com.bartlomiejpluta.base.api.character.Character; import com.bartlomiejpluta.base.api.character.Character;
import com.bartlomiejpluta.base.api.light.Light;
import com.bartlomiejpluta.base.api.map.layer.object.ObjectLayer;
import com.bartlomiejpluta.demo.world.item.Item; import com.bartlomiejpluta.demo.world.item.Item;
import com.bartlomiejpluta.demo.world.weapon.Ammunition; import com.bartlomiejpluta.demo.world.weapon.Ammunition;
import com.bartlomiejpluta.demo.world.weapon.RangedWeapon; import com.bartlomiejpluta.demo.world.weapon.RangedWeapon;
@@ -39,6 +41,9 @@ public abstract class Creature extends NamedCharacter {
@Getter @Getter
private NamedCharacter lastAttacker; private NamedCharacter lastAttacker;
@Getter
protected Light light;
public Creature(@NonNull Character entity) { public Creature(@NonNull Character entity) {
super(entity); super(entity);
} }
@@ -84,6 +89,43 @@ public abstract class Creature extends NamedCharacter {
} }
} }
public void heal(int hp) {
this.hp = Math.min(this.hp + hp, this.maxHp);
}
public void setLight(Light light) {
this.light = light;
if(getLayer() != null) {
var layer = getLayer().getMap().getLayer(0);
if(light != null) {
layer.addLight(light);
} else if (this.light != null){
layer.removeLight(this.light);
}
}
this.light = light;
}
@Override
public void onAdd(ObjectLayer layer) {
super.onAdd(layer);
if(light != null) {
layer.getMap().getLayer(0).addLight(light);
}
}
@Override
public void onRemove(ObjectLayer layer) {
super.onRemove(layer);
if(light != null) {
layer.getMap().getLayer(0).removeLight(light);
}
}
@Override @Override
public void update(float dt) { public void update(float dt) {
super.update(dt); super.update(dt);
@@ -96,6 +138,10 @@ public abstract class Creature extends NamedCharacter {
alive = false; alive = false;
die(); die();
} }
if(light != null) {
light.setPosition(getPosition());
}
} }
protected void die() { protected void die() {
@@ -105,4 +151,6 @@ public abstract class Creature extends NamedCharacter {
} }
public abstract String getName(); public abstract String getName();
public abstract void removeItemFromEquipment(Item item);
} }

View File

@@ -0,0 +1,48 @@
package com.bartlomiejpluta.demo.entity;
import A.maps;
import com.bartlomiejpluta.base.api.map.layer.object.MapPin;
import com.bartlomiejpluta.demo.runner.DemoRunner;
import lombok.NonNull;
import java.util.concurrent.CompletableFuture;
public class Door extends MapObject {
private final String mapUid;
private final int targetX;
private final int targetY;
private final int layerId;
private final Player player;
public Door(@NonNull MapPin label, @NonNull String id) {
super(id);
this.mapUid = label.getMap();
this.layerId = label.getLayer();
this.targetX = label.getX();
this.targetY = label.getY();
player = DemoRunner.instance().getPlayer();
setPositionOffset(0, 16);
}
public Door(@NonNull String mapName, @NonNull String layerName, int targetX, int targetY, @NonNull String id) {
super(id);
var map = maps.byName(mapName);
this.mapUid = map.$;
this.targetX = targetX;
this.targetY = targetY;
this.layerId = map.layer(layerName).$;
player = DemoRunner.instance().getPlayer();
setPositionOffset(0, 16);
}
@Override
protected CompletableFuture<?> interact() {
context.openMap(mapUid);
context.getMap().getObjectLayer(layerId).addEntity(player);
player.setCoordinates(targetX, targetY);
reset();
return CompletableFuture.completedFuture(null);
}
}

View File

@@ -1,7 +1,5 @@
package com.bartlomiejpluta.demo.entity; package com.bartlomiejpluta.demo.entity;
import DB.EnemyDropDAO;
import DB.dao;
import com.bartlomiejpluta.base.api.ai.AI; import com.bartlomiejpluta.base.api.ai.AI;
import com.bartlomiejpluta.base.api.ai.NPC; import com.bartlomiejpluta.base.api.ai.NPC;
import com.bartlomiejpluta.base.api.context.ContextHolder; import com.bartlomiejpluta.base.api.context.ContextHolder;
@@ -9,22 +7,22 @@ import com.bartlomiejpluta.base.api.move.MoveEvent;
import com.bartlomiejpluta.base.lib.ai.NoopAI; import com.bartlomiejpluta.base.lib.ai.NoopAI;
import com.bartlomiejpluta.base.lib.animation.AnimationRunner; import com.bartlomiejpluta.base.lib.animation.AnimationRunner;
import com.bartlomiejpluta.base.lib.animation.SimpleAnimationRunner; import com.bartlomiejpluta.base.lib.animation.SimpleAnimationRunner;
import com.bartlomiejpluta.base.lib.db.Relop;
import com.bartlomiejpluta.base.util.random.DiceRoller; import com.bartlomiejpluta.base.util.random.DiceRoller;
import com.bartlomiejpluta.demo.ai.*; import com.bartlomiejpluta.demo.ai.*;
import com.bartlomiejpluta.demo.event.EnemyDiedEvent; import com.bartlomiejpluta.demo.event.EnemyDiedEvent;
import com.bartlomiejpluta.demo.runner.DemoRunner;
import com.bartlomiejpluta.demo.util.LootGenerator;
import com.bartlomiejpluta.demo.world.item.Item; import com.bartlomiejpluta.demo.world.item.Item;
import com.bartlomiejpluta.demo.world.junk.Junk;
import com.bartlomiejpluta.demo.world.weapon.Ammunition; import com.bartlomiejpluta.demo.world.weapon.Ammunition;
import com.bartlomiejpluta.demo.world.weapon.MeleeWeapon; import com.bartlomiejpluta.demo.world.weapon.MeleeWeapon;
import com.bartlomiejpluta.demo.world.weapon.RangedWeapon; import com.bartlomiejpluta.demo.world.weapon.RangedWeapon;
import com.bartlomiejpluta.demo.world.weapon.ThrowingWeapon;
import lombok.Getter; import lombok.Getter;
import lombok.NonNull; import lombok.NonNull;
import lombok.Setter;
import java.util.Random; import java.util.Random;
import static com.bartlomiejpluta.demo.util.ListUtil.randomIntSequence;
public class Enemy extends Creature implements NPC { public class Enemy extends Creature implements NPC {
public static final int MAX_LOOT = 4 * 4; public static final int MAX_LOOT = 4 * 4;
@@ -42,23 +40,27 @@ public class Enemy extends Creature implements NPC {
private MeleeWeapon meleeWeapon; private MeleeWeapon meleeWeapon;
@Getter @Getter
private RangedWeapon rangedWeapon; private RangedWeapon rangedWeapon;
@Getter
@Setter
private ThrowingWeapon throwingWeapon;
public Enemy(@NonNull String id) { public Enemy(@NonNull String id) {
this(DB.dao.enemy.find(id)); this(DB.dao.enemy.find(id));
} }
public Enemy(@NonNull DB.model.EnemyModel template) { public Enemy(@NonNull DB.model.EnemyModel template) {
super(ContextHolder.INSTANCE.getContext().createCharacter(A.charsets.get(template.getCharset()).uid)); super(ContextHolder.INSTANCE.getContext().createCharacter(A.charsets.byName(template.getCharset()).$));
this.template = template; this.template = template;
name = template.getName(); name = template.getName();
maxHp = DiceRoller.of(template.getHp()).roll(); maxHp = DiceRoller.roll(template.getHp());
hp = maxHp; hp = maxHp;
var speed = DiceRoller.of(template.getSpeed()).roll() / 10f; var speed = DiceRoller.roll(template.getSpeed()) / 10f;
setSpeed(speed); setSpeed(speed);
setAnimationSpeed(speed / 2.0f); setAnimationSpeed(speed / 2.0f);
setBlocking(template.isBlocking()); setBlocking(template.isBlocking());
var meleeWeaponTemplate = template.getMeleeWeapon(); var meleeWeaponTemplate = template.getMeleeWeapon();
var rangedWeaponTemplate = template.getRangedWeapon(); var rangedWeaponTemplate = template.getRangedWeapon();
var throwingWeaponTemplate = template.getThrowingWeapon();
if (meleeWeaponTemplate != null) { if (meleeWeaponTemplate != null) {
this.meleeWeapon = new MeleeWeapon(meleeWeaponTemplate); this.meleeWeapon = new MeleeWeapon(meleeWeaponTemplate);
@@ -68,10 +70,15 @@ public class Enemy extends Creature implements NPC {
var split = rangedWeaponTemplate.split(","); var split = rangedWeaponTemplate.split(",");
this.rangedWeapon = new RangedWeapon(split[0]); this.rangedWeapon = new RangedWeapon(split[0]);
setAmmunition(new Ammunition(split[1], DiceRoller.of(split[2]).roll())); setAmmunition(new Ammunition(split[1], DiceRoller.roll(split[2])));
} }
this.dieAnimation = new SimpleAnimationRunner(A.animations.get(template.getDieAnimation()).uid); if (throwingWeaponTemplate != null) {
var split = throwingWeaponTemplate.split(",");
this.throwingWeapon = new ThrowingWeapon(split[0], DiceRoller.roll(split[1]));
}
this.dieAnimation = new SimpleAnimationRunner(A.animations.byName(template.getDieAnimation()).$);
} }
@Override @Override
@@ -79,10 +86,15 @@ public class Enemy extends Creature implements NPC {
return ai; return ai;
} }
@Override
public void removeItemFromEquipment(Item item) {
// noop
}
@Override @Override
public void die() { public void die() {
super.die(); super.die();
changeCharacterSet(A.charsets.get(template.getDeadCharset()).uid); changeCharacterSet(A.charsets.byName(template.getDeadCharset()).$);
setScale(0.5f); setScale(0.5f);
setBlocking(false); setBlocking(false);
setZIndex(-1); setZIndex(-1);
@@ -90,38 +102,12 @@ public class Enemy extends Creature implements NPC {
ai = NoopAI.INSTANCE; ai = NoopAI.INSTANCE;
dieAnimation.run(context, getLayer(), this); dieAnimation.run(context, getLayer(), this);
context.playSound(A.sounds.get(template.getDieSound()).uid); context.playSound(A.sounds.byName(template.getDieSound()).$);
context.fireEvent(new EnemyDiedEvent(this)); context.fireEvent(new EnemyDiedEvent(this));
drawLoot(); LootGenerator.generate(template.getId(), loot);
} }
private void drawLoot() {
var def = dao.enemy_drop.query()
.where(EnemyDropDAO.Column.ENEMY, Relop.EQ, template.getId())
.orderBy("rand()")
.find();
var indexesIterator = randomIntSequence(0, loot.length).iterator();
for (var d : def) {
if (!indexesIterator.hasNext()) {
break;
}
var index = indexesIterator.next();
var split = d.getItem().split(":");
loot[index] = switch (split[0]) {
case "melee_weapon" -> new MeleeWeapon(split[1]);
case "ranged_weapon" -> new RangedWeapon(split[1]);
case "ammo" -> new Ammunition(split[1], DiceRoller.of(d.getAmount()).roll());
case "junk" -> new Junk(split[1]);
default -> throw new IllegalArgumentException("Unsupported item type");
};
}
}
public Enemy followAndAttack(Creature target, int range) { public Enemy followAndAttack(Creature target, int range) {
var ai = new SimpleEnemyAI(this, target, range); var ai = new SimpleEnemyAI(this, target, range);
@@ -157,7 +143,7 @@ public class Enemy extends Creature implements NPC {
} }
public Enemy defaultAI() { public Enemy defaultAI() {
var ai = new WeaponBasedAI(this, runner.getPlayer()); var ai = new WeaponBasedAI(this, DemoRunner.instance().getPlayer());
addEventListener(MoveEvent.TYPE, ai::recomputePath); addEventListener(MoveEvent.TYPE, ai::recomputePath);
addEventListener(EnemyDiedEvent.TYPE, e -> ai.recomputePath()); addEventListener(EnemyDiedEvent.TYPE, e -> ai.recomputePath());

View File

@@ -0,0 +1,102 @@
package com.bartlomiejpluta.demo.entity;
import DB.model.FriendModel;
import com.bartlomiejpluta.base.api.ai.AI;
import com.bartlomiejpluta.base.api.ai.NPC;
import com.bartlomiejpluta.base.api.character.Character;
import com.bartlomiejpluta.base.api.context.ContextHolder;
import com.bartlomiejpluta.base.lib.ai.FollowPathAI;
import com.bartlomiejpluta.base.lib.ai.NoopAI;
import com.bartlomiejpluta.base.lib.ai.RandomMovementAI;
import com.bartlomiejpluta.base.util.path.Path;
import com.bartlomiejpluta.base.util.random.DiceRoller;
import com.bartlomiejpluta.demo.world.item.Item;
import lombok.Getter;
import lombok.NonNull;
import org.joml.Vector2ic;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
public class Friend extends Creature implements NPC {
@Getter
private AI strategy = NoopAI.INSTANCE;
private AI priorStrategy;
private boolean interacting;
@Getter
private final String name;
@Getter
private final int dialogNameColor;
private Function<Friend, CompletableFuture<Object>> interaction;
public Friend(@NonNull String id) {
this(DB.dao.friend.find(id));
}
public Friend(@NonNull FriendModel template) {
super(ContextHolder.INSTANCE.getContext().createCharacter(A.charsets.byName(template.getCharset()).$));
name = template.getName();
setSpeed(DiceRoller.roll(template.getSpeed()) / 10f);
setBlocking(template.isBlocking());
dialogNameColor = Integer.parseInt(template.getDialogColor(), 16);
}
@Override
public void removeItemFromEquipment(Item item) {
}
public CompletableFuture<Object> interact(Character trigger) {
if (interaction != null && !interacting) {
setFaceDirection(getDirectionTowards(trigger));
var movement = getMovement();
if (movement != null) {
movement.abort();
}
priorStrategy = strategy;
strategy = NoopAI.INSTANCE;
interacting = true;
return interaction.apply(this).thenApply(o -> {
strategy = priorStrategy;
interacting = false;
return o;
});
}
return CompletableFuture.completedFuture(null);
}
public Friend interaction(Function<Friend, CompletableFuture<Object>> interaction) {
this.interaction = interaction;
return this;
}
public Friend followPath(@NonNull Path<Friend> path) {
var ai = new FollowPathAI<>(this);
ai.setPath(path);
this.strategy = ai;
return this;
}
public Friend followPath(@NonNull Function<Friend, Path<Friend>> pathSupplier) {
var ai = new FollowPathAI<>(this);
ai.setPath(pathSupplier.apply(this));
this.strategy = ai;
return this;
}
public Friend randomMovementAI(float intervalSeconds, Vector2ic origin, int radius) {
this.strategy = new RandomMovementAI<>(this, intervalSeconds, origin, radius);
return this;
}
public Friend randomMovementAI(float intervalSeconds) {
this.strategy = new RandomMovementAI<>(this, intervalSeconds);
return this;
}
}

View File

@@ -1,85 +1,40 @@
package com.bartlomiejpluta.demo.entity; package com.bartlomiejpluta.demo.entity;
import com.bartlomiejpluta.base.api.context.Context;
import com.bartlomiejpluta.base.api.context.ContextHolder; import com.bartlomiejpluta.base.api.context.ContextHolder;
import com.bartlomiejpluta.base.api.move.Direction; import com.bartlomiejpluta.demo.runner.DemoRunner;
import com.bartlomiejpluta.base.util.path.CharacterPath;
import com.bartlomiejpluta.base.util.path.PathExecutor;
import lombok.Getter; import lombok.Getter;
import lombok.NonNull; import lombok.NonNull;
public abstract class MapObject extends NamedCharacter { import java.util.concurrent.CompletableFuture;
private final PathExecutor<MapObject> pathExecutor = new PathExecutor<>(this);
private final DB.model.MapObjectModel template;
private final Short frame;
private final String interactSound;
import static java.util.concurrent.CompletableFuture.completedFuture;
public abstract class MapObject extends com.bartlomiejpluta.base.util.world.MapObject {
protected final Context context;
protected final DemoRunner runner;
@Getter @Getter
private final String name; private final String name;
private final String interactSound;
private boolean interacting = false;
public MapObject(@NonNull String id) { public MapObject(@NonNull String id) {
this(DB.dao.map_object.find(id)); this(DB.dao.object.find(id));
} }
public MapObject(@NonNull DB.model.MapObjectModel template) { public MapObject(@NonNull DB.model.ObjectModel template) {
super(ContextHolder.INSTANCE.getContext().createCharacter(A.charsets.get(template.getCharset()).uid)); super(ContextHolder.INSTANCE.getContext().createCharacter(A.charsets.byName(template.getCharset()).$), template.getFrame());
this.template = template; this.context = ContextHolder.INSTANCE.getContext();
this.frame = template.getFrame(); this.runner = DemoRunner.instance();
this.name = template.getName(); this.name = template.getName();
this.interactSound = A.sounds.get(template.getInteractSound()).uid; this.interactSound = A.sounds.byName(template.getInteractSound()).$;
setBlocking(true);
disableAnimation();
if (frame != null) {
setAnimationFrame(frame);
}
pathExecutor.setPath(
frame != null
? new CharacterPath<MapObject>()
.run(this::startInteraction)
.turn(Direction.LEFT, frame)
.wait(0.05f)
.turn(Direction.RIGHT, frame)
.wait(0.05f)
.turn(Direction.UP, frame)
.wait(0.5f)
.suspend(this::shouldGoFurther)
.turn(Direction.RIGHT, frame)
.wait(0.05f)
.turn(Direction.LEFT, frame)
.wait(0.05f)
.turn(Direction.DOWN, frame)
.wait(0.5f)
.run(this::finishInteraction)
: new CharacterPath<>()
);
}
protected boolean shouldGoFurther(MapObject object) {
return true;
}
public void interact(Creature creature) {
interacting = true;
}
protected void startInteraction() {
if (interactSound != null) {
context.playSound(interactSound);
}
}
protected void finishInteraction() {
interacting = false;
} }
@Override @Override
public void update(float dt) { protected @NonNull CompletableFuture<?> onInteractionBegin() {
if (interacting) { if (interactSound != null) {
pathExecutor.execute(getLayer(), dt); context.playSound(interactSound);
} }
return completedFuture(null);
} }
} }

View File

@@ -3,8 +3,14 @@ package com.bartlomiejpluta.demo.entity;
import com.bartlomiejpluta.base.api.character.Character; import com.bartlomiejpluta.base.api.character.Character;
import com.bartlomiejpluta.base.api.context.Context; import com.bartlomiejpluta.base.api.context.Context;
import com.bartlomiejpluta.base.api.context.ContextHolder; import com.bartlomiejpluta.base.api.context.ContextHolder;
import com.bartlomiejpluta.base.lib.animation.AnimationRunner;
import com.bartlomiejpluta.base.lib.animation.SimpleAnimationRunner;
import com.bartlomiejpluta.base.lib.character.CharacterDelegate; import com.bartlomiejpluta.base.lib.character.CharacterDelegate;
import com.bartlomiejpluta.demo.runner.DemoRunner; import com.bartlomiejpluta.demo.runner.DemoRunner;
import lombok.NonNull;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
public abstract class NamedCharacter extends CharacterDelegate { public abstract class NamedCharacter extends CharacterDelegate {
protected final Context context; protected final Context context;
@@ -13,8 +19,30 @@ public abstract class NamedCharacter extends CharacterDelegate {
public NamedCharacter(Character character) { public NamedCharacter(Character character) {
super(character); super(character);
this.context = ContextHolder.INSTANCE.getContext(); this.context = ContextHolder.INSTANCE.getContext();
this.runner = (DemoRunner) context.getGameRunner(); this.runner = DemoRunner.instance();
} }
public abstract String getName(); public abstract String getName();
public int getDialogNameColor() {
return 0xFFFFFF;
}
public CompletableFuture<Void> runEmoji(@NonNull String animation) {
return runEmoji(animation, null);
}
public CompletableFuture<Void> runEmoji(@NonNull String animation, Consumer<SimpleAnimationRunner> customizer) {
var runner = AnimationRunner
.simple(animation)
.scale(0.4f)
.animationSpeed(1.6f)
.offset(0, -30);
if (customizer != null) {
customizer.accept(runner);
}
return runner.run(context, this);
}
} }

View File

@@ -1,22 +1,45 @@
package com.bartlomiejpluta.demo.entity; package com.bartlomiejpluta.demo.entity;
import com.bartlomiejpluta.base.api.character.Character; import com.bartlomiejpluta.base.api.character.Character;
import com.bartlomiejpluta.base.util.random.DiceRoller;
import com.bartlomiejpluta.demo.world.item.Item; import com.bartlomiejpluta.demo.world.item.Item;
import com.bartlomiejpluta.demo.world.item.ItemStack;
import com.bartlomiejpluta.demo.world.weapon.Ammunition; import com.bartlomiejpluta.demo.world.weapon.Ammunition;
import com.bartlomiejpluta.demo.world.weapon.ThrowingWeapon;
import com.bartlomiejpluta.demo.world.weapon.Weapon; import com.bartlomiejpluta.demo.world.weapon.Weapon;
import lombok.NonNull; import lombok.NonNull;
import org.joml.Vector2i; import org.joml.Vector2i;
import java.util.List; import java.util.Arrays;
public class Player extends Creature { public class Player extends Creature {
private final Item[] equipment = new Item[4 * 4]; public static final int EQUIPMENT_SIZE = 6 * 6;
private final Item[] equipment = new Item[EQUIPMENT_SIZE];
private int interactionCooldown = 0; private int interactionCooldown = 0;
public Player(@NonNull Character entity) { public Player(@NonNull Character entity) {
super(entity); super(entity);
this.hp = 500; reset();
this.maxHp = 500; }
public void reset() {
var data = DB.dao.levels.find(1);
this.maxHp = DiceRoller.roll(data.getMaxHp());
this.hp = this.maxHp;
alive = true;
changeCharacterSet(A.charsets.luna.$);
setScale(1f);
setSpeed(4f);
setAnimationSpeed(1f);
setBlocking(true);
var light = context.createLight();
light.setAttenuation(4f, 0, 0.001f);
light.setIntensity(1f, 1f, 1f);
setLight(light);
Arrays.fill(equipment, null);
} }
public void interact() { public void interact() {
@@ -29,12 +52,22 @@ public class Player extends Creature {
for (var i = 0; i < entities.size(); ++i) { for (var i = 0; i < entities.size(); ++i) {
var entity = entities.get(i); var entity = entities.get(i);
if (entity.getCoordinates().equals(coords)) {
// Use some map object which player is looking at // Use some map object which player is looking at
if (entity.getCoordinates().equals(coords) && entity instanceof MapObject object) { if(entity instanceof MapObject object) {
object.interact(this); object.triggerInteraction();
return; return;
} }
// Interact with friend creature which player is looking at
if(entity instanceof Friend friend) {
friend.interact(this).thenApply(o -> interactionCooldown = INTERACTION_COOLDOWN);
return;
}
}
if (entity.getCoordinates().equals(getCoordinates())) { if (entity.getCoordinates().equals(getCoordinates())) {
// Pick some item from the ground // Pick some item from the ground
@@ -47,7 +80,7 @@ public class Player extends Creature {
// Search the enemy corpse // Search the enemy corpse
if (entity instanceof Enemy enemy && !enemy.isAlive()) { if (entity instanceof Enemy enemy && !enemy.isAlive()) {
runner.openLootWindow(enemy); runner.getGuiManager().openLootWindow(enemy);
interactionCooldown = INTERACTION_COOLDOWN; interactionCooldown = INTERACTION_COOLDOWN;
return; return;
} }
@@ -56,6 +89,49 @@ public class Player extends Creature {
} }
public boolean pushItemToEquipment(@NonNull Item item) { public boolean pushItemToEquipment(@NonNull Item item) {
if (item instanceof Ammunition ammo) {
if (getAmmunition() != null && ammo.getId().equals(getAmmunition().getId())) {
getAmmunition().increase(ammo.getCount());
return true;
}
}
if (item instanceof ThrowingWeapon weapons) {
if (getWeapon() instanceof ThrowingWeapon currentWeapons && currentWeapons.getId().equals(weapons.getId())) {
currentWeapons.increase(weapons.getCount());
return true;
}
}
if (item instanceof ItemStack stack) {
return pushItemStackToEquipment(stack);
}
return pushSingleItemToEquipment(item);
}
private boolean pushItemStackToEquipment(@NonNull ItemStack items) {
var availableSlot = -1;
for (int i = 0; i < equipment.length; ++i) {
if (equipment[i] instanceof ItemStack stack && stack.getId().equals(items.getId())) {
stack.increase(items.getCount());
return true;
}
if (availableSlot == -1 && equipment[i] == null) {
availableSlot = i;
}
}
if (availableSlot > -1) {
equipment[availableSlot] = items;
return true;
}
return false;
}
private boolean pushSingleItemToEquipment(@NonNull Item item) {
for (int i = 0; i < equipment.length; ++i) { for (int i = 0; i < equipment.length; ++i) {
if (equipment[i] == null) { if (equipment[i] == null) {
equipment[i] = item; equipment[i] = item;
@@ -70,6 +146,7 @@ public class Player extends Creature {
return equipment[index]; return equipment[index];
} }
@Override
public void removeItemFromEquipment(@NonNull Item item) { public void removeItemFromEquipment(@NonNull Item item) {
for (int i = 0; i < equipment.length; ++i) { for (int i = 0; i < equipment.length; ++i) {
if (equipment[i] == item) { if (equipment[i] == item) {
@@ -94,18 +171,42 @@ public class Player extends Creature {
} }
@Override @Override
public void setWeapon(Weapon weapon) { public void setWeapon(Weapon newWeapon) {
var currentWeapon = getWeapon(); var currentWeapon = getWeapon();
if (weapon != null) { if (newWeapon == null) {
removeItemFromEquipment(weapon); disarmWeapon(currentWeapon);
return;
} }
if (currentWeapon instanceof ThrowingWeapon currentWeapons && newWeapon instanceof ThrowingWeapon weapons && currentWeapons.getId().equals(weapons.getId())) {
updateStackableWeapon(currentWeapons, weapons);
return;
}
changeWeaponForWeapon(currentWeapon, newWeapon);
}
private void disarmWeapon(Weapon currentWeapon) {
if (!(currentWeapon instanceof ThrowingWeapon)) {
pushItemToEquipment(currentWeapon);
}
super.setWeapon(null);
}
private void updateStackableWeapon(ThrowingWeapon currentWeapon, ThrowingWeapon newWeapon) {
currentWeapon.increase(newWeapon.getCount());
removeItemFromEquipment(newWeapon);
}
private void changeWeaponForWeapon(Weapon currentWeapon, Weapon newWeapon) {
super.setWeapon(newWeapon);
removeItemFromEquipment(newWeapon);
if (currentWeapon != null) { if (currentWeapon != null) {
pushItemToEquipment(currentWeapon); pushItemToEquipment(currentWeapon);
} }
super.setWeapon(weapon);
} }
@Override @Override
@@ -137,7 +238,12 @@ public class Player extends Creature {
@Override @Override
public String getName() { public String getName() {
return "Player"; return "Luna";
}
@Override
public int getDialogNameColor() {
return 0x00AA00;
} }
@Override @Override

View File

@@ -6,7 +6,7 @@ import com.bartlomiejpluta.base.api.gui.Component;
import com.bartlomiejpluta.base.api.gui.GUI; import com.bartlomiejpluta.base.api.gui.GUI;
import com.bartlomiejpluta.base.api.screen.Screen; import com.bartlomiejpluta.base.api.screen.Screen;
import com.bartlomiejpluta.base.lib.gui.BaseComponent; import com.bartlomiejpluta.base.lib.gui.BaseComponent;
import lombok.Setter; import lombok.NonNull;
import java.util.Map; import java.util.Map;
@@ -14,7 +14,6 @@ public class Bar extends BaseComponent {
private final Color stroke; private final Color stroke;
private final Color fill; private final Color fill;
@Setter
private float value = 1.0f; private float value = 1.0f;
private float actualValue = 1.0f; private float actualValue = 1.0f;
private final float speed = 0.05f; private final float speed = 0.05f;
@@ -29,6 +28,10 @@ public class Bar extends BaseComponent {
fill.setAlpha(1f); fill.setAlpha(1f);
} }
public void setValue(@NonNull Float value) {
this.value = value;
}
public void setStrokeColor(Integer hex) { public void setStrokeColor(Integer hex) {
stroke.setRGB(hex); stroke.setRGB(hex);
} }
@@ -53,12 +56,12 @@ public class Bar extends BaseComponent {
actualValue += remainingDistance * speed; actualValue += remainingDistance * speed;
gui.beginPath(); gui.beginPath();
gui.drawRectangle(x, y, Math.max(width * actualValue, 0), height); gui.drawRectangle(x + paddingLeft, y + paddingTop, Math.max(width * actualValue, 0), height);
gui.setFillColor(fill); gui.setFillColor(fill);
gui.fill(); gui.fill();
gui.closePath(); gui.closePath();
gui.beginPath(); gui.beginPath();
gui.drawRectangle(x, y, width, height); gui.drawRectangle(x + paddingLeft, y + paddingTop, width, height);
gui.setStrokeColor(stroke); gui.setStrokeColor(stroke);
gui.stroke(); gui.stroke();
gui.closePath(); gui.closePath();

View File

@@ -0,0 +1,54 @@
package com.bartlomiejpluta.demo.gui;
import A.fonts;
import com.bartlomiejpluta.base.api.context.Context;
import com.bartlomiejpluta.base.api.gui.*;
import com.bartlomiejpluta.base.lib.gui.TextView;
import com.bartlomiejpluta.base.lib.gui.VOptionChoice;
import java.util.Collections;
import java.util.Map;
public class DialogChoiceWindow extends DecoratedWindow {
@Ref("speaker")
private TextView speaker;
@Ref("choice")
private VOptionChoice choice;
@SuppressWarnings("unchecked")
@Override
public void onOpen(WindowManager manager, Object[] args) {
super.onOpen(manager, args);
speaker.setText((String) args[0]);
speaker.setColor((int) args[1]);
var index = 0;
choice.removeAllChildren();
var options = (String[]) args[2];
for(var option : options) {
var button = new Button(context, gui, Collections.emptyMap());
choice.add(button);
button.setText(option);
button.setColor(0xFFFFFF);
button.setWidthMode(SizeMode.RELATIVE);
button.setWidth(1f);
button.setFont(fonts.roboto_regular.$);
button.setFontSize(20f);
button.setAction(onChoose(index));
++index;
}
choice.focus();
}
private Runnable onChoose(int index) {
return () -> resolve(index);
}
public DialogChoiceWindow(Context context, GUI gui, Map<String, Component> refs) {
super(context, gui, refs);
}
}

View File

@@ -0,0 +1,66 @@
package com.bartlomiejpluta.demo.gui;
import com.bartlomiejpluta.base.api.context.Context;
import com.bartlomiejpluta.base.api.gui.*;
import com.bartlomiejpluta.base.api.input.Key;
import com.bartlomiejpluta.base.api.input.KeyAction;
import com.bartlomiejpluta.base.api.input.KeyEvent;
import com.bartlomiejpluta.base.lib.gui.PrintedTextView;
import com.bartlomiejpluta.base.lib.gui.TextView;
import java.util.Map;
public class DialogWindow extends DecoratedWindow {
@Ref("speaker")
private TextView speaker;
@Ref("message")
private PrintedTextView text;
public DialogWindow(Context context, GUI gui, Map<String, Component> refs) {
super(context, gui, refs);
addEventListener(KeyEvent.TYPE, this::handleKey);
}
private void handleKey(KeyEvent event) {
if (event.getKey() == Key.KEY_ESCAPE) {
event.consume();
return;
}
if (event.getKey() == Key.KEY_ENTER && event.getAction() == KeyAction.PRESS) {
if (text.isPrinting()) {
text.printAll();
event.consume();
return;
}
manager.close();
event.consume();
}
}
@Override
public void onOpen(WindowManager manager, Object[] args) {
super.onOpen(manager, args);
speaker.setText((String) args[0]);
speaker.setColor((int) args[1]);
text.setText((String) args[2]);
if (args.length > 3) {
setWindowPosition((WindowPosition) args[3]);
}
text.start();
}
@Override
public void onClose(WindowManager manager) {
super.onClose(manager);
text.setText("");
}
}

View File

@@ -2,6 +2,10 @@ package com.bartlomiejpluta.demo.gui;
import com.bartlomiejpluta.base.api.context.Context; import com.bartlomiejpluta.base.api.context.Context;
import com.bartlomiejpluta.base.api.gui.*; import com.bartlomiejpluta.base.api.gui.*;
import com.bartlomiejpluta.base.api.input.Key;
import com.bartlomiejpluta.base.api.input.KeyAction;
import com.bartlomiejpluta.base.api.input.KeyEvent;
import com.bartlomiejpluta.base.lib.gui.HOptionChoice;
import com.bartlomiejpluta.base.lib.gui.Label; import com.bartlomiejpluta.base.lib.gui.Label;
import com.bartlomiejpluta.base.lib.gui.VGridOptionChoice; import com.bartlomiejpluta.base.lib.gui.VGridOptionChoice;
import com.bartlomiejpluta.base.lib.gui.VOptionChoice; import com.bartlomiejpluta.base.lib.gui.VOptionChoice;
@@ -9,33 +13,40 @@ import com.bartlomiejpluta.demo.entity.Player;
import com.bartlomiejpluta.demo.runner.DemoRunner; import com.bartlomiejpluta.demo.runner.DemoRunner;
import com.bartlomiejpluta.demo.world.item.Item; import com.bartlomiejpluta.demo.world.item.Item;
import com.bartlomiejpluta.demo.world.item.Useable; import com.bartlomiejpluta.demo.world.item.Useable;
import com.bartlomiejpluta.demo.world.potion.Medicament;
import com.bartlomiejpluta.demo.world.weapon.MeleeWeapon; import com.bartlomiejpluta.demo.world.weapon.MeleeWeapon;
import com.bartlomiejpluta.demo.world.weapon.RangedWeapon; import com.bartlomiejpluta.demo.world.weapon.RangedWeapon;
import com.bartlomiejpluta.demo.world.weapon.ThrowingWeapon;
import java.util.Map; import java.util.Map;
import java.util.function.Consumer; import java.util.function.BiConsumer;
import static java.lang.String.format; import static java.lang.String.format;
public class EquipmentWindow extends DecoratedWindow { public class EquipmentWindow extends DecoratedWindow {
private final DemoRunner runner;
private final Player player; private final Player player;
private final Window eqItemMenuWindow; private final Window popupMenuWindow;
private final Button useBtn; private final Button useBtn;
private final Button dropBtn; private final Button dropBtn;
private final Button cancelBtn; private final Button cancelBtn;
private final VOptionChoice eqItemMenu; private final VOptionChoice popupMenu;
@Ref("eq") @Ref("layout")
private VGridOptionChoice eqGrid; private HOptionChoice layout;
@Ref("equipment")
private VGridOptionChoice equipment;
@Ref("inventory")
private VGridOptionChoice inventory;
@Ref("weapon") @Ref("weapon")
private ItemIconView weapon; private ItemIconView weaponSlot;
@Ref("ammo") @Ref("ammo")
private ItemIconView ammo; private ItemIconView ammoSlot;
@Ref("item-name") @Ref("item-name")
private Label nameLbl; private Label nameLbl;
@@ -43,15 +54,26 @@ public class EquipmentWindow extends DecoratedWindow {
@Ref("item-details") @Ref("item-details")
private Label detailsLbl; private Label detailsLbl;
public EquipmentWindow(Context context, GUI gui, Map<String, Component> refs) { public EquipmentWindow(Context context, GUI gui, Map<String, Component> refs) {
super(context, gui, refs); super(context, gui, refs);
this.runner = (DemoRunner) context.getGameRunner(); this.player = DemoRunner.instance().getPlayer();
this.player = runner.getPlayer(); this.popupMenuWindow = gui.inflateWindow(A.widgets.eq_item_menu.$);
this.eqItemMenuWindow = gui.inflateWindow(A.widgets.eq_item_menu.uid); this.popupMenu = popupMenuWindow.reference("menu", VOptionChoice.class);
this.eqItemMenu = eqItemMenuWindow.reference("menu", VOptionChoice.class); this.useBtn = popupMenuWindow.reference("use", Button.class);
this.useBtn = eqItemMenuWindow.reference("use", Button.class); this.dropBtn = popupMenuWindow.reference("drop", Button.class);
this.dropBtn = eqItemMenuWindow.reference("drop", Button.class); this.cancelBtn = popupMenuWindow.reference("cancel", Button.class);
this.cancelBtn = eqItemMenuWindow.reference("cancel", Button.class);
addEventListener(KeyEvent.TYPE, this::handleKey);
}
private void handleKey(KeyEvent event) {
if (event.getKey() == Key.KEY_TAB && event.getAction() == KeyAction.PRESS) {
layout.selectNext();
layout.focus();
updateItemDetails(((VGridOptionChoice) layout.getSelectedComponent()).getSelectedComponent());
event.consume();
}
} }
@Override @Override
@@ -59,33 +81,69 @@ public class EquipmentWindow extends DecoratedWindow {
super.onOpen(manager, args); super.onOpen(manager, args);
cancelBtn.setAction(manager::close); cancelBtn.setAction(manager::close);
eqGrid.setOnSelect(this::updateItemDetails); inventory.setOnSelect(this::updateItemDetails);
equipment.setOnSelect(this::updateItemDetails);
updateEquipment(); updateEquipment();
eqGrid.select(0, 0); layout.select(1);
eqGrid.focus(); layout.focus();
}
@Override
public void onClose(WindowManager manager) {
super.onClose(manager);
layout.blur();
} }
private void updateEquipment() { private void updateEquipment() {
var i = 0; var i = 0;
for (var child : eqGrid.getChildren()) { for (var child : inventory.getChildren()) {
var slot = (ItemIconView) child; var slot = (ItemIconView) child;
slot.setItem(player.getEquipmentItem(i++)); slot.setItem(player.getEquipmentItem(i++));
slot.setAction(handleClick(slot)); slot.setAction(this::handleInventoryClick);
} }
weapon.setItem(player.getWeapon()); weaponSlot.setItem(player.getWeapon());
ammo.setItem(player.getAmmunition()); weaponSlot.setAction(handleEquipmentClick(() -> {
player.setWeapon(null);
updateEquipment();
manager.close();
}));
ammoSlot.setItem(player.getAmmunition());
ammoSlot.setAction(handleEquipmentClick(() -> {
player.setAmmunition(null);
updateEquipment();
manager.close();
}));
} }
private Consumer<Item> handleClick(ItemIconView slot) { private BiConsumer<ItemIconView, Item> handleEquipmentClick(Runnable deequip) {
return item -> { return (slot, item) -> {
useBtn.setText("Disarm");
popupMenu.select(0);
popupMenu.focus();
manager.open(popupMenuWindow);
useBtn.setAction(deequip);
dropBtn.setAction(() -> {
player.dropItemFromEquipment(item);
slot.setItem(null);
updateItemDetails(slot);
manager.close();
});
};
}
private void handleInventoryClick(ItemIconView slot, Item item) {
useBtn.setText(getButtonTitle(item)); useBtn.setText(getButtonTitle(item));
eqItemMenu.select(0); popupMenu.select(0);
eqItemMenu.focus(); popupMenu.focus();
manager.open(eqItemMenuWindow); manager.open(popupMenuWindow);
if (item instanceof Useable useable) { if (item instanceof Useable useable) {
useBtn.setAction(() -> { useBtn.setAction(() -> {
@@ -101,7 +159,6 @@ public class EquipmentWindow extends DecoratedWindow {
updateItemDetails(slot); updateItemDetails(slot);
manager.close(); manager.close();
}); });
};
} }
private void updateItemDetails(Component slot) { private void updateItemDetails(Component slot) {
@@ -123,6 +180,15 @@ public class EquipmentWindow extends DecoratedWindow {
if (item instanceof RangedWeapon weapon) { if (item instanceof RangedWeapon weapon) {
detailsLbl.setText(format("Damage: %s\nRange: %s\nCooldown: %s\n", weapon.getDmgRoller(), weapon.getRangeRoller(), weapon.getCooldown())); detailsLbl.setText(format("Damage: %s\nRange: %s\nCooldown: %s\n", weapon.getDmgRoller(), weapon.getRangeRoller(), weapon.getCooldown()));
return;
}
if (item instanceof ThrowingWeapon weapon) {
detailsLbl.setText(format("Damage: %s\nRange: %s\nCooldown: %s\n", weapon.getDmgRoller(), weapon.getRangeRoller(), weapon.getCooldown()));
}
if (item instanceof Medicament medicament) {
detailsLbl.setText(format("Restores: %s HP\n", medicament.getRoller()));
} }
} }

View File

@@ -3,33 +3,26 @@ package com.bartlomiejpluta.demo.gui;
import com.bartlomiejpluta.base.api.context.Context; import com.bartlomiejpluta.base.api.context.Context;
import com.bartlomiejpluta.base.api.gui.Component; import com.bartlomiejpluta.base.api.gui.Component;
import com.bartlomiejpluta.base.api.gui.GUI; import com.bartlomiejpluta.base.api.gui.GUI;
import com.bartlomiejpluta.base.api.gui.Inflatable;
import com.bartlomiejpluta.base.api.gui.Ref; import com.bartlomiejpluta.base.api.gui.Ref;
import lombok.Getter; import com.bartlomiejpluta.base.api.gui.WindowManager;
import com.bartlomiejpluta.base.lib.gui.VOptionChoice;
import java.util.Map; import java.util.Map;
public class GameMenuWindow extends DecoratedWindow implements Inflatable { public class GameMenuWindow extends DecoratedWindow {
@Ref("resume_game") @Ref("menu")
@Getter private VOptionChoice menu;
private Button resumeGameBtn;
@Ref("start_menu")
@Getter
private Button startMenuBtn;
@Ref("exit")
@Getter
private Button exitBtn;
public GameMenuWindow(Context context, GUI gui, Map<String, Component> refs) { public GameMenuWindow(Context context, GUI gui, Map<String, Component> refs) {
super(context, gui, refs); super(context, gui, refs);
} }
@Override @Override
public void onInflate() { public void onOpen(WindowManager manager, Object[] args) {
resumeGameBtn.focus(); super.onOpen(manager, args);
menu.select(0);
menu.focus();
} }
} }

View File

@@ -6,14 +6,14 @@ import com.bartlomiejpluta.base.api.gui.GUI;
import com.bartlomiejpluta.base.api.gui.Ref; import com.bartlomiejpluta.base.api.gui.Ref;
import com.bartlomiejpluta.base.api.screen.Screen; import com.bartlomiejpluta.base.api.screen.Screen;
import com.bartlomiejpluta.base.lib.gui.BorderLayout; import com.bartlomiejpluta.base.lib.gui.BorderLayout;
import com.bartlomiejpluta.base.lib.gui.IconView;
import com.bartlomiejpluta.base.lib.gui.Label; import com.bartlomiejpluta.base.lib.gui.Label;
import com.bartlomiejpluta.base.lib.gui.TextView;
import com.bartlomiejpluta.demo.entity.Player; import com.bartlomiejpluta.demo.entity.Player;
import com.bartlomiejpluta.demo.event.EnemyDiedEvent; import com.bartlomiejpluta.demo.event.EnemyDiedEvent;
import com.bartlomiejpluta.demo.event.HitEvent; import com.bartlomiejpluta.demo.event.HitEvent;
import com.bartlomiejpluta.demo.runner.DemoRunner; import com.bartlomiejpluta.demo.runner.DemoRunner;
import com.bartlomiejpluta.demo.util.LimitedQueue; import com.bartlomiejpluta.demo.util.LimitedQueue;
import com.bartlomiejpluta.demo.world.weapon.Weapon; import com.bartlomiejpluta.demo.world.time.WorldTime;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import java.util.Map; import java.util.Map;
@@ -24,32 +24,27 @@ public class HUD extends BorderLayout {
private static final int MAX_LOG_SIZE = 10; private static final int MAX_LOG_SIZE = 10;
private static final float LOG_VISIBILITY_DURATION = 8000f; private static final float LOG_VISIBILITY_DURATION = 8000f;
private static final float LOG_VISIBILITY_FADING_OUT = 1000f; private static final float LOG_VISIBILITY_FADING_OUT = 1000f;
private final DemoRunner runner;
private final Player player; private final Player player;
private final WorldTime time;
private final Runtime runtime; private final Runtime runtime;
private final LimitedQueue<String> logger = new LimitedQueue<>(MAX_LOG_SIZE); private final LimitedQueue<String> logger = new LimitedQueue<>(MAX_LOG_SIZE);
private float logVisibilityDuration = 0f; private float logVisibilityDuration = 0f;
private Weapon currentWeapon;
@Ref("hp") @Ref("hp")
private Bar hp; private Bar hp;
@Ref("debug") @Ref("debug")
private Label debugLbl; private TextView debugTxt;
@Ref("log") @Ref("log")
private Label logLbl; private Label logLbl;
@Ref("weapon")
private IconView weapon;
public HUD(Context context, GUI gui, Map<String, Component> refs) { public HUD(Context context, GUI gui, Map<String, Component> refs) {
super(context, gui, refs); super(context, gui, refs);
this.runner = (DemoRunner) context.getGameRunner(); this.player = DemoRunner.instance().getPlayer();
this.player = runner.getPlayer();
this.runtime = Runtime.getRuntime(); this.runtime = Runtime.getRuntime();
this.time = DemoRunner.instance().getTime();
context.addEventListener(HitEvent.TYPE, this::logHitEvent); context.addEventListener(HitEvent.TYPE, this::logHitEvent);
context.addEventListener(EnemyDiedEvent.TYPE, this::logEnemyDiedEvent); context.addEventListener(EnemyDiedEvent.TYPE, this::logEnemyDiedEvent);
} }
@@ -80,16 +75,13 @@ public class HUD extends BorderLayout {
} else { } else {
logVisibilityDuration = 0; logVisibilityDuration = 0;
} }
this.currentWeapon = player.getWeapon();
} }
@Override @Override
public void draw(Screen screen, GUI gui) { public void draw(Screen screen, GUI gui) {
var coords = player.getCoordinates(); var coords = player.getCoordinates();
var pos = player.getPosition(); var pos = player.getPosition();
debugLbl.setText(String.format("FPS: %.2f\n" + "Mem: %.2f / %.2f [MB]\n" + "Coords: %d : %d\n" + "Pos: %.2f : %.2f\n" + "Entities: %d", runner.instantFPS(), runtime.totalMemory() / 1024f / 1024f, runtime.maxMemory() / 1024f / 1024f, coords.x(), coords.y(), pos.x(), pos.y(), player.getLayer().getEntities().size() - 1)); debugTxt.setText(String.format("Clock: %02d:%02d\nTime: %.2f\nMem: %.2f / %.2f [MB]\nCoords: %d : %d\nPos: %.2f : %.2f\nEntities: %d\n", time.getHour(), time.getMinute(), time.getProgress(), runtime.totalMemory() / 1024f / 1024f, runtime.maxMemory() / 1024f / 1024f, coords.x(), coords.y(), pos.x(), pos.y(), player.getLayer().getEntities().size()));
logLbl.setAlpha(Math.min(1f, logVisibilityDuration / LOG_VISIBILITY_FADING_OUT)); logLbl.setAlpha(Math.min(1f, logVisibilityDuration / LOG_VISIBILITY_FADING_OUT));

View File

@@ -2,15 +2,14 @@ package com.bartlomiejpluta.demo.gui;
import A.fonts; import A.fonts;
import com.bartlomiejpluta.base.api.context.Context; import com.bartlomiejpluta.base.api.context.Context;
import com.bartlomiejpluta.base.api.gui.Color; import com.bartlomiejpluta.base.api.gui.*;
import com.bartlomiejpluta.base.api.gui.Component;
import com.bartlomiejpluta.base.api.gui.GUI;
import com.bartlomiejpluta.base.api.icon.Icon; import com.bartlomiejpluta.base.api.icon.Icon;
import com.bartlomiejpluta.base.api.input.Key; import com.bartlomiejpluta.base.api.input.Key;
import com.bartlomiejpluta.base.api.input.KeyAction; import com.bartlomiejpluta.base.api.input.KeyAction;
import com.bartlomiejpluta.base.api.input.KeyEvent; import com.bartlomiejpluta.base.api.input.KeyEvent;
import com.bartlomiejpluta.base.api.screen.Screen; import com.bartlomiejpluta.base.api.screen.Screen;
import com.bartlomiejpluta.base.lib.gui.IconView; import com.bartlomiejpluta.base.lib.gui.IconView;
import com.bartlomiejpluta.demo.util.IconUtil;
import com.bartlomiejpluta.demo.world.item.Item; import com.bartlomiejpluta.demo.world.item.Item;
import com.bartlomiejpluta.demo.world.item.ItemStack; import com.bartlomiejpluta.demo.world.item.ItemStack;
import lombok.Getter; import lombok.Getter;
@@ -18,9 +17,10 @@ import lombok.NonNull;
import lombok.Setter; import lombok.Setter;
import java.util.Map; import java.util.Map;
import java.util.function.Consumer; import java.util.function.BiConsumer;
public class ItemIconView extends IconView { public class ItemIconView extends IconView {
private final GUI gui;
private final Color normal; private final Color normal;
private final Color hover; private final Color hover;
private final Color textColor; private final Color textColor;
@@ -28,11 +28,18 @@ public class ItemIconView extends IconView {
@Getter @Getter
private Item item; private Item item;
private IconSet placeholderIconSet;
private Paint placeholderIconPaint;
private int placeholderIconSetRow;
private int placeholderIconSetColumn;
@Setter @Setter
private Consumer<Item> action; private BiConsumer<ItemIconView, Item> action;
public ItemIconView(Context context, GUI gui, Map<String, Component> refs) { public ItemIconView(Context context, GUI gui, Map<String, Component> refs) {
super(context, gui, refs); super(context, gui, refs);
this.gui = gui;
this.normal = gui.createColor(); this.normal = gui.createColor();
this.hover = gui.createColor(); this.hover = gui.createColor();
this.textColor = gui.createColor(); this.textColor = gui.createColor();
@@ -71,10 +78,18 @@ public class ItemIconView extends IconView {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Attribute(value = "placeholder", separator = ",")
public void setPlaceholderIcon(String icon, int row, int column) {
this.placeholderIconPaint = gui.createPaint();
this.placeholderIconSet = gui.getIconSet(A.iconsets.byName(icon).$);
this.placeholderIconSetRow = row;
this.placeholderIconSetColumn = column;
}
private void handleKeyEvent(KeyEvent event) { private void handleKeyEvent(KeyEvent event) {
if (event.getKey() == Key.KEY_ENTER && event.getAction() == KeyAction.PRESS && item != null && action != null) { if (event.getKey() == Key.KEY_ENTER && event.getAction() == KeyAction.PRESS && item != null && action != null) {
event.consume(); event.consume();
action.accept(item); action.accept(this, item);
} }
} }
@@ -96,11 +111,17 @@ public class ItemIconView extends IconView {
gui.fill(); gui.fill();
gui.closePath(); gui.closePath();
if (item == null && placeholderIconSet != null) {
gui.icon(this.x, this.y, 2, 2, 0, 0.2f, placeholderIconSet, placeholderIconSetRow, placeholderIconSetColumn, placeholderIconPaint);
return;
}
super.draw(screen, gui); super.draw(screen, gui);
if (item != null && item instanceof ItemStack stack) { if (item != null && item instanceof ItemStack stack) {
gui.beginPath(); gui.beginPath();
gui.setFontFace(fonts.roboto_regular.uid); gui.setFontFace(fonts.roboto_regular.$);
gui.setFontSize(17); gui.setFontSize(17);
gui.putText(x + 15, y + 5, String.valueOf(stack.getCount())); gui.putText(x + 15, y + 5, String.valueOf(stack.getCount()));
gui.setFillColor(textColor); gui.setFillColor(textColor);

View File

@@ -26,7 +26,7 @@ public class LootWindow extends DecoratedWindow implements Inflatable {
public LootWindow(Context context, GUI gui, Map<String, Component> refs) { public LootWindow(Context context, GUI gui, Map<String, Component> refs) {
super(context, gui, refs); super(context, gui, refs);
this.player = ((DemoRunner) context.getGameRunner()).getPlayer(); this.player = DemoRunner.instance().getPlayer();
} }
@Override @Override
@@ -46,6 +46,8 @@ public class LootWindow extends DecoratedWindow implements Inflatable {
this.loot = (Item[]) args[0]; this.loot = (Item[]) args[0];
this.titleLbl.setText((String) args[1]); this.titleLbl.setText((String) args[1]);
this.lootMenu.select(0, 0);
this.lootMenu.focus();
updateSlots(); updateSlots();
} }
@@ -57,7 +59,7 @@ public class LootWindow extends DecoratedWindow implements Inflatable {
this.loot = null; this.loot = null;
} }
private void handleClick(Item item) { private void handleClick(ItemIconView slot, Item item) {
if (item == null) { if (item == null) {
return; return;
} }
@@ -66,7 +68,7 @@ public class LootWindow extends DecoratedWindow implements Inflatable {
for (int i = 0; i < Enemy.MAX_LOOT; i++) { for (int i = 0; i < Enemy.MAX_LOOT; i++) {
if (loot[i] == item) { if (loot[i] == item) {
loot[i] = null; loot[i] = null;
slots[i].setItem(null); slot.setItem(null);
break; break;
} }
} }

View File

@@ -0,0 +1,49 @@
package com.bartlomiejpluta.demo.gui;
import com.bartlomiejpluta.base.api.context.Context;
import com.bartlomiejpluta.base.api.gui.Component;
import com.bartlomiejpluta.base.api.gui.GUI;
import com.bartlomiejpluta.base.lib.gui.TextView;
import lombok.Setter;
import java.util.Map;
public class PrintTextView extends TextView {
@Setter
private Float duration;
private float acc;
private String originalText;
public void start() {
acc = 0f;
}
public boolean isPrinting() {
return originalText.length() != super.getText().length();
}
public void printAll() {
acc = originalText.length() * duration;
}
@Override
public void setText(String text) {
super.setText("");
this.originalText = text;
}
@Override
public void update(float dt) {
super.update(dt);
acc += dt;
super.setText(originalText.substring(0, Math.min(originalText.length(), (int) (acc / duration))));
}
public PrintTextView(Context context, GUI gui, Map<String, Component> refs) {
super(context, gui, refs);
}
}

View File

@@ -3,22 +3,13 @@ package com.bartlomiejpluta.demo.gui;
import com.bartlomiejpluta.base.api.context.Context; import com.bartlomiejpluta.base.api.context.Context;
import com.bartlomiejpluta.base.api.gui.Component; import com.bartlomiejpluta.base.api.gui.Component;
import com.bartlomiejpluta.base.api.gui.GUI; import com.bartlomiejpluta.base.api.gui.GUI;
import com.bartlomiejpluta.base.api.gui.Inflatable;
import com.bartlomiejpluta.base.api.gui.Ref; import com.bartlomiejpluta.base.api.gui.Ref;
import com.bartlomiejpluta.base.api.gui.WindowManager;
import com.bartlomiejpluta.base.lib.gui.VOptionChoice; import com.bartlomiejpluta.base.lib.gui.VOptionChoice;
import lombok.Getter;
import java.util.Map; import java.util.Map;
public class StartMenuWindow extends DecoratedWindow implements Inflatable { public class StartMenuWindow extends DecoratedWindow {
@Ref("new_game")
@Getter
private Button newGameBtn;
@Ref("exit")
@Getter
private Button exitBtn;
@Ref("menu") @Ref("menu")
private VOptionChoice menu; private VOptionChoice menu;
@@ -28,7 +19,8 @@ public class StartMenuWindow extends DecoratedWindow implements Inflatable {
} }
@Override @Override
public void onInflate() { public void onOpen(WindowManager manager, Object[] args) {
super.onOpen(manager, args);
menu.select(0); menu.select(0);
menu.focus(); menu.focus();
} }

View File

@@ -2,40 +2,53 @@ package com.bartlomiejpluta.demo.map;
import com.bartlomiejpluta.base.api.camera.Camera; import com.bartlomiejpluta.base.api.camera.Camera;
import com.bartlomiejpluta.base.api.context.Context; import com.bartlomiejpluta.base.api.context.Context;
import com.bartlomiejpluta.base.api.entity.Entity;
import com.bartlomiejpluta.base.api.gui.WindowPosition;
import com.bartlomiejpluta.base.api.icon.Icon; import com.bartlomiejpluta.base.api.icon.Icon;
import com.bartlomiejpluta.base.api.input.Input; import com.bartlomiejpluta.base.api.input.Input;
import com.bartlomiejpluta.base.api.input.Key; import com.bartlomiejpluta.base.api.input.Key;
import com.bartlomiejpluta.base.api.light.Light;
import com.bartlomiejpluta.base.api.map.handler.MapHandler; import com.bartlomiejpluta.base.api.map.handler.MapHandler;
import com.bartlomiejpluta.base.api.map.layer.object.ObjectLayer; import com.bartlomiejpluta.base.api.map.layer.object.MapPin;
import com.bartlomiejpluta.base.api.map.model.GameMap; import com.bartlomiejpluta.base.api.map.model.GameMap;
import com.bartlomiejpluta.base.api.move.Direction;
import com.bartlomiejpluta.base.api.screen.Screen; import com.bartlomiejpluta.base.api.screen.Screen;
import com.bartlomiejpluta.base.lib.camera.CameraController; import com.bartlomiejpluta.base.lib.camera.CameraController;
import com.bartlomiejpluta.base.lib.camera.FollowingCameraController; import com.bartlomiejpluta.base.lib.camera.FollowingCameraController;
import com.bartlomiejpluta.base.util.input.InputUtil;
import com.bartlomiejpluta.base.util.world.CharacterSpawner; import com.bartlomiejpluta.base.util.world.CharacterSpawner;
import com.bartlomiejpluta.base.util.world.Warp; import com.bartlomiejpluta.base.util.world.Warp;
import com.bartlomiejpluta.demo.entity.Chest; import com.bartlomiejpluta.demo.entity.*;
import com.bartlomiejpluta.demo.entity.Enemy;
import com.bartlomiejpluta.demo.entity.Player;
import com.bartlomiejpluta.demo.event.EnemyDiedEvent; import com.bartlomiejpluta.demo.event.EnemyDiedEvent;
import com.bartlomiejpluta.demo.menu.GuiManager;
import com.bartlomiejpluta.demo.runner.DemoRunner; import com.bartlomiejpluta.demo.runner.DemoRunner;
import com.bartlomiejpluta.demo.world.light.Torch;
import com.bartlomiejpluta.demo.world.potion.Medicament;
import lombok.NonNull; import lombok.NonNull;
import java.util.concurrent.CompletableFuture;
import static java.lang.Math.*;
public abstract class BaseMapHandler implements MapHandler { public abstract class BaseMapHandler implements MapHandler {
protected Screen screen; protected Screen screen;
protected Context context; protected Context context;
protected DemoRunner runner; protected DemoRunner runner;
protected GuiManager guiManager;
protected Camera camera; protected Camera camera;
protected GameMap map; protected GameMap map;
protected Player player; protected Player player;
protected ObjectLayer mainLayer;
protected CameraController cameraController; protected CameraController cameraController;
protected boolean dayNightCycle = false;
protected boolean controls = true;
@Override @Override
public void onCreate(Context context, GameMap map) { public void onCreate(Context context, GameMap map) {
this.context = context; this.context = context;
this.screen = context.getScreen(); this.screen = context.getScreen();
this.runner = (DemoRunner) context.getGameRunner(); this.runner = DemoRunner.instance();
this.guiManager = runner.getGuiManager();
this.camera = context.getCamera(); this.camera = context.getCamera();
this.map = map; this.map = map;
this.player = runner.getPlayer(); this.player = runner.getPlayer();
@@ -50,7 +63,7 @@ public abstract class BaseMapHandler implements MapHandler {
return; return;
} }
if (runner.openedWindows() > 0) { if (guiManager.openedWindows() > 0) {
return; return;
} }
@@ -62,73 +75,101 @@ public abstract class BaseMapHandler implements MapHandler {
player.interact(); player.interact();
} }
if (input.isKeyPressed(Key.KEY_LEFT_CONTROL)) { if (!controls) {
if (input.isKeyPressed(Key.KEY_DOWN)) { return;
player.setFaceDirection(Direction.DOWN);
} else if (input.isKeyPressed(Key.KEY_UP)) {
player.setFaceDirection(Direction.UP);
} else if (input.isKeyPressed(Key.KEY_LEFT)) {
player.setFaceDirection(Direction.LEFT);
} else if (input.isKeyPressed(Key.KEY_RIGHT)) {
player.setFaceDirection(Direction.RIGHT);
}
} else {
if (input.isKeyPressed(Key.KEY_DOWN)) {
player.getLayer().pushMovement(player.prepareMovement(Direction.DOWN));
} else if (input.isKeyPressed(Key.KEY_UP)) {
player.getLayer().pushMovement(player.prepareMovement(Direction.UP));
} else if (input.isKeyPressed(Key.KEY_LEFT)) {
player.getLayer().pushMovement(player.prepareMovement(Direction.LEFT));
} else if (input.isKeyPressed(Key.KEY_RIGHT)) {
player.getLayer().pushMovement(player.prepareMovement(Direction.RIGHT));
}
} }
InputUtil.handleBasicControl(player, input);
} }
@Override @Override
public void update(Context context, GameMap map, float dt) { public void update(Context context, GameMap map, float dt) {
cameraController.update(); cameraController.update();
if(!dayNightCycle) {
return;
} }
public Enemy enemy(@NonNull String id) { var x = runner.getTime().getProgress();
return new Enemy(id); map.setAmbientColor(
ambientColor(1.2f, -0.3f, 0, x),
ambientColor(1.4f, -0.6f, 0.05f, x),
ambientColor(1.7f, -1.1f, 0.2f, x)
);
} }
public Enemy enemy(ObjectLayer layer, int x, int y, @NonNull String id) { private float ambientColor(float a, float b, float offset, float x) {
var enemy = new Enemy(id); return ((float) max(sin(x * PI * a + b), 0) + offset) / (1 + offset);
enemy.setCoordinates(x, y);
layer.addEntity(enemy);
return enemy;
} }
public Chest chest(ObjectLayer layer, int x, int y, @NonNull String id) { public CompletableFuture<Object> dialog(NamedCharacter speaker, String message, WindowPosition position) {
var chest = new Chest(id); return guiManager.showDialog(speaker.getName(), speaker.getDialogNameColor(), message, position);
chest.setCoordinates(x, y);
layer.addEntity(chest);
return chest;
} }
public CharacterSpawner spawner(ObjectLayer layer, int x, int y) { public CompletableFuture<Object> dialog(NamedCharacter speaker, String message) {
var spawner = new CharacterSpawner().trackEntities(EnemyDiedEvent.TYPE); return guiManager.showDialog(speaker.getName(), speaker.getDialogNameColor(), message, WindowPosition.BOTTOM);
spawner.setCoordinates(x, y);
layer.addEntity(spawner);
return spawner;
} }
public Icon icon(ObjectLayer layer, int x, int y, String iconSetUid, int row, int column) { public CompletableFuture<Integer> dialogChoice(NamedCharacter speaker, String... choices) {
return guiManager.showDialogChoice(speaker.getName(), speaker.getDialogNameColor(), choices);
}
protected <T extends Entity> T addEntity(T entity, MapPin tile) {
entity.setCoordinates(tile.getX(), tile.getY());
map.getObjectLayer(tile.getLayer()).addEntity(entity);
return entity;
}
public Enemy enemy(@NonNull MapPin tile, @NonNull String id) {
return addEntity(new Enemy(id), tile);
}
public Friend friend(@NonNull MapPin tile, @NonNull String id) {
return addEntity(new Friend(id), tile);
}
public Chest chest(@NonNull MapPin tile, @NonNull String id) {
return addEntity(new Chest(id), tile);
}
public Door door(@NonNull MapPin tile, @NonNull MapPin target, @NonNull String id) {
return addEntity(new Door(target, id), tile);
}
public CharacterSpawner spawner(@NonNull MapPin tile) {
return addEntity(new CharacterSpawner().trackEntities(EnemyDiedEvent.TYPE), tile);
}
public Medicament medicament(@NonNull MapPin tile, @NonNull String id, int count) {
return addEntity(new Medicament(id, count), tile);
}
public Icon icon(@NonNull MapPin tile, String iconSetUid, int row, int column) {
var icon = context.createIcon(iconSetUid, row, column); var icon = context.createIcon(iconSetUid, row, column);
icon.setScale(1f); icon.setScale(1f);
icon.setZIndex(-1); icon.setZIndex(-1);
icon.setCoordinates(x, y); return addEntity(icon, tile);
layer.addEntity(icon);
return icon;
} }
public Warp warp(ObjectLayer layer, int x, int y, String targetMap, String targetLayer, int targetX, int targetY) { public Torch torch(MapPin tile) {
var warp = new Warp(A.maps.get(targetMap).uid, A.maps.getLayer(targetMap, targetLayer), targetX, targetY); var torch = new Torch();
map.getLayer(tile.getLayer()).addLight(torch);
torch.setCoordinates(tile.toCoordinates());
return torch;
}
public Light light(MapPin tile) {
var light = context.createLight();
map.getLayer(tile.getLayer()).addLight(light);
light.setCoordinates(tile.toCoordinates());
light.setIntensity(1f, 1f, 1f);
light.setAttenuation(0.1f, 0, 0.001f);
return light;
}
public Warp warp(@NonNull MapPin tile, MapPin target) {
var warp = new Warp(target);
warp.setEntity(player); warp.setEntity(player);
warp.setCoordinates(x, y); return addEntity(warp, tile);
layer.addEntity(warp);
return warp;
} }
} }

View File

@@ -1,5 +1,12 @@
package com.bartlomiejpluta.demo.map; package com.bartlomiejpluta.demo.map;
public class ForrestHandler extends BaseMapHandler { import com.bartlomiejpluta.base.api.context.Context;
import com.bartlomiejpluta.base.api.map.model.GameMap;
public class ForrestHandler extends BaseMapHandler {
@Override
public void onCreate(Context context, GameMap map) {
super.onCreate(context, map);
dayNightCycle = true;
}
} }

View File

@@ -1,17 +0,0 @@
package com.bartlomiejpluta.demo.map;
import com.bartlomiejpluta.base.api.context.Context;
import com.bartlomiejpluta.base.api.map.model.GameMap;
public class ForrestTempleHandler extends BaseMapHandler {
public static final String UID = "f845355e-b9ad-4884-a217-dd3a4c18a3fa";
public static final A.maps.GameMapAsset_Layers_ForrestTemple LAYERS = A.maps.forrest_temple.layers;
public static final int MAIN_LAYER = 4;
@Override
public void onCreate(Context context, GameMap map) {
super.onCreate(context, map);
this.mainLayer = map.getObjectLayer(MAIN_LAYER);
}
}

View File

@@ -0,0 +1,81 @@
package com.bartlomiejpluta.demo.map;
import A.animations;
import A.maps;
import com.bartlomiejpluta.base.api.context.Context;
import com.bartlomiejpluta.base.api.map.model.GameMap;
import com.bartlomiejpluta.base.util.path.CharacterPath;
import com.bartlomiejpluta.base.util.pathfinder.AstarPathFinder;
import com.bartlomiejpluta.base.util.pathfinder.PathFinder;
import com.bartlomiejpluta.demo.entity.Friend;
import java.util.concurrent.CompletableFuture;
import static com.bartlomiejpluta.base.api.move.Direction.LEFT;
public class HeroHomeHandler extends BaseMapHandler {
private final PathFinder finder = new AstarPathFinder(100);
@Override
public void onCreate(Context context, GameMap map) {
super.onCreate(context, map);
map.setAmbientColor(0.05f, 0.01f, 0.01f);
}
protected CharacterPath<Friend> grandmaPath(Friend grandma) {
return new CharacterPath<Friend>()
.run(() -> controls = false)
.run(() -> player.runEmoji(A.animations.zzz.$, r -> r.repeat(5)))
.insertPath(finder.findPath(grandma.getLayer(), grandma, maps.hero_home.main.grandma_waking.toCoordinates()))
.wait(2f)
.turn(LEFT)
.wait(1f)
.suspend(() -> morningDialogWithGrandma(grandma))
.wait(1f)
.run(() -> controls = true)
.insertPath(finder.findPath(grandma.getLayer(), maps.hero_home.main.grandma_waking.toCoordinates(), maps.hero_home.main.grandma_origin.toCoordinates()))
.run(() -> grandma.randomMovementAI(4f, grandma.getCoordinates(), 4));
}
private CompletableFuture<Object> morningDialogWithGrandma(Friend grandma) {
return dialog(grandma, "Hello Honey, wake up, it's another beautiful day!")
.thenCompose(n -> dialog(player, "Ahhh, good morning Grandma!"))
.thenCompose(n -> dialog(grandma, "Have a wonderful day, Luna!"))
.thenCompose(n -> dialog(player, "Thank you Grandma, have a nice day too!"));
}
protected CompletableFuture<Object> triggerGrandmaDialog(Friend grandma) {
return dialog(grandma, "What are you going to do today, Luna?")
.thenCompose(n -> dialogChoice(player,
"I'm going to fix your roof, Grandma",
"I'd like to look for some hidden treasure around your house",
"I'm going to kill the Dekus outside",
"Hmm... I don't know yet..."
)).thenCompose(o -> dialog(grandma, switch (o) {
case 0 -> "Ohh, Luna! It would be amazing, thank you!";
case 1 -> "It seems you are going to have a wonderful adventure. Good luck!";
case 2 -> "Be careful! Dekus are capable to attack from a distance!";
case 3 -> "Hmm... our roof requires urgent fix... also there are some dangerous Dekus around our house...";
default -> null;
}).thenApply(n -> o))
.thenCompose(o -> dialog(player, switch (o) {
case 0 -> "You're welcome Grandma!";
case 1 -> "Thank you Grandma! Hopefully will found something interesting...";
case 2 -> "Oh, thanks. I believe I also would need to have some ranged weapon...";
case 3 -> "Okay, there is lot of things to be done then.";
default -> null;
}))
.thenCompose(n -> dialog(player, "Okay, I need to go. Thank you Grandma!"))
.thenCompose(n -> dialog(grandma, "Thank you Luna! Be careful!"));
}
protected CompletableFuture<Object> triggerNekoDialog(Friend neko) {
return dialog(player, "Ohhh, here you are Kitty...")
.thenCompose(n -> CompletableFuture.allOf(
player.runEmoji(animations.heart_emoji.$),
neko.runEmoji(animations.heart_emoji.$, r -> r.offset(0, -15).delay(100))
))
.thenCompose(n -> dialog(neko, "Meow, meow..."))
.thenCompose(n -> dialog(neko, "Purr, purr..."));
}
}

View File

@@ -0,0 +1,12 @@
package com.bartlomiejpluta.demo.map;
import com.bartlomiejpluta.base.api.context.Context;
import com.bartlomiejpluta.base.api.map.model.GameMap;
public class HeroHouse extends BaseMapHandler {
@Override
public void onCreate(Context context, GameMap map) {
super.onCreate(context, map);
dayNightCycle = true;
}
}

View File

@@ -2,25 +2,20 @@ package com.bartlomiejpluta.demo.menu;
import A.widgets; import A.widgets;
import com.bartlomiejpluta.base.api.context.Context; import com.bartlomiejpluta.base.api.context.Context;
import com.bartlomiejpluta.base.api.gui.DisplayMode; import com.bartlomiejpluta.base.api.gui.*;
import com.bartlomiejpluta.base.api.gui.GUI;
import com.bartlomiejpluta.base.api.gui.UpdateMode;
import com.bartlomiejpluta.base.api.gui.WindowManager;
import com.bartlomiejpluta.base.api.input.Key; import com.bartlomiejpluta.base.api.input.Key;
import com.bartlomiejpluta.base.api.input.KeyAction; import com.bartlomiejpluta.base.api.input.KeyAction;
import com.bartlomiejpluta.base.api.input.KeyEvent; import com.bartlomiejpluta.base.api.input.KeyEvent;
import com.bartlomiejpluta.demo.entity.Chest; import com.bartlomiejpluta.demo.entity.Chest;
import com.bartlomiejpluta.demo.entity.Enemy; import com.bartlomiejpluta.demo.entity.Enemy;
import com.bartlomiejpluta.demo.gui.EquipmentWindow; import com.bartlomiejpluta.demo.gui.*;
import com.bartlomiejpluta.demo.gui.GameMenuWindow;
import com.bartlomiejpluta.demo.gui.LootWindow;
import com.bartlomiejpluta.demo.gui.StartMenuWindow;
import com.bartlomiejpluta.demo.runner.DemoRunner; import com.bartlomiejpluta.demo.runner.DemoRunner;
import lombok.NonNull; import lombok.NonNull;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer; import java.util.function.Consumer;
public class MenuManager { public class GuiManager {
private final DemoRunner runner; private final DemoRunner runner;
private final Context context; private final Context context;
private final GUI gui; private final GUI gui;
@@ -30,9 +25,11 @@ public class MenuManager {
private final GameMenuWindow gameMenu; private final GameMenuWindow gameMenu;
private final EquipmentWindow equipment; private final EquipmentWindow equipment;
private final LootWindow loot; private final LootWindow loot;
private final DialogWindow dialog;
private final DialogChoiceWindow dialogChoice;
private final Consumer<KeyEvent> gameMenuHandler = this::handleGameMenuKeyEvent; private final Consumer<KeyEvent> gameMenuHandler = this::handleGameMenuKeyEvent;
public MenuManager(@NonNull DemoRunner runner, @NonNull Context context) { public GuiManager(@NonNull DemoRunner runner, @NonNull Context context) {
this.runner = runner; this.runner = runner;
this.context = context; this.context = context;
this.gui = context.newGUI(); this.gui = context.newGUI();
@@ -40,17 +37,21 @@ public class MenuManager {
this.gui.setRoot(this.manager); this.gui.setRoot(this.manager);
this.startMenu = gui.inflateWindow(A.widgets.start_menu.uid, StartMenuWindow.class); this.startMenu = gui.inflateWindow(A.widgets.start_menu.$, StartMenuWindow.class);
this.startMenu.getNewGameBtn().setAction(runner::newGame); this.startMenu.reference("new_game", Button.class).setAction(runner::newGame);
this.startMenu.getExitBtn().setAction(runner::exit); this.startMenu.reference("exit", Button.class).setAction(runner::exit);
this.gameMenu = gui.inflateWindow(A.widgets.game_menu.uid, GameMenuWindow.class); this.equipment = gui.inflateWindow(A.widgets.equipment.$, EquipmentWindow.class);
this.gameMenu.getResumeGameBtn().setAction(this::resumeGame);
this.gameMenu.getStartMenuBtn().setAction(runner::returnToStartMenu);
this.gameMenu.getExitBtn().setAction(runner::exit);
this.equipment = gui.inflateWindow(A.widgets.equipment.uid, EquipmentWindow.class); this.gameMenu = gui.inflateWindow(A.widgets.game_menu.$, GameMenuWindow.class);
this.loot = gui.inflateWindow(widgets.loot_menu.uid, LootWindow.class); this.gameMenu.reference("resume_game", Button.class).setAction(this::resumeGame);
this.gameMenu.reference("equipment", Button.class).setAction(() -> manager.open(equipment));
this.gameMenu.reference("start_menu", Button.class).setAction(runner::returnToStartMenu);
this.gameMenu.reference("exit", Button.class).setAction(runner::exit);
this.dialog = gui.inflateWindow(A.widgets.dialog.$, DialogWindow.class);
this.dialogChoice = gui.inflateWindow(A.widgets.dialog_choice.$, DialogChoiceWindow.class);
this.loot = gui.inflateWindow(widgets.loot_menu.$, LootWindow.class);
} }
private void handleGameMenuKeyEvent(KeyEvent event) { private void handleGameMenuKeyEvent(KeyEvent event) {
@@ -69,11 +70,10 @@ public class MenuManager {
manager.close(); manager.close();
} else { } else {
manager.open(gameMenu); manager.open(gameMenu);
context.pause();
} }
if (manager.size() > 0) { if (manager.isEmpty()) {
context.pause();
} else {
context.resume(); context.resume();
} }
@@ -85,9 +85,9 @@ public class MenuManager {
return manager.size(); return manager.size();
} }
public void showStartMenu() { public CompletableFuture<Object> showStartMenu() {
manager.closeAll(); manager.closeAll();
manager.open(startMenu); return manager.open(startMenu);
} }
public void enableGameMenu() { public void enableGameMenu() {
@@ -102,16 +102,24 @@ public class MenuManager {
manager.setDisplayMode(DisplayMode.DISPLAY_TOP); manager.setDisplayMode(DisplayMode.DISPLAY_TOP);
} }
public void openLootWindow(@NonNull Enemy enemy) { public CompletableFuture<Object> showDialog(@NonNull String speaker, int color, @NonNull String message, @NonNull WindowPosition position) {
manager.closeAll(); return manager.open(dialog, speaker, color, message, position);
manager.open(loot, enemy.getLoot(), "Loot");
} }
public void openChestWindow(@NonNull Chest chest) { public CompletableFuture<Integer> showDialogChoice(@NonNull String speaker, int color, @NonNull String... choices) {
manager.closeAll(); return manager.openForResult(Integer.class, dialogChoice, speaker, color, choices);
}
manager.open(loot, chest.getContent(), chest.getName()); public CompletableFuture<Object> openLootWindow(@NonNull Enemy enemy) {
return manager.open(loot, enemy.getLoot(), "Loot");
}
public CompletableFuture<Object> openChestWindow(@NonNull Chest chest) {
return manager.open(loot, chest.getContent(), chest.getName());
}
public CompletableFuture<Object> openGameMenu() {
return manager.open(gameMenu);
} }
public void closeAll() { public void closeAll() {

View File

@@ -1,15 +1,14 @@
package com.bartlomiejpluta.demo.runner; package com.bartlomiejpluta.demo.runner;
import DB.dao;
import com.bartlomiejpluta.base.api.context.Context; import com.bartlomiejpluta.base.api.context.Context;
import com.bartlomiejpluta.base.api.gui.GUI; import com.bartlomiejpluta.base.api.gui.GUI;
import com.bartlomiejpluta.base.api.runner.GameRunner; import com.bartlomiejpluta.base.api.runner.GameRunner;
import com.bartlomiejpluta.base.api.screen.Screen; import com.bartlomiejpluta.base.api.screen.Screen;
import com.bartlomiejpluta.base.util.profiler.FPSProfiler;
import com.bartlomiejpluta.demo.entity.Chest;
import com.bartlomiejpluta.demo.entity.Enemy;
import com.bartlomiejpluta.demo.entity.Player; import com.bartlomiejpluta.demo.entity.Player;
import com.bartlomiejpluta.demo.menu.MenuManager; import com.bartlomiejpluta.demo.menu.GuiManager;
import com.bartlomiejpluta.demo.world.weapon.RangedWeapon; import com.bartlomiejpluta.demo.world.time.WorldTime;
import lombok.Getter; import lombok.Getter;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -17,18 +16,99 @@ import org.slf4j.LoggerFactory;
public class DemoRunner implements GameRunner { public class DemoRunner implements GameRunner {
private static final Logger log = LoggerFactory.getLogger(DemoRunner.class); private static final Logger log = LoggerFactory.getLogger(DemoRunner.class);
private final FPSProfiler fpsProfiler = FPSProfiler.create(20);
@Getter
private WorldTime time;
private static DemoRunner INSTANCE;
private Screen screen; private Screen screen;
private Context context; private Context context;
private MenuManager menu;
private GUI hud; private GUI hud;
@Getter
private GuiManager guiManager;
@Getter @Getter
private Player player; private Player player;
public static DemoRunner instance() {
return INSTANCE;
}
private void configureScreen() {
var resolution = screen.getCurrentResolution();
var config = dao.config.find("screen").getValue().split("x");
var width = Integer.parseInt(config[0]);
var height = Integer.parseInt(config[1]);
screen.setSize(width, height);
screen.setPosition((resolution.x() - width) / 2, (resolution.y() - height) / 2);
}
private void configureCamera() {
context.getCamera().setScale(Float.parseFloat(dao.config.find("camera_scale").getValue()));
}
private void initMenu() {
this.guiManager = new GuiManager(this, context);
}
private void initHUD() {
hud = context.newGUI();
hud.hide();
var hudComponent = hud.inflateComponent(A.widgets.hud.$);
hud.setRoot(hudComponent);
}
private void initPlayer() {
this.player = new Player(context.createCharacter(A.charsets.luna.$));
}
public void newGame() {
context.resetMaps();
guiManager.closeAll();
guiManager.enableGameMenu();
player.reset();
var start = dao.config.find("start_game").getValue().split(",");
var map = A.maps.byName(start[0]);
var layer = map.layer(start[1]);
var label = layer.label(start[2]);
time.setTime(dao.config.find("initial_time").getValue());
context.openMap(map.$);
context.getMap().getObjectLayer(layer.$).addEntity(this.player);
player.setCoordinates(label.getX(), label.getY());
context.resume();
hud.show();
}
public void returnToStartMenu() {
guiManager.closeAll();
hud.hide();
context.pause();
context.closeMap();
guiManager.disableGameMenu();
guiManager.showStartMenu();
}
public void exit() {
context.close();
}
@Override
public void dispose() {
// Do something after game loop is end
}
@Override @Override
public void init(Context context) { public void init(Context context) {
DemoRunner.INSTANCE = this;
this.context = context; this.context = context;
this.screen = context.getScreen(); this.screen = context.getScreen();
this.time = new WorldTime(context);
configureScreen(); configureScreen();
configureCamera(); configureCamera();
@@ -36,91 +116,13 @@ public class DemoRunner implements GameRunner {
initHUD(); initHUD();
initMenu(); initMenu();
menu.showStartMenu(); guiManager.showStartMenu();
screen.show(); screen.show();
} }
private void configureScreen() {
var resolution = screen.getCurrentResolution();
screen.setSize(1800, 1000);
screen.setPosition((resolution.x() - 1800) / 2, (resolution.y() - 1000) / 2);
}
private void configureCamera() {
context.getCamera().setScale(2f);
}
private void initMenu() {
this.menu = new MenuManager(this, context);
}
public int openedWindows() {
return this.menu.openedWindows();
}
private void initHUD() {
hud = context.newGUI();
hud.hide();
var hudComponent = hud.inflateComponent(A.widgets.hud.uid);
hud.setRoot(hudComponent);
}
private void initPlayer() {
this.player = new Player(context.createCharacter(A.charsets.luna.uid));
}
private void resetPlayer() {
this.player.changeCharacterSet(A.charsets.luna.uid);
this.player.setScale(1f);
this.player.setSpeed(4f);
this.player.setAnimationSpeed(1f);
this.player.setBlocking(true);
}
public void newGame() {
menu.closeAll();
menu.enableGameMenu();
resetPlayer();
context.openMap(A.maps.forrest.uid);
context.getMap().getObjectLayer(A.maps.forrest.layers.main).addEntity(this.player);
player.setCoordinates(5, 36);
context.resume();
hud.show();
}
public void returnToStartMenu() {
menu.closeAll();
hud.hide();
context.pause();
context.closeMap();
menu.disableGameMenu();
menu.showStartMenu();
}
public void openLootWindow(Enemy enemy) {
menu.openLootWindow(enemy);
}
public void openChestWindow(Chest chest) {
menu.openChestWindow(chest);
}
public void exit() {
context.close();
}
public double instantFPS() {
return fpsProfiler.getInstantFPS();
}
@Override @Override
public void update(float dt) { public void update(float dt) {
fpsProfiler.update(dt); time.update(dt);
}
@Override
public void dispose() {
// Do something after game loop is end
} }
} }

View File

@@ -0,0 +1,11 @@
package com.bartlomiejpluta.demo.util;
import com.bartlomiejpluta.base.api.context.ContextHolder;
import com.bartlomiejpluta.base.api.icon.Icon;
public class IconUtil {
public static Icon parseIcon(String iconDefinition) {
var parts = iconDefinition.split(",");
return ContextHolder.INSTANCE.getContext().createIcon(A.iconsets.byName(parts[0]).$, Integer.parseInt(parts[1]), Integer.parseInt(parts[2]));
}
}

View File

@@ -0,0 +1,67 @@
package com.bartlomiejpluta.demo.util;
import DB.EnemyDropDAO;
import DB.dao;
import com.bartlomiejpluta.base.lib.db.Relop;
import com.bartlomiejpluta.demo.world.item.Item;
import com.bartlomiejpluta.demo.world.item.ItemStack;
import com.bartlomiejpluta.demo.world.junk.Junk;
import com.bartlomiejpluta.demo.world.potion.Medicament;
import com.bartlomiejpluta.demo.world.weapon.Ammunition;
import com.bartlomiejpluta.demo.world.weapon.MeleeWeapon;
import com.bartlomiejpluta.demo.world.weapon.RangedWeapon;
import com.bartlomiejpluta.demo.world.weapon.ThrowingWeapon;
import lombok.NonNull;
import java.util.Map;
import java.util.Random;
import java.util.function.BiFunction;
import java.util.function.Function;
import static com.bartlomiejpluta.base.util.random.DiceRoller.roll;
import static com.bartlomiejpluta.demo.util.ListUtil.randomIntSequence;
public class LootGenerator {
private static final Random rand = new Random();
private static final Map<String, Function<String, Item>> itemGenerators = Map.of(
"melee", MeleeWeapon::new,
"ranged", RangedWeapon::new,
"junk", Junk::new
);
private static final Map<String, BiFunction<String, Integer, ItemStack>> stackableGenerator = Map.of(
"ammo", Ammunition::new,
"throwing", ThrowingWeapon::new,
"med", Medicament::new
);
public static void generate(@NonNull String enemy, @NonNull Item[] loot) {
var def = dao.enemy_drop.query()
.where(EnemyDropDAO.Column.ENEMY, Relop.EQ, enemy)
.orderBy("rand()")
.find();
var index = randomIntSequence(0, loot.length).iterator();
for (var template : def) {
var parts = template.getItem().split(":");
var item = itemGenerators.get(parts[0]);
if (item != null) {
for (int i = 0; i < roll(template.getAmount()) && index.hasNext(); ++i) {
if (rand.nextFloat() <= template.getChance()) {
loot[index.next()] = item.apply(parts[1]);
}
}
continue;
}
var stack = stackableGenerator.get(parts[0]);
if (stack != null && index.hasNext()) {
if (rand.nextFloat() <= template.getChance()) {
loot[index.next()] = stack.apply(parts[1], roll(template.getAmount()));
}
}
}
}
}

View File

@@ -0,0 +1,12 @@
package com.bartlomiejpluta.demo.world.item;
import com.bartlomiejpluta.base.lib.icon.IconDelegate;
import com.bartlomiejpluta.demo.util.IconUtil;
import lombok.NonNull;
public abstract class BaseItem extends IconDelegate implements Item {
protected BaseItem(@NonNull String icon) {
super(IconUtil.parseIcon(icon));
setZIndex(-1);
}
}

View File

@@ -1,6 +1,8 @@
package com.bartlomiejpluta.demo.world.item; package com.bartlomiejpluta.demo.world.item;
public interface ItemStack extends Item { public interface ItemStack extends Item {
String getId();
int getCount(); int getCount();
void setCount(int count); void setCount(int count);

View File

@@ -0,0 +1,38 @@
package com.bartlomiejpluta.demo.world.item;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
public abstract class StackableItem extends BaseItem implements ItemStack {
@Getter
@Setter
protected int count;
protected StackableItem(@NonNull String id, int count) {
super(id);
this.count = Math.max(0, count);
}
@Override
public void decrease() {
if (count > 0) {
--count;
}
}
@Override
public void increase() {
++count;
}
@Override
public void increase(int count) {
this.count += count;
}
@Override
public void decrease(int count) {
this.count = Math.max(0, count);
}
}

View File

@@ -0,0 +1,18 @@
package com.bartlomiejpluta.demo.world.item;
import com.bartlomiejpluta.demo.entity.Creature;
import lombok.NonNull;
public abstract class UseableStackableItem extends StackableItem implements Useable {
protected UseableStackableItem(@NonNull String id, int count) {
super(id, count);
}
@Override
public void use(Creature creature) {
if (--count == 0) {
creature.removeItemFromEquipment(this);
}
}
}

View File

@@ -1,13 +1,10 @@
package com.bartlomiejpluta.demo.world.junk; package com.bartlomiejpluta.demo.world.junk;
import com.bartlomiejpluta.base.api.context.ContextHolder; import com.bartlomiejpluta.demo.world.item.BaseItem;
import com.bartlomiejpluta.base.api.icon.Icon;
import com.bartlomiejpluta.base.lib.icon.IconDelegate;
import com.bartlomiejpluta.demo.world.item.Item;
import lombok.Getter; import lombok.Getter;
import lombok.NonNull; import lombok.NonNull;
public class Junk extends IconDelegate implements Item { public class Junk extends BaseItem {
@Getter @Getter
private final String name; private final String name;
@@ -17,12 +14,7 @@ public class Junk extends IconDelegate implements Item {
} }
public Junk(@NonNull DB.model.JunkModel template) { public Junk(@NonNull DB.model.JunkModel template) {
super(createIcon(template)); super(template.getIcon());
this.name = template.getName(); this.name = template.getName();
} }
private static Icon createIcon(DB.model.JunkModel template) {
var icons = template.getIcon().split(",");
return ContextHolder.INSTANCE.getContext().createIcon(A.iconsets.get(icons[0]).uid, Integer.parseInt(icons[1]), Integer.parseInt(icons[2]));
}
} }

View File

@@ -0,0 +1,29 @@
package com.bartlomiejpluta.demo.world.light;
import com.bartlomiejpluta.base.api.context.ContextHolder;
import com.bartlomiejpluta.base.lib.light.LightDelegate;
import java.util.Random;
public class Torch extends LightDelegate {
private final Random random = new Random();
private float acc = 0;
public Torch() {
super(ContextHolder.INSTANCE.getContext().createLight());
setIntensity(100f, 50f, 0f);
setConstantAttenuation(1f);
}
@Override
public void update(float dt) {
super.update(dt);
if (acc > 0.1f) {
setQuadraticAttenuation(0.1f * (1f + ((float) random.nextGaussian()) * 0.1f));
acc = 0;
}
acc += dt;
}
}

View File

@@ -0,0 +1,39 @@
package com.bartlomiejpluta.demo.world.potion;
import DB.dao;
import com.bartlomiejpluta.base.util.random.DiceRoller;
import com.bartlomiejpluta.demo.entity.Creature;
import com.bartlomiejpluta.demo.world.item.Useable;
import com.bartlomiejpluta.demo.world.item.UseableStackableItem;
import lombok.Getter;
import lombok.NonNull;
import static java.lang.String.format;
public class Medicament extends UseableStackableItem implements Useable {
@Getter
private final String id;
@Getter
private final String name;
@Getter
private final DiceRoller roller;
public Medicament(@NonNull String id, int count) {
this(dao.medicaments.find(id), count);
}
public Medicament(@NonNull DB.model.MedicamentsModel template, int count) {
super(template.getIcon(), count);
this.name = template.getName();
this.roller = DiceRoller.of(template.getHp());
this.id = format("med:%s", template.getId());
}
@Override
public void use(Creature creature) {
super.use(creature);
creature.heal(roller.roll());
}
}

View File

@@ -0,0 +1,56 @@
package com.bartlomiejpluta.demo.world.time;
import DB.dao;
import com.bartlomiejpluta.base.api.context.Context;
import lombok.Getter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import static java.lang.Math.max;
import static java.lang.Math.min;
public class WorldTime {
private static final float MINUTES_PER_DAY = 1440f; // 60min * 24
@Getter
private float progress = 0;
private final float period; // seconds
private final Context context;
public WorldTime(@NonNull Context context) {
this.context = context;
this.period = Float.parseFloat(dao.config.find("full_day_duration").getValue());
}
public void setProgress(float progress) {
this.progress = max(0, min(1, progress));
}
public void setTime(@NonNull String time) {
var splitted = time.split(":");
this.setTime(Integer.valueOf(splitted[0], 10), Integer.valueOf(splitted[1], 10));
}
public void setTime(int h, int m) {
this.progress = (h * 60 + m) / MINUTES_PER_DAY;
}
public int getHour() {
return (int) (progress * 24);
}
public int getMinute() {
return (int) (progress * 24 * 60) % 60;
}
public void update(float dt) {
if (context.isPaused()) {
return;
}
progress += dt / period;
if (progress > 1) {
progress = 0;
}
}
}

View File

@@ -1,26 +1,20 @@
package com.bartlomiejpluta.demo.world.weapon; package com.bartlomiejpluta.demo.world.weapon;
import com.bartlomiejpluta.base.api.context.ContextHolder;
import com.bartlomiejpluta.base.api.icon.Icon;
import com.bartlomiejpluta.base.lib.icon.IconDelegate;
import com.bartlomiejpluta.demo.entity.Creature; import com.bartlomiejpluta.demo.entity.Creature;
import com.bartlomiejpluta.demo.world.item.ItemStack; import com.bartlomiejpluta.demo.world.item.StackableItem;
import com.bartlomiejpluta.demo.world.item.Useable; import com.bartlomiejpluta.demo.world.item.Useable;
import lombok.Getter; import lombok.Getter;
import lombok.NonNull; import lombok.NonNull;
import lombok.Setter;
import lombok.ToString; import lombok.ToString;
import static java.lang.String.format;
@ToString @ToString
public class Ammunition extends IconDelegate implements ItemStack, Useable { public class Ammunition extends StackableItem implements Useable {
@Getter @Getter
private final String id; private final String id;
@Getter
@Setter
private int count;
@Getter @Getter
private final String name; private final String name;
@@ -32,39 +26,13 @@ public class Ammunition extends IconDelegate implements ItemStack, Useable {
} }
public Ammunition(@NonNull DB.model.AmmunitionModel template, int count) { public Ammunition(@NonNull DB.model.AmmunitionModel template, int count) {
super(createIcon(template)); super(template.getIcon(), count);
this.id = template.getId();
this.id = format("ammo:%s", template.getId());
this.name = template.getName(); this.name = template.getName();
this.count = count;
this.appliesTo = template.getAppliesTo(); this.appliesTo = template.getAppliesTo();
} }
private static Icon createIcon(DB.model.AmmunitionModel template) {
var icons = template.getIcon().split(",");
return ContextHolder.INSTANCE.getContext().createIcon(A.iconsets.get(icons[0]).uid, Integer.parseInt(icons[1]), Integer.parseInt(icons[2]));
}
@Override
public void decrease() {
if (count > 0) {
--count;
}
}
@Override
public void increase() {
++count;
}
@Override
public void increase(int count) {
this.count += count;
}
@Override
public void decrease(int count) {
this.count = Math.max(0, count);
}
@Override @Override
public void use(Creature creature) { public void use(Creature creature) {
@@ -73,6 +41,6 @@ public class Ammunition extends IconDelegate implements ItemStack, Useable {
@Override @Override
public String usageName() { public String usageName() {
return "Equip"; return "Arm";
} }
} }

View File

@@ -2,18 +2,17 @@ package com.bartlomiejpluta.demo.world.weapon;
import com.bartlomiejpluta.base.api.context.Context; import com.bartlomiejpluta.base.api.context.Context;
import com.bartlomiejpluta.base.api.context.ContextHolder; import com.bartlomiejpluta.base.api.context.ContextHolder;
import com.bartlomiejpluta.base.api.icon.Icon;
import com.bartlomiejpluta.base.lib.animation.AnimationRunner; import com.bartlomiejpluta.base.lib.animation.AnimationRunner;
import com.bartlomiejpluta.base.lib.animation.RandomAnimationsRunner; import com.bartlomiejpluta.base.lib.animation.RandomAnimationsRunner;
import com.bartlomiejpluta.base.lib.icon.IconDelegate;
import com.bartlomiejpluta.base.util.random.DiceRoller; import com.bartlomiejpluta.base.util.random.DiceRoller;
import com.bartlomiejpluta.demo.entity.Creature; import com.bartlomiejpluta.demo.entity.Creature;
import com.bartlomiejpluta.demo.event.HitEvent; import com.bartlomiejpluta.demo.event.HitEvent;
import com.bartlomiejpluta.demo.world.item.BaseItem;
import lombok.Getter; import lombok.Getter;
import lombok.NonNull; import lombok.NonNull;
import org.joml.Vector2i; import org.joml.Vector2i;
public class MeleeWeapon extends IconDelegate implements Weapon { public class MeleeWeapon extends BaseItem implements Weapon {
private final Context context; private final Context context;
private final AnimationRunner animation; private final AnimationRunner animation;
private final String sound; private final String sound;
@@ -32,14 +31,14 @@ public class MeleeWeapon extends IconDelegate implements Weapon {
} }
public MeleeWeapon(@NonNull DB.model.MeleeWeaponModel template) { public MeleeWeapon(@NonNull DB.model.MeleeWeaponModel template) {
super(createIcon(template)); super(template.getIcon());
this.context = ContextHolder.INSTANCE.getContext(); this.context = ContextHolder.INSTANCE.getContext();
this.name = template.getName(); this.name = template.getName();
this.dmgRoller = DiceRoller.of(template.getDamage()); this.dmgRoller = DiceRoller.of(template.getDamage());
this.cooldown = template.getCooldown(); this.cooldown = template.getCooldown();
this.animation = new RandomAnimationsRunner(2).nRange(0, 2f).nScale(0.2f, 0.15f).uAnimationSpeed(0.5f, 1f).nRotation(0, 10).offset(0, -10).uDelay(250, 500).with(A.animations.get(template.getAnimation()).uid); this.animation = new RandomAnimationsRunner(2).nRange(0, 2f).nScale(0.2f, 0.15f).uAnimationSpeed(0.5f, 1f).nRotation(0, 10).offset(0, -10).uDelay(250, 500).with(A.animations.byName(template.getAnimation()).$);
this.sound = A.sounds.get(template.getSound()).uid; this.sound = A.sounds.byName(template.getSound()).$;
} }
@Override @Override
@@ -66,11 +65,6 @@ public class MeleeWeapon extends IconDelegate implements Weapon {
@Override @Override
public String usageName() { public String usageName() {
return "Equip"; return "Arm";
}
private static Icon createIcon(DB.model.MeleeWeaponModel template) {
var icons = template.getIcon().split(",");
return ContextHolder.INSTANCE.getContext().createIcon(A.iconsets.get(icons[0]).uid, Integer.parseInt(icons[1]), Integer.parseInt(icons[2]));
} }
} }

View File

@@ -4,19 +4,18 @@ import com.bartlomiejpluta.base.api.animation.Animation;
import com.bartlomiejpluta.base.api.context.Context; import com.bartlomiejpluta.base.api.context.Context;
import com.bartlomiejpluta.base.api.context.ContextHolder; import com.bartlomiejpluta.base.api.context.ContextHolder;
import com.bartlomiejpluta.base.api.entity.Entity; import com.bartlomiejpluta.base.api.entity.Entity;
import com.bartlomiejpluta.base.api.icon.Icon;
import com.bartlomiejpluta.base.api.move.Movable; import com.bartlomiejpluta.base.api.move.Movable;
import com.bartlomiejpluta.base.lib.animation.AnimationRunner; import com.bartlomiejpluta.base.lib.animation.AnimationRunner;
import com.bartlomiejpluta.base.lib.animation.BulletAnimationRunner; import com.bartlomiejpluta.base.lib.animation.BulletAnimationRunner;
import com.bartlomiejpluta.base.lib.animation.SimpleAnimationRunner; import com.bartlomiejpluta.base.lib.animation.SimpleAnimationRunner;
import com.bartlomiejpluta.base.lib.icon.IconDelegate;
import com.bartlomiejpluta.base.util.random.DiceRoller; import com.bartlomiejpluta.base.util.random.DiceRoller;
import com.bartlomiejpluta.demo.entity.Creature; import com.bartlomiejpluta.demo.entity.Creature;
import com.bartlomiejpluta.demo.event.HitEvent; import com.bartlomiejpluta.demo.event.HitEvent;
import com.bartlomiejpluta.demo.world.item.BaseItem;
import lombok.Getter; import lombok.Getter;
import lombok.NonNull; import lombok.NonNull;
public class RangedWeapon extends IconDelegate implements Weapon { public class RangedWeapon extends BaseItem implements Weapon {
private final Context context; private final Context context;
private final BulletAnimationRunner animation; private final BulletAnimationRunner animation;
private final String sound; private final String sound;
@@ -45,7 +44,7 @@ public class RangedWeapon extends IconDelegate implements Weapon {
} }
public RangedWeapon(@NonNull DB.model.RangedWeaponModel template) { public RangedWeapon(@NonNull DB.model.RangedWeaponModel template) {
super(createIcon(template)); super(template.getIcon());
this.context = ContextHolder.INSTANCE.getContext(); this.context = ContextHolder.INSTANCE.getContext();
this.name = template.getName(); this.name = template.getName();
@@ -53,12 +52,12 @@ public class RangedWeapon extends IconDelegate implements Weapon {
this.dmgRoller = DiceRoller.of(template.getDamage()); this.dmgRoller = DiceRoller.of(template.getDamage());
this.rangeRoller = DiceRoller.of(template.getRange()); this.rangeRoller = DiceRoller.of(template.getRange());
this.cooldown = template.getCooldown(); this.cooldown = template.getCooldown();
this.animation = new BulletAnimationRunner(A.animations.get(template.getAnimation()).uid).infinite().offset(0, -15).onHit(this::onHit).onMiss(this::onMiss).speed(7f).animationSpeed(4f).scale(0.6f); this.animation = new BulletAnimationRunner(A.animations.byName(template.getAnimation()).$).infinite().offset(0, -15).onHit(this::onHit).onMiss(this::onMiss).speed(7f).animationSpeed(4f).scale(0.6f);
this.sound = A.sounds.get(template.getSound()).uid; this.sound = A.sounds.byName(template.getSound()).$;
this.punchAnimation = new SimpleAnimationRunner(A.animations.get(template.getPunchAnimation()).uid); this.punchAnimation = new SimpleAnimationRunner(A.animations.byName(template.getPunchAnimation()).$);
this.punchSound = A.sounds.get(template.getPunchSound()).uid; this.punchSound = A.sounds.byName(template.getPunchSound()).$;
this.missAnimation = new SimpleAnimationRunner(A.animations.get(template.getMissAnimation()).uid).scale(0.4f); this.missAnimation = new SimpleAnimationRunner(A.animations.byName(template.getMissAnimation()).$).scale(0.4f);
this.missSound = A.sounds.get(template.getMissSound()).uid; this.missSound = A.sounds.byName(template.getMissSound()).$;
} }
private void onHit(Movable attacker, Entity target) { private void onHit(Movable attacker, Entity target) {
@@ -98,11 +97,6 @@ public class RangedWeapon extends IconDelegate implements Weapon {
@Override @Override
public String usageName() { public String usageName() {
return "Equip"; return "Arm";
}
private static Icon createIcon(DB.model.RangedWeaponModel template) {
var icons = template.getIcon().split(",");
return ContextHolder.INSTANCE.getContext().createIcon(A.iconsets.get(icons[0]).uid, Integer.parseInt(icons[1]), Integer.parseInt(icons[2]));
} }
} }

View File

@@ -0,0 +1,113 @@
package com.bartlomiejpluta.demo.world.weapon;
import DB.dao;
import com.bartlomiejpluta.base.api.animation.Animation;
import com.bartlomiejpluta.base.api.context.Context;
import com.bartlomiejpluta.base.api.context.ContextHolder;
import com.bartlomiejpluta.base.api.entity.Entity;
import com.bartlomiejpluta.base.api.move.Movable;
import com.bartlomiejpluta.base.lib.animation.AnimationRunner;
import com.bartlomiejpluta.base.lib.animation.BulletAnimationRunner;
import com.bartlomiejpluta.base.lib.animation.SimpleAnimationRunner;
import com.bartlomiejpluta.base.util.random.DiceRoller;
import com.bartlomiejpluta.demo.entity.Creature;
import com.bartlomiejpluta.demo.entity.Enemy;
import com.bartlomiejpluta.demo.event.HitEvent;
import com.bartlomiejpluta.demo.world.item.StackableItem;
import lombok.Getter;
import lombok.NonNull;
import static java.lang.String.format;
public class ThrowingWeapon extends StackableItem implements Weapon {
private final Context context;
private final BulletAnimationRunner animation;
private final String sound;
private final AnimationRunner punchAnimation;
private final String punchSound;
private final AnimationRunner missAnimation;
private final String missSound;
@Getter
private final String id;
@Getter
private final String name;
@Getter
private final DiceRoller dmgRoller;
@Getter
private final DiceRoller rangeRoller;
@Getter
private final int cooldown;
public ThrowingWeapon(@NonNull String id, int count) {
this(dao.throwing_weapon.find(id), count);
}
public ThrowingWeapon(@NonNull DB.model.ThrowingWeaponModel template, int count) {
super(template.getIcon(), count);
this.context = ContextHolder.INSTANCE.getContext();
this.id = format("throwing:%s", template.getId());
this.name = template.getName();
this.dmgRoller = DiceRoller.of(template.getDamage());
this.rangeRoller = DiceRoller.of(template.getRange());
this.cooldown = template.getCooldown();
this.animation = new BulletAnimationRunner(A.animations.byName(template.getAnimation()).$).infinite().offset(0, -15).onHit(this::onHit).onMiss(this::onMiss).speed(7f).animationSpeed(4f).scale(0.6f);
this.sound = A.sounds.byName(template.getSound()).$;
this.punchAnimation = new SimpleAnimationRunner(A.animations.byName(template.getPunchAnimation()).$);
this.punchSound = A.sounds.byName(template.getPunchSound()).$;
this.missAnimation = new SimpleAnimationRunner(A.animations.byName(template.getMissAnimation()).$).scale(0.4f);
this.missSound = A.sounds.byName(template.getMissSound()).$;
}
private void onHit(Movable attacker, Entity target) {
if (target.isBlocking() && target instanceof Creature character) {
var namedAttacker = (Creature) attacker;
var damage = dmgRoller.roll();
character.hit(namedAttacker, damage);
punchAnimation.run(context, character.getLayer(), character);
context.playSound(punchSound);
context.fireEvent(new HitEvent(namedAttacker, character, damage));
}
}
private void onMiss(Movable attacker, Animation animation) {
missAnimation.run(context, ((Creature) attacker).getLayer(), animation.getPosition());
context.playSound(missSound);
}
@Override
public boolean attack(Creature attacker) {
if (--count == 0) {
attacker.setWeapon(null);
if (attacker instanceof Enemy enemy) {
enemy.setThrowingWeapon(null);
}
}
var direction = attacker.getFaceDirection();
context.playSound(sound);
animation.range(rangeRoller.roll())
.direction(direction)
.rotation(direction.xAngle - 180)
.run(context, attacker.getLayer(), attacker);
return true;
}
@Override
public void use(Creature creature) {
creature.setWeapon(this);
}
@Override
public String usageName() {
return "Arm";
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 928 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 521 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 KiB

View File

@@ -3,6 +3,7 @@
<demo:HUD <demo:HUD
xmlns:base="com.bartlomiejpluta.base.lib.gui" xmlns:base="com.bartlomiejpluta.base.lib.gui"
xmlns:demo="com.bartlomiejpluta.demo.gui" xmlns:demo="com.bartlomiejpluta.demo.gui"
padding="20f"
height="relative" height="relative"
width="relative"> width="relative">
@@ -16,13 +17,13 @@
</base:BorderLayout-TopLeft> </base:BorderLayout-TopLeft>
<base:BorderLayout-TopRight> <base:BorderLayout-TopRight>
<base:IconView ref="weapon" scale="2f"/> <base:FPSMonitor monitor="5,40" padding="15f" width="150" height="100f"/>
</base:BorderLayout-TopRight> </base:BorderLayout-TopRight>
<base:BorderLayout-BottomLeft> <base:BorderLayout-BottomLeft>
<base:Label <base:Label
ref="log" ref="log"
font="A.fonts.roboto_regular.uid" font="A.fonts.roboto_regular.$"
width="400f" width="400f"
height="25f" height="25f"
alignment="bottom|left" alignment="bottom|left"
@@ -30,13 +31,11 @@
fontSize="15f"/> fontSize="15f"/>
</base:BorderLayout-BottomLeft> </base:BorderLayout-BottomLeft>
<base:BorderLayout-BottomRight> <base:BorderLayout-BottomRight width="auto" height="auto">
<base:Label <base:TextView
ref="debug" ref="debug"
font="A.fonts.roboto_regular.uid" font="A.fonts.roboto_regular.$"
width="200f" alignment="top|right"
height="25f"
alignment="bottom|right"
color="0xFFFFFF" color="0xFFFFFF"
fontSize="15f"/> fontSize="15f"/>
</base:BorderLayout-BottomRight> </base:BorderLayout-BottomRight>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<demo:DialogWindow
xmlns:base="com.bartlomiejpluta.base.lib.gui"
xmlns:demo="com.bartlomiejpluta.demo.gui"
windowPosition="bottom"
padding="20f"
margin="20f"
width="900f"
height="auto">
<base:VLayout width="relative" height="auto">
<base:TextView ref="speaker" alignment="top|left" font="A.fonts.roboto_regular.$" fontSize="40f" width="relative" color="0x00AA00" />
<base:PrintedTextView ref="message" duration="0.01f" alignment="top|left" font="A.fonts.roboto_regular.$" fontSize="40f" width="relative" rows="4" color="0xFFFFFF"/>
</base:VLayout>
</demo:DialogWindow>

View File

@@ -10,7 +10,7 @@
<demo:Button <demo:Button
ref="use" ref="use"
font="A.fonts.roboto_regular.uid" font="A.fonts.roboto_regular.$"
width="relative" width="relative"
red="1f" red="1f"
green="1f" green="1f"
@@ -20,7 +20,7 @@
<demo:Button <demo:Button
ref="drop" ref="drop"
font="A.fonts.roboto_regular.uid" font="A.fonts.roboto_regular.$"
width="relative" width="relative"
red="1f" red="1f"
green="1f" green="1f"
@@ -30,7 +30,7 @@
<demo:Button <demo:Button
ref="cancel" ref="cancel"
font="A.fonts.roboto_regular.uid" font="A.fonts.roboto_regular.$"
width="relative" width="relative"
red="1f" red="1f"
green="1f" green="1f"

View File

@@ -10,7 +10,7 @@
<base:VLayout width="200f"> <base:VLayout width="200f">
<base:Label <base:Label
font="A.fonts.roboto_regular.uid" font="A.fonts.roboto_regular.$"
width="relative" width="relative"
alignment="top|center" alignment="top|center"
red="1f" red="1f"
@@ -20,10 +20,10 @@
fontSize="30f">Game Menu fontSize="30f">Game Menu
</base:Label> </base:Label>
<base:VOptionChoice width="relative"> <base:VOptionChoice ref="menu" width="relative">
<demo:Button <demo:Button
ref="resume_game" ref="resume_game"
font="A.fonts.roboto_regular.uid" font="A.fonts.roboto_regular.$"
width="relative" width="relative"
red="1f" red="1f"
green="1f" green="1f"
@@ -31,9 +31,19 @@
fontSize="17f">Resume game fontSize="17f">Resume game
</demo:Button> </demo:Button>
<demo:Button
ref="equipment"
font="A.fonts.roboto_regular.$"
width="relative"
red="1f"
green="1f"
blue="1f"
fontSize="17f">Equipment
</demo:Button>
<demo:Button <demo:Button
ref="start_menu" ref="start_menu"
font="A.fonts.roboto_regular.uid" font="A.fonts.roboto_regular.$"
width="relative" width="relative"
red="1f" red="1f"
green="1f" green="1f"
@@ -43,7 +53,7 @@
<demo:Button <demo:Button
ref="exit" ref="exit"
font="A.fonts.roboto_regular.uid" font="A.fonts.roboto_regular.$"
width="relative" width="relative"
red="1f" red="1f"
green="1f" green="1f"

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<demo:DialogChoiceWindow
xmlns:base="com.bartlomiejpluta.base.lib.gui"
xmlns:demo="com.bartlomiejpluta.demo.gui"
windowPosition="bottom"
padding="20f"
margin="20f"
width="900f"
height="auto">
<base:VLayout width="relative" height="auto">
<base:TextView ref="speaker" alignment="top|left" font="A.fonts.roboto_regular.$" fontSize="40f" width="relative" color="0x00AA00" />
<base:VOptionChoice ref="choice" width="relative" />
</base:VLayout>
</demo:DialogChoiceWindow>

View File

@@ -9,7 +9,7 @@
<base:VLayout width="200f"> <base:VLayout width="200f">
<base:Label <base:Label
font="A.fonts.roboto_regular.uid" font="A.fonts.roboto_regular.$"
width="relative" width="relative"
alignment="top|center" alignment="top|center"
red="1f" red="1f"
@@ -22,7 +22,7 @@
<base:VOptionChoice ref="menu" width="relative"> <base:VOptionChoice ref="menu" width="relative">
<demo:Button <demo:Button
ref="new_game" ref="new_game"
font="A.fonts.roboto_regular.uid" font="A.fonts.roboto_regular.$"
width="relative" width="relative"
red="1f" red="1f"
green="1f" green="1f"
@@ -32,7 +32,7 @@
<demo:Button <demo:Button
ref="exit" ref="exit"
font="A.fonts.roboto_regular.uid" font="A.fonts.roboto_regular.$"
width="relative" width="relative"
red="1f" red="1f"
green="1f" green="1f"

View File

@@ -10,23 +10,44 @@
<base:VLayout width="auto" height="auto"> <base:VLayout width="auto" height="auto">
<base:Label <base:Label
font="A.fonts.roboto_regular.uid" font="A.fonts.roboto_regular.$"
width="relative" width="relative"
alignment="top|center" alignment="top|left"
red="1f" red="1f"
green="1f" green="1f"
blue="1f" blue="1f"
alpha="0.5f" alpha="0.5f"
fontSize="30f">Equipment fontSize="30f">Inventory &amp; Equipment
</base:Label> </base:Label>
<base:HLayout> <base:HLayout margin="0f" padding="0f">
<base:VGridLayout columns="2" padding="20f" width="250f"> <base:HOptionChoice ref="layout">
<demo:ItemIconView ref="weapon" margin="5f"/> <base:VGridOptionChoice ref="equipment" columns="2" width="auto">
<demo:ItemIconView ref="ammo" margin="5f"/> <demo:ItemIconView ref="weapon" placeholder="Generic,5,10" margin="5f"/>
</base:VGridLayout> <demo:ItemIconView ref="ammo" placeholder="Generic,8,10" margin="5f"/>
</base:VGridOptionChoice>
<base:VGridOptionChoice ref="eq" columns="4" width="auto" height="auto"> <base:VGridOptionChoice ref="inventory" columns="6" width="auto" height="auto">
<demo:ItemIconView margin="5f"/>
<demo:ItemIconView margin="5f"/>
<demo:ItemIconView margin="5f"/>
<demo:ItemIconView margin="5f"/>
<demo:ItemIconView margin="5f"/>
<demo:ItemIconView margin="5f"/>
<demo:ItemIconView margin="5f"/>
<demo:ItemIconView margin="5f"/>
<demo:ItemIconView margin="5f"/>
<demo:ItemIconView margin="5f"/>
<demo:ItemIconView margin="5f"/>
<demo:ItemIconView margin="5f"/>
<demo:ItemIconView margin="5f"/>
<demo:ItemIconView margin="5f"/>
<demo:ItemIconView margin="5f"/>
<demo:ItemIconView margin="5f"/>
<demo:ItemIconView margin="5f"/>
<demo:ItemIconView margin="5f"/>
<demo:ItemIconView margin="5f"/>
<demo:ItemIconView margin="5f"/>
<demo:ItemIconView margin="5f"/> <demo:ItemIconView margin="5f"/>
<demo:ItemIconView margin="5f"/> <demo:ItemIconView margin="5f"/>
<demo:ItemIconView margin="5f"/> <demo:ItemIconView margin="5f"/>
@@ -44,10 +65,11 @@
<demo:ItemIconView margin="5f"/> <demo:ItemIconView margin="5f"/>
<demo:ItemIconView margin="5f"/> <demo:ItemIconView margin="5f"/>
</base:VGridOptionChoice> </base:VGridOptionChoice>
</base:HOptionChoice>
<base:VLayout height="relative" padding="20f" width="250f"> <base:VLayout height="relative" padding="20f" width="250f">
<base:Label ref="item-name" <base:Label ref="item-name"
font="A.fonts.roboto_regular.uid" font="A.fonts.roboto_regular.$"
width="relative" width="relative"
alignment="top|center" alignment="top|center"
color="0xFFFFFF" color="0xFFFFFF"
@@ -55,7 +77,7 @@
margin="5f"/> margin="5f"/>
<base:Label ref="item-details" <base:Label ref="item-details"
font="A.fonts.roboto_regular.uid" font="A.fonts.roboto_regular.$"
width="relative" width="relative"
alignment="top|left" alignment="top|left"
color="0xFFFFFF" color="0xFFFFFF"
@@ -63,7 +85,6 @@
margin="5f"/> margin="5f"/>
</base:VLayout> </base:VLayout>
</base:HLayout> </base:HLayout>
</base:VLayout> </base:VLayout>

View File

@@ -11,7 +11,7 @@
<base:VLayout width="auto" height="auto"> <base:VLayout width="auto" height="auto">
<base:Label <base:Label
ref="title" ref="title"
font="A.fonts.roboto_regular.uid" font="A.fonts.roboto_regular.$"
width="relative" width="relative"
alignment="top|center" alignment="top|center"
red="1f" red="1f"