Programming#

This page contains information for many different things you should know when programming.

Logging#

We use a logging library. You should call getLogger() like so:

class MyClass {
  private val logger = getLogger()

  fun someFunction() {
    logger.info("Something has happened!")
  }
}

Note that getLogger() requires it to be called inside of a class because there’s some magic happening behind the scenes. If you need to have a Logger instance outside of a class (such as a function), you can create an object in the same file and call getLogger() there.

Logging is preferred over println() because it adds timestamps to the output and allows us to know exactly what class/file the log message came from. Logging is available in every single module.

Packages#

Packages are a concept for JVM languages such as Java and Kotlin. Packages are a way to organize code just like modules or namespaces in other programming languages. All packages start with com.enigmashowdown. Most modules have a unique suffix to the package to make it easy to tell what module a package belongs to.

If something is specific to the game Conquest, that file should go in the com.enigmashowdown.game.conquest package, as it is not apart of the EnigmaShowdown framework code.

libGDX#

We use libGDX inside of the visualization module. There are many different components to libGDX. There is extensive documentation online for them, but here are some summaries of important concepts.

Stages#

Stages are a concept in libGDX that help us create a virtual 2D world for sprites, text, and other things to be placed on. By using a stage, we save ourselves from having to manage what size to draw a sprite at, and we get some nice features that help us layout UI. At its core, a stage is just something to keep track of “actors” at x,y coordinates. The real advantage of using a stage is a stages ability to render all of the actors on the stage. This saves us from rendering each sprite, text, button, etc individually, and even more importantly, it saves us from having to worry about how to render actors after a screen resize.

The title screen (enigmashowdown/blob/main/visualization/src/main/kotlin/com/enigmashowdown/visual/screens/TitleScreen.kt) is a good example of a stage in action. In the title screen example, you will notice we have named our stage uiStage indicating this stage is used for UI. It is important that we have one stage for UI components and one stage for “world” components. UI components want to be on a stage that uses a viewport with a width and height that represents pixels, not world units.

Skins#

libGDX has the concept of skins. There are many skins designed for UI there. Our uiSkin will always be one of the pre-made UI skins.

Skins can be used for more than just UI components. In this project we also have a mainSkin, which should contain sprites that are not apart of the map (such as entities that can move). We use the visualization-packer to create a skin from the assets inside of enigmashowdown/tree/main/visualization-packer/raw-assets. From that autogenerated skin, we can do stuff like mainSkin.newDrawable("cherry") to get the Drawable object of the cherry.png sprite.

Renderable#

Renderable is not a concept from libGDX, but it is a construct that exists in this project (enigmashowdown/blob/main/visualization/src/main/kotlin/com/enigmashowdown/visual/render/Renderable.kt).

interface Renderable : Disposable {
    fun render(delta: Float)
    fun resize(width: Int, height: Int)
}

You can see that it’s a simple interface. By defining this interface, we can create classes that implement this. This forces us to define things that need to be rendered to the screen in a standard way, and allows for powerful code snippets such as this:

renderable = RenderableMultiplexer(listOf(
    ResetRenderable(Color.BLACK),
    StageRenderable(uiStage),
))

We have now defined a single Renderable, which is made up of smaller Renderables. This helps us modularize our rendering code by making it reusable.