Alchemy Day 2: As far as the eye can see

Posted: March 13, 2013 in Uncategorized

Day 2 of Alchemy was tough – trying to snatch some hours of game coding in between “real work”. Nevertheless still managed to make some good progress.

2013-03-13 LOS features

As you can see, it’s starting to look a bit more like a real Roguelike. But equally importantly, things are starting to come together under the hood.

Line of Sight

Main visual feature of the day is a LOS algorithm. I kept this fairly straightforward: casting rays in 100 directions. The core algorithm proved to be surprisingly short in Clojure:

(def LOS_RAYS 100)
(def RAY_INC 0.33)
(def RAY_LEN 15)

(defn update-visibility [game]
  (let [bg (BitGrid.)
        hloc (hero-location game)
        hx (.x hloc) hy (.y hloc) hz (.z hloc)]
    (.set bg hx hy hz true)
    (dotimes [i LOS_RAYS]
      (let [dx (Math/sin (* i (/ (* 2.0 Math/PI) LOS_RAYS)))
            dy (Math/cos (* i (/ (* 2.0 Math/PI) LOS_RAYS)))]
        (loop [d 1.0]
          (when (< d RAY_LEN)
            (let [px (int (Math/round (+ hx (* dx d))))
                  py (int (Math/round (+ hy (* dy d))))
                  view-ok? (not (get-pred game (loc px py hz) :is-view-blocking))]
              (when view-ok?
                (.set bg px py hz true)
                (recur (+ d RAY_INC))))))))
    (extend-visibility bg) ;; extend visibility by 1 square in all directions
    (assoc game :visibility bg)))

My nod to functional programming here is in the “get-pred” function. This finds an object in a square that satisfies an arbitrary predicate, in this case we want to test the “:is-view-blocking” property to determine if we should terminate the LOS ray. get-pred is implemented like this:

(defn get-pred
  "Gets the first object satisfying a predicate in a square. Considers tile last."
  ([game loc pred]
    (let [ts (get-things game loc)
          tl (get-tile game loc)]
      (or
        (find/find-first pred ts)
        (if (pred tl) tl nil)))))

I’m quite pleased with this – the function should be generally useful throughout the game because finding an object in a given square is going to be a very common operation. Also, since it returns “nil” for not found it can easily be used in conditional statements (I really like Clojure’s concept of “truthy” and “falsey” – nil or false are false, everything else is true).

Creatures

You can probably see a rat in the screenshot above. He is implemented like this, using the “proclaim” function I developed yesterday to build up the object library:

    (proclaim "base creature" "base thing"
                   {:is-mobile true
                    :is-blocking true
                    :is-creature true
                    :is-hostile true
                    :on-action engine/monster-action
                    :aps 0
                    :z-order 75
                    :SK 5 :ST 5 :AG 5 :TG 5 :IN 5 :WP 5 :CH 5 :CR 5})
    ....
    (proclaim "base rat" "base creature"
                   {:SK 4 :ST 3 :AG 6 :TG 2 :IN 1 :WP 5 :CH 2 :CR 2
                    :char \r
                    :colour-fg (colour 0xB0A090)})
    ....
    (proclaim "rat" "base rat"
                   {:char \r
                    :colour-fg (colour 0xB0A090)})

Note how we are starting to get dividends from our prototype inheritance hierarchy: a rat is really just a base creature with a couple of customisations.

The :on-action property defines a handler function that gets called to drive monster movement whenever it is the monster’s turn to move. Currently it is just a blank stub, but with a bit of work tomorrow we’ll have fully fledged fighting monsters.

Items

I defined a few items, using the same library functionality as the creatures. This is ridiculously easy – I’m going to have no problem creating 20-30 creatures and 20-30 items for the finished game. It’s like having a DSL for item definition at your fingertips.

You can see a few slime moulds in the screenshot above.

Lighting

Final feature today was a visual touch – falloff lighting based on distance from the player which gives a nice spooking “torchlight” effect.

Code was also pretty simple to achieve this – it was just a matter of fading the colour towards zero (black) based on the squared distance from the player. I experimented a bit with different formulae, and like this on most:

(defn shade-colour
  "Produces a fade to black over distance"
  ([^Color c ^double d2]
    (let [BD 50.0
          p (/ BD (+ BD d2))]
      (if (&lt; p 1.0)
        (let [p (/ p 255.0)
              r (float (* p (.getRed c)))
              g (float (* p (.getGreen c)))
              b (float (* p (.getBlue c)))]
          (Color. r g b (float 1.0)))
        c))))

Light falloff (p) is basically 1/(1+r^2) where r is proportional to the squared distance from the player. Note the use of liberal Java interop with java.awt.Color to define the colour – no point reinventing the wheel when Java has a perfectly decent Color representation.

Planning

So I need to get a move on if this is going to be finished in 7 days. Tomorrow will be about action: monster AI, combat, item actions etc. While I want to get into the alchemy stuff, I think I need the basic game mechanics all sorted first so that the more advanced features can be done in this context.

Advertisements
Comments
  1. georgek says:

    Tiles and color look nice, keep up the good work!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s