SharkWithLasers

Ludum Dare 45

First LDJam in the books!

Made the deadline for my first LDJAM! Damn, I am exhausted.

The game is about gathering fuel and oxygen as you make it back to your home planet. Also, avoiding asteroids.

12emhit/eman_asteroid.gif

  • https://ldjam.com/events/ludum-dare/45/spacedrifter-4500
  • https://sharkwithlasers.itch.io/spacedrifter-4500

SpaceDrifter 4500 - Belated Post-Mortem and Results

First Ludum Dare completed! What an exhausting, yet rewarding experience! I didn't know that I had it in me to make a complete a game in 48 hours, let alone a game that I'd be proud of enough to show to others. Looking forward to participating in many more of these. In any case, here is my belated post-mortem (sorry if its a bit ramble-y, mostly using this as a place to put my thoughts down lol):

Game Description

https://ldjam.com/events/ludum-dare/45/spacedrifter-4500

"Spacedrifter 4500" is a game where you must pilot your spaceship back to your home planet, while managing your limited fuel and oxygen (picking up fuel and oxygen tanks that are scattered throughout space). Also, you must avoid asteroids. You start the game with no fuel, drifting haplessly through space.

I think there's an interesting balance in the game between moving quickly before your oxygen runs out, and moving carefully so that you don't crash into an asteroid. The fuel gauge is another variable that complicates the mix a bit (overall the game is still pretty simple though lol).

12emhit/eman_asteroid.gif

Development Timeline

The 48 hour stretch of game development is a bit of a blur. IIRC, a lot of coffee and insta-ramen were present. I basically lived like a college student again. I believe it went something like this:

Ideation:

Woke up to the theme of "Start with Nothing". I can't fully remember my brainstorming session, but I found that taking a short walk around the neighborhood helped me come to an idea that I liked. I settled on "shmup where you start with no fuel or ammo". My initial idea was for the controls to behave like a typical side-scrolling shmup, and if the player ran out of fuel, the ship would remain stationary. The player would have to decide between moving to dodge enemy bullets, and moving to ammo/fuel power ups.

During development, the design of the game changed. I noticed that it doesn't really make sense for a ship in space to remain stationary if it runs out of fuel. It should drift endlessly in the direction it was previously going. This led me to the design of the current game. With all the asteroids, oxygen tanks and fuel tanks galore.

