walking stickman is now also crawling
@@ -55,6 +55,7 @@
|
|||||||
pkgs.probe-rs-tools
|
pkgs.probe-rs-tools
|
||||||
pkgs.bear
|
pkgs.bear
|
||||||
pkgs.chafa
|
pkgs.chafa
|
||||||
|
pkgs.imagemagick
|
||||||
mbedTools
|
mbedTools
|
||||||
pyOcd
|
pyOcd
|
||||||
];
|
];
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.4 MiB After Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 1.6 MiB After Width: | Height: | Size: 1.6 MiB |
7
semestralka1/chafa/character/2out.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
.....a@$..
|
||||||
|
.....7PF..
|
||||||
|
..yaM@@__y
|
||||||
|
..@.y@FFF~
|
||||||
|
..._$M@_..
|
||||||
|
yaa@~.`@y.
|
||||||
|
........@r
|
||||||
7
semestralka1/chafa/character/3out.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
.g@$
|
||||||
|
.7PF
|
||||||
|
y@$.
|
||||||
|
0@F.
|
||||||
|
4@$.
|
||||||
|
y$@.
|
||||||
|
u@..
|
||||||
9
semestralka1/chafa/character/out.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
......_g@$w..
|
||||||
|
......4@@@F..
|
||||||
|
.....yyyy`...
|
||||||
|
...g@~@@@y_ys
|
||||||
|
..4F..@@FTF~.
|
||||||
|
.....g@@g,...
|
||||||
|
..._a@^.4@_..
|
||||||
|
4R@F~....7@y.
|
||||||
|
..........~@.
|
||||||
4
semestralka1/chafa/character/out_crawl1.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
.._$@.
|
||||||
|
.$By`.
|
||||||
|
4@$@@a
|
||||||
|
aa@W@.
|
||||||
3
semestralka1/chafa/character/out_crawl2.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
a@@Bw_,
|
||||||
|
7@@Db@$
|
||||||
|
4@@PF#@
|
||||||
BIN
semestralka1/chafa/character/predloha.jpg
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
semestralka1/chafa/character/predloha2.jpg
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
semestralka1/chafa/character/predloha2_scaled.xcf
Normal file
BIN
semestralka1/chafa/character/predloha_crawl1.jpg
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
semestralka1/chafa/character/predloha_crawl2.jpg
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
semestralka1/chafa/character/predloha_run_a.jpg
Normal file
|
After Width: | Height: | Size: 8.3 KiB |
BIN
semestralka1/chafa/character/predloha_run_b.jpg
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
4
semestralka1/chafa/character/run_chafa.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
chafa --symbols ascii-block -c none --fill none --invert --size=13x20 predloha_run_a.jpg > out.txt
|
||||||
|
|
||||||
|
a = 78x111
|
||||||
|
b = 34x111
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "background.h"
|
#include "background.h"
|
||||||
#include "mbed.h"
|
#include "mbed.h"
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
|
#include "player_mask.h"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
extern BufferedSerial serial_port;
|
extern BufferedSerial serial_port;
|
||||||
@@ -17,19 +18,24 @@ static bool message_active = false;
|
|||||||
|
|
||||||
void draw_mask(const char *unused_filename, int shift, const char *text);
|
void draw_mask(const char *unused_filename, int shift, const char *text);
|
||||||
|
|
||||||
static bool read_uart() {
|
// Returns:
|
||||||
|
// 0 = no change - walk1
|
||||||
|
// 1 = normal redraw - walk2
|
||||||
|
// 2 = button triggered - crawl1
|
||||||
|
static int read_uart() {
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
bool triggered = false;
|
||||||
|
|
||||||
// cita spravu z uartu
|
// cita spravu z uartu
|
||||||
if (serial_port.readable()) {
|
if (serial_port.readable()) {
|
||||||
memset(rx_buffer, 0, sizeof(rx_buffer));
|
memset(rx_buffer, 0, sizeof(rx_buffer));
|
||||||
ssize_t num = serial_port.read(rx_buffer, sizeof(rx_buffer) - 1);
|
ssize_t num = serial_port.read(rx_buffer, sizeof(rx_buffer) - 1);
|
||||||
if (num > 0) {
|
if (num > 0) {
|
||||||
// toogle ledky
|
led = !led; // toogle ledky
|
||||||
led = !led;
|
|
||||||
strncpy(message, rx_buffer, sizeof(message) - 1);
|
strncpy(message, rx_buffer, sizeof(message) - 1);
|
||||||
message_active = true;
|
message_active = true;
|
||||||
changed = true;
|
changed = true;
|
||||||
|
triggered = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,11 +55,15 @@ static bool read_uart() {
|
|||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return changed;
|
if (triggered)
|
||||||
|
return 2; // LED toggled press
|
||||||
|
if (changed)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool update_animation(Timer &anim_timer, int &shift, int speed) {
|
static bool update_animation(Timer &anim_timer, int &shift, int speed) {
|
||||||
if (anim_timer.elapsed_time() >= 200ms) {
|
if (anim_timer.elapsed_time() >= 170ms) {
|
||||||
// speed determines scroll steps per tick
|
// speed determines scroll steps per tick
|
||||||
shift += speed;
|
shift += speed;
|
||||||
anim_timer.reset();
|
anim_timer.reset();
|
||||||
@@ -75,17 +85,28 @@ void render_loop(int speed) {
|
|||||||
while (true) {
|
while (true) {
|
||||||
need_redraw = false;
|
need_redraw = false;
|
||||||
|
|
||||||
if (read_uart()) {
|
int uart_state = read_uart(); // returns 0/1/2
|
||||||
need_redraw = true;
|
if (uart_state == 1)
|
||||||
}
|
need_redraw = true;
|
||||||
|
|
||||||
|
bool triggered = (uart_state == 2);
|
||||||
|
|
||||||
if (update_animation(anim_timer, shift, speed))
|
if (update_animation(anim_timer, shift, speed))
|
||||||
need_redraw = true;
|
need_redraw = true;
|
||||||
|
|
||||||
if (need_redraw) {
|
if (need_redraw || triggered) {
|
||||||
draw_mask(bg_file, shift, message_active ? message : nullptr);
|
draw_mask(bg_file, shift, message_active ? message : nullptr);
|
||||||
draw_player(18, 16);
|
|
||||||
ThisThread::sleep_for(50ms);
|
static int frame = 0;
|
||||||
|
if (triggered) {
|
||||||
|
// Display triggered frame once
|
||||||
|
draw_player(18, 13, 2);
|
||||||
|
} else {
|
||||||
|
draw_player(18, 13, frame);
|
||||||
|
frame = (frame + 1) % 2; // alternate between frame 0 and 1
|
||||||
|
}
|
||||||
|
|
||||||
|
ThisThread::sleep_for(50ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
ThisThread::sleep_for(25ms);
|
ThisThread::sleep_for(25ms);
|
||||||
|
|||||||
@@ -4,16 +4,32 @@
|
|||||||
#include "player_mask.h"
|
#include "player_mask.h"
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
void draw_player(int view_width, int view_height) {
|
void draw_player(int view_width, int view_height, int frame_index) {
|
||||||
const int sprite_height = PLAYER_MASK_LINES;
|
if (frame_index < 0 || frame_index >= PLAYER_FRAME_COUNT)
|
||||||
const int sprite_width = 3; // all rows are same width (3 chars)
|
frame_index = 0; // fallback
|
||||||
|
|
||||||
|
const char **sprite = PLAYER_FRAMES[frame_index];
|
||||||
|
int sprite_height = 0;
|
||||||
|
if (frame_index == 0)
|
||||||
|
sprite_height = PLAYER_MASK_LINES_FRAME_1;
|
||||||
|
else if (frame_index == 1)
|
||||||
|
sprite_height = PLAYER_MASK_LINES_FRAME_2;
|
||||||
|
else
|
||||||
|
sprite_height = PLAYER_MASK_LINES_FRAME_3;
|
||||||
|
|
||||||
|
// Width from first line
|
||||||
|
int sprite_width = 0;
|
||||||
|
if (sprite_height > 0) {
|
||||||
|
const char *first_line = sprite[0];
|
||||||
|
while (first_line[sprite_width] != '\0')
|
||||||
|
sprite_width++;
|
||||||
|
}
|
||||||
|
|
||||||
int center_x = view_width / 2 - sprite_width / 2;
|
int center_x = view_width / 2 - sprite_width / 2;
|
||||||
int center_y = view_height / 2 - sprite_height / 2;
|
int center_y = view_height / 2 - sprite_height / 2;
|
||||||
|
|
||||||
for (int i = 0; i < sprite_height; i++) {
|
for (int i = 0; i < sprite_height; i++) {
|
||||||
printf("\033[%d;%dH%s", center_y + i + 1, center_x + 1, PLAYER_MASK[i]);
|
printf("\033[%d;%dH%s", center_y + i + 1, center_x + 1, sprite[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,4 +2,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Draw the player object centered over the background
|
// Draw the player object centered over the background
|
||||||
void draw_player(int view_width, int view_height);
|
void draw_player(int view_width, int view_height, int frame_index);
|
||||||
|
|||||||
@@ -1,12 +1,50 @@
|
|||||||
// src/render/player_mask.h
|
// src/render/player_mask.h
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Simple 3x3 player sprite for overlay drawing
|
// Player frame 1
|
||||||
static const char *PLAYER_MASK[] = {
|
static const char *PLAYER_MASK_FRAME_1[] = {
|
||||||
" @ ",
|
".....a@$..",
|
||||||
"/|\\",
|
".....7PF..",
|
||||||
"/ \\"
|
"..yaM@@__y",
|
||||||
|
"..@.y@FFF~",
|
||||||
|
"..._$M@_..",
|
||||||
|
"yaa@~.`@y.",
|
||||||
|
"........@r"
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int PLAYER_MASK_LINES =
|
// Player frame 2
|
||||||
sizeof(PLAYER_MASK) / sizeof(PLAYER_MASK[0]);
|
static const char *PLAYER_MASK_FRAME_2[] = {
|
||||||
|
".g@$",
|
||||||
|
".7PF",
|
||||||
|
"y@$.",
|
||||||
|
"0@F.",
|
||||||
|
"4@$.",
|
||||||
|
"y$@.",
|
||||||
|
"u@.."
|
||||||
|
};
|
||||||
|
|
||||||
|
// Player frame 3 (triggered)
|
||||||
|
static const char *PLAYER_MASK_FRAME_3[] = {
|
||||||
|
".._$@.",
|
||||||
|
".$By`.",
|
||||||
|
"4@$@@a",
|
||||||
|
"aa@W@."
|
||||||
|
};
|
||||||
|
|
||||||
|
// Combine frames for easy access
|
||||||
|
static const char **PLAYER_FRAMES[] = {
|
||||||
|
PLAYER_MASK_FRAME_1, // 0
|
||||||
|
PLAYER_MASK_FRAME_2, // 1
|
||||||
|
PLAYER_MASK_FRAME_3 // 2 (triggered)
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int PLAYER_FRAME_COUNT = sizeof(PLAYER_FRAMES) / sizeof(PLAYER_FRAMES[0]);
|
||||||
|
|
||||||
|
// Line counts per frame
|
||||||
|
static const int PLAYER_MASK_LINES_FRAME_1 =
|
||||||
|
sizeof(PLAYER_MASK_FRAME_1) / sizeof(PLAYER_MASK_FRAME_1[0]);
|
||||||
|
static const int PLAYER_MASK_LINES_FRAME_2 =
|
||||||
|
sizeof(PLAYER_MASK_FRAME_2) / sizeof(PLAYER_MASK_FRAME_2[0]);
|
||||||
|
static const int PLAYER_MASK_LINES_FRAME_3 =
|
||||||
|
sizeof(PLAYER_MASK_FRAME_3) / sizeof(PLAYER_MASK_FRAME_3[0]);
|
||||||
|
|||||||