dc99af6bb3
Build and deploy / deploy (push) Successful in 36s
Un score falsifié envoyé directement à submit_icarus_score/submit_melon_score pouvait se convertir en vraies gloires au Tribunal (plafond abaissé de 1 000 000 à 5000, contrainte + RPC). Les fonctions cron-only award_*_points_if_due() n'étaient protégées que par un commentaire, pas un vrai REVOKE. Le bucket avatars n'avait aucune limite de taille/type. La banque complète des questions du Char (spoiler du jeu) était lisible par tout Citoyen via /char ou un appel direct — RLS restreinte aux juges, /char passe désormais par la RPC chariot_revealed_question(). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
84 lines
4.2 KiB
TypeScript
84 lines
4.2 KiB
TypeScript
// Format classique Flappy Bird : le personnage reste à une position d'écran
|
|
// fixe, le décor défile de droite à gauche (pas de piste qui change de
|
|
// forme selon le jour — parcours procédural à chaque partie, sans graine
|
|
// partagée, puisqu'il n'y a plus de comparaison "même tracé pour tous").
|
|
export const VIEWPORT_WIDTH = 340;
|
|
export const VIEWPORT_HEIGHT = 500;
|
|
|
|
export const GROUND_HEIGHT = 36;
|
|
export const GROUND_Y = VIEWPORT_HEIGHT - GROUND_HEIGHT;
|
|
|
|
export const ICARUS_X = VIEWPORT_WIDTH * 0.3;
|
|
export const ICARUS_RADIUS = 12;
|
|
export const ICARUS_START_Y = VIEWPORT_HEIGHT / 2;
|
|
|
|
export const GRAVITY = 900; // unités/seconde²
|
|
export const FLAP_IMPULSE = -300; // vitesse verticale imposée à chaque battement d'aile
|
|
export const MAX_FALL_SPEED = 480;
|
|
export const TILT_MAX_RADIANS = (45 * Math.PI) / 180;
|
|
|
|
// Animation des ailes (indépendante de l'inclinaison du corps) : un battement
|
|
// continu en boucle (pour que ça se voie même sans taper, dès l'écran de
|
|
// repos) + un battement plus ample et net à chaque tap, qui prend le dessus
|
|
// brièvement sur le cycle continu.
|
|
export const WING_REST_RADIANS = -(20 * Math.PI) / 180;
|
|
export const WING_IDLE_PEAK_RADIANS = (15 * Math.PI) / 180;
|
|
export const WING_IDLE_PERIOD_MS = 480;
|
|
export const WING_FLAP_MAX_RADIANS = (75 * Math.PI) / 180;
|
|
export const WING_FLAP_ANIM_MS = 260;
|
|
|
|
export const FORWARD_SPEED = 130; // unités/seconde, vitesse de défilement des colonnes de base
|
|
export const COLUMN_WIDTH = 46;
|
|
export const COLUMN_GAP = 128; // écart de base entre les colonnes d'une paire
|
|
export const COLUMN_SPACING = 210;
|
|
export const COLUMN_GAP_MARGIN = 50; // distance mini entre le centre du trou et le sol/plafond
|
|
|
|
// Difficulté progressive : au-delà de DIFFICULTY_START_SCORE, la vitesse
|
|
// augmente et l'écart entre les colonnes se resserre progressivement,
|
|
// jusqu'à un palier atteint à DIFFICULTY_START_SCORE + DIFFICULTY_RAMP_SPAN
|
|
// (au-delà, la difficulté n'augmente plus — évite un jeu qui devient
|
|
// littéralement impossible sur une très longue partie).
|
|
export const DIFFICULTY_START_SCORE = 10;
|
|
export const DIFFICULTY_RAMP_SPAN = 40;
|
|
export const SPEED_MAX_MULTIPLIER = 1.6;
|
|
export const GAP_MIN_MULTIPLIER = 0.75;
|
|
|
|
export const FIXED_DT_MS = 1000 / 60;
|
|
export const MAX_FRAME_DT_MS = 250; // évite la "spirale de la mort" après un onglet en arrière-plan
|
|
|
|
// Boost (éclair de Zeus) : apparaît tous les BOOST_MIN..MAX_COLUMN_INTERVAL
|
|
// colonnes (tirage aléatoire à chaque fois), au centre du trou de la
|
|
// colonne qui le porte. Le ramasser active le bouclier pour les
|
|
// BOOST_MIN..MAX_CHARGES prochaines colonnes (distance, pas un budget de
|
|
// casses) : tant qu'il en reste, toucher une colonne (ce qui tuerait
|
|
// normalement) la casse à la place — mais une colonne franchie sans
|
|
// contact compte aussi dans cette distance, elle n'est pas cassée pour
|
|
// autant.
|
|
export const BOOST_RADIUS = 14; // taille du rond dessiné
|
|
// Rayon de ramassage réel, plus généreux que le rond dessiné : sinon seul
|
|
// un vol quasi pile au centre du trou le ramassait, malgré une fréquence
|
|
// d'apparition correcte (vérifié par simulation).
|
|
export const BOOST_COLLECT_RADIUS = 34;
|
|
// Rare et exceptionnel plutôt que fréquent : intervalle large, pas de
|
|
// plafond dur — une partie moyenne (~50 de score) n'en voit naturellement
|
|
// que 1 à 2, mais une partie plus longue peut légitimement en voir plus.
|
|
export const BOOST_MIN_COLUMN_INTERVAL = 15;
|
|
export const BOOST_MAX_COLUMN_INTERVAL = 25;
|
|
export const BOOST_MIN_CHARGES = 3;
|
|
export const BOOST_MAX_CHARGES = 8;
|
|
// Vitesse de défilement multipliée tant que le bouclier est actif (sans
|
|
// risque : une colonne touchée casse au lieu de tuer pendant cette
|
|
// période) — renforce la sensation de vitesse du bouclier actif.
|
|
export const BOOST_SPEED_MULTIPLIER = 1.7;
|
|
// Animation de cueillette : Icare fait un bond en avant (aller-retour,
|
|
// pic à mi-parcours) plutôt que le halo statique d'avant.
|
|
export const BOOST_DASH_MS = 350;
|
|
export const BOOST_DASH_DISTANCE = 22;
|
|
export const SHATTER_ANIM_MS = 450;
|
|
|
|
export const MIN_SCORE = 0;
|
|
// Doit rester aligné avec la contrainte icarus_scores_best_score_check
|
|
// (supabase/schema.sql) — celle-ci est la vraie garantie, cette constante
|
|
// n'est qu'une valeur de référence côté client.
|
|
export const MAX_SCORE = 5000;
|