General Timeline: 1. Ideation 2. Ship controls (spent a lot of time getting this the way I wanted to from the onset) (Played around with shmup controls, asteroids style and the current "snappy but drifty" style. 3. Gas Tank and Oxygen Tank implementation 4. A Full Game Loop (lose if you run out of oxygen, win if you reach the home planet) 5. Minimap implementation, Fuel and Oxygen UI 6. UI for level lose/win 7. Asteroid implementation 8. Procedural Level Generation based on Halton Sequences: https://en.wikipedia.org/wiki/Halton_sequence 9. Dynamic Difficulty Adjustment (less asteroids or more fuel/oxy tanks if you lose. more asteroids or less fuel/oxy tanks if you win) 10. particle effects...juicy stuff 11. Sound Effects 12. various polish 13. Tutorial / Intro Scene 14. Polish and make sure WebGL works

I'm happy with this sequence. I like that I started with the idea, then the controls, then the mechanics, then level design (a.k.a. lazy proc gen), then juicy-stuff (visual effects, ui, sfx, tutorial level).

I did mess up on the UI (didn't anchor it properly so it would work on many resolutions, had to fix that post jam).

Because of the stress of the deadline, I didn't make too many gifs during development. But here is the sequence that I have (note there are some things missing):

https://www.youtube.com/watch?v=86PDjgUMN7s

( 1. basic movement; 2 bullets; 3 parallax scrolling; 4 drift controls; 5 snappy-drift controls; 6 gas-tankmouseclick_accl; 7 full-game-loop; 8 minimap-pickups-UI; 9 Basic UI & Level Complete; 10 Level-Lost-Text; 11 Tutorial-Out-Of-Fuel; 12 Hit An Asteroid Playthrough )

Results

Drumroll please...

Screen Shot 2019-11-09 at 5.49.39 PM.png

Ayyy! Pretty happy with these results! Great to know there is a lot of room for growth and improvement. My main goal for this jam was to create a complete experience in 48 hours, so the low score for Innovation is understandable. Over the course of the next 6 months I'll try to create many different prototypes and stretch my game design skills creatively.

Learnings / Thoughts

  • Streamers are a great resource. It's always insightful to observe people playing your game, and they gave me some fantastic input. Utilize streamers! Especially if you don't have any IRL friends on hand (:cryingcatface: :cryingcatface: :cryingcatface:).
  • I've always found that doing some physical activity and then relaxing allows more creative ideas to come to me. I think I'm gunna start the next jam with a brisk walk as well.
  • Gameplay Improvements:
    • French people are people too! Have an alternative to WASD input!
    • The ships angle's is not quite perpendicular when holding a vertical input (it's around 80 degrees I believe?). This caused some confusion for some players about the direction the ship would move. The ships angle should represent the direction it will go in, purely vertical. The animations would be a bit choppier, but clear representation is more important. (plus I could add an interpolating animation to reduce the choppiness)
    • because the camera doesn't zoom in/out based on the speed of the ship, players are more inclined to move slowly (lest they crash into an asteroid). I don't want to discourage players from going fast, so variably zooming out the camera based on speed would have been a nice addition.
    • level ramp is weird (starts out harder, ends up easier as you hoard a bunch of fuel and oxygen, resulting in the level kind of being a chore at the end)
    • Initially, the game was too difficult. A common trend of the games I played seemed to suffer from this. Let's make it less punishing! Perhaps a health bar would be better than an insta-asteroid death.
    • the game is not diverse/interesting enough to constitute such a long game loop. Either shorter the level loop, or add move variation to the level or a sense of progression.
    • I spent a decent amount of time getting the spaceship physics to feel "snappy". They intentionally did not behave like real life physics because I wanted players to move fast and be able to quickly react to oncoming asteroids. However, direction changes were a bit jarring and harsh (I believe a perpendicular angle would completely cancel your speed). I think that having the ship direction based completely on user input was okay, but the speed changes could have been tweaked.
    • The font I used was a bit hard to read
  • Dynamic Difficulty Adjustment is an interesting mechanic. The game becomes easier/harder every time you win or lose (even on the first level). No one noticed/mentioned that the game got easier the more times that they played it. I assume that without this, the game would have been way too hard and my score would have suffered (I also think players would have a worse experience. In this kind of format, I assume that people have less patience for difficult/frustrating games). I do think it may be better to be explicit about the adjustment however.
  • I find the Halton sequence to be a great way of generating a level: https://en.wikipedia.org/wiki/Halton_sequence . The distribution of items seems natural, and its deterministic as well!
  • I liked the fact that the final design of the game was not what I initially drafted in the initial hours of the game. It's cool to see how the design of a game changes as its developed, especially at the rapid pace of a jam.
  • I love how much the system here promotes giving constructive feedback. It's incredibly motivating and I've learned things that would have gone completely over my head.

See y'all in April!

Ludum Dare 47

misclick

whoops accidentally clicked publish too soon and can't delete the post...

The Making of Splines 'n Shapes (Big ol' post)

Second Ludum Dare in the books! I'm absolutely overwhelmed by the response. Thank you so much to everyone who played Splines 'n Shapes! For me, finishing a game in 48 hours counts as a huge success. I didn't even consider these results to be a possibility going into this jam:

resultsemld/emyo.png

I'll try to go over the process of making Splines 'n Shapes, as well as learnings, thoughts and next steps. It might get a bit long and ramble-y so feel free to skim this or just skip it entirely.

Game Description

https://ldjam.com/events/ludum-dare/47/splines-n-shapes

