0.1.0-0-pre.6

This commit is contained in:
2026-09-16 08:49:45 +02:00
parent 380a24681d
commit 21e45d333d
22 changed files with 452 additions and 34 deletions

7
Android/.gitignore vendored Normal file
View File

@@ -0,0 +1,7 @@
# file: Android/.gitignore
# version: 1
.gradle/
**/build/
local.properties
libs/*.aar

View File

@@ -1,13 +1,11 @@
<!-- file: Android/README.md --> <!-- file: Android/README.md -->
<!-- version: 1 --> <!-- version: 2 -->
# Android # Android
Squelette du frontend Android multi-module. Le frontend Android est un projet Gradle multi-module séparé du workspace Cargo.
La baseline définit les frontières Java et les modules, mais ne fige pas encore Android Gradle Plugin, SDK/NDK, SDL3 AAR ni le pipeline Cargo/NDK. Ces éléments seront ajoutés ensemble dans la prerelease Android exécutable afin d'éviter une fausse configuration partiellement fonctionnelle. ## Modules
Structure cible :
```text ```text
Android/ Android/
@@ -16,4 +14,44 @@ Android/
└── game-snake-poc/ └── game-snake-poc/
``` ```
`common` deviendra une Android Library. Chaque module jeu deviendra une application indépendante et réutilisera directement les crates Rust du workspace racine sans les recopier. `common` est une Android Library Java qui fournit la frontière commune et dépend de l'AAR officiel SDL3.
Chaque module `game-*` est une application Android indépendante et dépend du module `common`.
## Toolchain de référence
Pour la baseline `0.1.0-0-pre.6` :
- Android Gradle Plugin `9.4.0` ;
- Gradle `9.6.0` attendu par AGP 9.4 ;
- JDK `17` ;
- `compileSdk 36` ;
- `targetSdk 36` ;
- `minSdk 21` ;
- SDL3 Android AAR `3.4.16`.
Le NDK n'est pas encore utilisé directement dans ce delta. Le prochain jalon introduira la compilation Rust Android `cdylib` et figera la configuration NDK réellement nécessaire.
## SDL3 AAR
L'archive n'est pas vendorizée dans le dépôt.
Placer :
```text
SDL3-3.4.16.aar
```
dans :
```text
Android/libs/
```
Le module `common` consomme cet artefact et `SaseGameActivity` étend désormais `org.libsdl.app.SDLActivity`.
## Limite volontaire de ce jalon
Les APK peuvent être compilés côté Java/SDL3 une fois l'AAR disponible, mais ne disposent pas encore du `cdylib` Rust contenant le point d'entrée de jeu.
Le lancement fonctionnel sur appareil/émulateur appartient donc au delta suivant.

View File

@@ -1,4 +1,7 @@
// file: Android/build.gradle // file: Android/build.gradle
// version: 1 // version: 2
// Android Gradle Plugin and repositories are intentionally introduced in the dedicated executable Android prerelease. plugins {
id 'com.android.application' version '9.4.0' apply false
id 'com.android.library' version '9.4.0' apply false
}

View File

@@ -1,4 +1,26 @@
// file: Android/common/build.gradle // file: Android/common/build.gradle
// version: 1 // version: 2
// This module will become the reusable Android library containing SDLActivity integration and common platform services. plugins {
id 'com.android.library'
}
def sdl3AarName = providers.gradleProperty("sdl3AarName").get()
android {
namespace 'com.sasedev.games.common'
compileSdk 36
defaultConfig {
minSdk 21
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
}
dependencies {
api files("../libs/${sdl3AarName}")
}

View File

@@ -0,0 +1,3 @@
<!-- file: Android/common/src/main/AndroidManifest.xml -->
<!-- version: 1 -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" />

View File

@@ -1,14 +1,14 @@
// file: Android/common/src/main/java/com/sasedev/games/common/SaseGameActivity.java // file: Android/common/src/main/java/com/sasedev/games/common/SaseGameActivity.java
// version: 1 // version: 2
package com.sasedev.games.common; package com.sasedev.games.common;
/** /**
* Common Android activity boundary for games.sasedev applications. * Common Android activity boundary for games.sasedev applications.
* *
* <p>The executable Android delta will make this class extend SDLActivity once the SDL3 AAR is introduced.</p> * <p>The SDL3 Android AAR supplies the common {@code SDLActivity} host. Game-specific activities extend this class.</p>
*/ */
public abstract class SaseGameActivity { public abstract class SaseGameActivity extends org.libsdl.app.SDLActivity {
/** /**
* Returns the stable identifier of the game hosted by the activity. * Returns the stable identifier of the game hosted by the activity.
* *

View File

@@ -1,4 +1,28 @@
// file: Android/game-reflex-poc/build.gradle // file: Android/game-reflex-poc/build.gradle
// version: 1 // version: 2
// This module will become the Reflex POC Android application. plugins {
id 'com.android.application'
}
android {
namespace 'com.sasedev.games.reflex'
compileSdk 36
defaultConfig {
applicationId 'com.sasedev.games.reflex'
minSdk 21
targetSdk 36
versionCode 1
versionName '0.1.0-0-pre.6'
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
}
dependencies {
implementation project(':common')
}

View File

@@ -0,0 +1,19 @@
<!-- file: Android/game-reflex-poc/src/main/AndroidManifest.xml -->
<!-- version: 1 -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:allowBackup="true"
android:label="@string/app_name"
android:supportsRtl="true">
<activity
android:name=".ReflexActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
android:exported="true"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -1,4 +1,28 @@
// file: Android/game-snake-poc/build.gradle // file: Android/game-snake-poc/build.gradle
// version: 1 // version: 2
// This module will become the Snake POC Android application. plugins {
id 'com.android.application'
}
android {
namespace 'com.sasedev.games.snake'
compileSdk 36
defaultConfig {
applicationId 'com.sasedev.games.snake'
minSdk 21
targetSdk 36
versionCode 1
versionName '0.1.0-0-pre.6'
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
}
dependencies {
implementation project(':common')
}

View File

@@ -0,0 +1,19 @@
<!-- file: Android/game-snake-poc/src/main/AndroidManifest.xml -->
<!-- version: 1 -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:allowBackup="true"
android:label="@string/app_name"
android:supportsRtl="true">
<activity
android:name=".SnakeActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
android:exported="true"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -0,0 +1,6 @@
# file: Android/gradle.properties
# version: 1
android.useAndroidX=true
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
sdl3AarName=SDL3-3.4.16.aar

24
Android/libs/README.md Normal file
View File

@@ -0,0 +1,24 @@
<!-- file: Android/libs/README.md -->
<!-- version: 1 -->
# SDL3 Android Archive
Le projet Android consomme l'archive Android officielle SDL3 sous forme de dépendance externe locale.
Version attendue pour cette baseline :
```text
SDL3-3.4.16.aar
```
Le fichier doit être placé ici :
```text
Android/libs/SDL3-3.4.16.aar
```
L'archive AAR n'est pas versionnée dans le dépôt.
La version attendue est déclarée dans `Android/gradle.properties` avec `sdl3AarName`.
SDL recommande l'utilisation de son archive Android pour éviter de recopier les sources C et Java de SDL dans chaque projet Android. L'AAR contient notamment la couche Java SDL et les bibliothèques natives nécessaires au runtime Android.

View File

@@ -1,5 +1,21 @@
// file: Android/settings.gradle // file: Android/settings.gradle
// version: 1 // version: 2
pluginManagement {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}
rootProject.name = "games-sasedev-android" rootProject.name = "games-sasedev-android"

View File

@@ -1,5 +1,5 @@
# file: Cargo.toml # file: Cargo.toml
# version: 11 # version: 12
[workspace] [workspace]
resolver = "3" resolver = "3"
@@ -15,7 +15,7 @@ members = [
] ]
[workspace.package] [workspace.package]
version = "0.1.0-0-pre.5.fix.3" version = "0.1.0-0-pre.6"
edition = "2024" edition = "2024"
license = "MIT" license = "MIT"
repository = "https://git.sasedev.com/Sasedev/games" repository = "https://git.sasedev.com/Sasedev/games"

View File

@@ -1,5 +1,5 @@
<!-- file: ROADMAP.md --> <!-- file: ROADMAP.md -->
<!-- version: 4 --> <!-- version: 5 -->
# Roadmap # Roadmap
@@ -9,12 +9,13 @@
- [x] `0-pre.2` — consolidation documentaire issue de l'architecture de référence, runners Desktop par jeu et politique normative des commandes. - [x] `0-pre.2` — consolidation documentaire issue de l'architecture de référence, runners Desktop par jeu et politique normative des commandes.
- [x] `0-pre.3` — première boucle moteur exécutable Desktop : temps, input abstrait, capacités de monétisation optionnelles et état de jeu minimal via les runners. - [x] `0-pre.3` — première boucle moteur exécutable Desktop : temps, input abstrait, capacités de monétisation optionnelles et état de jeu minimal via les runners.
- [x] `0-pre.4` — architecture de tests hors `src/`, stratégie de tests ciblés et socle `tracing`/`tracing-subscriber`/`tracing-appender`. - [x] `0-pre.4` — architecture de tests hors `src/`, stratégie de tests ciblés et socle `tracing`/`tracing-subscriber`/`tracing-appender`.
- [ ] `0-pre.5` — intégration SDL3 Desktop réelle et premier rendu POC Reflex. - [x] `0-pre.5` — intégration SDL3 Desktop réelle et premier rendu POC Reflex.
- [ ] `0-pre.6`projet Gradle Android exécutable, SDL3 AAR/NDK, compilation Rust `cdylib`, lancement sur appareil/émulateur. - [ ] `0-pre.6`fondation Gradle Android, SDL3 AAR, Activity Java commune et politique de fenêtre Desktop redimensionnable.
- [ ] `0-pre.7`bridge Java/JNI minimal et input tactile Android. - [ ] `0-pre.7`compilation Rust Android `cdylib`, point d'entrée SDL Android et premier lancement APK sur appareil/émulateur.
- [ ] `0-pre.8`assets communs + spécifiques empaquetés sans copie dans les crates. - [ ] `0-pre.8`bridge Java/JNI minimal et input tactile Android.
- [ ] `0-pre.9`POC Reflex jouable Desktop + Android. - [ ] `0-pre.9`assets communs + spécifiques empaquetés sans copie dans les crates.
- [ ] `0-pre.10` — POC Snake jouable et validation de la réutilisation du moteur. - [ ] `0-pre.10` — POC Reflex jouable Desktop + Android.
- [ ] `0-pre.11` — POC Snake jouable et validation de la réutilisation du moteur.
- [ ] `1-alpha.1` — première API moteur V1 volontairement stabilisée. - [ ] `1-alpha.1` — première API moteur V1 volontairement stabilisée.
- [ ] `2-beta.1` — stabilisation, packaging, tests multi-appareils. - [ ] `2-beta.1` — stabilisation, packaging, tests multi-appareils.
- [ ] `3-rc.1` — candidat de release du socle 0.1.0. - [ ] `3-rc.1` — candidat de release du socle 0.1.0.

View File

@@ -1,5 +1,5 @@
// file: crates/apps/game-reflex-poc-desktop/src/main.rs // file: crates/apps/game-reflex-poc-desktop/src/main.rs
// version: 4 // version: 5
#![warn(missing_docs)] #![warn(missing_docs)]
#![deny(unreachable_pub)] #![deny(unreachable_pub)]
@@ -17,7 +17,7 @@ fn main() {
}; };
tracing::info!(target: "games::runner", game = "reflex", "desktop SDL3 runner started"); tracing::info!(target: "games::runner", game = "reflex", "desktop SDL3 runner started");
let _monetization = engine_v1_platform_api::MonetizationCapabilities::disabled(); let _monetization = engine_v1_platform_api::MonetizationCapabilities::disabled();
let runtime = engine_v1_sdl::SdlRuntime::new("Reflex POC", 720, 1280, std::time::Duration::from_millis(16)); let runtime = engine_v1_sdl::SdlRuntime::new("Reflex POC", 405, 720, std::time::Duration::from_millis(16));
let mut state = game_reflex_poc::ReflexState::new(); let mut state = game_reflex_poc::ReflexState::new();
match runtime.run(&mut state) { match runtime.run(&mut state) {
std::result::Result::Ok(()) => {}, std::result::Result::Ok(()) => {},

View File

@@ -1,5 +1,5 @@
// file: crates/apps/game-snake-poc-desktop/src/main.rs // file: crates/apps/game-snake-poc-desktop/src/main.rs
// version: 4 // version: 5
#![warn(missing_docs)] #![warn(missing_docs)]
#![deny(unreachable_pub)] #![deny(unreachable_pub)]
@@ -17,7 +17,7 @@ fn main() {
}; };
tracing::info!(target: "games::runner", game = "snake", "desktop SDL3 runner started"); tracing::info!(target: "games::runner", game = "snake", "desktop SDL3 runner started");
let _monetization = engine_v1_platform_api::MonetizationCapabilities::disabled(); let _monetization = engine_v1_platform_api::MonetizationCapabilities::disabled();
let runtime = engine_v1_sdl::SdlRuntime::new("Snake POC", 720, 1280, std::time::Duration::from_millis(16)); let runtime = engine_v1_sdl::SdlRuntime::new("Snake POC", 405, 720, std::time::Duration::from_millis(16));
let mut state = game_snake_poc::SnakeState::new(); let mut state = game_snake_poc::SnakeState::new();
match runtime.run(&mut state) { match runtime.run(&mut state) {
std::result::Result::Ok(()) => {}, std::result::Result::Ok(()) => {},

View File

@@ -1,5 +1,5 @@
// file: crates/engines/engine-v1-sdl/src/runtime.rs // file: crates/engines/engine-v1-sdl/src/runtime.rs
// version: 3 // version: 4
/// Minimal SDL3 runtime used by Desktop POC runners. /// Minimal SDL3 runtime used by Desktop POC runners.
pub struct SdlRuntime { pub struct SdlRuntime {
@@ -29,7 +29,7 @@ impl SdlRuntime {
std::result::Result::Ok(value) => value, std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()), std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
}; };
let window = match video.window(&self.title, self.width, self.height).position_centered().build() { let window = match video.window(&self.title, self.width, self.height).position_centered().resizable().build() {
std::result::Result::Ok(value) => value, std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()), std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
}; };

140
deltas/0.1.0/0-pre.6.md Normal file
View File

@@ -0,0 +1,140 @@
<!-- file: deltas/0.1.0/0-pre.6.md -->
<!-- version: 1 -->
# Delta 0.1.0-0-pre.6
## Base
Base validée : `0.1.0-0-pre.5.fix.3`.
## Validation du delta précédent
`0.1.0-0-pre.5.fix.3` a été validée par l'utilisateur le 2026-09-16.
Les résultats fournis étaient propres pour :
- formatage Rust ;
- audits Rust/workspace ;
- audit Markdown : `1 table(s), 43 file(s)` ;
- `cargo check --workspace` ;
- Clippy global strict ;
- test ciblé `engine-v1-sdl` ;
- runners SDL3 Reflex et Snake.
Les runners ont utilisé `sdl3 0.20.0` / `sdl3-sys 0.7.1` et se sont fermés proprement.
## Objectifs
- préparer le projet Gradle Android réel sans introduire prématurément le `cdylib` Rust ;
- utiliser l'AAR officiel SDL3 comme frontière Android commune ;
- conserver Java comme langage Android du projet ;
- réduire la taille initiale des fenêtres Desktop et autoriser leur redimensionnement.
## Desktop
Les runners portrait utilisent désormais une fenêtre initiale :
```text
405 × 720
```
La fenêtre SDL3 est redimensionnable.
Cette dimension est une taille physique de développement, pas une résolution logique de gameplay.
## Android
Le projet Android introduit :
- AGP `9.4.0` ;
- `compileSdk 36` ;
- `targetSdk 36` ;
- `minSdk 21` ;
- Java 17 ;
- SDL3 AAR `3.4.16` ;
- module `common` Android Library ;
- modules applications `game-reflex-poc` et `game-snake-poc` ;
- manifests de lancement portrait ;
- `SaseGameActivity` dérivée de `org.libsdl.app.SDLActivity`.
L'AAR SDL3 reste externe et n'est pas commité dans le dépôt.
## Découpage volontaire de la roadmap
Le précédent objectif `0-pre.6` regroupait trop de frontières à la fois : Gradle, AAR SDL3, NDK, Rust `cdylib` et lancement.
Il est scindé en :
- `0-pre.6` : projet Gradle + AAR + Java SDLActivity ;
- `0-pre.7` : Rust Android `cdylib` + point d'entrée SDL + premier APK lancé ;
- `0-pre.8` : Java/JNI services + input tactile.
## Validation Rust à exécuter par l'utilisateur
Le delta modifie du Rust :
```bash
cargo fmt --all
cargo fmt --all -- --check
python3 scripts/audit_rust_workspace_rules.py
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates Android deltas history
cargo check --workspace
cargo clippy --workspace --all-targets --all-features -- -D warnings
```
Test ciblé SDL3 :
```bash
cargo test -p engine-v1-sdl --all-targets --all-features
```
Smokes Desktop :
```bash
cargo run -p game-reflex-poc-desktop
cargo run -p game-snake-poc-desktop
```
Vérifier notamment que :
- la fenêtre initiale est sensiblement plus petite que précédemment ;
- elle est redimensionnable ;
- `Escape` et la fermeture système restent fonctionnels.
## Préflight Android
Vérifier Java :
```bash
java -version
```
Une JVM 17 doit être disponible pour AGP 9.4.
Placer l'AAR officiel SDL3 :
```text
Android/libs/SDL3-3.4.16.aar
```
Le build Gradle est alors validable avec Gradle `9.6.0` ou via Android Studio compatible AGP 9.4.
Si une installation Gradle 9.6.0 est disponible :
```bash
cd Android
gradle :common:assembleDebug
gradle :game-reflex-poc:assembleDebug
gradle :game-snake-poc:assembleDebug
cd ..
```
Le lancement des APK n'est pas une gate de ce delta : le `cdylib` Rust et le point d'entrée SDL Android seront ajoutés en `0-pre.7`.
## Règle de transition
Si les gates Rust sont propres et que la synchronisation/build Android Java+SDL3 AAR est propre sur la machine équipée, passer automatiquement à `0.1.0-0-pre.7`.
En cas d'échec provoqué par les fichiers de ce delta, produire `0.1.0-0-pre.6.fix.1`.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/000-README.md --> <!-- file: docs/000-README.md -->
<!-- version: 7 --> <!-- version: 8 -->
# Documentation games.sasedev # Documentation games.sasedev
@@ -49,6 +49,7 @@ Voir [`../RULES.md`](../RULES.md), notamment [`rules/RULES_COMMANDS.md`](rules/R
- [`testing/001-TEST_ARCHITECTURE.md`](testing/001-TEST_ARCHITECTURE.md) — séparation `unit_tests/` / `tests/`, tests ciblés et tracing de test. - [`testing/001-TEST_ARCHITECTURE.md`](testing/001-TEST_ARCHITECTURE.md) — séparation `unit_tests/` / `tests/`, tests ciblés et tracing de test.
- [`development/003-TRACING_AND_DIAGNOSTICS.md`](development/003-TRACING_AND_DIAGNOSTICS.md) — socle `tracing`, subscriber et appender communs. - [`development/003-TRACING_AND_DIAGNOSTICS.md`](development/003-TRACING_AND_DIAGNOSTICS.md) — socle `tracing`, subscriber et appender communs.
- [`development/004-SDL3_DESKTOP_PREREQUISITES.md`](development/004-SDL3_DESKTOP_PREREQUISITES.md) — prérequis SDL3 Desktop, stratégie de liaison système et vérification `pkg-config`. - [`development/004-SDL3_DESKTOP_PREREQUISITES.md`](development/004-SDL3_DESKTOP_PREREQUISITES.md) — prérequis SDL3 Desktop, stratégie de liaison système et vérification `pkg-config`.
- [`development/005-DESKTOP_WINDOW_POLICY.md`](development/005-DESKTOP_WINDOW_POLICY.md) — taille initiale, redimensionnement et séparation future entre fenêtre physique et résolution virtuelle.
## Historique validé ## Historique validé

View File

@@ -0,0 +1,36 @@
<!-- file: docs/development/005-DESKTOP_WINDOW_POLICY.md -->
<!-- version: 1 -->
# Politique de fenêtre Desktop
## Objectif
La taille de fenêtre Desktop est une surface de développement et ne doit pas être confondue avec la résolution logique ou la résolution d'un téléphone.
## Baseline portrait
Les POC portrait utilisent par défaut :
```text
405 × 720
```
La fenêtre SDL3 est redimensionnable.
Cette taille initiale tient plus facilement sur un écran Desktop qu'une fenêtre `720 × 1280`, tout en conservant un ratio portrait proche de `9:16`.
## Évolution
Le moteur devra ensuite distinguer :
- taille physique de fenêtre ;
- taille du drawable/backbuffer ;
- résolution virtuelle logique ;
- viewport ;
- scaling ;
- letterboxing/pillarboxing ;
- densité de pixels.
Le gameplay ne devra jamais dépendre directement de la taille physique de la fenêtre.
Une politique de taille minimale et de conservation éventuelle du ratio pourra être ajoutée lorsque le renderer 2D réel sera introduit.

View File

@@ -0,0 +1,35 @@
<!-- file: history/0.1.0/0-pre.5.fix.3.md -->
<!-- version: 1 -->
# Historique 0.1.0-0-pre.5.fix.3
## Statut
Validé par l'utilisateur le 2026-09-16.
## Gates validées
- `cargo fmt --all` ;
- `cargo fmt --all -- --check` ;
- audits Python du workspace et des tableaux Markdown ;
- `cargo check --workspace` ;
- `cargo clippy --workspace --all-targets --all-features -- -D warnings` ;
- `cargo test -p engine-v1-sdl --all-targets --all-features` ;
- smoke interactif `game-reflex-poc-desktop` ;
- smoke interactif `game-snake-poc-desktop`.
## Résultats observés
La crate Rust SDL3 a été résolue en `sdl3 0.20.0` avec `sdl3-sys 0.7.1`.
Les deux runners ont ouvert puis fermé proprement leur fenêtre SDL3 avec tracing actif.
## Portée durable
Ce jalon valide :
- SDL3 Desktop réel ;
- liaison Linux via `pkg-config` ;
- version SDL3 Rust canonique portée par le workspace ;
- features SDL3 portées uniquement par la crate consommatrice ;
- séparation fonctionnelle entre crates de jeu et runners Desktop.