allow neko to scratch the walls of the monitor

This commit is contained in:
Virt 2025-04-15 14:16:10 +02:00
commit 8892e69e93
3 changed files with 116 additions and 26 deletions

134
wayneko.c
View file

@ -33,6 +33,7 @@ const char usage[] =
" --background-colour 0xRRGGBB[AA]\n"
" --outline-colour 0xRRGGBB[AA]\n"
" --type plain|striped|random\n"
" --wall none|left|right|both\n"
" --idle-sleep seconds\n"
" --sleep-phase seconds-seconds\n"
" --awake-phase seconds-seconds\n"
@ -74,6 +75,18 @@ enum Neko
NEKO_RUN_RIGHT_2,
NEKO_RUN_LEFT_1,
NEKO_RUN_LEFT_2,
NEKO_WALL_RIGHT_1,
NEKO_WALL_RIGHT_2,
NEKO_WALL_LEFT_1,
NEKO_WALL_LEFT_2,
};
// lsb is right, next bit is left
enum Wall {
WALL_NONE = 0,
WALL_RIGHT,
WALL_LEFT,
WALL_BOTH
};
const uint16_t animation_timeout = 200; /* milliseconds */
@ -84,6 +97,7 @@ bool follow_pointer = false; // TODO: implement this again
bool recreate_surface_on_close = false;
enum zwlr_layer_shell_v1_layer layer = ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM;
float start_position = 0.5;
enum Wall wall_behaviour = WALL_BOTH;
struct ext_idle_notifier_v1 *idle_notifier = NULL;
uint32_t neko_idle_timeout_ms = 180000; /* 3 minutes. */
@ -150,6 +164,7 @@ struct Surface surface = { 0 };
const uint32_t desired_surface_height = neko_size;
const uint8_t neko_x_advance = 15;
const uint32_t neko_x_wall_attraction = 400;
int ret = EXIT_SUCCESS;
bool loop = true;
@ -772,9 +787,9 @@ static void atlas_composite_neko (struct Buffer *buffer, enum Neko neko_type, ui
);
}
static bool animation_can_run_left (void)
static bool animation_can_run_left (bool tight)
{
return surface.neko_x > neko_x_advance;
return surface.neko_x > (tight ? 0 : neko_x_advance);
}
static void animation_neko_do_run_left (void)
@ -783,9 +798,9 @@ static void animation_neko_do_run_left (void)
animation_ticks_until_next_frame = 0;
}
static bool animation_can_run_right (void)
static bool animation_can_run_right (bool tight)
{
return surface.neko_x < surface.width - neko_size - neko_x_advance;
return surface.neko_x < surface.width - neko_size - (tight ? 0 : neko_x_advance);
}
static void animation_neko_do_run_right (void)
@ -794,16 +809,20 @@ static void animation_neko_do_run_right (void)
animation_ticks_until_next_frame = 0;
}
static void animation_neko_advance_left (void)
static void animation_neko_advance_left (bool tight)
{
surface.prev_neko_x = surface.neko_x;
surface.neko_x -= neko_x_advance;
if (tight) surface.neko_x = 0;
else surface.neko_x -= neko_x_advance;
}
static void animation_neko_advance_right (void)
static void animation_neko_advance_right (bool tight)
{
surface.prev_neko_x = surface.neko_x;
surface.neko_x += neko_x_advance;
if (tight) surface.neko_x = (uint16_t) surface.width - neko_size;
else surface.neko_x += neko_x_advance;
}
static void animation_neko_do_stare (bool quick)
@ -842,6 +861,18 @@ static void animation_neko_do_scratch (void)
animation_ticks_until_next_frame = 0;
}
static void animation_neko_do_wall_left (void)
{
current_neko = current_neko == NEKO_WALL_LEFT_1 ? NEKO_WALL_LEFT_2 : NEKO_WALL_LEFT_1;
animation_ticks_until_next_frame = 0;
}
static void animation_neko_do_wall_right (void)
{
current_neko = current_neko == NEKO_WALL_RIGHT_1 ? NEKO_WALL_RIGHT_2 : NEKO_WALL_RIGHT_1;
animation_ticks_until_next_frame = 0;
}
static bool animtation_neko_wants_sleep (void)
{
/* Neko likes to sleep at night. */
@ -875,12 +906,12 @@ static bool animation_next_state_with_hotspot (uint32_t x)
case NEKO_SHOCK:
case NEKO_RUN_LEFT_1:
case NEKO_RUN_LEFT_2:
if (!animation_can_run_left())
if (!animation_can_run_left(false))
{
animation_neko_do_stare(true);
return true;
}
animation_neko_advance_left();
animation_neko_advance_left(false);
animation_neko_do_run_left();
return true;
@ -896,12 +927,12 @@ static bool animation_next_state_with_hotspot (uint32_t x)
case NEKO_SHOCK:
case NEKO_RUN_RIGHT_1:
case NEKO_RUN_RIGHT_2:
if (!animation_can_run_right())
if (!animation_can_run_right(false))
{
animation_neko_do_stare(true);
return true;
}
animation_neko_advance_right();
animation_neko_advance_right(false);
animation_neko_do_run_right();
return true;
@ -972,19 +1003,31 @@ static bool animation_next_state_awake (void)
break;
case 4:
if (!animation_can_run_left())
if (!animation_can_run_left(false))
return false;
animation_neko_advance_left();
animation_neko_advance_left(false);
animation_neko_do_run_left();
break;
case 5:
if (!animation_can_run_right())
if (!animation_can_run_right(false))
return false;
animation_neko_advance_right();
animation_neko_advance_right(false);
animation_neko_do_run_right();
break;
case 6:
case 7:
case 8:
case 9:
if (surface.neko_x == 0 && (wall_behaviour & WALL_LEFT))
animation_neko_do_wall_left();
else if (surface.neko_x + neko_size == surface.width && (wall_behaviour & WALL_RIGHT))
animation_neko_do_wall_right();
else
return false;
break;
default:
return false;
}
@ -992,23 +1035,30 @@ static bool animation_next_state_awake (void)
case NEKO_RUN_RIGHT_1:
case NEKO_RUN_RIGHT_2:
if ( animation_can_run_right() && rand() % 4 != 0 )
{
bool attracted_right = surface.width - surface.neko_x + neko_size < neko_x_wall_attraction;
if (!animation_can_run_right(false) && animation_can_run_right(true) && rand() % 8 != 0) {
animation_neko_do_run_right();
animation_neko_advance_right();
}
else
animation_neko_advance_right(true);
} else if ( animation_can_run_right(false) && rand() % (attracted_right ? 8 : 4) != 0 ) {
animation_neko_do_run_right();
animation_neko_advance_right(false);
} else
animation_neko_do_stare(false);
return true;
case NEKO_RUN_LEFT_1:
case NEKO_RUN_LEFT_2:
if ( animation_can_run_left() && rand() % 4 != 0 )
{
bool attracted_left = surface.neko_x < neko_x_wall_attraction;
if (!animation_can_run_left(false) && animation_can_run_left(true) && rand() % 8 != 0) {
animation_neko_do_run_left();
animation_neko_advance_left();
}
else
animation_neko_advance_left(true);
} else if ( animation_can_run_left(false) && rand() % (attracted_left ? 8 : 4) != 0 ) {
animation_neko_do_run_left();
animation_neko_advance_left(false);
} else
animation_neko_do_stare(false);
return true;
@ -1028,6 +1078,22 @@ static bool animation_next_state_awake (void)
animation_neko_do_scratch();
return true;
case NEKO_WALL_LEFT_1:
case NEKO_WALL_LEFT_2:
if ( rand() % 12 == 0 )
animation_neko_do_stare(false);
else
animation_neko_do_wall_left();
return true;
case NEKO_WALL_RIGHT_1:
case NEKO_WALL_RIGHT_2:
if ( rand() % 12 == 0 )
animation_neko_do_stare(false);
else
animation_neko_do_wall_right();
return true;
case NEKO_THINK:
if ( rand() % 2 == 0 )
animation_neko_do_stare(false);
@ -1456,6 +1522,22 @@ int main (int argc, char *argv[])
return EXIT_FAILURE;
}
}
else if ( strcmp(argv[i], "--wall") == 0 )
{
const char *t = get_argument(argc, argv, &i);
if ( t == NULL )
return EXIT_FAILURE;
if (strcmp(t, "none") == 0) wall_behaviour = WALL_NONE;
else if (strcmp(t, "right") == 0) wall_behaviour = WALL_RIGHT;
else if (strcmp(t, "left") == 0) wall_behaviour = WALL_LEFT;
else if (strcmp(t, "both") == 0) wall_behaviour = WALL_BOTH;
else
{
fprintf(stderr, "ERROR: Unknown argument '%s' for flag '--wall'.\n", t);
return EXIT_FAILURE;
}
}
else if ( strcmp(argv[i], "--follow-pointer") == 0 )
{
fprintf(stderr, "ERROR: Functionality for flag '--follow-pointer' is not yet implemented in this fork.\n");