Skip to content

Latest commit

ย 

History

11 Commits

Folders and files

NameName
Last commit message
Last commit date
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐ŸŽฒ Fate Dice Roll

Roll the Fate. Trust the Dice. Shape Your Story.


Android Kotlin Jetpack Compose GitHub Actions Figma


A beautifully crafted Fate RPG dice roller for Android โ€” fully built with Jetpack Compose.
Originally developed with XML layouts, now modernized with a declarative UI architecture.


๐Ÿ“ธ Screenshots

๐ŸŽฒ Main Screen ๐Ÿ“œ Roll History
Roll four Fate dice with a single tap Full session history in a slide-up bottom sheet

๐ŸŽฎ What is the Fate RPG System?

Fate Core is a narrative-driven tabletop RPG by Evil Hat Productions. Instead of d20s or percentile dice, Fate uses its own special Fate Dice (dF) โ€” each face shows one of three symbols:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚   [ + ]   โ”‚   [   ]   โ”‚   [ - ]   โ”‚
โ”‚           โ”‚           โ”‚           โ”‚
โ”‚   Plus    โ”‚   Blank   โ”‚   Minus   โ”‚
โ”‚    +1     โ”‚     0     โ”‚    -1     โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

You roll 4 dice simultaneously and sum the results. The total ranges from -4 to +4, compared against a skill level or opponent roll to determine the narrative outcome.

Result Ladder Rank Narrative Meaning
+4 ๐ŸŒŸ Legendary Beyond extraordinary โ€” a moment for the ages
+3 โœจ Fantastic Things go spectacularly well
+2 ๐Ÿ‘ Great Clear, clean success
+1 ๐Ÿ™‚ Good Success, but with a small twist
0 ๐Ÿ˜ Fair Neutral outcome โ€” something happens
-1 ๐Ÿ˜ฌ Average Minor setback, minor cost
-2 ๐Ÿ˜Ÿ Mediocre Failure with consequence
-3 ๐Ÿ˜จ Poor Bad failure
-4 ๐Ÿ’€ Terrible Catastrophic โ€” the story just got dramatic

๐Ÿง™ Learn more at faterpg.com


โœจ Features

โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
โ•‘                                                                  โ•‘
โ•‘   ๐ŸŽฒ  4-Dice Roll        Roll all four Fate dice simultaneously  โ•‘
โ•‘   ๐ŸŒ€  Roll Animation     Rapid dice shuffle before final reveal  โ•‘
โ•‘   ๐Ÿ’ฅ  Score Bounce       Spring animation on result display      โ•‘
โ•‘   ๐Ÿ“œ  Roll History       Slide-up bottom sheet with session log  โ•‘
โ•‘   ๐ŸŽจ  Custom Dice Art    Hand-designed dice imagery via Figma    โ•‘
โ•‘   ๐ŸŸข  Custom Button      Distinctive branded "ROLL THE DICE" UI  โ•‘
โ•‘   ๐ŸŒ™  Indigo Theme       Calming, immersive color palette        โ•‘
โ•‘   โ™พ๏ธ   Infinite Sessions  No roll limit, persistent history      โ•‘
โ•‘                                                                  โ•‘
โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

๐ŸŽจ Design

The dice faces, roll button, and screen layouts were all designed from scratch in Figma before being implemented in Compose.

Open in Figma

