
> SYSTEM BOOT COMPLETE
> USER: Solus Bian
> LOCATION: Projects Archive
> STATUS: Experimenting with creative ideas in search of my next internship orbit

[ Feel free to interact with the embedded site on the left (desktop) or below (mobile), or view it directly at this link: sundog.rip. ]
Sundog.rip. My personal freelance website, active for over 10 years. I started taking monetary commissions for artwork from strangers in 2017—back in middle school. What began as a way to make some money doing what I enjoyed has evolved into a daily practice. I complete commissions daily and weekly for over multiple years, balancing client work with personal projects. This site is where all of that happens: terms of service, commission information & rates, and the process for working together. You can also sign up for my commission update and newsletter.
> ACTIVE PROJECT LOGS
> Real-time development entries. Current builds, bugs encountered, and progress updates. Scroll within container to view full entry.
entry 006:
to be published ...
entry 005: Snake Collector Game
>02-12-2026After the core systems were working with placeholder rectangles, started the art pass. Created a visual novel-style intro with oStartMan that handles 5 background sprites playing once then idling (alternating last 2 frames every 0.2s for a "breathing" effect), typewriter text at 2 chars/frame, and click-to-advance system. The tricky part was detecting animation end with imageindex >= imagenumber - 1, locking to last frame with imagespeed = 0, then manually alternating frames for the idle loop. Added a pulsing "Click to continue" using sin(currenttime / 200) for smooth alpha. After page 5, auto-transitions to battle with roomgotonext().
Battle Visual Polish
Upgraded all battle elements to proper sprites. Cards are now 180x80 with a face/back system: faceSprite stores the actual card sprite (sBasicAttack, etc.), while spriteindex switches to sCard when in deck. Critical detail: must save face sprite BEFORE setting to card back, or it's lost. Positioned deck in bottom-right corner with 10px Y-offset stacking (targetY = decky + i * 10) to create visual depth. Hand cards fan from screen center using roomwidth/2 - (handSize * handxoffset)/2 + i * handxoffset with 100px offset for nice overlap. Added hover tooltips above cards showing descriptions in black boxes with wrapped text using drawtextext(). Player HP is now an 800x50 bar (red background, green fill based on hp percent, centered text) that overlays the background sprite since the player character is baked into the background art.
Animation Systems
Snake sprites got frame-based animation: manual counter increments, checks ranges (0-4 idle, 5-9 attack), imageindex = currentFrame. Attack damage triggers mid-animation at frame 7 using alarm[0] = animationSpeed * 2 for perfect timing punch. Energy dice flash rapidly during isAnimating = true (cycle through all 4 colors every 3 frames) then lock to final result after 60 frames. When hovering cards, energy highlights in two passes: first loop grabs matching colors, second loop fills remaining with white wildcards. All buttons got uniform polish: lerp to 110% scale on hover, 3px offset shadow at 0.3 alpha, scale to 90% on click, text scales with button using drawtexttransformed(). Dark screen (0.85 alpha) appears during energy rolling to focus attention.
Technical Wins & Next Steps
The biggest "aha" was separating hover counter (0-10) from boolean - creates smooth transitions perfect for lerping. Two-pass energy consumption (colored then white) stays clean by looping twice instead of complex nested logic. Storing isAnimating separately from state prevents bugs when you're in ROLLING phase but waiting for player input. Current sprite sizes: cards 180x80, energy dice ~40x40, HP bar 800x50, stars sprite sheet with 9 frames for half-star increments. Game is now playable and looks real - next phase is map polish, better car sprite, task system juice, sound effects, and particle effects for damage numbers. Most time went into card positioning math for centered hands with variable counts. ~8-11 hours total for intro + battle art pass.ShareArtifactsDownload allDevlog 01 foundation dayDocument · MD Devlog 02 art and polishDocument · MD Orating review systemGML Otask card systemGML Otaskman call systemGML Omapman grass systemGML Rmmap driving systemGML Ostartman completeGML Snake animation quickGML Snake animation fixedGML End turn quick fixGML Fixed end turn cycleGML All buttons with hoverGML End turn hoverGML Implementation summaryGML Oman alarm 0GML Oman draw 0GML Ocard step 0GML Osnake other 10GML Osnake alarm 0GML Three fixes referenceGML Fixed highlighting and rerollGML Reroll dark screen systemGML Implementation guideGML Project contentsnakeGameCreated by youpdf
entry 004: Snack Collector Game
> 02-11-2026Started development on a snake-catching card battler. In one marathon session (~8-10 hours), built the entire battle system from scratch: energy dice rolling with reroll mechanics, a deck-building card system with prioritized energy consumption (colored first, then white wildcards), and a complete turn-based state machine. Implemented smooth animations everywhere using lerp - dice flash through colors for 1 second before landing, cards slide from deck to hand, buttons scale on hover. The trickiest bug was dice rerolling ALL instead of just selected ones, fixed by adding if(isAnimating) checks on individual dice. Created 12 objects including card manager, energy manager, snake with frame-based attack animations (frames 0-4 idle, 5-9 attack), and a player HP system with defense/reflect/buff mechanics.
Technical Highlights
State machines carried everything. Energy system: ROLLING → WAITING → LOCKED. Battle flow: START (roll dice, dark screen) → DEAL (cards dealt) → PLAYERTURN → SNAKETURN → loop. Used GameMaker's alarm system for turn transitions and dslist for all dynamic collections (deck, hand, discard, energy). Two-click card system: first click highlights required energy with color priority logic, second click consumes and plays. Snake animations trigger damage mid-attack at frame 7 using alarm[0] = animationSpeed * 2 for perfect timing. All buttons got hover effects (scale to 110%, shadow on hover, scale to 90% on click) with lerp smoothing at 0.2 speed.
After getting battles working perfectly, moved to the map portion. Created a 4000x5000 room with WASD-controlled car and camera that follows and rotates with the car using camerasetviewangle(cam, -imageangle). But here's the problem: the car rotates, the camera rotates to match, but pressing W drives in the car's world-space direction, not screen-space. I want it like a racing game where forward is ALWAYS up on screen. The camera also rotates around its top-left corner instead of its center, so the car drifts off-center when rotating. Tried calculating offsets with lengthdirx/y based on camera dimensions and angle, but the math isn't clicking yet. The battle system is solid and fun - just need to crack this camera centering to complete the core game loop.
Reach me via email: [email protected] for personal matters
or [email protected] for work matters