Splines 'n Shapes is an abstract puzzle game where you adjust loops and collect shapes. Loops are adjusted by repositioning control points and shapes must be collected in order (tri -> square -> pentagon -> etc) as well as in a single loop cycle. (Also... you must make a full revolution and collect the first triangle again :sweat_smile:)

https://www.youtube.com/watch?v=ieoemXV6vnc

Development Timeline

Initial Ideation

Whenever the theme of a jam is announced, I spend the first couple hours brainstorming ideas. I usually do this by taking a walk, away from my phone, my computer, or any distractions of that sort. I've heard that being in a calm, diffuse mode of thinking is better for creativity than a focused, active mode of thought. I find that walking and removing distractions helps put me into that diffuse state.

Having said all that, I didn't really brainstorm anything too interesting :sweatsmile: :sweatsmile: :sweat_smile:. Initial ideas included: 1. trying to escape a recursive function / for/while loop 2. nascar game w/ left turns? 3. something something hyperloop elon musk 4. some sort of paper plane game where you control how the plane loops 5. a game where you repeatedly throw and catch a boomerang in place.

Ending up going with option 5. I envisioned some sort of topdown view of a seated guy throwing a boomerang where the player could adjust the trajectory of the throw. The idea was still hazy, but it was time to start implementing.

Initial Implementation and Salvaging the Design

My initial implementation was for the boomerang throw to follow a Bezier curve where the two endpoints of the curve are at a single static position (explanation of Bezier curves). The two inner control points are adjusted with WASD and arrow keys or gamepad sticks:

preem0/embezier.gif

I found this control scheme to be pretty bad for a couple reasons: 1. Reorienting the curve into a new direction (e.g. north to south, east to west) took an unacceptably long time. This wouldn't work for any sort of semi-realtime game. 2. It's pretty easy to get the control points mixed up. For example, if WASD control the initial left point and arrow keys control the initial right point, things could get mixed up if the initial left point was moved to the right of the initial right point.

It became pretty clear to me that if I was going to continue in this curve route, I'd need to switch to a click and drag interface. And I'd need to spice things up a bit.

Enter Splines

I recalled the term "Spline" and that it was related somehow to Bezier curves. Google led me to this document explaining them. Here's my shitty layman's summary of it (images taken/modified from the doc itself):

Splines are essentially a bunch of polynomial curves glued together. However, if you simply match the end values of these curves, there can be irregularities and kinks in the spline:

coarse_kink.png (C0 is a cubic bezier curve defined by control point sequence <P0, P1, P2, S>. C1 is defined by <S, Q1, Q2, Q3>)

There's a special set of splines called relaxed uniformed cubic B-splines. These splines are made up of Bezier curves glued together such that the spline remains smooth when moving from curve to curve. We can do this by setting anchor points, and then determining control points of each Bezier curve such that the slope and curvature at each matching end point is equal. The following image and algorithm might help explain:

bemspline/emslightly_cropped.png

  • First we must place our anchor points (denoted by the points B_i above).
  • We then trisect each line segment between B_i and B_(i+1) in order to obtain the inner control points P_i,0 and P_i,1 for Bezier curve C_i
  • We then find matching endpoint S_i as the midpoints between P_(i-1),1 and P_i,0. S_i is the endpoint of curve C_(i-1) and the start point of curve C_i.
    • also note that the start point of C_0 is S_0 which equals B_0. the end point of C_(n-1) is S_n which equals B_n. (n is the number of anchor points in the spline)

