Files
andros 3ad1636c9c Port to LÖVE 11.5, translate to Spanish and wire up endings
Compatibility (0.10 -> 11.x):
- love.audio.newSource now requires a source type argument
- love.graphics.setColor uses 0-1 range instead of 0-255
  (stress overlay and MessageInABottle text/background/alpha)
- love.keyboard.isDown space key is "space", not " "
- conf.lua version bumped to 11.5

Content:
- Translate all in-game texts to Spanish
- Prepend control instructions to the welcome message
- Add the missing cap5stage text (bra reflection)
- Show endgood/endbad texts on the final screen

Bug fixes:
- stage7 crashed on the bad ending: music2 was only set on the
  good branch, guard the play() call
- stress overlay leaked its faded color; restore full color after draw
2026-08-14 21:40:53 +02:00

464 lines
11 KiB
Lua
Executable File

--[[
MessageInABottle.lua - 2010-11-08
http://bitbucket.org/dannyfritz/message-in-a-bottle/
Danny "TechnoCat" Fritz dannyfritz@gmail.com
Commons Attribution-ShareAlike 3.0
--]]
--An OO library for Lua by Kikito,
--can be found at https://github.com/kikito/middleclass
require 'assets/scripts/vendor/MiddleClass'
require 'assets/scripts/vendor/GraphicsStateStack'
MessageBottle = class('MessageBottle')
TimeBottle = MessageBottle:subclass('TimeBottle')
--[[
Default values
--]]
MessageBottle.DEFAULT_SOUND = 'assets/audio/fx/messages/blip.ogg'
MessageBottle.DEFAULT_VOLUME = 0.5
MessageBottle.DEFAULT_BUTTON = 'space' --Button to close/select
MessageBottle.DEFAULT_INDICATOR = love.graphics.newImage('assets/sprites/messages/input-indicator.png') --Image to
MessageBottle.DEFAULT_X = 20
MessageBottle.DEFAULT_Y = 180
MessageBottle.DEFAULT_WIDTH = 300
MessageBottle.DEFAULT_HEIGHT = 80
MessageBottle.DEFAULT_FONT = love.graphics.newFont(18)
MessageBottle.DEFAULT_ALIGN = 'left'
MessageBottle.DEFAULT_FGCOLOR = {r=255,g=255,b=255}
MessageBottle.DEFAULT_FGALPHA = 1
MessageBottle.DEFAULT_BGRADIUS = 10 --pixels to draw the rounded corners
MessageBottle.DEFAULT_BGRADIUSSEGMENTS = 32 --how precisely to draw the circle
MessageBottle.DEFAULT_BGCOLOR = {r=0,g=0,b=0}
MessageBottle.DEFAULT_BGALPHA = 0.3
MessageBottle.DEFAULT_EASETIME = 0.5 --seconds to ease
MessageBottle.DEFAULT_FADETIME = 0.3 --seconds to fade alpha
MessageBottle.DEFAULT_EASEOFFSET = 10
MessageBottle.DEFAULT_ID = "NO_ID"
MessageBottle.DEFAULT_TEXT = "Text is not set."
TimeBottle.TIMEOUT = 6 --seconds to keep the bottle alive
function MessageBottle:drawBackground()
--draw background
--self.bgAlpha
--self.alpha
love.graphics.pushState()
local r,g,b,a = self.bgColor.r, self.bgColor.g, self.bgColor.b
local a = self.bgAlpha * self.alpha
local r = self.bgRadius
local x,y = self.x, self.y
local w,h = self.width, self.height
local segments = self.bgRadiusSegments
love.graphics.setColor(r/255,g/255,b/255,a/255)
--center rectangle
love.graphics.rectangle("fill",
x, y,
w, h)
--top border
love.graphics.rectangle("fill",
x, y-r,
w, r)
-- right border
love.graphics.rectangle("fill",
x+w, y,
r, h)
--bottom border
love.graphics.rectangle("fill",
x, y+h,
w, r)
--left border
love.graphics.rectangle("fill",
x-r, y,
r, h)
--top left corner
love.graphics.setScissor(
x-r, y-r,
r, r)
love.graphics.circle("fill",
x, y,
r, segments)
--top right corner
love.graphics.setScissor(
x+w, y-r,
r, r)
love.graphics.circle("fill",
x+w, y,
r, segments)
--bottom right corner
love.graphics.setScissor(
x+w, y+h,
r, r)
love.graphics.circle("fill",
x+w, y+h,
r, segments)
--bottom left corner
love.graphics.setScissor(
x-r, y+h,
r, r)
love.graphics.circle("fill",
x, y+h,
r, segments)
love.graphics.popState()
end
--[[
Ocean
This is a class to store and invoke the focussed bottles
(A queue)
--]]
Ocean = class('Ocean')
function Ocean:initialize()
super.initialize(self)
self.bottles = {}
self.response = ""
self.responseTime = 0
self.responseID = ""
self.time = 0
end
function Ocean:update(dt)
if #self.bottles > 0 then
self.time = self.time + dt
local bottle = self.bottles[1]
if bottle.focusTime == 0 then
bottle:enterCallback()
end
local tmp = self.response
self.response = bottle:update(dt)
if self.response==nil then
self.response = tmp
else
self.responseTime = self.time
self.responseID = self.bottles[1].id
end
if not bottle.alive then
bottle:exitCallback(self.response)
table.remove(self.bottles,1)
end
end
end
function Ocean:draw()
if #self.bottles > 0 then
self.bottles[1]:draw()
end
end
function Ocean:addBottle(bottle)
local bottles = self.bottles
table.insert(bottles, #bottles+1, bottle)
end
--[[
Message Bottle
This is a default message bottle class
Bottle background is drawn here.
--]]
function MessageBottle:initialize(id, text)
super.initialize(self)
self.id = id or self.class.DEFAULT_ID
self.text = text or self.class.DEFAULT_TEXT
self.alive = true --Set to flag to mark for deletion
--Callbacks
self.enterCB = function() return end
self.exitCB = function(response) return end
--Sounds
self.sound = self.class.DEFAULT_SOUND
self.volume = self.class.DEFAULT_VOLUME
--Buttons
self.button = self.class.DEFAULT_BUTTON
self.buttonDown = false --Flag to make the button action happen on release
self.indicator = indicator or self.class.DEFAULT_INDICATOR
--Dimensions
self.x = self.class.DEFAULT_X
self.y = self.class.DEFAULT_Y
self.width = self.class.DEFAULT_WIDTH
self.height = self.class.DEFAULT_HEIGHT
--Foreground settings
self.fgColor = self.class.DEFAULT_FGCOLOR
self.fgAlpha = self.class.DEFAULT_FGALPHA
self.font = self.class.DEFAULT_FONT
self.align = self.class.DEFAULT_ALIGN
--Background settings
self.bgColor = self.class.DEFAULT_BGCOLOR
self.bgAlpha = self.class.DEFAULT_BGALPHA
self.bgRadius = self.class.DEFAULT_BGRADIUS
self.bgRadiusSegments = self.class.DEFAULT_RADIUSSEGMENTS
--Ease settings
self.easeTarget = self.class.DEFAULT_Y
self.easeOffset = self.class.DEFAULT_EASEOFFSET
self.easeTime = self.class.DEFAULT_EASETIME
--Fade settings
self.focusTime = 0 --seconds the message has been in focus
self.alpha = 0
self.fadeTime = self.class.DEFAULT_FADETIME
end
function MessageBottle:baseUpdate(dt, focusTime)
self.y = self:ease(focusTime,self.easeTime, self.easeTarget,self.easeOffset)
self.alpha = self:fade(focusTime,self.fadeTime, 0,255)
self.focusTime = self.focusTime + dt
end
function MessageBottle:enterCallback()
--Sound
self.source = love.audio.newSource(self.sound, "static")
self.source:setVolume(self.volume)
self.source:play()
self.enterCB()
end
function MessageBottle:exitCallback(response)
self.exitCB(response)
end
function MessageBottle:ease(t,d, a,b)
if d <= t then
function self:ease(t,d, a,b) return self.y end
end
local v = -(t/d)*(t/d-2)*b+a
return math.floor(v)
end
function MessageBottle:fade(t,d, a,b)
if d <= t then
function self:fade(t,d, a,b) return 255 end
end
local v = t/d*b+a
if v>=255 then
v=255
function self:fade(t,d, a,b) return 255 end
end
return v
end
function MessageBottle:setX(x)
self.x = x
end
function MessageBottle:setY(y)
self.easeTarget = y
self.y = y
end
function MessageBottle:setPosition(x, y)
self.x = x
self.y = y
self.easeTarget = y
end
function MessageBottle:setWidth(width)
self.width = width
end
function MessageBottle:setHeight(height)
self.height = height
end
function MessageBottle:setButton(button)
self.button = button
end
function MessageBottle:setEase(ease)
self.ease = ease
end
function MessageBottle:setEaseTime(easeTime)
self.easeTime = easeTime
end
function MessageBottle:setFade(fade)
self.fade = fade
end
function MessageBottle:setFadeTime(fadeTime)
self.fadeTime = fadeTime
end
function MessageBottle:setEnterCallback(enterCB)
self.enterCB = enterCB
end
function MessageBottle:setExitCallback(exitCB)
self.exitCB = exitCB
end
function MessageBottle:setSound(sound)
if sound==nil then
self.volume = 0
return
end
self.sound = sound
end
function MessageBottle:setVolume(volume)
self.volume = volume
end
function MessageBottle:setIndicator(indicator)
self.indicator = love.graphics.newImage(indicator)
end
function MessageBottle:setFgColor(r, g, b, a)
self.fgColor = {r, g, b, a}
end
function MessageBottle:setFont(font, size)
self.font = love.graphics.newFont(font,size)
end
function MessageBottle:setAlign(align)
self.align = align
end
function MessageBottle:setBgColor(r, g, b, a)
self.bgColor = {r, g, b, a}
end
function MessageBottle:setBgRadius(bgRadius)
self.bgRadius = bgRadius
end
function MessageBottle:setBgRadiusSegments(bgRadiusSegments)
self.bgRadiusSegments = bgRadiusSegments
end
--[[
Staying Bottle
This pops up a message bottle and
goes away after a button is pressed
--]]
StayBottle = MessageBottle:subclass('StayBottle')
function StayBottle:initialize(id, text)
super.initialize(self, id, text)
end
function StayBottle:update(dt)
self:baseUpdate(dt,self.focusTime)
if love.keyboard.isDown(self.button) and self.buttonDown==false then
self.buttonDown = true
elseif self.buttonDown==true and not love.keyboard.isDown(self.button) then
self.alive = false
return 0
end
end
function StayBottle:draw()
love.graphics.pushState()
self:drawBackground()
local color = self.fgColor
love.graphics.setColor(color.r/255,color.g/255,color.b/255,self.alpha/255)
love.graphics.setFont(self.font)
local text = ""
text = text..self.text..'\n'
local button = self.button
if button == "space" or button == " " then
button = "ESPACIO"
end
if math.floor(self.focusTime)%2 == 0 then
text = text..'pulsa \''..button..'\' para continuar'
else
text = text..'pulsa \''..button..'\' para continuar...'
end
love.graphics.printf(text, self.x,self.y, self.width, self.align)
local floaty = math.sin(self.focusTime*3)*3
local y = self.y + self.height + floaty - self.indicator:getHeight()/2
love.graphics.draw(self.indicator,self.x+self.width/2, y)
love.graphics.popState()
end
--[[
Timed Bottle
This pops up a message bottle and
goes away after a set time duration
--]]
function TimeBottle:initialize(id, text, timeout)
super.initialize(self, id, text)
self.timeout = timeout or self.class.TIMEOUT
end
function TimeBottle:update(dt)
self:baseUpdate(dt,self.focusTime)
self.timeout = self.timeout - dt
if love.keyboard.isDown(self.button) and self.buttonDown==false then
self.buttonDown = true
elseif self.buttonDown==true and not love.keyboard.isDown(self.button) then
self.alive = false
return 0
end
if self.timeout <= 0 then --count down a timer
self.alive = false
return 1
end
end
function TimeBottle:draw()
love.graphics.pushState()
self:drawBackground()
local color = self.fgColor
love.graphics.setColor(color.r/255,color.g/255,color.b/255,self.alpha/255)
love.graphics.setFont(self.font)
love.graphics.printf(self.text, self.x,self.y, self.width, self.align)
love.graphics.popState()
end
function TimeBottle:setTimeout(timeout)
self.timeout = timeout
end
--[[
Choice Bottle
This pops up a message with choices bottle
and goes away after a choice is made
--]]
ChoiceBottle = MessageBottle:subclass('ChoiceBottle')
function ChoiceBottle:initialize(id, text, ...)
super.initialize(self, id, text)
end
function ChoiceBottle:update(dt)
--Draw text and choices along with cursor
--Check keyboard / mouse input for selection
end
function ChoiceBottle:draw()
end