The Figma file contains:

  • ๐ŸŽฒ All three Fate dice face variants ([+], [ ], [-]) with 3D styling
  • ๐ŸŸข The custom "ROLL THE DICE" button graphic
  • ๐Ÿ“ Full screen layout compositions and spacing guides
  • ๐ŸŽจ Color tokens: indigo/periwinkle palette (#A5B4FC, #2D3748, #4A5568)

๐Ÿ—๏ธ Architecture

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                        UI LAYER                              โ”‚
โ”‚                   DiceScreen.kt                              โ”‚
โ”‚                  (Jetpack Compose)                           โ”‚
โ”‚                                                              โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚  DiceImage  โ”‚  โ”‚  RollButton  โ”‚  โ”‚  ModalBottomSheet  โ”‚  โ”‚
โ”‚  โ”‚ @Composable โ”‚  โ”‚ @Composable  โ”‚  โ”‚  (Roll History)    โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
          โ”‚  collectAsState()          
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                    VIEWMODEL LAYER                           โ”‚
โ”‚                  DiceViewModel.kt                            โ”‚
โ”‚                                                              โ”‚
โ”‚   diceFaces: StateFlow<List<Int>>                            โ”‚
โ”‚   isRolling: StateFlow<Boolean>                              โ”‚
โ”‚   rollHistory: StateFlow<List<RollRecord>>                   โ”‚
โ”‚                                                              โ”‚
โ”‚   startRolling() โ†’ stopRolling() โ†’ updateDice()             โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                          โ”‚  Kotlin Coroutines
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                    LOGIC LAYER                               โ”‚
โ”‚   generateRandomDice() โ†’ random pick from [-1, 0, 1]        โ”‚
โ”‚   RollRecord(id, total) โ†’ prepended to history list         โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Tech Stack

Layer Technology
Language Kotlin
UI Toolkit Jetpack Compose
State Management ViewModel + StateFlow
Async / Animation Kotlin Coroutines
UI Components Material 3 (ModalBottomSheet, Surface)
Animation animateFloatAsState + Spring spec
Build System Gradle KTS
CI/CD GitHub Actions
Design Figma

๐Ÿ”„ XML โ†’ Jetpack Compose Migration

This project was originally built using classic Android XML layouts and has since been fully refactored to Jetpack Compose.

BEFORE (XML Views)                    AFTER (Jetpack Compose)
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€        โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
activity_main.xml                     DiceScreen.kt @Composable
res/layout/*.xml files                Composable function hierarchy
View Binding / findViewById           State-driven recomposition
AnimatorSet / ObjectAnimator          animateFloatAsState + spring()
LiveData + Observer pattern           StateFlow + collectAsState()
RecyclerView + Adapter                LazyColumn + items { }
Fragment transactions                 Direct composable calls
Manual lifecycle management           LaunchedEffect + ViewModel scope

Result: ~60% less boilerplate, dramatically smoother animations, and a far more maintainable codebase.


๐ŸŒ€ Roll Flow

   User taps [ROLL THE DICE]
             โ”‚
             โ–ผ
   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
   โ”‚  startRolling()      โ”‚โ”€โ”€โ–บ isRolling = true
   โ”‚  ViewModel call      โ”‚โ”€โ”€โ–บ UI shows "Rolling..." text
   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
              โ”‚
              โ–ผ
   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
   โ”‚   LaunchedEffect(isRolling)          โ”‚
   โ”‚   Coroutine launches on main thread  โ”‚
   โ”‚                                      โ”‚
   โ”‚   repeat(10):                        โ”‚
   โ”‚     updateDice(generateRandom())  โ—„โ”€โ”€โ”ผโ”€โ”€ visual shuffle
   โ”‚     delay(50ms)                      โ”‚   every 50ms
   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                          โ”‚
                          โ–ผ
   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
   โ”‚   stopRolling(finalFaces)            โ”‚
   โ”‚     diceFaces updated                โ”‚
   โ”‚     isRolling = false                โ”‚
   โ”‚     rollCounter++                    โ”‚
   โ”‚     RollRecord prepended to list     โ”‚
   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                          โ”‚
                          โ–ผ
   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
   โ”‚   UI recomposes automatically        โ”‚
   โ”‚     Score shown with sign (+/-)      โ”‚
   โ”‚     Spring bounce animation fires    โ”‚โ”€โ”€โ–บ scale 1.0 โ†’ 1.2 โ†’ 1.0
   โ”‚     History list instantly updated   โ”‚
   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐Ÿ“ Project Structure

Fate-Dice-Roll/
โ”œโ”€โ”€ .github/
โ”‚   โ””โ”€โ”€ workflows/
โ”‚       โ””โ”€โ”€ android.yml              # CI/CD pipeline definition
โ”œโ”€โ”€ app/
โ”‚   โ””โ”€โ”€ src/main/
โ”‚       โ”œโ”€โ”€ java/com/stargazer/fatediceroll/
โ”‚       โ”‚   โ”œโ”€โ”€ MainActivity.kt      # App entry point
โ”‚       โ”‚   โ”œโ”€โ”€ ui/
โ”‚       โ”‚   โ”‚   โ””โ”€โ”€ DiceScreen.kt    # All UI composables
โ”‚       โ”‚   โ””โ”€โ”€ viewmodel/
โ”‚       โ”‚       โ””โ”€โ”€ DiceViewModel.kt # State + business logic
โ”‚       โ””โ”€โ”€ res/
โ”‚           โ””โ”€โ”€ drawable/            # Dice images & button graphics
โ”œโ”€โ”€ build.gradle.kts                 # Module build config
โ””โ”€โ”€ settings.gradle.kts

โš™๏ธ CI/CD Pipeline

Every push to master triggers the Android CI workflow via GitHub Actions:

Push to master / Pull Request
          โ”‚
          โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚      GitHub Actions Runner      โ”‚
โ”‚                                 โ”‚
โ”‚  1. โœ…  Checkout repository     โ”‚
โ”‚  2. โœ…  Set up JDK 17           โ”‚
โ”‚  3. โœ…  Cache Gradle packages   โ”‚
โ”‚  4. โœ…  ./gradlew build         โ”‚
โ”‚  5. โœ…  Run unit tests          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
          โ”‚
          โ–ผ
     Build artifact + status badge updated

Latest run: Android CI #1 โ€” โœ… passed in 3m 54s


๐Ÿ› ๏ธ Getting Started

Prerequisites

Requirement Minimum Version
Android Studio Hedgehog (2023.1+)
JDK 17
Android minSdk 24 (Android 7.0)
Android targetSdk 35
Gradle 8.x

Clone & Run

# Clone the repository
git clone https://github.com/berat-karabuga/Fate-Dice-Roll.git
cd Fate-Dice-Roll

# Build debug APK
./gradlew assembleDebug

# Run unit tests
./gradlew test

Or open in Android Studio and press โ–ถ๏ธ Run directly on a device or emulator.


๐Ÿค Contributing

Contributions, bug reports, and feature ideas are all welcome!

# 1. Fork the repository
# 2. Create your feature branch
git checkout -b feature/your-feature-name

# 3. Commit with a clear message
git commit -m "feat: describe your change"

# 4. Push and open a Pull Request
git push origin feature/your-feature-name

๐Ÿ“„ License

This project is open source and available under the MIT License.


Made with โค๏ธ for the Fate RPG community

"In Fate, you are the author of your own story โ€” the dice just add the drama."


โญ Star this repo if you find it useful! ย ย |ย ย  ๐ŸŽจ View Figma Design

About

A modern FATE RPG dice roller built with Kotlin and Jetpack Compose, featuring roll history and CI/CD automation.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages