From 395aa7d1c312e495517701be11c21425d9a5838e Mon Sep 17 00:00:00 2001 From: Elizabeth Hunt Date: Sun, 26 Oct 2025 17:25:13 -0700 Subject: Checkpoint --- .../liz/abstractionengine/AbstractionEngine.kt | 5 - .../kotlin/coffee/liz/abstractionengine/App.kt | 28 ----- .../coffee/liz/abstractionengine/Greeting.kt | 9 -- .../coffee/liz/abstractionengine/Platform.kt | 2 +- .../kotlin/coffee/liz/abstractionengine/app/App.kt | 24 ++++ .../coffee/liz/abstractionengine/app/ui/Theme.kt | 32 +++++ .../abstractionengine/game/AbstractionEngine.kt | 5 + .../coffee/liz/abstractionengine/game/Game.kt | 37 +----- .../liz/abstractionengine/game/RenderSystem.kt | 70 ----------- .../coffee/liz/abstractionengine/game/Renderer.kt | 65 +++++++++++ .../liz/abstractionengine/ui/ArcadeButton.kt | 52 --------- .../liz/abstractionengine/ui/ArcadeControls.kt | 130 --------------------- .../kotlin/coffee/liz/abstractionengine/ui/DPad.kt | 105 ----------------- .../liz/abstractionengine/ui/PCBBackground.kt | 85 -------------- .../coffee/liz/abstractionengine/ui/Theme.kt | 32 ----- 15 files changed, 131 insertions(+), 550 deletions(-) delete mode 100644 composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/AbstractionEngine.kt delete mode 100644 composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/App.kt delete mode 100644 composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/Greeting.kt create mode 100644 composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/app/App.kt create mode 100644 composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/app/ui/Theme.kt create mode 100644 composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/game/AbstractionEngine.kt delete mode 100644 composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/game/RenderSystem.kt create mode 100644 composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/game/Renderer.kt delete mode 100644 composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui/ArcadeButton.kt delete mode 100644 composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui/ArcadeControls.kt delete mode 100644 composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui/DPad.kt delete mode 100644 composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui/PCBBackground.kt delete mode 100644 composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui/Theme.kt (limited to 'composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine') diff --git a/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/AbstractionEngine.kt b/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/AbstractionEngine.kt deleted file mode 100644 index d557fd8..0000000 --- a/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/AbstractionEngine.kt +++ /dev/null @@ -1,5 +0,0 @@ -package coffee.liz.abstractionengine - -class AbstractionEngine { - -} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/App.kt b/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/App.kt deleted file mode 100644 index a69e711..0000000 --- a/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/App.kt +++ /dev/null @@ -1,28 +0,0 @@ -package coffee.liz.abstractionengine - -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.material3.MaterialTheme -import androidx.compose.runtime.* -import androidx.compose.ui.Modifier -import coffee.liz.abstractionengine.ui.ArcadeControls -import coffee.liz.abstractionengine.ui.GameBoyTheme -import org.jetbrains.compose.ui.tooling.preview.Preview - -@Composable -@Preview -fun App() { - MaterialTheme(colorScheme = GameBoyTheme) { - ArcadeControls( - onDirectionPressed = { direction -> - println("Direction pressed: $direction") - }, - onActionA = { - println("Action A pressed!") - }, - onActionB = { - println("Action B pressed!") - }, - modifier = Modifier.fillMaxSize() - ) - } -} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/Greeting.kt b/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/Greeting.kt deleted file mode 100644 index 6f23320..0000000 --- a/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/Greeting.kt +++ /dev/null @@ -1,9 +0,0 @@ -package coffee.liz.abstractionengine - -class Greeting { - private val platform = getPlatform() - - fun greet(): String { - return "Hello, ${platform.name}!" - } -} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/Platform.kt b/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/Platform.kt index 91faf62..17ca317 100644 --- a/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/Platform.kt +++ b/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/Platform.kt @@ -1,7 +1,7 @@ package coffee.liz.abstractionengine interface Platform { - val name: String + val needsTouchscreenControls: Boolean } expect fun getPlatform(): Platform \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/app/App.kt b/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/app/App.kt new file mode 100644 index 0000000..50e72f0 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/app/App.kt @@ -0,0 +1,24 @@ +package coffee.liz.abstractionengine.app + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import coffee.liz.abstractionengine.app.ui.GameBoyTheme +import coffee.liz.abstractionengine.getPlatform +import org.jetbrains.compose.ui.tooling.preview.Preview + +@Composable +@Preview +fun App() { + + MaterialTheme(colorScheme = GameBoyTheme) { + Box(modifier = Modifier.fillMaxSize()) { + if (getPlatform().needsTouchscreenControls) { + Text("NEEDS TOUCHSCREEN CONTROLS") + } + } + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/app/ui/Theme.kt b/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/app/ui/Theme.kt new file mode 100644 index 0000000..be6c3ad --- /dev/null +++ b/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/app/ui/Theme.kt @@ -0,0 +1,32 @@ +package coffee.liz.abstractionengine.app.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, +) diff --git a/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/game/AbstractionEngine.kt b/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/game/AbstractionEngine.kt new file mode 100644 index 0000000..18349c3 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/game/AbstractionEngine.kt @@ -0,0 +1,5 @@ +package coffee.liz.abstractionengine.game + +class AbstractionEngine { + +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/game/Game.kt b/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/game/Game.kt index 9490f83..0c3a007 100644 --- a/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/game/Game.kt +++ b/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/game/Game.kt @@ -6,64 +6,35 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import coffee.liz.ecs.World import kotlinx.coroutines.isActive +import kotlin.time.Duration.Companion.nanoseconds /** - * Manages the game loop for an ECS world. - * Syncs with Compose's frame rate (like requestAnimationFrame) and provides - * the world to child content for custom rendering/UI. - * - * @param world The ECS world containing entities and systems - * @param content Composable content that can use the world for rendering + * Manages and paints the [World]. */ @Composable fun Game( world: World, content: @Composable () -> Unit ) { - // Trigger recomposition when we need to redraw var frameCount by remember { mutableStateOf(0) } - // Game loop - syncs with Compose's frame rate like requestAnimationFrame LaunchedEffect(world) { - var lastFrameTimeNanos = 0L + var lastUpdate: Long? = null while (isActive) { - // Wait for next frame (like requestAnimationFrame) withFrameNanos { frameTimeNanos -> - val deltaTime = if (lastFrameTimeNanos != 0L) { - (frameTimeNanos - lastFrameTimeNanos) / 1_000_000_000f - } else { - 0f - } - lastFrameTimeNanos = frameTimeNanos - - // Update ECS world (runs all systems) - if (deltaTime > 0f) { - world.update(deltaTime) - } - - // Trigger recomposition to redraw frameCount++ } } } - // Render content content() } -/** - * A Canvas that renders sprites from an ECS world using a RenderSystem. - * - * @param world The ECS world containing entities to render - * @param renderSystem The system responsible for rendering sprites - * @param backgroundColor Background color for the canvas - * @param modifier Modifier for the Canvas - */ @Composable fun GameCanvas( world: World, - renderSystem: RenderSystem, + renderSystem: Renderer, backgroundColor: Color = Color.Transparent, modifier: Modifier = Modifier ) { diff --git a/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/game/RenderSystem.kt b/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/game/RenderSystem.kt deleted file mode 100644 index 1d22ae6..0000000 --- a/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/game/RenderSystem.kt +++ /dev/null @@ -1,70 +0,0 @@ -package coffee.liz.abstractionengine.game - -import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.geometry.Size -import androidx.compose.ui.graphics.drawscope.DrawScope -import androidx.compose.ui.unit.IntOffset -import androidx.compose.ui.unit.IntSize -import coffee.liz.ecs.System -import coffee.liz.ecs.World -import coffee.liz.ecs.animation.AnimationSystem -import coffee.liz.ecs.animation.Animator -import coffee.liz.ecs.animation.Position -import coffee.liz.ecs.animation.SpriteSheet -import kotlin.reflect.KClass - -/** - * System that renders sprites to a DrawScope. - * - * This system queries all entities with Position, SpriteSheet, and Animator components, - * then draws their current animation frame to the provided DrawScope. - * - * Depends on AnimationSystem to ensure animations are updated before rendering. - */ -class RenderSystem( - private val imageCache: ImageCache -) : System { - - override val dependencies: Set> = setOf(AnimationSystem::class) - - /** - * The update method is required by the System interface, but rendering - * happens synchronously during Compose's draw phase via the render() method. - */ - override fun update(world: World, deltaTime: Float) { - // Rendering happens in render() method, not here - } - - /** - * Renders all entities with sprites to the given DrawScope. - * This should be called from a Compose Canvas during the draw phase. - */ - fun render(world: World, drawScope: DrawScope) { - // Query all entities that can be rendered - world.query(Position::class, SpriteSheet::class, Animator::class).forEach { entity -> - val position = entity.get(Position::class) ?: return@forEach - val spriteSheet = entity.get(SpriteSheet::class) ?: return@forEach - val animator = entity.get(Animator::class) ?: return@forEach - - // Get the current frame name from the animator - val frameName = animator.getCurrentFrameName() ?: return@forEach - - // Look up the frame rectangle in the sprite sheet - val frameRect = spriteSheet.frames[frameName] ?: return@forEach - - // Get the image from cache - val image = imageCache.getImage(spriteSheet.imagePath) ?: return@forEach - - // Draw the sprite - with(drawScope) { - drawImage( - image = image, - srcOffset = IntOffset(frameRect.x, frameRect.y), - srcSize = IntSize(frameRect.width, frameRect.height), - dstOffset = IntOffset(position.x.toInt(), position.y.toInt()), - dstSize = IntSize(frameRect.width, frameRect.height) - ) - } - } - } -} diff --git a/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/game/Renderer.kt b/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/game/Renderer.kt new file mode 100644 index 0000000..57511f3 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/game/Renderer.kt @@ -0,0 +1,65 @@ +package coffee.liz.abstractionengine.game + +import androidx.compose.ui.graphics.drawscope.DrawScope +import androidx.compose.ui.unit.IntOffset +import androidx.compose.ui.unit.IntSize +import coffee.liz.ecs.System +import coffee.liz.ecs.World +import coffee.liz.ecs.animation.AnimationSystem +import coffee.liz.ecs.animation.Animator +import coffee.liz.ecs.animation.Position +import coffee.liz.ecs.animation.SpriteSheet +import kotlin.reflect.KClass +import kotlin.time.Duration + +/** + * System that renders sprites to a DrawScope. + * + * This system queries all entities with Position, SpriteSheet, and Animator components, + * then draws their current animation frame to the provided DrawScope. + * + * Depends on AnimationSystem to ensure animations are updated before rendering. + */ +class Renderer( + private val imageCache: ImageCache +) : System { + + override val dependencies: Set> = setOf(AnimationSystem::class) + + override fun update(world: World, duration: Duration) { + // Rendering happens in render() method, not here + } + + /** + * Renders all entities with sprites to the given DrawScope. + * This should be called from a Compose Canvas during the draw phase. + */ + fun render(world: World, drawScope: DrawScope) { + // Query all entities that can be rendered + world.query(Position::class, SpriteSheet::class, Animator::class).forEach { entity -> + val position = entity.get(Position::class) ?: return@forEach + val spriteSheet = entity.get(SpriteSheet::class) ?: return@forEach + val animator = entity.get(Animator::class) ?: return@forEach + + // Get the current frame name from the animator + val frameName = animator.getCurrentFrameName() ?: return@forEach + + // Look up the frame rectangle in the sprite sheet + val frameRect = spriteSheet.frames[frameName] ?: return@forEach + + // Get the image from cache + val image = imageCache.getImage(spriteSheet.imagePath) ?: return@forEach + + // Draw the sprite + with(drawScope) { + drawImage( + image = image, + srcOffset = IntOffset(frameRect.x, frameRect.y), + srcSize = IntSize(frameRect.width, frameRect.height), + dstOffset = IntOffset(position.x.toInt(), position.y.toInt()), + dstSize = IntSize(frameRect.width, frameRect.height) + ) + } + } + } +} diff --git a/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui/ArcadeButton.kt b/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui/ArcadeButton.kt deleted file mode 100644 index 9d50192..0000000 --- a/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui/ArcadeButton.kt +++ /dev/null @@ -1,52 +0,0 @@ -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 deleted file mode 100644 index f5b4839..0000000 --- a/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui/ArcadeControls.kt +++ /dev/null @@ -1,130 +0,0 @@ -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(null) } - var lastAction by remember { mutableStateOf(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 deleted file mode 100644 index 52f5866..0000000 --- a/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui/DPad.kt +++ /dev/null @@ -1,105 +0,0 @@ -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 deleted file mode 100644 index be35a1a..0000000 --- a/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui/PCBBackground.kt +++ /dev/null @@ -1,85 +0,0 @@ -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 deleted file mode 100644 index 661cb09..0000000 --- a/composeApp/src/commonMain/kotlin/coffee/liz/abstractionengine/ui/Theme.kt +++ /dev/null @@ -1,32 +0,0 @@ -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, -) -- cgit v1.2.3-70-g09d2