#import "gdd_template.typ": *
#import "@preview/gentle-clues:0.7.1": question, info, quote as quotation
#import "@preview/cetz:0.2.2"

#show: gdd.with(
  title: [IO],
  authors: (
    (
      name: "Jengamon",
      url: "https://nest.pijul.com/Jengamon/bevy_games/"
    ),
  )
)

= Introduction

== Game Summary

#figure(
cetz.canvas(length: 3cm, {
  import cetz.draw: *

  set-style(
    mark: (fill: black, scale: 2),
    stroke: (thickness: 0.4pt, cap: "round"),
    angle: (
      radius: 0.3,
      label-radius: .22,
      fill: green.lighten(80%),
      stroke: (paint: green.darken(50%))
    ),
    content: (padding: 1pt)
  )

  grid((-1.5, -1.5), (1.4, 1.4), step: 0.5, stroke: gray + 0.2pt)

  circle((0,0), radius: 1)

  line((-1.5, 0), (1.5, 0), mark: (end: "stealth"))
  content((), $ x $, anchor: "west")
  line((0, -1.5), (0, 1.5), mark: (end: "stealth"))
  content((), $ y $, anchor: "south")

  for (x, ct) in ((-1, $ -1 $), (-0.5, $ -1/2 $), (1, $ 1 $)) {
    line((x, 3pt), (x, -3pt))
    content((), anchor: "north", ct)
  }

  for (y, ct) in ((-1, $ -1 $), (-0.5, $ -1/2 $), (0.5, $ 1/2 $), (1, $ 1 $)) {
    line((3pt, y), (-3pt, y))
    content((), anchor: "east", ct)
  }

  // Draw the green angle
  cetz.angle.angle((0,0), (1,0), (1, calc.tan(30deg)),
    label: text(green, [#sym.alpha]))

  line((0,0), (1, calc.tan(30deg)))

  set-style(stroke: (thickness: 1.2pt))

  line((30deg, 1), ((), "|-", (0,0)), stroke: (paint: red), name: "sin")
  content(("sin.start", 50%, "sin.end"), text(red)[$ sin alpha $])
  line("sin.end", (0,0), stroke: (paint: blue), name: "cos")
  content(("cos.start", 50%, "cos.end"), text(blue)[$ cos alpha $], anchor: "north")
  line((1, 0), (1, calc.tan(30deg)), name: "tan", stroke: (paint: orange))
  content("tan.end", $ text(#orange, tan alpha) = text(#red, sin alpha) / text(#blue, cos alpha) $, anchor: "west")
}), caption: [the _*real*_ content]
)

Io (stylized _IO_) is a platformer bullet-hell about escaping the depths of a decaying and
rusting factory to the surface above.

#question(title: [About the name _Io_])[
  I was today years old when I looked up #link("https://en.wikipedia.org/wiki/Io_(moon)")[Io on Wikipedia]
  and it's an infernal hellscape. Do we play on this? #small[yes.] _I was always thinking of Europa!_
]

== Inspiration

This goes out to young me thinking they want to make Cave Story again. Got me into gamedev, and
eventually to work as a programmer, but making games has always been close to my heart.
Beyond collecting the tools that I _think_ should be sufficient to complete a game, this
is a reduced scope idea to get more of a feel of how to use the tools, while making a cool game!

=== #link("https:/develop.games")[Pirate Software]
Motivation to move beyond tutorials and toys to invest the time to put together
something of a "completed product".

=== Other Inspirations
#lorem(60)

== Player Experience

There are 4 levels to platform across, all consisting of a subboss, and a main boss.
For now, there is 1 side quest per level, providing an additional skill.
The player learns to time their combos (Ideal timings and all), and learn how to
transverse the platforms, understanding the patterns of each boss, in order to complete
the levels and reach the surface.

== Platform

The game will be released for Desktop primarily, with no intentions of requiring a web build
(if there is one, it will only be for a demo to download the desktop version).

== Development Software

We are using #link("https://bevyengine.org")[Bevy Engine] and
#link("https://rust-lang.org")[Rust]. I've really wanted to take the time to learn
how to use Bevy, and Rust is plain fun to me, so here we are.

The high-risk part of this is that Bevy is not stable software, but the guarantees of
Cargo should mitigate incompatibilities due to this, and the Bevy ecosystem has a really
good precedent of marking explicitly the compatible versions of their packages with the
core Bevy engine, which makes this doable.

For code editing, I'm using a mix of #link("https://helix-editor.com")[Helix] and
#link("https://zed.dev")[Zed]. Graphics are in #link("https://aseprite.org")[Aseprite].

Audio is coming from #link("https://github.com/tildearrow/furnace")[Furnace Tracker] for main
themes, but #link("https://bitwig.com")[Bitwig Studio] for general sound design ideally, but we'll
have to see. #link("https://github.com/SamiPerttu/fundsp")[FunDSP] is an interesting project.
Our audio system itself is powered by #link("https://github.com/tesselode/kira")[Kira] instead of
using the default `bevy_audio`.

The other major experimental part of this game is that scripting will use
#link("https://github.com/kyren/piccolo")[Piccolo], an implementation of Lua in Rust
that tries some different things. If it doesn't work out, as we design Lua interfaces, we
can substitute in #link("https://github.com/mlua-rs/mlua")[MLua] with minimal API
breakage.

== Genre

We are a platformer bullet-hell, in that order.
Bosses are where the bullet-hell aspect becomes incredibly apparent.
We are a single player game.
This is an involved game (but we *must* support full pausing because of that).

== Target Audience

Because our combat system is relatively involved, and bullet hell sections are involved,
platformer proficiency is required/expected.

= Concept

== Gameplay Overview

#lorem(600)

== Themes

#lorem(300)

== Primary Mechanics

#lorem(600)

== Secondary Mechanics

#lorem(600)

= Art

== Themes

#lorem(300)

== Design

#lorem(300)

= Audio

== Music

#lorem(300)

== Sound Effects

#lorem(300)

= Game Experience

== UI

#lorem(300)

== Controls

#lorem(300)

= Development Timeline

#dev_timeline(
  ..dev_timeline_event(name: "Create GDD", completed: true, date: ymd(2024, 4, 21))[Start the GDD and the design process],
)

= Terms

#set terms(separator: [#sym.angle.r ])

/ Ideal: A time period with every move where cancelling into the next move leaves the damage unchanged (instead of
  multiplying the damage by x0.7), but if the opponent hits you during this time, they deal x1.5 stagger damage.
/ Stagger: A stat that when filled, stuns the entity.
/ Overstagger: If an entity is dealt stagger damage while they have over the amount of max Stagger they have (tends to happen
  if they were uninterruptible), the difference between their Stagger and their max Stagger is dealt as unblocked damage
  them directly before stunning them.
/ Uninterruptible: All moves have 3 stages: #code_term("Windup"), #code_term("Execute"), and #code_term("Winddown").
  Uninterruptible means that an entity cannot be struck out of their #code_term("Windup") nor #code_term("Execute")
  phases (however damage and stagger damage goes through as normal)