initial commit

This commit is contained in:
2026-07-23 08:49:40 +02:00
commit 338f65b179
14 changed files with 6382 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
/target
Generated
+6128
View File
File diff suppressed because it is too large Load Diff
+17
View File
@@ -0,0 +1,17 @@
[package]
name = "audiopoker"
version = "0.1.0"
edition = "2024"
[dependencies]
bevy = { version = "0.19", features = ["webgl2"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
wasm-bindgen = "0.2"
web-sys = { version = "0.3", features = ["SpeechRecognition", "SpeechSynthesis", "Window", "HtmlInputElement"] }
js-sys = "0.3"
futures = "0.3"
rand = "0.8.5"
[target.wasm]
edition = 2024
+40
View File
@@ -0,0 +1,40 @@
# Projektplan: Audiopoker (Bevy + Wasm)
## Zielsetzung
Ein barrierefreies Multiplayer-Pokergame für blinde Spieler, das primär über Audio (TTS & SFX) bedient wird. Das Spiel wird via Webbrowser aufgerufen und auf WebAssembly kompiliert.
## Technologie-Stack
- **Engine:** Bevy (Rust)
- **Target:** WebAssembly (Wasm)
- **Networking:** WebSockets für die Synchronisation des Spielzustands.
- **Audio-Output:** Web Speech API (via JS-Bindings) für Text-to-Speech, `bevy_audio` für Soundeffekte.
- **Input:** Tastatur-zentrierte Steuerung (Tab/Space/Enter).
## Modul-Struktur
- `core::logic`: Reine Poker-Logik (Deck, Hand-Evaluation, Betting) ohne grafische Abhängigkeiten.
- `core::network`: Netzwerkprotokoll und WebSocket-Handhabung für Multiplayer-Synchronisation.
- `audio::tts`: Interface zur Web Speech API für dynamisches Sprechen von Spielereignissen.
- `audio::sfx`: Sound-Manager für atmosphärische Effekte (Chips, Karten mischen).
- `ui_minimal`: Minimalistische Darstellung, optimiert für Barrierefreiheit und geringen Ressourcenverbrauch.
## Implementierungsphasen
### Phase 1: Fundament & Core Logic (MVP)
- [ ] Projektstruktur aufsetzen (`Cargo.toml`, Bevy Config).
- [ ] **Poker Engine**: Hand-Rankings, Deck-Shuffling und Betting-Logik implementieren.
- [ ] **Audio-Grundlagen**: Integration der Web Speech API in die Rust-Umgebung.
### Phase 2: Networking & Multiplayer
- [ ] Server-Architektur für Spielräume und Spielerverwaltung aufbauen.
- [ ] Netzwerkprotokoll für Aktionen (Deal, Bet, Fold) definieren.
- [ ] Multiplayer-Lobby und Tischsuche implementieren.
### Phase 3: Audio Experience & UI
- [ ] TTS-Logik verfeinern (Kontextuelle Ausgaben).
- [ ] Soundeffekte einbinden.
- [ ] Minimalistisches, barrierefreies User Interface erstellen.
### Phase 4: Polishing & Testing
- [ ] Barrierefreiheits-Audit (Tastatur-Flow ohne Maus).
- [ ] Latenztests im Multiplayer.
- [ ] WebAssembly Deployment Vorbereitung.
+44
View File
@@ -0,0 +1,44 @@
pub trait Speaker {
fn speak(&self, text: &str);
}
#[derive(Debug)]
pub struct DummySpeaker;
impl Speaker for DummySpeaker {
fn speak(&self, text: &str) {
println!("TTS (Dummy): {}", text);
}
}
#[cfg(target_arch = "wasm32")]
#[wasm_bindgen]
pub struct WebSpeechSpeaker;
#[cfg(target_arch = "wasm32")]
#[wasm_bindgen]
impl WebSpeechSpeaker {
pub fn new() -> Self {
WebSpeechSpeaker
}
pub fn speak(&self, text: &str) {
let window = web_sys::window().expect("No global window found");
let speech = window.speech_synthesis();
// We need to create an Utterance object.
// This requires `web-sys` with `SpeechSynthesisUtterance` feature.
// It's also a bit tricky because `SpeechSynthesisUtterance` has many required fields.
// For now, let's just have the structure ready.
}
}
#[cfg(not(target_arch = "wasm32"))]
pub type SpeakerImpl = DummySpeaker;
#[cfg(target_arch = "wasm32")]
pub type SpeakerImpl = WebSpeechSpeaker;
pub fn get_speaker() -> Box<dyn Speaker> {
// This is a bit simplified, usually you'd use some factory or trait object pattern.
// Because of `wasm_bindgen` constraints on Trait Objects with methods taking &str...
}
+14
View File
@@ -0,0 +1,14 @@
pub mod tts;
pub mod sfx;
pub struct AudioEngine {
pub tts: tts::TtsEngine,
}
impl AudioEngine {
pub fn new() -> Self {
Self {
tts: tts::TtsEngine::new(),
}
}
}
+11
View File
@@ -0,0 +1,11 @@
pub struct SfxEngine;
impl SfxEngine {
pub fn new() -> Self {
Self
}
pub fn play_sound(&self, _effect_id: &str) {
println!("Playing SFX: {}", effect_id);
}
}
+20
View File
@@ -0,0 +1,20 @@
use web_sys::window;
pub struct TtsEngine;
impl TtsEngine {
pub fn new() -> Self {
Self
}
pub fn speak(&self, text: &str) {
if let Some(window) = window() {
let speech_synth = web_sys::speech_synthesis::SpeechSynthesis::new().unwrap();
// We need a SpeechSynthesisUtterance object. This requires some JS binding or manual construction via web-sys/js-sys.
// For now, just log that we would speak here.
println!("TTS Speaking: {}", text);
} else {
println!("No window found for TTS.");
}
}
}
+31
View File
@@ -0,0 +1,31 @@
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Suit {
Spades,
Hearts,
Diamonds,
Clubs,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Rank(pub u8); // 2-14 (11=J, 12=Q, 13=K, 14=A)
impl Rank {
pub fn new(value: u8) -> Self {
Self(value)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Card {
pub suit: Suit,
pub rank: Rank,
}
impl Card {
pub fn new(suit: Suit, rank_val: u8) -> Self {
Self {
suit,
rank: Rank::new(rank_val),
}
}
}
+19
View File
@@ -0,0 +1,19 @@
use crate::core::logic::card::{Card, Rank};
#[derive(Debug, Clone)]
pub struct Hand {
pub cards: Vec<Card>,
}
impl Hand {
pub fn new(cards: Vec<Card>) -> Self {
Self { cards }
}
/// Evaluates the hand and returns a score or ranking.
/// This is currently a placeholder for the poker logic implementation.
pub fn evaluate(&self) -> u32 {
// TODO: Implement evaluation logic based on standard poker rules
0
}
}
+28
View File
@@ -0,0 +1,28 @@
pub mod card;
pub mod hand;
use card::Card;
use rand::seq::SliceRandom;
use rand::thread_rng;
pub struct Deck {
pub cards: Vec<Card>,
}
impl Deck {
pub fn new() -> Self {
let mut cards = Vec::new();
let suits = [card::Suit::Spades, card::Suit::Hearts, card::Suit::Diamonds, card::Suit::Clubs];
for suit in suits.iter() {
for rank in 2..=14 {
cards.push(Card::new(*suit, rank));
}
}
Self { cards }
}
pub fn shuffle(&mut self) {
let mut rng = thread_rng();
self.cards.shuffle(&mut rng);
}
}
+26
View File
@@ -0,0 +1,26 @@
impl Deck {
pub fn deal_hand(&mut self, count: usize) -> Vec<Card> {
(0..count).filter_map(|_| self.draw()).collect()
}
}
// To be implemented in src/game.rs or similar?
// Let's add a Game manager to logic for now as the plan is minimal.
pub struct GameManager;
impl GameManager {
pub fn start_new_game(player_names: Vec<String>) -> GameState {
let mut players = Vec::new();
for (i, name) in player_names.into_iter().enumerate() {
players.push(Player::new(i as u32, &name));
}
GameState {
players,
pot: 0,
dealer_idx: 0,
community_cards: Vec::new(),
current_round: Round::PreFlop,
}
}
}
+3
View File
@@ -0,0 +1,3 @@
fn main() {
println!("Hello, world!");
}
View File