301 Days (redux)

Another metric leap year of gamedev experiments and such

New Day 1 - Beholder on Your Phone pt6

Mar 14, 2023 - 5 minute read - NewDayssms-beholderblog

Hello Hugo

A new/old look, and some other stuff.

Everything old is new again

Thanks to Hugo and the Hugo-Octopress theme, this blog now looks a lot like it originally did. Of course, I found it necessary to fork and expand on Octopress, so I’ve had to do that again to fully support my old blog posts. Luckily Hugo shortcodes are pretty easy and convenient.

codeblock

The codecaption shortcode from the Hugo Octopress theme gives a nice Octopress look, but I really like to specify a starting line number with a link to that line in the source repository. So along with a title, I need a URL, the link text, and optionally a line number on which to start.

shortcodes/codeblock.html GitLab
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<!-- Based on the codecaption shortcode by
   Parsia Hakimian https://github.com/parsiya/Hugo-Shortcodes -->

     <figure class="code">
        <figcaption>
            <span>{{ .Get "title" }} <a href="{{ .Get "url" }}">{{ .Get "linktext" }}</a></span>
        </figcaption>
        <div class="codewrapper">
          {{ $options := printf "linenos=true,linenostart=%d" (.Get "linenostart" | default 1) }}
          {{ highlight (trim .Inner "\n\r") (.Get "lang") $options }}
        </div>
      </figure>

rawhtml

I also tripped over how to handle the HTML I’d embedded directly in a couple of blog posts. Those sections would simply not show up at all, unless I opted for “unsafe” rendering in the markdown settings. Instead of doing that, I found someone’s trivial shortcode to wrap around them:

shortcodes/rawhtml.html
1
2
3
{{/*  Thanks to Ana Ulin https://anaulin.org/blog/hugo-raw-html-shortcode/  */}}
<!-- raw html -->
{{.Inner}}

Close enough

I’m sure I’ll tweak more in future (maybe even fork the theme), but so far I’m satisfied.


Beholder on Your Phone pt6

Beholder emerges from AT&T logo

At some point during my hiatus, I resumed work on the SMS port of Beholder High. I was close to a textual MVP, but the art was one of the best parts of the game. The web-based version of the game was free to composite the images in real time, and do some idle animations; but for the sake of bandwidth and simplicity, I decided it was better to pre-process the images for the SMS (technically SMS and MMS, now) version.

A Little Image Magick

I had some history with ImageMagick, so was glad to find a handy Ruby gem: rmagick. With some trial and error, I started putting together images in MMS-friendly resolution:

image_comp.rb GitLab
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
require 'json'
require 'rmagick'
include Magick

def beholder_compose_image(image_spec, filename=nil, dir="composite")
  if image_spec[:bg]
    bg_image_name = "images/bg/#{image_spec[:bg]}.jpg"
    return unless File.file?(bg_image_name)
    bg_image = ImageList.new(bg_image_name).resize(600, 400)
    new_image = bg_image
    if image_spec[:beholder]
      beholder_image_name = "images/char/#{image_spec[:beholder]}/#{image_spec[:beholder]}-" \
        "#{image_spec[:beholderExp]}.png"
      return unless File.file?(beholder_image_name)
      beholder_image = ImageList.new(beholder_image_name)
      new_image = bg_image.composite(beholder_image, CenterGravity, SrcOverCompositeOp)
      debug_text(image_spec, new_image) if image_spec[:debug]
    end
    if filename
      new_image.write("#{dir}/#{filename}")
    else
      new_image.write("#{dir}/#{image_spec[:bg]}_#{image_spec[:beholder]}_" \
                      "#{image_spec[:beholderExp]}#{image_spec[:debug] ? '_debug' : ''}.png")
    end
  else
    print("Bad image_spec: #{image_spec}")
  end
end

Happy beholder Moxanimous on the sports field.

I wasn’t going to spend much time putting together tests for this run-once code, so the ability to superimpose debug info on the image was useful for human verification.

image_comp.rb GitLab
30
31
32
33
34
35
36
37
38
39
40
41
42
43
def debug_text(image_spec, image)
  text = Magick::Draw.new
  text.font = "Helvetica"
  text.pointsize = 30
  text.gravity = Magick::SouthGravity
  new_text = "#{image_spec[:beholder]} is #{image_spec[:beholderExp]}" \
    " at #{image_spec[:bg]}"
  text.fill = 'gray83'
  text.annotate(image, 0, 0, 2, 2, new_text)
  text.fill = 'gray40'
  text.annotate(image, 0, 0, -1.5, -1.5, new_text)
  text.fill = 'darkred'
  text.annotate(image, 0, 0, 0, 0, new_text)
end

Angry beholder Siriak the Rapid in the lunchroom with debug text.

Continuous (Visual) Integration

Of course I wanted to generate the images as part of a CI workflow, which seemed straightforward:

.gitlab-ci.yml GitLab
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
image: ruby:2.7

before_script:
  - apt-get update -qq
  - ruby -v
  - which ruby
  - gem install bundler
  - bundle install --jobs $(nproc)  "${FLAGS[@]}"
  - mkdir composite
  - bundle exec ruby image_comp.rb
  - ls composite

…but had issues with my debug text.

$ bundle exec ruby image_comp.rb
/usr/local/bundle/gems/json-2.1.0/lib/json/common.rb:156: warning: Using the last argument as keyword parameters is deprecated
image_comp.rb:38:in `annotate': unable to read font `Helvetica' @ error/annotate.c/RenderFreetype/1396 (Magick::ImageMagickError)
	from image_comp.rb:38:in `debug_text'
	from image_comp.rb:17:in `beholder_compose_image'
	from image_comp.rb:56:in `block in <main>'
	from image_comp.rb:47:in `each'
	from image_comp.rb:47:in `<main>'

After a little research, it seemed like maybe installing Ghostscript would give me the fonts I needed, so I added that.

.gitlab-ci.yml GitLab
3
4
5
6
7
8
9
before_script:
  - apt-get update -qq
  - apt-get install ghostscript -q -y
  - ruby -v
  - which ruby
  - gem install bundler
  - bundle install --jobs $(nproc)  "${FLAGS[@]}"

I ran the image compositing at part of the rspec test pipeline, and archived the results.

.gitlab-ci.yml GitLab
16
17
18
19
20
21
22
23
24
25
26
27
28
rspec:
  script:
    - mkdir composite
    - bundle exec ruby image_comp.rb
    - ls composite
    - bundle exec rspec --format progress --format RspecJunitFormatter --out rspec.xml
  artifacts:
    when: always
    paths:
      - composite/
      - rspec.xml
    reports:
      junit: rspec.xml
On GitLab, the pipeline successfully ran and created artifacts On GitLab, the pipeline successfully ran and created artifacts

Download and unzip, and…

I have all of my composited images. I have all of my composited images.

Now to put them somewhere public so they can be attached to messages.


More to come

sms-beholder New Day 001 code