Add analytics integration with Horchposten backend
Implements session-based analytics tracking that sends gameplay
stats to the Horchposten API. Adds stats.{c,h} for accumulating
per-session metrics (kills, deaths, shots, dashes, jumps, pickups,
damage, time) and analytics.{c,h} with EM_JS bridge for fetch()
calls to the backend. Client ID is persisted in localStorage.
Session start/end hooks are wired into all game lifecycle events
(level transitions, restart, quit, tab close via sendBeacon).
Analytics URL/key are configured via data attributes on the canvas
container. Non-WASM builds compile with no-op stubs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
#include "game/spacecraft.h"
|
||||
#include "game/sprites.h"
|
||||
#include "game/entity_registry.h"
|
||||
#include "game/stats.h"
|
||||
#include "engine/core.h"
|
||||
#include "engine/renderer.h"
|
||||
#include "engine/physics.h"
|
||||
@@ -174,9 +175,11 @@ bool level_load_generated(Level *level, Tilemap *gen_map) {
|
||||
static Camera *s_active_camera = NULL;
|
||||
|
||||
static void damage_entity(Entity *target, int damage) {
|
||||
stats_record_damage_dealt(damage);
|
||||
target->health -= damage;
|
||||
if (target->health <= 0) {
|
||||
target->flags |= ENTITY_DEAD;
|
||||
stats_record_kill();
|
||||
|
||||
/* Death particles — centered on entity */
|
||||
Vec2 center = vec2(
|
||||
@@ -210,6 +213,7 @@ static void damage_entity(Entity *target, int damage) {
|
||||
|
||||
static void damage_player(Entity *player, int damage, Entity *source) {
|
||||
PlayerData *ppd = (PlayerData *)player->data;
|
||||
stats_record_damage_taken(damage);
|
||||
damage_entity(player, damage);
|
||||
|
||||
/* Screen shake on player hit (stronger) */
|
||||
@@ -264,6 +268,7 @@ static void handle_collisions(EntityManager *em) {
|
||||
if (from_player && entity_is_enemy(b)) {
|
||||
if (physics_overlap(&a->body, &b->body)) {
|
||||
damage_entity(b, a->damage);
|
||||
stats_record_shot_hit();
|
||||
hit = true;
|
||||
}
|
||||
}
|
||||
@@ -366,6 +371,7 @@ static void handle_collisions(EntityManager *em) {
|
||||
}
|
||||
|
||||
if (picked_up) {
|
||||
stats_record_pickup();
|
||||
/* Pickup particles */
|
||||
Vec2 center = vec2(
|
||||
a->body.pos.x + a->body.size.x * 0.5f,
|
||||
@@ -566,6 +572,7 @@ void level_update(Level *level, float dt) {
|
||||
for (int i = 0; i < level->entities.count; i++) {
|
||||
Entity *e = &level->entities.entities[i];
|
||||
if (e->active && e->type == ENT_PLAYER && player_wants_respawn(e)) {
|
||||
stats_record_death();
|
||||
player_respawn(e, level->map.player_spawn);
|
||||
Vec2 center = vec2(
|
||||
e->body.pos.x + e->body.size.x * 0.5f,
|
||||
|
||||
Reference in New Issue
Block a user