Hooray we have now have a relaxed uniformed cubic B-spline (I'm gunna call these B-splines from now on):

thick_spline.png

(The reasoning for why this algorithm works is in the paper linked above.)

In order to make this B-spline a loop, we add an additional curve between B_n and B_0. Like in the above steps, we must trisect the line segment to get our inner control points, and then update S_0 and S_n based on these inner control points:

1eminitial/emcontrols.gif

ayyy! check out our B-Spline loop! The small gray points are our anchor points (our B points). The calculated S and P points are hidden. Looks pretty ugly though, so I resized/rethickened the shapes and loop, and used a 3 color gradient that I cycled to turn it into this:

02emcontrols/emprettier.gif

The shapes and loop are all rendered with Freya Holmér's Shapes Library. This asset is a godsend in jams, especially for the artistically challenged like myself.


At this point, I had a pretty fun toy to play around with. Now I just needed to turn it into a game. I had some thoughts spinning in my mind. The main idea I had was for the revolving orb to hit a sequence of targets on the screen. The targets would need to be hit in a particular order, and these ordered targets would be represented by regular polygons (triangle, square, pentagon, etc). But by now I was about 13 hours into the jam, it was super late at night, and I fell asleep.

However, I woke up after only like 3 hours of sleep. Wasn't intentional. I think I was a bit anxious and excited about all the things I needed to implement, so I had trouble falling back asleep. In my groggy haze, I started to implement sounds.

Sounds

Decided to go with synth sound effects for this game, mostly because it's within my current skillset (I'm about 3/4 of the way through Syntorial...that's about it :sweat_smile:) and because I felt some influence from Mini Metro.

The sound effects I knew I needed were: - orb properly hitting a target - orb incorrectly hitting a target - selecting/deselecting an anchor point

I played around with Synth1 in Reaper and came up with a basic patch that sounded pretty soothing. Main properties include: - sine and triangle waveforms for osc1 and 2. - Low Pass filter at about half cutoff. - High amp release - Chorus - a bunch of reverb from stock plugins

(also had some minor variances between the orb hit patch and the anchor selected patch. 'Orb hit' has some FM w/ osc2 pitched at 28 semitones (FM amount is modulated with an envelope). This gives it a bit of a bell-like quality. 'Anchor selected' has zero amp sustain and osc2 pitched at 31 semis above)

The Synth1 patches are available to download on my itch page: https://sharkwithlasers.itch.io/splines-n-shapes

After getting a general sense of how the synth patches would sound, I noodled around on the keyboard to figure out note sequences that sounded nice. (for when an orb properly hits a sequence of targets)

I arbitrarily decided to play notes in the key of Bflat major (because C major is basic AF). And came up with ascending note sequences based on the number of targets that would need to be hit for a particular level:

number of notes | Note sequence (in scale degrees!) | Actual notes --------------- | --------------------------------- | --- 2 | 1, 3 | Bb, D 3 | 1, 2, 5 | Bb, C, F 4 | 1, 3, 5, 6 | Bb, D, F, G 5 | 1, 2, 3, 5, 7 | Bb, C, D, F, A 6 | 1, 2, 3, 5, 7, 9 | Bb, C, D, F, A, C 7 | 1, 2, 3, 5, 7, 8, 10 | Bb, C, D, F, A, Bb, D

There wasn't too much rhyme or reason to how I came up with these. I kinda just followed my ear. I think I reduced the potential cheesiness by: - avoiding long runs of the major scale (nothing longer than 3 notes here) - avoiding outlining the I chord (I do this in the 4 note sequence though :slight_frown: ) - ending the longer note sequences on chord extensions of the I chord. (gives it a little bit of spice?) - (and perhaps ending on the 3 and 5 in the first sequences helps establish the key? maybe?)

For the "Anchor point selected" notes, I would randomly choose a note in the scale degrees {1, 2, 3, 4} (and ensure no repeates). The "anchor point deselected" note would be a perfect fifth below the "selected" note. This pairing of notes felt pretty smooth and consonant.

For the "Target improperly hit" note, I landed on using Eb (perfect fourth above Bb). I experimented with using dissonances like the tritone, but these sounds clashed with the chill mood that my game was headed in. The perfect fourth seemed like the perfect balance of consonance and dissonance for this sound.

In order to get these sounds into Unity, I rendered the notes at Bb, then modified the pitches at runtime with Unity's AudioSource. These didn't sound as nice as when I was playing in Reaper, though. Going forward, I'll probably render each note separately in Reaper and dynamically play the correct audio clip in Unity.

Design and Game Feel Iteration

If I remember correctly, I spent the next portion of the jam working on polish and finalizing the small details of the gameplay loop.

Design Decisions

One thing I find pretty neat about game jams is that I start with a hazy initial idea, and through the process of iterating through many micro design decisions, end up with a totally different, but concrete result. These micro decisions sculpt and shape the game into a product I would have never thought of during the initial brainstorm. I think that's pretty cool.

Some of the many decisions I had to make included: - deciding that the shapes must be collected in order - capping the number of shapes in a level to 6 (it's hard to distinguish shapes once you go beyond 8 sides) - deciding that all shapes must be collected within a single revolution - deciding that this single revolution starts when you hit the first shape (triangle) - deciding that you could still adjust the loop while the shapes are being hit / validated - deciding that the orb must finish it's cycle and hit the triangle again. - increasing the speed of the orb when it hits the first shape (to discourage loop adjustments during validation)

I'm not sure if all of these decisions were correct, but overall, I think it led to interesting puzzles where the player is not punished for experimenting.

Polish / Game Feel

For game feel / polish, I basically follow some lessons from the great Juice it or Lose it talk. Primarily, for any object/player interaction, there should be visual and/or audio feedback.

Some interactions (and feedback) in the game included: - shape getting hit (shape flashes and enlarges, orb gets larger, loop thickens, audio) - hovering over, selecting, and deselecting anchor points (enlarging the points on hover and select, shrinking on deselect, aura radiates from point, audio) - revolution passes that is invalid (all shapes darken and then reset, audio) - anchor point added/removed (during level transitions) - shape added/removed - ...

I mainly used DOTween to handle the visual feedback. Tweening is dope.

04emanother/emcontrol.gif

After this, I had to work on structing my code to have a level sequence, and properly transition between levels. This took a while and was pretty messy, so I'm just going to leave it at that. At the time of completion of all of this, I had about 3 or 4 hours left to design levels. (I think I snuck in a 3 hour nap in there somewhere. Unintentional once again, I think the anxiety of the jam made it hard for me to fall back asleep).

Level Design

For some reason, I always leave the designing of levels/puzzles until the end of the jam. I think a reason for this is because level design is such an open ended subject. In any case, I didn't have much time, so I followed these general principles: - Convey the mechanics of the game through the sequence of puzzles (I'm not a fan of tutorialization) - Show interesting, unique properties of B-Splines through these puzzles

The way I found interesting mechanics of B-Splines was by toying around with them in a sandbox, noticing an interesting loop/property, and then sprinkling shapes along the loop to turn it into a puzzle. It was a bit of a rushed process, but by the end of the jam, I had about 20 levels! Hooray!

Made a build, made a page, submitted. slept.

After the Jam

Over the past weeks, I've been playtesting the game with friends and streamers. The feedback I've gotten has been incredibly helpful and supportive! And it's been great getting to know people in the LD community!

(There are a ton of improvements that I could add to this game. Some low-hanging fruit, as well as design decisions that don't have a clear answer. (maybe I'll list some here later))


Because of the external support, as well as the fact that the aesthetic fits my limited art and audio skills, I plan on expanding this into my first full project. There's so much to do / think about! - What should the scope of the game be? - Should I limit the curves to just B-Spline loops? - What kind of gameplay do I want players to experience (casual and chill, or stimulating puzzles)? - What mechanics/extensions should I add to this game to keep it interesting? - Can I jam a narrative into this? - What should the game teach the player? (interesting shapes? interesting abstract properties of curves?) - ...

It's pretty exciting, yet daunting to think about. It seems like these questions can only be answered by doing the work and iterating.

So, it's time to get to work! I might post updates on my twitter if you are interested.

Thank you for the wonderful jam experience!