feat: Integrated Stream asset and Kai animation system

This commit is contained in:
2026-01-29 00:09:00 +01:00
parent 94565adffc
commit afa0e3c662
59 changed files with 1477 additions and 19 deletions

View File

@@ -1,4 +1,5 @@
import GrassScene from './scenes/GrassScene_Clean.js';
import UIScene from './scenes/UIScene.js';
const config = {
type: Phaser.AUTO,
@@ -17,7 +18,7 @@ const config = {
gravity: { y: 0 }
}
},
scene: [GrassScene]
scene: [GrassScene, UIScene]
};
const game = new Phaser.Game(config);

View File

@@ -19,7 +19,29 @@ export default class GrassSceneClean extends Phaser.Scene {
// 4. Items & Charts
this.load.image('hay', 'DEMO_FAZA1/Items/hay_drop_0.png');
this.load.image('kai', 'characters/kai.png');
// REPLACED STATIC KAI WITH SPRITE SHEET
// Frame size 256x256 based on 1024x1024 sheet
this.load.spritesheet('kai', 'DEMO_FAZA1/Characters/kai_walk_sheet.png', {
frameWidth: 256,
frameHeight: 256
}); // Loading as 'kai' to keep existing references working, but now it has frames.
// 5. UI Assets (Loaded from DEMO_FAZA1/UI)
this.load.image('ui_health_bar', 'DEMO_FAZA1/UI/health_bar.png');
this.load.image('ui_weather_widget', 'DEMO_FAZA1/UI/weather_widget.png');
this.load.image('ui_minimap', 'DEMO_FAZA1/UI/minimap_frame.png');
this.load.image('ui_hotbar', 'DEMO_FAZA1/UI/hotbar_background.png');
this.load.image('ui_action_btn', 'DEMO_FAZA1/UI/action_btn.png');
// 6. Camp Assets
this.load.image('campfire', 'DEMO_FAZA1/Environment/taborni_ogenj.png');
this.load.image('tent', 'DEMO_FAZA1/Environment/sotor.png');
this.load.image('sleeping_bag', 'DEMO_FAZA1/Items/spalna_vreca.png');
// 7. NEW: Sliced Stream Assets
this.load.image('stream_head', 'DEMO_FAZA1/Environment/stream_head.png');
this.load.image('stream_body', 'DEMO_FAZA1/Environment/stream_body.png');
}
create() {
@@ -36,8 +58,23 @@ export default class GrassSceneClean extends Phaser.Scene {
this.ground.setTileScale(1, 1);
this.ground.setDepth(-100);
// --- 2. VODNI KANALI (Water Integration) ---
// Removed as requested
// --- 2. STREAM (Single Pipe Channel) ---
// Placed at Z=0 (Ground Level)
const startX = WORLD_W / 2 + 50;
const startY = WORLD_H / 2 + 100;
this.stream = this.physics.add.staticImage(startX, startY, 'stream_muddy');
this.stream.setOrigin(0.5, 0.9);
this.stream.setDepth(0);
this.stream.setScale(1.0);
// Physics Body
this.stream.body.setSize(this.stream.width * 0.9, this.stream.height * 0.4);
this.stream.body.setOffset(this.stream.width * 0.05, this.stream.height * 0.5);
// Collider added later after Kai creation
// Collider added later after Kai creation
// --- 3. FOLIAGE (Trava - Šopi) ---
// Removed as requested
@@ -47,39 +84,136 @@ export default class GrassSceneClean extends Phaser.Scene {
// --- 5. CHAR (Kai) ---
this.kai = this.physics.add.sprite(WORLD_W / 2, WORLD_H / 2, 'kai');
this.kai.setScale(64 / this.kai.height);
// Povečava na 160px višine
this.kai.setScale(160 / 256); // Scale based on actual frame height (256) -> target 160
this.kai.setCollideWorldBounds(true);
this.kai.setOrigin(0.5, 0.9); // Anchor at feet
this.kai.body.setSize(24, 20);
this.kai.body.setOffset(this.kai.width / 2 - 12, this.kai.height - 20);
this.kai.setOrigin(0.5, 0.9);
// Adjust Physics Body for larger size
// Width ~40, Height ~30 (relative to scaled sprite)
this.kai.body.setSize(50, 40);
this.kai.body.setOffset(256 / 2 - 25, 256 - 40); // Pivot offset based on 256 frame
// Collider Stream <-> Kai
this.physics.add.collider(this.kai, this.stream);
// --- ANIMATIONS ---
// 0-3: Down, 4-7: Left, 8-11: Right, 12-15: Up
this.anims.create({
key: 'walk-down',
frames: this.anims.generateFrameNumbers('kai', { start: 0, end: 3 }),
frameRate: 8,
repeat: -1
});
this.anims.create({
key: 'walk-left',
frames: this.anims.generateFrameNumbers('kai', { start: 4, end: 7 }),
frameRate: 8,
repeat: -1
});
this.anims.create({
key: 'walk-right',
frames: this.anims.generateFrameNumbers('kai', { start: 8, end: 11 }),
frameRate: 8,
repeat: -1
});
this.anims.create({
key: 'walk-up',
frames: this.anims.generateFrameNumbers('kai', { start: 12, end: 15 }),
frameRate: 8,
repeat: -1
});
// Idle
this.kai.play('walk-down');
this.kai.stop();
// --- 7. CAMP SETUP (Oživitev) ---
this.campGroup = this.add.group();
// Tent (Behind Kai usually)
let tent = this.add.image(WORLD_W / 2 - 100, WORLD_H / 2 - 80, 'tent');
tent.setOrigin(0.5, 0.9); // Bottom anchor
tent.setScale(1.2); // Big enough for Kai
this.campGroup.add(tent);
// Campfire (In front)
let fire = this.add.image(WORLD_W / 2 + 50, WORLD_H / 2 + 50, 'campfire');
fire.setOrigin(0.5, 0.8);
fire.setScale(0.8);
this.campGroup.add(fire);
// Tweens for Fire (Little pulse)
this.tweens.add({
targets: fire,
scaleX: 0.85,
scaleY: 0.85,
duration: 500,
yoyo: true,
repeat: -1
});
// Sleeping Bag
let bag = this.add.image(WORLD_W / 2 - 80, WORLD_H / 2 + 20, 'sleeping_bag');
bag.setOrigin(0.5, 0.5); // Flat on ground?
bag.setScale(0.8);
this.campGroup.add(bag);
// Camera
this.cameras.main.startFollow(this.kai, true, 0.1, 0.1);
this.cameras.main.setZoom(1.5);
this.cursors = this.input.keyboard.createCursorKeys();
// Info
this.add.text(20, 20, 'PROBNA FARMA: Base Only', {
font: '16px Monospace', fill: '#ffffff', backgroundColor: '#000000aa'
}).setScrollFactor(0).setDepth(3000);
// Launch UI Scene
if (!this.scene.get('UIScene').scene.settings.active) {
this.scene.launch('UIScene');
}
}
update() {
const speed = 250;
this.kai.setVelocity(0);
if (this.cursors.left.isDown) this.kai.setVelocityX(-speed);
else if (this.cursors.right.isDown) this.kai.setVelocityX(speed);
let moving = false;
if (this.cursors.up.isDown) this.kai.setVelocityY(-speed);
else if (this.cursors.down.isDown) this.kai.setVelocityY(speed);
if (this.cursors.left.isDown) {
this.kai.setVelocityX(-speed);
this.kai.play('walk-left', true);
moving = true;
} else if (this.cursors.right.isDown) {
this.kai.setVelocityX(speed);
this.kai.play('walk-right', true);
moving = true;
}
if (this.cursors.up.isDown) {
this.kai.setVelocityY(-speed);
if (!this.cursors.left.isDown && !this.cursors.right.isDown) {
this.kai.play('walk-up', true);
}
moving = true;
} else if (this.cursors.down.isDown) {
this.kai.setVelocityY(speed);
if (!this.cursors.left.isDown && !this.cursors.right.isDown) {
this.kai.play('walk-down', true);
}
moving = true;
}
if (this.kai.body.velocity.length() > 0) {
this.kai.body.velocity.normalize().scale(speed);
} else {
this.kai.stop();
// Optional: reset to idle frame?
}
// --- Z-SORTING SYSTEM ---
// Player
this.kai.setDepth(this.kai.y);
// Camp Sorting
this.campGroup.children.each(item => {
item.setDepth(item.y);
});
}
}

42
src/scenes/UIScene.js Normal file
View File

@@ -0,0 +1,42 @@
export default class UIScene extends Phaser.Scene {
constructor() {
super({ key: 'UIScene', active: true });
}
preload() {
this.load.path = 'assets/';
// Load UI Assets here (moved from GrassScene)
this.load.image('ui_health_bar', 'DEMO_FAZA1/UI/health_bar.png');
this.load.image('ui_weather_widget', 'DEMO_FAZA1/UI/weather_widget.png');
this.load.image('ui_minimap', 'DEMO_FAZA1/UI/minimap_frame.png');
this.load.image('ui_hotbar', 'DEMO_FAZA1/UI/hotbar_background.png');
this.load.image('ui_action_btn', 'DEMO_FAZA1/UI/action_btn.png');
}
create() {
// Simple UI Layout
const width = this.cameras.main.width;
const height = this.cameras.main.height;
const PAD = 20;
// 1. Health (Top Left)
let health = this.add.image(PAD, PAD, 'ui_health_bar').setOrigin(0, 0).setScale(0.8);
// 2. Weather (Top Right)
let weather = this.add.image(width - PAD, PAD, 'ui_weather_widget').setOrigin(1, 0).setScale(0.8);
// 3. Minimap (Bottom Right)
let minimap = this.add.image(width - PAD, height - PAD, 'ui_minimap').setOrigin(1, 1).setScale(0.7);
// 4. Hotbar (Bottom Center)
let hotbar = this.add.image(width / 2, height - PAD, 'ui_hotbar').setOrigin(0.5, 1).setScale(0.8);
// 5. Action Button (Right of Hotbar)
let action = this.add.image(width / 2 + 350, height - 30, 'ui_action_btn').setOrigin(0.5, 1).setScale(0.8);
// Debug Text
this.add.text(width / 2, 50, 'HUD LAYER ACTIVE', {
fontSize: '24px', fill: '#00ff00', stroke: '#000', strokeThickness: 4
}).setOrigin(0.5);
}
}