feat: Integrated Stream asset and Kai animation system
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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
42
src/scenes/UIScene.js
Normal 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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user