Lovable Scala Rogues

Criteria for your first game!

Low barrier to entry…

  • Low graphical requirements
  • Audio optional
  • Strong gameplay / design template

Classic arcade games

 

Revised (!) criteria for your first game…

Low barrier to entry…

  • Low graphical requirements
  • Audio optional
  • Strong gameplay / design template

…but also…

  • Game archetype should scale (Games can be tiny or huge!)
  • Lots of scope for programming fun!
  • Great community!

Have you heard of Roguelikes?

(No not Rogue-lites, Rogue-likes!)

They may not be what you had in mind, but they tick all the boxes!

What is a Roguelike?

Games that are like the classic game Rogue (1980)

Rogue in color ASCII Rogue

https://en.wikipedia.org/wiki/Rogue_(video_game)

The Wonderous Variety of Modern Roguelikes

Dwarf Fortress

Bay 12 Games - Tarn Adams & Zach Adams

Hoplite

Hoplite

Douglas Cowley

Cogmind

Grid Sage Games - Josh Ge

Porklike

Krystian Majewski

https://krystman.itch.io/porklike

Enough! Let’s make a (bit of a) Roguelike!

Demo: The Roguelike Starterkit

Author credit: Anikki

Corresponding to the IBM Code Page 437 (Extended ASCII)

Dwarf Fortress Tileset Repository: https://dwarffortresswiki.org/Tileset_repository

Demo time!

Roguelike ASCII in Indigo

Now all we need is…

- Non-Player Characters - Levels
- Path finding - Dungeon generation
- Collectables - Combat mechanics
- Health & damage - Health potions
- Inventory - Puzzles
- Menus - Field of View

…etc.

The RoguelikeDev Community

https://rogueliketutorials.com/

Game Jams!

March 2nd to March 10th, 2024

Developers are challenged to create a complete Roguelike game in 7 days!

20th Annual 7DRL Challenge!

You finished the tutorial!

https://github.com/davesmith00000/roguelike-tutorial

Now what?

From ASCII Art to Pixel Art

From… To…
181 Lines of code 1149 Lines of code

These are the same game!

Demo: Hoplike!

(It’s a game like ‘Hoplite’, geddit?)

Our aim is to inform and immerse the player!

  1. Quick wins!
  2. Lighting
  3. Animation
  4. Turn Management
  5. Shaders

Quick wins!

Quick win 1: Swap the tile sheet!

From… To…

Quick win 2: Layered rendering!

Quick win 3: Sound!

Mood Lighting

Comparison

Textures for lighting

We need…

  1. Diffuse / Albedo - Base colour!
  2. Emissive - Glow in the dark!
  3. Height map - Depth! …so we can make…
  4. Normal map - The ‘Bumpiness’!

Lighting materials

To recieve dynamic light, we need a material that understands the lighting model.

(Note: The diffuse texture is already set on the graphic’s material.)

Adding Lights to the scene

Adding Lights to the scene

Animation

Animations as Functions

(t: Seconds) => A // For a give time t, produce a deterministic value A

Signals

opaque type Signal[A] = Seconds => A

Signals

opaque type Signal[A] = Seconds => A

Signals & Signal Functions

opaque type Signal[A]            = Seconds => A
opaque type SignalFunction[A, B] = Signal[A] => Signal[B]

Signals can be piped, composed, and parallelised.

def move(shape: Shape.Circle): SignalFunction[Vector2, Shape.Circle] =
  SignalFunction(v => shape.moveTo(v.toPoint))

val orbit =
  SignalFunction.orbit(Vector2(0), 1, Radians(0))

Signal.Time |> orbit >>> move(myCircle)

Timeline Animations

A timeline animation DSL built on Signals and SignalFunctions.

Turn Management

Recall the ASCII game…

The bump function is the whole game!

1. Wait for the player to hit an arrow key
2. Bump! Instantly update everything
3. GOTO 1

Turn Based Games & State Machines

Once we have animation, we need a more controlled ‘states’ for each phase of a turn loop.

1. Wait for player input // keyboard, mouse, or touch!
2. Update the game model (player turn)
3. Animate the player actions
4. Update the game model (NPC/Enemy turn)
5. Animate the NPC/Enemy actions
6. GOTO 1

Demo: Managing Turn States

Shaders

Did you notice there were no rainbows on the tilesheet? It’s a shader!

What is a shader?

Intuition for a ‘Fragment’ shader:

Parallel map over all the screen coordinates, and choose a colour for each pixel.

type UV                   = (Float, Float)
val context: T            = ???
val UVs: List[UV]         = ??? // screen coordinates
val frag: (UV, T) => RGBA = ???

UVs.par.map(uv => frag(uv, context))

(This is a lie! …but good enough for now…)

Demo: Basic Shader

Rainbow Maths: step

Demo

A Rainbow made of step functions

Rainbow Maths: mix

mix(a, b, x)

Demo

Demo: Rainbow Shader

Food for thought

def rainbow(value: Float): RGB = ...

Nowhere does it say the rainbow must go in a straight line…

Thank you for listening!

Rainbow scene, one shader, about 130 lines of code.

Takeaways

  • ⚔️ Roguelikes! The games and the community!
  • 🎮 Scala is more fun than you think it is!
  • 📈 Scala can do more that you thought it could!
  • 👾 Game dev in Scala is easier than you imagined?
  • 🚀 You should have a go!
  • 💪 …and bravely show us your work!
  • 🙇 Scala.js is amazing.
  • (Also, try Mill. 😁)

Handy links for inspired adventurers seeking guidance on their quest:

Indigo
Discord https://discord.gg/b5CD47g
Indigo https://github.com/PurpleKingdomGames/indigo
Starterkit https://github.com/PurpleKingdomGames/roguelike-starterkit
Website https://indigoengine.io/
Twitter https://twitter.com/indigoengine
Mastodon https://mastodon.gamedev.place/@davesmith00000

Handy links for inspired adventurers seeking guidance on their quest:

Roguelikes
Discord https://discord.com/invite/S5F2H32
Reddit https://www.reddit.com/r/roguelikedev/
Official Tutorials https://rogueliketutorials.com/
Roguelike Celebration Conference https://www.roguelike.club/
7DRL https://7drl.com/