summaryrefslogtreecommitdiff
path: root/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui
diff options
context:
space:
mode:
authorElizabeth Hunt <me@liz.coffee>2025-10-23 21:59:37 -0700
committerElizabeth Hunt <me@liz.coffee>2025-10-24 20:00:58 -0700
commit64f825465de9fa30c4dfe2707067efdb96110db8 (patch)
tree5241385e316e2f4ceede5018603103d71be75202 /composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui
downloadabstraction-engine-kt-64f825465de9fa30c4dfe2707067efdb96110db8.tar.gz
abstraction-engine-kt-64f825465de9fa30c4dfe2707067efdb96110db8.zip
Init
Diffstat (limited to 'composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui')
-rw-r--r--composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui/ArcadeButton.kt52
-rw-r--r--composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui/ArcadeControls.kt130
-rw-r--r--composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui/DPad.kt105
-rw-r--r--composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui/PCBBackground.kt85
-rw-r--r--composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui/Theme.kt32
5 files changed, 404 insertions, 0 deletions
diff --git a/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui/ArcadeButton.kt b/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui/ArcadeButton.kt
new file mode 100644
index 0000000..9d50192
--- /dev/null
+++ b/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui/ArcadeButton.kt
@@ -0,0 +1,52 @@
+package coffee.liz.abstractionengine.ui
+
+import androidx.compose.foundation.border
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.material3.Button
+import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+
+enum class ArcadeButtonColor {
+ RED, YELLOW
+}
+
+@Composable
+fun ArcadeButton(
+ label: String,
+ color: ArcadeButtonColor = ArcadeButtonColor.RED,
+ onClick: () -> Unit,
+ modifier: Modifier = Modifier
+) {
+ val buttonColor = when (color) {
+ ArcadeButtonColor.RED -> GameBoyColors.ButtonRed
+ ArcadeButtonColor.YELLOW -> GameBoyColors.ButtonYellow
+ }
+
+ Button(
+ onClick = onClick,
+ modifier = modifier
+ .size(65.dp)
+ .border(1.dp, MaterialTheme.colorScheme.outline, CircleShape),
+ shape = CircleShape,
+ colors = ButtonDefaults.buttonColors(
+ containerColor = buttonColor,
+ contentColor = MaterialTheme.colorScheme.onPrimary
+ ),
+ contentPadding = PaddingValues(0.dp)
+ ) {
+ Text(
+ text = label,
+ fontSize = 20.sp,
+ fontWeight = FontWeight.Bold,
+ color = MaterialTheme.colorScheme.onPrimary
+ )
+ }
+}
diff --git a/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui/ArcadeControls.kt b/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui/ArcadeControls.kt
new file mode 100644
index 0000000..f5b4839
--- /dev/null
+++ b/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui/ArcadeControls.kt
@@ -0,0 +1,130 @@
+package coffee.liz.abstractionengine.ui
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.border
+import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.*
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.text.font.FontFamily
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+
+@Composable
+fun ArcadeControls(
+ onDirectionPressed: (Direction) -> Unit,
+ onActionA: () -> Unit,
+ onActionB: () -> Unit,
+ modifier: Modifier = Modifier,
+ gameContent: @Composable BoxScope.() -> Unit = {
+ // Default placeholder content
+ Column(
+ horizontalAlignment = Alignment.CenterHorizontally,
+ verticalArrangement = Arrangement.spacedBy(16.dp)
+ ) {
+ Text(
+ text = "GAME AREA",
+ fontSize = 18.sp,
+ fontWeight = FontWeight.Bold,
+ fontFamily = FontFamily.Monospace,
+ color = MaterialTheme.colorScheme.onPrimary
+ )
+ }
+ }
+) {
+ var lastDirection by remember { mutableStateOf<Direction?>(null) }
+ var lastAction by remember { mutableStateOf<String?>(null) }
+
+ Box(modifier = modifier.fillMaxSize()) {
+ // PCB background layer
+ PCBBackground()
+
+ // Transparent casing overlay
+ Box(
+ modifier = Modifier
+ .fillMaxSize()
+ .background(Color(0x33000000))
+ )
+
+ // Content
+ Column(
+ modifier = Modifier
+ .fillMaxSize()
+ .padding(16.dp),
+ horizontalAlignment = Alignment.CenterHorizontally,
+ verticalArrangement = Arrangement.spacedBy(16.dp)
+ ) {
+ // Game area (square)
+ Box(
+ modifier = Modifier
+ .fillMaxWidth(0.95f)
+ .aspectRatio(1f)
+ .background(
+ color = GameBoyColors.ScreenGreen.copy(alpha = 0.85f),
+ shape = RoundedCornerShape(8.dp)
+ )
+ .border(1.dp, MaterialTheme.colorScheme.outline, RoundedCornerShape(8.dp))
+ .padding(8.dp),
+ contentAlignment = Alignment.Center,
+ content = gameContent
+ )
+
+ // Control panel
+ Box(
+ modifier = Modifier
+ .fillMaxWidth(0.95f)
+ .background(
+ color = MaterialTheme.colorScheme.surface.copy(alpha = 0.7f),
+ shape = RoundedCornerShape(16.dp)
+ )
+ .border(1.dp, MaterialTheme.colorScheme.outline, RoundedCornerShape(16.dp))
+ .padding(horizontal = 16.dp, vertical = 16.dp),
+ contentAlignment = Alignment.Center
+ ) {
+ Row(
+ modifier = Modifier.fillMaxWidth(),
+ horizontalArrangement = Arrangement.SpaceEvenly,
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ // D-Pad on the left
+ DPad(
+ onDirectionPressed = { direction ->
+ lastDirection = direction
+ lastAction = null
+ onDirectionPressed(direction)
+ }
+ )
+
+ // Action buttons on the right
+ Row(
+ horizontalArrangement = Arrangement.spacedBy(12.dp)
+ ) {
+ ArcadeButton(
+ label = "B",
+ color = ArcadeButtonColor.YELLOW,
+ onClick = {
+ lastAction = "B"
+ lastDirection = null
+ onActionB()
+ }
+ )
+ ArcadeButton(
+ label = "A",
+ color = ArcadeButtonColor.RED,
+ onClick = {
+ lastAction = "A"
+ lastDirection = null
+ onActionA()
+ }
+ )
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui/DPad.kt b/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui/DPad.kt
new file mode 100644
index 0000000..52f5866
--- /dev/null
+++ b/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui/DPad.kt
@@ -0,0 +1,105 @@
+package coffee.liz.abstractionengine.ui
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.border
+import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.*
+import androidx.compose.runtime.*
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+
+enum class Direction {
+ UP, DOWN, LEFT, RIGHT
+}
+
+@Composable
+fun DPad(
+ onDirectionPressed: (Direction) -> Unit,
+ modifier: Modifier = Modifier
+) {
+ Box(
+ modifier = modifier
+ .size(140.dp)
+ .background(
+ color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.6f),
+ shape = CircleShape
+ )
+ .border(1.dp, MaterialTheme.colorScheme.outline, CircleShape)
+ ) {
+ // Up button
+ DirectionButton(
+ text = "▲",
+ onClick = { onDirectionPressed(Direction.UP) },
+ modifier = Modifier
+ .align(Alignment.TopCenter)
+ .offset(y = 20.dp)
+ )
+
+ // Down button
+ DirectionButton(
+ text = "▼",
+ onClick = { onDirectionPressed(Direction.DOWN) },
+ modifier = Modifier
+ .align(Alignment.BottomCenter)
+ .offset(y = (-20).dp)
+ )
+
+ // Left button
+ DirectionButton(
+ text = "◀",
+ onClick = { onDirectionPressed(Direction.LEFT) },
+ modifier = Modifier
+ .align(Alignment.CenterStart)
+ .offset(x = 20.dp)
+ )
+
+ // Right button
+ DirectionButton(
+ text = "▶",
+ onClick = { onDirectionPressed(Direction.RIGHT) },
+ modifier = Modifier
+ .align(Alignment.CenterEnd)
+ .offset(x = (-20).dp)
+ )
+
+ // Center circle
+ Box(
+ modifier = Modifier
+ .align(Alignment.Center)
+ .size(38.dp)
+ .background(
+ color = MaterialTheme.colorScheme.surface.copy(alpha = 0.5f),
+ shape = CircleShape
+ )
+ .border(1.dp, MaterialTheme.colorScheme.outline, CircleShape)
+ )
+ }
+}
+
+@Composable
+private fun DirectionButton(
+ text: String,
+ onClick: () -> Unit,
+ modifier: Modifier = Modifier
+) {
+ Button(
+ onClick = onClick,
+ modifier = modifier.size(38.dp),
+ shape = RoundedCornerShape(4.dp),
+ colors = ButtonDefaults.buttonColors(
+ containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.6f),
+ contentColor = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.3f)
+ ),
+ contentPadding = PaddingValues(0.dp)
+ ) {
+ Text(
+ text = text,
+ fontSize = 14.sp,
+ style = MaterialTheme.typography.headlineMedium
+ )
+ }
+}
diff --git a/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui/PCBBackground.kt b/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui/PCBBackground.kt
new file mode 100644
index 0000000..be35a1a
--- /dev/null
+++ b/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui/PCBBackground.kt
@@ -0,0 +1,85 @@
+package coffee.liz.abstractionengine.ui
+
+import androidx.compose.foundation.Canvas
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.PathEffect
+
+@Composable
+fun PCBBackground(modifier: Modifier = Modifier) {
+ val pcbGreen = Color(0xFF0D5F0D)
+ val traceColor = Color(0xFF1A7F1A)
+ val padColor = Color(0xFFD4AF37)
+
+ Canvas(modifier = modifier.fillMaxSize().background(pcbGreen)) {
+ val width = size.width
+ val height = size.height
+
+ // Draw circuit traces (horizontal and vertical lines)
+ val pathEffect = PathEffect.dashPathEffect(floatArrayOf(10f, 5f), 0f)
+
+ // Horizontal traces
+ for (i in 0..15) {
+ val y = (i * height / 15)
+ drawLine(
+ color = traceColor,
+ start = Offset(0f, y),
+ end = Offset(width, y),
+ strokeWidth = 2f,
+ pathEffect = pathEffect
+ )
+ }
+
+ // Vertical traces
+ for (i in 0..10) {
+ val x = (i * width / 10)
+ drawLine(
+ color = traceColor,
+ start = Offset(x, 0f),
+ end = Offset(x, height),
+ strokeWidth = 2f,
+ pathEffect = pathEffect
+ )
+ }
+
+ // Draw pads/components (small circles at intersections)
+ for (i in 0..10 step 2) {
+ for (j in 0..15 step 3) {
+ val x = i * width / 10
+ val y = j * height / 15
+ drawCircle(
+ color = padColor,
+ radius = 4f,
+ center = Offset(x, y)
+ )
+ }
+ }
+
+ // Draw some resistor-like rectangles
+ for (i in 1..9 step 4) {
+ val x = i * width / 10
+ val y = height / 2
+ drawRect(
+ color = Color(0xFF2A4A2A),
+ topLeft = Offset(x - 15f, y - 8f),
+ size = androidx.compose.ui.geometry.Size(30f, 16f)
+ )
+ // Resistor contacts
+ drawCircle(
+ color = padColor,
+ radius = 3f,
+ center = Offset(x - 15f, y)
+ )
+ drawCircle(
+ color = padColor,
+ radius = 3f,
+ center = Offset(x + 15f, y)
+ )
+ }
+ }
+}
diff --git a/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui/Theme.kt b/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui/Theme.kt
new file mode 100644
index 0000000..661cb09
--- /dev/null
+++ b/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui/Theme.kt
@@ -0,0 +1,32 @@
+package coffee.liz.abstractionengine.ui
+
+import androidx.compose.material3.darkColorScheme
+import androidx.compose.ui.graphics.Color
+
+// GameBoy-inspired color palette
+object GameBoyColors {
+ val DarkestGreen = Color(0xFF0F380F)
+ val DarkGreen = Color(0xFF306230)
+ val MediumGreen = Color(0xFF8BAC0F)
+ val LightGreen = Color(0xFF9BBC0F)
+ val ScreenGreen = Color(0xFF8BAC0F)
+
+ // Accent colors for buttons (still retro but with more variety)
+ val ButtonRed = Color(0xFFE76F51)
+ val ButtonYellow = Color(0xFFF4A261)
+ val DPadGray = Color(0xFF4A5759)
+ val DPadLight = Color(0xFF6B7F82)
+}
+
+val GameBoyTheme = darkColorScheme(
+ primary = GameBoyColors.MediumGreen,
+ onPrimary = GameBoyColors.DarkestGreen,
+ secondary = GameBoyColors.LightGreen,
+ onSecondary = GameBoyColors.DarkestGreen,
+ background = GameBoyColors.DarkestGreen,
+ onBackground = GameBoyColors.LightGreen,
+ surface = GameBoyColors.DarkGreen,
+ onSurface = GameBoyColors.LightGreen,
+ surfaceVariant = GameBoyColors.DPadGray,
+ outline = GameBoyColors.DarkestGreen,
+)