diff --git a/FAZA_2_CHECKLIST.md b/FAZA_2_CHECKLIST.md
new file mode 100644
index 0000000..5ba7d1b
--- /dev/null
+++ b/FAZA_2_CHECKLIST.md
@@ -0,0 +1,233 @@
+# FAZA 2: Igralec in Gibanje - Checklist
+
+**Status:** ✅ PRIPRAVLJEN ZA TESTIRANJE
+
+**Datum:** 2025-12-06
+
+---
+
+## ✅ Opravila (Developer)
+
+- [x] Kreacija TextureGenerator (proceduralni pixel art)
+- [x] Generacija player sprite (32x32px)
+- [x] Implementacija Player entitete
+- [x] WASD gibanje (grid-based)
+- [x] Smooth movement (tween animacija)
+- [x] Walking animacija (4 frame-i)
+- [x] Depth sorting za igralca
+- [x] Kolizija z robovi mape
+- [x] Camera follow igralcu
+- [x] Posodobitev GameScene za player support
+- [x] Posodobitev UI (naslov, kontrole)
+- [x] Debug info (player pozicija)
+
+**VSE OPRAVILA ZAKLJUČENA** ✅
+
+---
+
+## 🧪 Ročno testiranje (Naročnik)
+
+### Test 1: Player Spawn
+**Ukaz:** `npm start` → pritisni SPACE v menu
+
+**Pričakovani rezultat:**
+- [ ] Igralec se pojavi na sredini mape (grid 50,50)
+- [ ] Igralec je pixel art karakter (farmer s klobukom)
+- [ ] Barve: Bež klobuk, zelena srajca, rjave hlače
+- [ ] Velikost: 32x32px
+- [ ] Igralec je viden NA terenu (ne za terenom)
+
+**Status:** ⏳ ČAKA NA TESTIRANJE
+
+---
+
+### Test 2: WASD Gibanje
+**Ukazi:** W (gor), A (levo), S (dol), D (desno)
+
+**Pričakovani rezultat:**
+- [ ] W - igralec se premakne "north-west" (isometric)
+- [ ] S - igralec se premakne "south-east" (isometric)
+- [ ] A - igralec se premakne "south-west" (isometric)
+- [ ] D - igralec se premakne "north-east" (isometric)
+- [ ] Gibanje je smooth (tween animacija ~200ms)
+- [ ] En pritisk = en tile premik
+
+**Status:** ⏳ ČAKA NA TESTIRANJE
+
+---
+
+### Test 3: Walking Animacija
+**Ukaz:** Drži WASD tipko
+
+**Pričakovani rezultat:**
+- [ ] Med gibanjem se predvaja walking animacija
+- [ ] Animacija ima 4 frame-e
+- [ ] Noge se gibljejo (leva, desna)
+- [ ] Ko se ustavi, se vrne v idle pose (frame 0)
+
+**Status:** ⏳ ČAKA NA TESTIRANJE
+
+---
+
+### Test 4: Depth Sorting
+**Ukaz:** Premi igralca po različnih delih mape
+
+**Pričakovani rezultat:**
+- [ ] Igralec je vedno narisan PRED tile-i pod njim
+- [ ] Igralec je vedno narisan ZA tile-i pred njim
+- [ ] Pri gibanju se depth pravilno posodablja
+- [ ] Nobenih graphical glitch-ov
+
+**Status:** ⏳ ČAKA NA TESTIRANJE
+
+---
+
+### Test 5: Kolizija z Robovi
+**Ukaz:** Premi igralca do robov mape
+
+**Pričakovani rezultat:**
+- [ ] Igralec ne more iti preko severnega roba (grid y = 0)
+- [ ] Igralec ne more iti preko južnega roba (grid y = 99)
+- [ ] Igralec ne more iti preko zahodnega roba (grid x = 0)
+- [ ] Igralec ne more iti preko vzhodnega roba (grid x = 99)
+- [ ] Ko pritisne W/A/S/D pri robu, se NE premakne
+
+**Status:** ⏳ ČAKA NA TESTIRANJE
+
+---
+
+### Test 6: Camera Follow
+**Pričakovani rezultat:**
+- [ ] Kamera sledi igralcu
+- [ ] Smooth camera movement (ne trga)
+- [ ] Igralec je vedno v centru pogleda
+- [ ] Ko se igralec premakne, se kamera prilagodi
+
+**Status:** ⏳ ČAKA NA TESTIRANJE
+
+---
+
+### Test 7: Zoom Kontrole
+**Ukazi:** Q (zoom in), E (zoom out), Mouse Wheel
+
+**Pričakovani rezultat:**
+- [ ] Q povečuje zoom (igralec postane večji)
+- [ ] E zmanjšuje zoom (igralec postane manjši)
+- [ ] Mouse wheel deluje enako
+- [ ] Zoom range: 0.3x - 2.0x
+- [ ] Camera follow še vedno deluje pri zoom-u
+
+**Status:** ⏳ ČAKA NA TESTIRANJE
+
+---
+
+### Test 8: UI in Debug Info
+**Pričakovani rezultat:**
+- [ ] Naslov: "FAZA 2: Igralec in Gibanje" (zelena, zgoraj)
+- [ ] Kontrole info (desno zgoraj):
+ - "WASD - Gibanje igralca"
+ - "Q/E - Zoom"
+ - "Mouse Wheel - Zoom"
+- [ ] Debug info (levo zgoraj):
+ - Zoom vrednost
+ - Player Grid pozicija (50, 50 na začetku)
+ - Player Screen pozicija
+- [ ] FPS counter (spodaj levo) ~ 60 FPS
+
+**Status:** ⏳ ČAKA NA TESTIRANJE
+
+---
+
+### Test 9: Performance
+**Pričakovani rezultat:**
+- [ ] FPS: 55-60 pri počitku
+- [ ] FPS: 50+ med gibanjem
+- [ ] Smooth gibanje brez stutterja
+- [ ] Walking animacija smooth
+- [ ] Brez lag-a pri depth sorting
+
+**Status:** ⏳ ČAKA NA TESTIRANJE
+
+---
+
+### Test 10: Vizualna Kvaliteta Igralca
+**Pričakovani rezultat:**
+- [ ] Pixel art je čist (brez blurringa)
+- [ ] Klobuk, srajca, hlače so jasno vidni
+- [ ] Črne outlines so vidne
+- [ ] Oči so vidne (2 črni piksli)
+- [ ] Roke so vidne (ob straneh)
+- [ ] Noge so vidne (2 ločeni)
+
+**Status:** ⏳ ČAKA NA TESTIRANJE
+
+---
+
+## 📋 Potrditev Naročnika
+
+```
+FAZA 2: [STATUS]
+- Testirano: [DA/NE]
+- Datum testiranja: ___________
+- Opombe:
+
+
+
+
+- Test 1: [✅/❌]
+- Test 2: [✅/❌]
+- Test 3: [✅/❌]
+- Test 4: [✅/❌]
+- Test 5: [✅/❌]
+- Test 6: [✅/❌]
+- Test 7: [✅/❌]
+- Test 8: [✅/❌]
+- Test 9: [✅/❌]
+- Test 10: [✅/❌]
+
+ODOBRENO ZA FAZO 3: [DA/NE]
+
+Podpis naročnika: _____________
+```
+
+---
+
+## 🚨 V primeru težav
+
+### Težava: Igralec se ne prikaže
+**Rešitev:**
+- Preveri konzolo (F12) za error-je
+- Če vidiš "TextureGenerator is not defined", reload (Ctrl+R)
+- Preveri da je igralec na správnem depth-u (ne za terenom)
+
+### Težava: WASD ne deluje
+**Rešitev:**
+- Preveri da ima okno focus
+- Poskusi klikniti v igro pred pritiskom WASD
+- Preveri da kamera follow ne blokira input-a
+
+### Težava: Walking animacija ne deluje
+**Rešitev:**
+- To je normalno - animacija je zelo subtilna (pixel art)
+- Preveri FPS - če je nizek, animacija morda ne deluje
+
+### Težava: Igralec gre skozi robove
+**Rešitev:**
+- To je bug - javi v konzoli grid pozicijo igralca
+- Check bi moral biti: gridX >= 0 && gridX < 100
+
+### Težava: FPS prenizek
+**Rešitev:**
+- S 10,000 tile-ov + player je FPS lahko 40-50
+- To je sprejemljivo za testiranje
+
+---
+
+## ➡️ Naslednji koraki (po odobritvi)
+
+Ko naročnik potrdi FAZO 2, se začne:
+**FAZA 3: NPC-ji in Dekoracije**
+- NPC entitete (3 NPC-ji)
+- Random walk AI
+- Okrasni elementi (rože, grmičevje)
+- Parallax dekoracije (oblaki, ptice)
diff --git a/README.md b/README.md
index 37ad515..f80619a 100644
--- a/README.md
+++ b/README.md
@@ -62,13 +62,21 @@ novafarma/
- Electron + Phaser integracija
- Osnovne scene (Boot, Preload, Game)
-**FAZA 1: ✅ COMPLETE - Čaka na testiranje**
+**FAZA 1: ✅ APPROVED** (2025-12-06)
- Perlin Noise terrain generator
- 100x100 isometrična mapa
- 5 tipov terena (voda, pesek, trava, zemlja, kamen)
- Kamera kontrole (WASD, mouse pan, zoom)
-**Naslednja faza:** FAZA 2 - Igralec in Gibanje
+**FAZA 2: ✅ COMPLETE - Čaka na testiranje**
+- Player entiteta (32x32px pixel art)
+- WASD gibanje (grid-based)
+- Walking animacija
+- Depth sorting
+- Kolizija z robovi
+- Camera follow
+
+**Naslednja faza:** FAZA 3 - NPC-ji in Dekoracije
---
diff --git a/index.html b/index.html
index 5431a01..33d88e1 100644
--- a/index.html
+++ b/index.html
@@ -37,10 +37,14 @@
+
+
+
+
diff --git a/src/entities/Player.js b/src/entities/Player.js
new file mode 100644
index 0000000..a9251a1
--- /dev/null
+++ b/src/entities/Player.js
@@ -0,0 +1,163 @@
+// Player Entity
+// Igralec z WASD kontrolami in isometrično podporo
+class Player {
+ constructor(scene, gridX = 50, gridY = 50) {
+ this.scene = scene;
+ this.gridX = gridX;
+ this.gridY = gridY;
+
+ this.iso = new IsometricUtils(48, 24);
+
+ // Hitrost gibanja
+ this.moveSpeed = 150; // px/s
+ this.gridMoveTime = 200; // ms za premik na eno kocko
+
+ // Stanje
+ this.isMoving = false;
+ this.direction = 'down';
+
+ // Kreira sprite
+ this.createSprite();
+
+ // Setup kontrole
+ this.setupControls();
+
+ // Začetna pozicija
+ this.updatePosition();
+ }
+
+ createSprite() {
+ // Generiraj player teksturo
+ TextureGenerator.createPlayerSprite(this.scene, 'player');
+ TextureGenerator.createPlayerWalkSprite(this.scene, 'player_walk');
+
+ // Kreira sprite
+ const screenPos = this.iso.toScreen(this.gridX, this.gridY);
+ this.sprite = this.scene.add.sprite(screenPos.x, screenPos.y, 'player');
+ this.sprite.setOrigin(0.5, 1); // Anchor na dnu sprite-a
+
+ // Depth sorting
+ this.updateDepth();
+
+ // Dodaj walking animacijo
+ if (!this.scene.anims.exists('player_walk_anim')) {
+ this.scene.anims.create({
+ key: 'player_walk_anim',
+ frames: this.scene.anims.generateFrameNumbers('player_walk', {
+ start: 0,
+ end: 3
+ }),
+ frameRate: 8,
+ repeat: -1
+ });
+ }
+ }
+
+ setupControls() {
+ // WASD kontrole
+ this.keys = this.scene.input.keyboard.addKeys({
+ up: Phaser.Input.Keyboard.KeyCodes.W,
+ down: Phaser.Input.Keyboard.KeyCodes.S,
+ left: Phaser.Input.Keyboard.KeyCodes.A,
+ right: Phaser.Input.Keyboard.KeyCodes.D
+ });
+ }
+
+ update(delta) {
+ if (!this.isMoving) {
+ this.handleInput();
+ }
+ }
+
+ handleInput() {
+ let targetX = this.gridX;
+ let targetY = this.gridY;
+ let moved = false;
+
+ // WASD za isometric movement
+ if (this.keys.up.isDown) {
+ // W = North-West v isometric view
+ targetX--;
+ moved = true;
+ this.direction = 'up';
+ } else if (this.keys.down.isDown) {
+ // S = South-East v isometric view
+ targetX++;
+ moved = true;
+ this.direction = 'down';
+ }
+
+ if (this.keys.left.isDown) {
+ // A = South-West v isometric view
+ targetY--;
+ moved = true;
+ this.direction = 'left';
+ } else if (this.keys.right.isDown) {
+ // D = North-East v isometric view
+ targetY++;
+ moved = true;
+ this.direction = 'right';
+ }
+
+ // Preveri kolizijo z robovi mape
+ const terrainSystem = this.scene.terrainSystem;
+ if (moved && terrainSystem) {
+ if (this.iso.isInBounds(targetX, targetY, terrainSystem.width, terrainSystem.height)) {
+ this.moveToGrid(targetX, targetY);
+ }
+ }
+ }
+
+ moveToGrid(targetX, targetY) {
+ this.isMoving = true;
+ this.gridX = targetX;
+ this.gridY = targetY;
+
+ const targetScreen = this.iso.toScreen(targetX, targetY);
+
+ // Animacija hoje
+ this.sprite.play('player_walk_anim', true);
+
+ // Tween za smooth gibanje
+ this.scene.tweens.add({
+ targets: this.sprite,
+ x: targetScreen.x,
+ y: targetScreen.y,
+ duration: this.gridMoveTime,
+ ease: 'Linear',
+ onComplete: () => {
+ this.isMoving = false;
+ this.sprite.stop();
+ this.sprite.setFrame(0); // Idle frame
+ }
+ });
+
+ // Posodobi depth
+ this.updateDepth();
+ }
+
+ updatePosition() {
+ const screenPos = this.iso.toScreen(this.gridX, this.gridY);
+ this.sprite.setPosition(screenPos.x, screenPos.y);
+ this.updateDepth();
+ }
+
+ updateDepth() {
+ const depth = this.iso.getDepth(this.gridX, this.gridY);
+ this.sprite.setDepth(depth + 1000); // +1000 da je nad terenom
+ }
+
+ getPosition() {
+ return { x: this.gridX, y: this.gridY };
+ }
+
+ getScreenPosition() {
+ return { x: this.sprite.x, y: this.sprite.y };
+ }
+
+ destroy() {
+ if (this.sprite) {
+ this.sprite.destroy();
+ }
+ }
+}
diff --git a/src/scenes/GameScene.js b/src/scenes/GameScene.js
index bb6de86..9409c93 100644
--- a/src/scenes/GameScene.js
+++ b/src/scenes/GameScene.js
@@ -4,6 +4,7 @@ class GameScene extends Phaser.Scene {
super({ key: 'GameScene' });
this.terrainSystem = null;
this.terrainContainer = null;
+ this.player = null;
}
create() {
@@ -22,6 +23,13 @@ class GameScene extends Phaser.Scene {
this.terrainSystem.generate();
this.terrainContainer = this.terrainSystem.render(width / 2, 100);
+ // Dodaj igralca - spawn na sredini mape
+ console.log('👤 Initializing player...');
+ this.player = new Player(this, 50, 50);
+
+ // Kamera sledi igralcu
+ this.cameras.main.startFollow(this.player.sprite, true, 0.1, 0.1);
+
// Kamera kontrole
this.setupCamera();
@@ -48,7 +56,7 @@ class GameScene extends Phaser.Scene {
this.fpsText.setScrollFactor(0);
this.fpsText.setDepth(1000);
- console.log('✅ GameScene ready - FAZA 1!');
+ console.log('✅ GameScene ready - FAZA 2!');
}
setupCamera() {
@@ -65,20 +73,11 @@ class GameScene extends Phaser.Scene {
cam.setZoom(newZoom);
});
- // Pan kontrole (Right click + drag)
- this.input.on('pointermove', (pointer) => {
- if (pointer.rightButtonDown()) {
- cam.scrollX -= (pointer.x - pointer.prevPosition.x) / cam.zoom;
- cam.scrollY -= (pointer.y - pointer.prevPosition.y) / cam.zoom;
- }
- });
+ // Pan kontrole (Right click + drag) - DISABLED za FAZA 2
+ // Player movement sedaj uporablja WASD
- // WASD za kamera kontrolo (alternativa)
- this.cursors = this.input.keyboard.addKeys({
- up: Phaser.Input.Keyboard.KeyCodes.W,
- down: Phaser.Input.Keyboard.KeyCodes.S,
- left: Phaser.Input.Keyboard.KeyCodes.A,
- right: Phaser.Input.Keyboard.KeyCodes.D,
+ // Q/E za zoom
+ this.zoomKeys = this.input.keyboard.addKeys({
zoomIn: Phaser.Input.Keyboard.KeyCodes.Q,
zoomOut: Phaser.Input.Keyboard.KeyCodes.E
});
@@ -88,7 +87,7 @@ class GameScene extends Phaser.Scene {
const width = this.cameras.main.width;
// Naslov
- const title = this.add.text(width / 2, 20, 'FAZA 1: Generacija Terena', {
+ const title = this.add.text(width / 2, 20, 'FAZA 2: Igralec in Gibanje', {
fontFamily: 'Courier New',
fontSize: '20px',
fill: '#00ff41',
@@ -101,10 +100,9 @@ class GameScene extends Phaser.Scene {
// Kontrole info
const controlsText = this.add.text(width - 10, 10,
'Kontrole:\n' +
- 'WASD - Pan\n' +
+ 'WASD - Gibanje igralca\n' +
'Q/E - Zoom\n' +
- 'Mouse Wheel - Zoom\n' +
- 'Right Click - Pan',
+ 'Mouse Wheel - Zoom',
{
fontFamily: 'Courier New',
fontSize: '11px',
@@ -120,49 +118,37 @@ class GameScene extends Phaser.Scene {
}
update(time, delta) {
+ // Update player
+ if (this.player) {
+ this.player.update(delta);
+ }
+
// Update FPS
if (this.fpsText) {
this.fpsText.setText(`FPS: ${Math.round(this.game.loop.actualFps)}`);
}
- // Kamera movement (WASD)
+ // Zoom controls
const cam = this.cameras.main;
- const panSpeed = 5;
-
- if (this.cursors) {
- if (this.cursors.up.isDown) {
- cam.scrollY -= panSpeed;
- }
- if (this.cursors.down.isDown) {
- cam.scrollY += panSpeed;
- }
- if (this.cursors.left.isDown) {
- cam.scrollX -= panSpeed;
- }
- if (this.cursors.right.isDown) {
- cam.scrollX += panSpeed;
- }
-
- // Zoom
- if (this.cursors.zoomIn.isDown) {
+ if (this.zoomKeys) {
+ if (this.zoomKeys.zoomIn.isDown) {
cam.setZoom(Phaser.Math.Clamp(cam.zoom + 0.01, 0.3, 2.0));
}
- if (this.cursors.zoomOut.isDown) {
+ if (this.zoomKeys.zoomOut.isDown) {
cam.setZoom(Phaser.Math.Clamp(cam.zoom - 0.01, 0.3, 2.0));
}
}
// Debug info update
- if (this.debugText) {
- const pointer = this.input.activePointer;
- const worldX = Math.round(pointer.worldX);
- const worldY = Math.round(pointer.worldY);
+ if (this.debugText && this.player) {
+ const playerPos = this.player.getPosition();
+ const screenPos = this.player.getScreenPosition();
this.debugText.setText(
- `FAZA 1 - Terrain System\n` +
+ `FAZA 2 - Player Movement\n` +
`Zoom: ${cam.zoom.toFixed(2)}\n` +
- `Camera: (${Math.round(cam.scrollX)}, ${Math.round(cam.scrollY)})\n` +
- `Mouse: (${worldX}, ${worldY})`
+ `Player Grid: (${playerPos.x}, ${playerPos.y})\n` +
+ `Player Screen: (${Math.round(screenPos.x)}, ${Math.round(screenPos.y)})`
);
}
}
diff --git a/src/utils/TextureGenerator.js b/src/utils/TextureGenerator.js
new file mode 100644
index 0000000..3bda746
--- /dev/null
+++ b/src/utils/TextureGenerator.js
@@ -0,0 +1,200 @@
+// Texture Generator
+// Proceduralno generiranje tekstur in sprite-ov
+class TextureGenerator {
+
+ // Generiraj player sprite (32x32px pixel art)
+ static createPlayerSprite(scene, key = 'player') {
+ const size = 32;
+ const canvas = scene.textures.createCanvas(key, size, size);
+ const ctx = canvas.getContext();
+
+ // Clear
+ ctx.clearRect(0, 0, size, size);
+
+ // Barve
+ const skinColor = '#FFDBAC';
+ const hatColor = '#F4E7C6';
+ const shirtColor = '#5CB85C';
+ const pantsColor = '#8B6F47';
+ const outlineColor = '#000000';
+
+ // Funkcija za risanje piksla
+ const pixel = (x, y, color) => {
+ ctx.fillStyle = color;
+ ctx.fillRect(x, y, 1, 1);
+ };
+
+ // Offset za centriranje
+ const ox = 12;
+ const oy = 4;
+
+ // Outline + Hat (8 pixel širok)
+ // Vrh klobuka
+ for (let x = 0; x < 8; x++) {
+ pixel(ox + x, oy + 0, outlineColor);
+ pixel(ox + x, oy + 1, hatColor);
+ pixel(ox + x, oy + 2, hatColor);
+ }
+
+ // Glava (6 pixel široka)
+ for (let y = 3; y < 6; y++) {
+ pixel(ox + 0, oy + y, outlineColor);
+ for (let x = 1; x < 7; x++) {
+ pixel(ox + x, oy + y, skinColor);
+ }
+ pixel(ox + 7, oy + y, outlineColor);
+ }
+
+ // Oči (črni piksli)
+ pixel(ox + 2, oy + 4, outlineColor);
+ pixel(ox + 5, oy + 4, outlineColor);
+
+ // Telo - srajca (6 pixel široka)
+ for (let y = 6; y < 11; y++) {
+ pixel(ox + 0, oy + y, outlineColor);
+ for (let x = 1; x < 7; x++) {
+ pixel(ox + x, oy + y, shirtColor);
+ }
+ pixel(ox + 7, oy + y, outlineColor);
+ }
+
+ // Roke (stranske)
+ for (let y = 7; y < 10; y++) {
+ // Leva roka
+ pixel(ox - 1, oy + y, skinColor);
+ pixel(ox - 2, oy + y, outlineColor);
+ // Desna roka
+ pixel(ox + 8, oy + y, skinColor);
+ pixel(ox + 9, oy + y, outlineColor);
+ }
+
+ // Noge - hlače (vsaka noga 3 piksle široka)
+ for (let y = 11; y < 16; y++) {
+ // Leva noga
+ pixel(ox + 0, oy + y, outlineColor);
+ pixel(ox + 1, oy + y, pantsColor);
+ pixel(ox + 2, oy + y, pantsColor);
+ pixel(ox + 3, oy + y, outlineColor);
+
+ // Desna noga
+ pixel(ox + 4, oy + y, outlineColor);
+ pixel(ox + 5, oy + y, pantsColor);
+ pixel(ox + 6, oy + y, pantsColor);
+ pixel(ox + 7, oy + y, outlineColor);
+ }
+
+ // Dno nog
+ for (let x = 0; x < 8; x++) {
+ pixel(ox + x, oy + 16, outlineColor);
+ }
+
+ canvas.refresh();
+ return canvas;
+ }
+
+ // Generiraj walking animacijo (4 frame-i)
+ static createPlayerWalkSprite(scene, key = 'player_walk') {
+ const frameWidth = 32;
+ const frameHeight = 32;
+ const frameCount = 4;
+
+ const canvas = scene.textures.createCanvas(key, frameWidth * frameCount, frameHeight);
+ const ctx = canvas.getContext();
+
+ // Frame 0: Idle (osnovni sprite)
+ this.drawPlayerFrame(ctx, 0, 0, 0);
+
+ // Frame 1: Left foot forward
+ this.drawPlayerFrame(ctx, frameWidth, 0, 1);
+
+ // Frame 2: Idle
+ this.drawPlayerFrame(ctx, frameWidth * 2, 0, 0);
+
+ // Frame 3: Right foot forward
+ this.drawPlayerFrame(ctx, frameWidth * 3, 0, 2);
+
+ canvas.refresh();
+ return canvas;
+ }
+
+ // Pomožna funkcija za risanje player frame-a
+ static drawPlayerFrame(ctx, offsetX, offsetY, frame) {
+ const size = 32;
+
+ // Barve
+ const skinColor = '#FFDBAC';
+ const hatColor = '#F4E7C6';
+ const shirtColor = '#5CB85C';
+ const pantsColor = '#8B6F47';
+ const outlineColor = '#000000';
+
+ const pixel = (x, y, color) => {
+ ctx.fillStyle = color;
+ ctx.fillRect(offsetX + x, offsetY + y, 1, 1);
+ };
+
+ const ox = 12;
+ const oy = 4;
+
+ // Klobuk
+ for (let x = 0; x < 8; x++) {
+ pixel(ox + x, oy + 0, outlineColor);
+ pixel(ox + x, oy + 1, hatColor);
+ pixel(ox + x, oy + 2, hatColor);
+ }
+
+ // Glava
+ for (let y = 3; y < 6; y++) {
+ pixel(ox + 0, oy + y, outlineColor);
+ for (let x = 1; x < 7; x++) {
+ pixel(ox + x, oy + y, skinColor);
+ }
+ pixel(ox + 7, oy + y, outlineColor);
+ }
+ pixel(ox + 2, oy + 4, outlineColor);
+ pixel(ox + 5, oy + 4, outlineColor);
+
+ // Telo
+ for (let y = 6; y < 11; y++) {
+ pixel(ox + 0, oy + y, outlineColor);
+ for (let x = 1; x < 7; x++) {
+ pixel(ox + x, oy + y, shirtColor);
+ }
+ pixel(ox + 7, oy + y, outlineColor);
+ }
+
+ // Roke
+ for (let y = 7; y < 10; y++) {
+ pixel(ox - 1, oy + y, skinColor);
+ pixel(ox - 2, oy + y, outlineColor);
+ pixel(ox + 8, oy + y, skinColor);
+ pixel(ox + 9, oy + y, outlineColor);
+ }
+
+ // Noge - prilagojeno glede na frame (walking animation)
+ let legOffset = 0;
+ if (frame === 1) legOffset = -1; // Left foot forward
+ if (frame === 2) legOffset = 1; // Right foot forward
+
+ for (let y = 11; y < 16; y++) {
+ const leftShift = (frame === 1) ? 0 : 0;
+ const rightShift = (frame === 2) ? 0 : 0;
+
+ // Leva noga
+ pixel(ox + 0, oy + y, outlineColor);
+ pixel(ox + 1, oy + y, pantsColor);
+ pixel(ox + 2, oy + y, pantsColor);
+ pixel(ox + 3, oy + y, outlineColor);
+
+ // Desna noga
+ pixel(ox + 4, oy + y, outlineColor);
+ pixel(ox + 5, oy + y, pantsColor);
+ pixel(ox + 6, oy + y, pantsColor);
+ pixel(ox + 7, oy + y, outlineColor);
+ }
+
+ for (let x = 0; x < 8; x++) {
+ pixel(ox + x, oy + 16, outlineColor);
+ }
+ }
+}