"End Credits" script (rolling credits)

Started by alexgleason, November 15, 2018, 09:54:14 PM

Previous topic - Next topic
November 15, 2018, 09:54:14 PM Last Edit: November 15, 2018, 09:56:44 PM by alexgleason
I didn't share this before because it'd likely need to be adapted and parts of the code aren't super nice, but I figure maybe this will benefit someone.

It requires a dialog called "end_credits", and it just rolls through it until it's done.
Code ( lua) Select
-- ♡ Copying is an act of love. Please copy and share.

-- Game credits. Plays at the end of the game.

local end_credits = {}


-- https://stackoverflow.com/a/8316375/8811886
function build_array(...)
  local arr = {}
  for v in ... do
    arr[#arr + 1] = v
  end
  return arr
end


-- Called when the menu is started
function end_credits:on_started()
  local lh = 12 -- line height in pixels
  local speed = 24 -- scroll speed in px/s

  -- Credits dialog
  self.dialog = sol.language.get_dialog("end_credits")

  -- Break dialog text into a table of lines
  local lines = self.dialog.text
  lines = lines:gsub("\r\n", "\n"):gsub("\r", "\n")
  lines = build_array(lines:gmatch("([^\n]*)\n"))


  -- Box where the credits go
  self.credits_surface = sol.surface.create(
    160, -- center the surface on the screen
    (#lines * lh) -- surface is large enough to hold all lines
      + 144 -- surface scrolls in from the bottom, so has a padding top equal to the screen size
      + 16 -- room for 8px top and bottom padding
  )

  -- Loop through all dialog lines and draw them
  for i, line in ipairs(lines) do
    local line_surface =  sol.text_surface.create({font="Comicoro", font_size=16, text=line})
    -- Draw the given line
    line_surface:draw(
      self.credits_surface,
      8, -- left padding
      i * lh -- bump it down by line number and line height
        + 8 -- top padding for whole box
    )
  end

  -- Animate the text box upwards
  local m = sol.movement.create("straight")
  m:set_angle(math.pi / 2)
  m:set_speed(speed)
  m:start(self.credits_surface)

  function m:on_position_changed()
    local credits_surface = end_credits.credits_surface
    local x, y = credits_surface:get_xy()
    local w, h = credits_surface:get_size()

    log(string.format("Credits text box: (%d, %d)  ;;  y+h = %d", x, y, y+h))

    if y + h < 0 then
      -- Credits are out of view, end the menu
      log("Credits animation finished.")
      self:stop()
      sol.menu.stop(end_credits)
    end
  end

end


-- Called each frame
function end_credits:on_draw(dst_surface)
  dst_surface:clear()
  self.credits_surface:draw(dst_surface, 48, 144)
end


return end_credits


It's a menu, so put it in a .lua file (eg scripts/menus/end_credits.lua) and use something like this:

Code ( lua) Select

local end_credits = require("scripts/menus/end_credits")

sol.menu.start(game, end_credits)
RIP Aaron Swartz

Cool!

You should have it start playing a music file and then synchronize the scroll speed so that it ends as the music ends.

hmm... I don't think there is any way to get the duration of a music track from the Solarus API, though.