everything I could before the deadline

This commit is contained in:
wan-may 2025-03-21 14:20:54 -03:00
parent 1ddffb71e4
commit 3f65959321
39 changed files with 412 additions and 155 deletions

View File

@ -33,9 +33,12 @@ IT WON'T BE LONG NOW, BEFORE WE GO TO OUR REWARD.
TETÉLESTAI TETÉLESTAI
]], ]],
phoneRing = "THE PHONE RINGS IMPATIENTLY", phoneRing = [[THE RED CONTEMPRA PHONE,
THE KING'S INCORPOREAL FORM,
RINGS IMPATIENTLY.]],
ringBell = "[%s]: RING BELLS",
phonePickup = "[%s]: PICK UP", --use key phonePickup = "[%s]: PICK UP", --use key
phoneRedial = "[%s]: *69", --use key phoneRedial = "[%s]: *69", --use key
phoneClue = "🔔🔔🔔🔔🔔🔔🔔", phoneClue = [[ZIMINIAR WILL BARGAIN. PLAY THIS TUNE TO ACCEPT.]],
phoneWin = "WHAT IS WANTED", phoneWin = "WHAT IS WANTED",
} }

View File

@ -9,11 +9,29 @@ local light = {}
light[1], light[2], light[3] = normal( 1.0, 1.0, 0.0 ) --direction TO the light btw light[1], light[2], light[3] = normal( 1.0, 1.0, 0.0 ) --direction TO the light btw
light.target = 1 light.target = 1
local targets = {}
local c, s, p = math.cos, math.sin, 2*math.pi local c, s, p = math.cos, math.sin, 2*math.pi
do
local c, s = c( p * 2 / 7 ), s( p * 2 / 7 )
local x, y, z = 1, 1, 0
for i = 1, 7 do
x, z = c*x-z*s,s*x+z*c
y = 1 + 0.5 * s
targets[i] = { x, y, z }
end
end
function light.setTarget( i ) function light.setTarget( i )
light.target = light.target + 1 light.target = i
i = i - 1 end
light[1], light[2], light[3] = normal( c(i*p/7), 1, s(i*p/7) )
function light.update( enteringCircle )
if enteringCircle then light.setTarget( enteringCircle ) end
if not light.target then return end
for i = 1, 3 do
light[i] = 0.999 * light[i] + 0.001 * targets[ light.target ][i]
end
light[1], light[2], light[3] = normal( light[1], light[2], light[3] )
end end

View File

@ -22,29 +22,38 @@ function t.start()
stencil = false, stencil = false,
depth = true, depth = true,
} }
-- water = require( "models.water" ) -- water = require( "models.water" )
sky = require( "models.sky" ) sky = require( "models.sky" )
bell = require( "models.bell" ) bell = require( "models.bell" )
t.bell = bell
contempra = require( "models.contempra" ) contempra = require( "models.contempra" )
t.phone = contempra
t.phone.ring()
terrain = require( "models.terrain" ) terrain = require( "models.terrain" )
spike = require( "models.spike" ) spike = require( "models.spike" )
local n = 1
t.circles = {}
local function addCircles( obj )
for i, circle in ipairs( obj.circles ) do
t.circles[n] = circle
n=n+1
end
end
addCircles( contempra )
addCircles( bell )
addCircles( spike )
end end
function t.debug() function t.debug()
isDebugging = true isDebugging = true
end end
local function matte( ) local text = love.graphics.newText( love.graphics.getFont() )
local list = drawLists.matte
local shader = shaders.matte
love.graphics.setShader( shader )
for mesh in pairs( list ) do
shader:send( "mdl", "column", meshes[mesh])
love.graphics.draw( mesh )
end
end
function t.draw( view, proj, x, z ) function t.draw( view, proj, x, z )
if isDebugging then if isDebugging then
@ -52,13 +61,15 @@ function t.draw( view, proj, x, z )
love.graphics.push( "all" ) love.graphics.push( "all" )
love.graphics.setColor( 1,1,1,1 )
love.graphics.setScissor( 0, 0, love.graphics.getDimensions() ) love.graphics.setScissor( 0, 0, love.graphics.getDimensions() )
love.graphics.setCanvas( canvas ) love.graphics.setCanvas( canvas )
love.graphics.clear() love.graphics.clear()
love.graphics.setDepthMode( "less", true ) love.graphics.setDepthMode( "less", true )
love.graphics.replaceTransform( tf ) love.graphics.replaceTransform( tf )
love.graphics.setMeshCullMode( "back" ) love.graphics.setMeshCullMode( "back" )
sky.draw( view, proj, light ) sky.draw( view, proj, light )
terrain.draw( view, proj, light ) terrain.draw( view, proj, light )
bell.draw( view, proj, light ) bell.draw( view, proj, light )
@ -70,24 +81,37 @@ function t.draw( view, proj, x, z )
love.graphics.setColor( 1, 1, 1, 1 ) love.graphics.setColor( 1, 1, 1, 1 )
love.graphics.draw( canvas[1] ) love.graphics.draw( canvas[1] )
if isDebugging then
isDebugging = false if t.msg then
io.flush() text:set( t.msg )
text:setf( t.msg, text:getWidth(), "center" )
end
local textx = 0.5 * (love.graphics.getWidth() - text:getWidth())
local w = text:getWidth()
if w > 0 then
love.graphics.setColor( 0,0,0,0.9 )
love.graphics.rectangle( "fill", textx - 10, 0, w + 20, text:getHeight() + 20 )
love.graphics.setColor( 1,0,0,1 )
love.graphics.draw( text, textx, 10 )
end end
end end
function t.update( player ) function t.update( player )
local msg
light.update( player.enteringCircle )
msg = bell.update( player.enteringCircle, player.leavingCircle, player.x, player.z )
local phoneMsg = contempra.update( player )
msg = msg or phoneMsg
t.msg = msg or ""
end end
function t.transposeBells( i, j ) function t.transposeBells( i, j )
return bell.transpose( i, j ) return bell.transpose( i, j )
end end
function t.targetLight( i )
return light.setTarget( i )
end
function t.pickupPhone() function t.pickupPhone()
return contempra.pickup() return contempra.pickup()
end end
@ -96,4 +120,8 @@ function t.ring( idx )
return bell.ring( idx ) return bell.ring( idx )
end end
function t.ringAll( i )
return bell.ringAll( i )
end
return t return t

View File

@ -3,6 +3,7 @@ local love = assert( love )
local lg = assert( love.graphics ) local lg = assert( love.graphics )
local math = math local math = math
local mat = require( "mat4" ) local mat = require( "mat4" )
local strings = require( "i18n" )
local attributeNames = { local attributeNames = {
@ -107,19 +108,33 @@ local bellMesh = lgMesh( asset.meshes[1].primitives[1] )
-- scale, x, z, colorparam -- scale, x, z, colorparam
local bells = {} local bells = {}
local bellInstanceMesh local bellInstanceMesh
local ringSource = love.audio.newSource( "sfx/bellC2.ogg", "static" ) local rings = { poly = false }
do
rings[true] = love.audio.newSource( "sfx/bellC2.ogg", "static" )
rings[false] = love.audio.newSource( "sfx/bellC2.ogg", "static" )
end
rings[true]:setVolume( 0.1 )
rings[false]:setVolume( 0.1 )
local function getPitch( size )
return 5.0 / size
end
do do
local c, s = math.cos( 2*math.pi / 7 ), -math.sin( 2*math.pi / 7 ) local c, s = math.cos( 2*math.pi / 7 ), -math.sin( 2*math.pi / 7 )
local x, z = math.cos(math.pi/7), -math.sin( math.pi/7 ) local x, z = math.cos(math.pi/7), -math.sin( math.pi/7 )
local pitches = { 0, 5, 8, 12, 10, 22, 25 } local pitches = { 0, 5, 8, 10, 12, 22, 26 }
for i = 1, #pitches do for i = 1, #pitches do
pitches[i] = math.pow( 2.0, pitches[i] / 12.0 ) pitches[i] = math.pow( 2.0, pitches[i] / 12.0 )
end end
local bellMt = { __index = { get = function(t)
return t[2], t[3], t[1]
end }}
local r = 20 local r = 20
for i = 1, 7 do for i = 1, 7 do
bells[i] = { 5.0 / pitches[i], r * x, r * z, (i-1)/6 } bells[i] = setmetatable({ 5.0 / pitches[i], r * x, r * z, (i-1)/6 }, bellMt )
x, z = c*x+s*z, c*z-s*x x, z = c*x+s*z, c*z-s*x
end end
bellInstanceMesh = lg.newMesh({{"bellInstance","float",4}}, bells, nil, "static" ) bellInstanceMesh = lg.newMesh({{"bellInstance","float",4}}, bells, nil, "static" )
@ -131,6 +146,8 @@ local t = {}
t.shader = require( "shaders.bell" ) t.shader = require( "shaders.bell" )
t.mesh = bellMesh t.mesh = bellMesh
t.timer = 0
function t.draw( view, proj, light ) function t.draw( view, proj, light )
local s = t.shader local s = t.shader
@ -142,19 +159,111 @@ function t.draw( view, proj, light )
lg.drawInstanced( t.mesh, 7 ) lg.drawInstanced( t.mesh, 7 )
end end
local queue = {}
function t.queue( i, ticks )
local time = ticks + (queue.time or t.timer)
local q = queue
while q.next do
q = q.next
end
q.time = time
q.bell = i
q.next = {}
end
function t.transpose( i, j ) function t.transpose( i, j )
print( "transposing:", i, j )
io.flush() io.flush()
bells[i][1], bells[j][1] = bells[j][1], bells[i][1] bells[i][1], bells[j][1] = bells[j][1], bells[i][1]
bellInstanceMesh:setVertices( bells ) bellInstanceMesh:setVertices( bells )
bellMesh:attachAttribute( "bellInstance", bellInstanceMesh, bellMesh:attachAttribute( "bellInstance", bellInstanceMesh,
"perinstance" ) "perinstance" )
t.ring( i )
t.queue( j, 100 )
end end
function t.ring( i ) function t.ring( i )
ringSource:stop() local b = rings.poly
ringSource:setPitch( bells[i][1] ) b = not( b )
ringSource:play() rings.poly = b
rings[b]:stop()
rings[b]:setPitch( getPitch( bells[i][1] ) )
rings[b]:setPosition( bells[i][2], 0, bells[i][3] )
rings[b]:play()
end end
function t.ringAll( i )
local b = i
for j = 0, 6 do
t.queue( b, j * 100 )
b = b + 1
if b > 7 then b = 1 end
end
end
function t.nearBell(x, z)
for i, bell in ipairs( bells ) do
local bx, bz, br = bell:get()
if (x-bx)*(x-bx)+(z-bz)*(z-bz) < 2 * (br*br) then
return i
end
end
end
t.solution = {
bells[7],
bells[6],
bells[4],
bells[5],
bells[3],
bells[2],
bells[1]
}
function t.checkWin( i )
local idx = i
for j = 1, 7 do
idx = idx + 1
if idx > 7 then idx = 1 end
local bell = t.solution[j]
if bell ~= bells[idx] then return false end
end
t.winTime = t.timer + 700
return true
end
local trans = {}
function t.update( enteringCircle, leavingCircle, x, z )
t.timer = t.timer + 1
if t.winTime and t.timer > t.winTime then
local strings = require( "i18n" )
local slideshow = require( "scenes.slideshow" )
return slideshow.play( strings.win, love.event.quit, "tex/win.jpg", "sfx/mus.ogg" )
end
if queue.time and (queue.time <= t.timer) then
t.ring( queue.bell )
queue = queue.next or {}
end
if enteringCircle then trans[1] = enteringCircle end
if leavingCircle then trans[2] = leavingCircle end
if trans[1] and trans[2] then
t.transpose( trans[1], trans[2] )
trans[1], trans[2] = nil
end
if t.winTime then
return strings.phoneWin
end
t.near = t.nearBell( x, z )
if t.near then
return strings.ringBell:format(strings.keyUse)
end
end
t.circles = bells
t.near = false
return t return t

View File

@ -2,6 +2,7 @@ local dkjson = require( "lib.dkjson" )
local love = assert( love ) local love = assert( love )
local shader = require( "shaders.flat" ) local shader = require( "shaders.flat" )
local mat = require( "mat4" ) local mat = require( "mat4" )
local strings = require( "i18n" )
local attributeNames = { local attributeNames = {
POSITION = "VertexPosition", POSITION = "VertexPosition",
@ -127,16 +128,16 @@ end
function obj.draw( view, proj, light, x, z ) function obj.draw( view, proj, light, x, z )
if veilAlpha( x, z ) > 0.0 then if veilAlpha( x, z ) > 0.0 then
love.graphics.setDepthMode( "less", false ) love.graphics.setDepthMode( "less", false )
local s = shaders.Veil local s = shaders.Veil
love.graphics.setShader( s ) love.graphics.setShader( s )
s:send( "view", "column", view ) s:send( "view", "column", view )
s:send( "proj", "column", proj ) s:send( "proj", "column", proj )
love.graphics.setColor( 0, 0, 0, veilAlpha( x, z ) ) love.graphics.setColor( 0, 0, 0, veilAlpha( x, z ) )
love.graphics.draw( meshes.Veil ) love.graphics.draw( meshes.Veil )
love.graphics.setBlendMode( "alpha" ) love.graphics.setBlendMode( "alpha" )
love.graphics.setDepthMode( "less", true ) love.graphics.setDepthMode( "less", true )
end end
shader:send( "view", "column", view ) shader:send( "view", "column", view )
shader:send( "proj", "column", proj ) shader:send( "proj", "column", proj )
shader:send( "light", light ) shader:send( "light", light )
@ -151,12 +152,56 @@ function obj.draw( view, proj, light, x, z )
end end
end end
function obj.update( player ) local phoneRing = love.audio.newSource( "sfx/phoneRing.ogg", "static" )
local phoneMessage = love.audio.newSource( "sfx/phoneMessage.ogg", "static" )
phoneRing:setPosition( 0, 0, 0 )
phoneRing:setAirAbsorption( 10 )
phoneRing:setLooping( true )
phoneRing:setVolume( 0.05 )
phoneRing:setPitch( 0.9 )
if love.audio.isEffectsSupported() then
love.audio.setEffect( "phonervb", {type = "reverb", volume = 1, decaytime = 20, density = 0.5, gain = 0.8 })
phoneRing:setEffect( "phonervb" )
end end
phoneMessage:setPosition( 0,0,0 )
phoneMessage:setVolume( 0.2 )
phoneMessage:stop()
function obj.update( player )
obj.pickedUp = phoneMessage:isPlaying()
obj.canPickup = (player.r < 2) and not( obj.pickedUp )
if player.r > 2 then
return obj.isRinging and strings.phoneRing
elseif obj.pickedUp then
return strings.phoneClue
else
return obj.canPickup and strings.phonePickup:format( strings.keyUse )
end
end
function obj.pickup( ) function obj.pickup( )
obj.pickedUp = true obj.pickedUp = true
obj.isRinging = false
phoneMessage:play()
phoneRing:stop()
end
function obj.ring()
obj.isRinging = true
phoneRing:play()
end
do
obj.circles = {}
local circleMT = {__index = { get = function(t) return t.x, t.z, t.r end } }
local x, z = 1, 0
local c, s = math.cos( 2 * math.pi / 7 ), math.sin( 2 * math.pi / 7 )
for i = 1, 7 do
obj.circles[i] = setmetatable( {x = 10 * x, z = 10 * z, r = 1} , circleMT )
x, z = x*c+s*z,-s*x+c*z
end
obj.circles[8] = setmetatable( {x = 0, z = 0, r = 1.5 }, circleMT )
end end
return obj return obj

View File

@ -3,6 +3,7 @@ local math = math
local mat = require( "mat4" ) local mat = require( "mat4" )
local dkjson = require( "lib.dkjson" ) local dkjson = require( "lib.dkjson" )
local shader = require( "shaders.spike" ) local shader = require( "shaders.spike" )
local terrainHeight = require( "models.terrain" ).getHeight
local attributeNames = { local attributeNames = {
POSITION = "VertexPosition", POSITION = "VertexPosition",
@ -104,35 +105,36 @@ local spike = lgMesh( asset.meshes[1].primitives[1] )
spike:setTexture( love.graphics.newImage( "tex/rock.png", { mipmaps = true } ) ) spike:setTexture( love.graphics.newImage( "tex/rock.png", { mipmaps = true } ) )
local spikeCount = 4096 local spikeCount = 4096
local obj = {}
do do
local function rad(x,z) local function rad(x,z)
return x*x+z*z return x*x+z*z
end end
local spikeMT = { __index = { get = function( t ) return t[1], t[3], 1 end }}
local spikes = {} local spikes = {}
local inner, outer = 25, 100 obj.circles = spikes
local inner, outer = 35, 250
for n = 1, spikeCount do for n = 1, spikeCount do
local r, a = math.sqrt( math.random() * (outer*outer-inner*inner)+outer*outer ), 2 * math.pi * math.random() local r, a = math.sqrt( math.random() * (outer*outer-inner*inner)+inner*inner ), 2 * math.pi * math.random()
local x, z = r*math.cos(a),r*math.sin(a) local x, z = r*math.cos(a),r*math.sin(a)
local h = 2 + 10 * math.random() local h = 12 + 10 * math.random()
spikes[n] = { x, -1, z, h, 0 } spikes[n] = setmetatable({ x, terrainHeight(x, z, -0.5), z, h }, spikeMT )
n=n+1 n=n+1
end end
local spikeInstanceMesh = love.graphics.newMesh( local spikeInstanceMesh = love.graphics.newMesh(
{{"spikeInstance", "float", 4}, {{"spikeInstance", "float", 4},
{"spikeOrientation", "float", 1 },
}, --vertexformat }, --vertexformat
spikes, spikes,
nil, nil,
"static" "static"
) )
spike:attachAttribute( "spikeInstance", spikeInstanceMesh, "perinstance" ) spike:attachAttribute( "spikeInstance", spikeInstanceMesh, "perinstance" )
spike:attachAttribute( "spikeOrientation", spikeInstanceMesh, "perinstance" )
end end
local spikes = {} function obj.draw( view, proj, light )
function spikes.draw( view, proj, light )
love.graphics.setColor( 1,1,1,1) love.graphics.setColor( 1,1,1,1)
shader:send( "view", "column", view ) shader:send( "view", "column", view )
shader:send( "proj", "column", proj ) shader:send( "proj", "column", proj )
@ -142,4 +144,4 @@ function spikes.draw( view, proj, light )
end end
return spikes return obj

View File

@ -21,7 +21,7 @@ do
local ptr = ffi.cast( "float*", p ) local ptr = ffi.cast( "float*", p )
local i = 0 local i = 0
for x = 0, sideLength-1 do for y = 0, sideLength-1 do for x = 0, sideLength-1 do for y = 0, sideLength-1 do
ptr[i],ptr[i+1] = x - sideLength / 2 ,y - sideLength / 2 ptr[i],ptr[i+1] = 4 * (x - sideLength / 2) , 4 * (y - sideLength / 2)
i=i+2 i=i+2
end end end end
mesh:setVertices( vertices ) mesh:setVertices( vertices )
@ -45,13 +45,14 @@ do
end end
local shader = love.graphics.newShader[[ local shader = love.graphics.newShader[[
#define fog vec4( 0.6, 0.6, 0.7, 1.0 ) #define fog vec4( 0.9, 0.9, 1.0, 1.0 )
#define fogHigh vec4( 1.0, 1.0, 0.9, 1.0 ) #define fogHigh vec4( 1.0, 1.0, 0.85, 1.0 )
#define fogFalloff 0.03 #define fogFalloff 0.03
varying vec2 uv; varying vec2 uv;
varying vec3 world; varying vec3 world;
varying vec3 normal; varying vec3 normal;
varying float depth; varying float depth;
varying float h;
#ifdef VERTEX #ifdef VERTEX
uniform sampler2D height; uniform sampler2D height;
uniform mat4 view; uniform mat4 view;
@ -65,11 +66,12 @@ local shader = love.graphics.newShader[[
pos = pos.xzyw; pos = pos.xzyw;
float y = Texel( height, pos.xz / 256.0 ).r - 0.5; float y = Texel( height, pos.xz / 256.0 ).r - 0.5;
uv = 0.25 * (pos.xz + vec2(y, sin( y ) )); uv = 0.25 * (pos.xz + vec2(y, sin( y ) ));
float r = dot( pos.xz, pos.xz ); float r = length( pos.xz );
pos.y = sigmoid( r / 50.0 - 20.0 ) * ( 1.0 + y ) * 0.05 * r / (sqrt( r ) + 1) - 0.01; pos.y = sigmoid( r / 10.0 - 6.0 ) * ( 2.0 + y ) * 0.1 * (r*r) / (r + 1) - 0.01;
world = pos.xyz; world = pos.xyz;
vec4 eye = view*pos; vec4 eye = view*pos;
h = clamp( world.y, 0.0, 1.0 );
depth = clamp( -eye.z * fogFalloff, 0.0, 1.0 ); depth = clamp( -eye.z * fogFalloff, 0.0, 1.0 );
normal = vec3( 0.0, 1.0, 0.0 ) + 1.5 * pos.y ; normal = vec3( 0.0, 1.0, 0.0 ) + 1.5 * pos.y ;
@ -87,7 +89,7 @@ local shader = love.graphics.newShader[[
vec3 norm = normalize( normal ); vec3 norm = normalize( normal );
vec3 toLight = normalize( light - world.xyz ); vec3 toLight = normalize( light - world.xyz );
float diff = max( dot( norm, light ), 0.1 ); float diff = max( dot( norm, light ), 0.1 );
vec4 d = vec4( diff * albedo, 1.0 ); vec4 d = vec4( diff * albedo * h, 1.0 );
return mix( color * d , fog, depth ); return mix( color * d , fog, depth );
} }
@ -109,8 +111,21 @@ local function worldSpaceToTexCoord( x, z )
return x, z return x, z
end end
function obj.getHeight( x, z ) local function sigmoid( x )
return heightMap:getPixel( worldSpaceToTexCoord(x,z) )[1] return 1.0 / ( 1.0 + math.exp( -x ) )
end
local function sqDistance( x, y, a, b )
return (x-a)*(x-a)+(y-b)*(y-b)
end
local function getWorldSpace( x, z )
return x / 4 + sideLength / 2 , z / 4 + sideLength / 2
end
function obj.getHeight( x, z, y )
local r = math.sqrt( sqDistance( x, z, 0, 0 ) )
return sigmoid( r / 10.0 - 6.0 ) * ( 2.0 + y ) * 0.1 * (r*r) / (r + 1) - 0.01
end end
function obj.draw( view, proj, light ) function obj.draw( view, proj, light )

View File

@ -3,6 +3,8 @@ local math = assert( math )
local mat = require( "mat4" ) local mat = require( "mat4" )
local sfx = require( "sfx" ) local sfx = require( "sfx" )
local getHeight = require( "models.terrain" ).getHeight
local maxPitch = math.pi / 2 local maxPitch = math.pi / 2
local function logistic( x ) local function logistic( x )
@ -12,10 +14,11 @@ end
local player = { local player = {
turnRate = 0, turnRate = 0,
rate = 0.01, --tick rate rate = 0.01, --tick rate
speed = 2, --movement speed m/s speed = 3, --movement speed m/s
x = 0, x = 35,
y = 1.5, y = 1.5,
z = 3, z = 75,
r = 4,
vx = 0, vx = 0,
vz = 0, vz = 0,
yaw = 1.5, yaw = 1.5,
@ -25,7 +28,7 @@ local player = {
view = mat.id(), view = mat.id(),
proj = mat.id(), proj = mat.id(),
footstepTimer = 0, footstepTimer = 0,
footstepStride = 0.5 --seconds before taking a step footstepStride = 0.8 --seconds before taking a step
} }
function player:updateDesiredDirection( forward, left, right, back ) function player:updateDesiredDirection( forward, left, right, back )
@ -38,10 +41,8 @@ function player:updateDesiredDirection( forward, left, right, back )
self.desx, self.desz = x * c + z * s, -x * s + z * c self.desx, self.desz = x * c + z * s, -x * s + z * c
end end
function player:setFOV( fov ) function player:setFOV( fov )
self.proj = mat.projection( 0.05, 100, math.rad( fov or 90 ) ) self.proj = mat.projection( 0.05, 500, math.rad( fov or 90 ) )
end end
function player:setTurnRate( sensitivity ) function player:setTurnRate( sensitivity )
@ -51,7 +52,7 @@ end
function player:turn( dx, dy ) function player:turn( dx, dy )
self.yaw = self.yaw + dx * self.turnRate self.yaw = self.yaw + dx * self.turnRate
self.pitch = math.min( maxPitch, math.max( -maxPitch, self.pitch = math.min( maxPitch, math.max( -maxPitch,
self.pitch + dy * self.turnRate )) self.pitch + dy * self.turnRate ))
end end
local function sqDistance( x, y, a, b ) local function sqDistance( x, y, a, b )
@ -71,39 +72,83 @@ local function distanceToSegment( ix, iy, fx, fy, cx, cy )
return sqDistance( cx, cy, u*ix+t*fx,u*iy+t*fy ) return sqDistance( cx, cy, u*ix+t*fx,u*iy+t*fy )
end end
--collide in 2D on the xz-plane. local function inCircle( x, y, cx, cy, cr )
local function collide( ix, iz, fx, fz, circles, lines ) return sqDistance( x, y, cx, cy ) < (cr * cr)
local x, z = ix, iz
for _, circle in pairs( circles ) do
if distanceToSegment( ix, iz, fx, fz, circle.x, circle.z ) <
circle.r * circle.r then
end
end
for _, line in pairs( lines ) do
end
return x, z, fx, fz
end end
function player:update() --collide in 2D on the xz-plane.
self.vx = self.desx * self.speed local function collide( ix, iz, fx, fz, circles )
self.vz = self.desz * self.speed local x, z = ix, iz
for _, circle in pairs( circles ) do
self.x = self.x + self.vx * self.rate local cx, cz, cr = circle:get()
self.z = self.z + self.vz * self.rate if inCircle( fx, fz, cx, cz, cr ) then
fx, fz = x, z
io.flush()
return true
end
end
return false
end
local function getSection( x, z )
local s = math.atan2( z, x )
s = ( s < 0 ) and s + 2.0 * math.pi or s
s = 0.5 * s / math.pi
local section = 1 + math.modf( s * 7, 1 )
print( section )
io.flush()
return section
end
local function enteringRing( x, z, fx, fz )
local fd = sqDistance( fx, fz, 0, 0 )
if fd < 90 and (sqDistance( x, z, 0, 0 ) > 90) then
return getSection( x, z )
end
return nil
end
local function leavingRing( x, z, fx, fz )
local fd = sqDistance( fx, fz, 0, 0 )
if fd > 50 and (sqDistance( x, z, 0, 0 ) < 50) then
return getSection( x, z )
end
return nil
end
function player:update( circles )
self.vx = 0.1 * self.desx * self.speed + 0.9 * self.vx
self.vz = 0.1 * self.desz * self.speed + 0.9 * self.vz
local fx, fz = self.x + self.vx * self.rate, self.z + self.vz * self.rate
self.enteringCircle, self.leavingCircle = enteringRing( self.x, self.z, fx, fz ), leavingRing( self.x, self.z, fx, fz )
if collide( self.x, self.z, fx, fz, circles ) then
self.vx, self.vz = -2.0 * self.vx, -2.0 * self.vz
else
self.x, self.z = fx, fz
end
local r = math.sqrt( sqDistance( self.x, self.z, 0, 0 ) )
self.r = r
self.y = 1.5 + getHeight( self.x, self.z, 0.2 )
--1.5 + logistic( -( r / 10.0 - 6.0 ) ) * ( 1.0 + 0 ) * 0.1 * (r*r) / (r + 1) - 0.01
self.view = mat.view( self.x, self.y, self.z, self.yaw, self.pitch ) self.view = mat.view( self.x, self.y, self.z, self.yaw, self.pitch )
self:footstep() self:footstep()
sfx.setPosition( self.x, self.y, self.z )
sfx.setOrientation( self.yaw )
end end
function player:isMoving() function player:isMoving()
return return
self.vx > 0.01 or self.vz > 0.01 or self.vx > 0.1 or self.vz > 0.1 or
self.vx < 0.01 or self.vz < 0.01 self.vx <-0.1 or self.vz < -0.1
end end
function player:footstep() function player:footstep()
@ -126,16 +171,16 @@ function player:tostring()
pitch:%3.2f pitch:%3.2f
desx: %3.2f desx: %3.2f
desz: %3.2f desz: %3.2f
]]):format( ]]):format(
player.x, player.x,
player.y, player.y,
player.z, player.z,
player.vx, player.vx,
player.vz, player.vz,
player.yaw, player.yaw,
player.pitch, player.pitch,
player.desx, player.desx,
player.desz player.desz
) )
end end

View File

@ -6,7 +6,6 @@ local mat = require( "mat4" )
local t = {} local t = {}
local frameStart = love.timer.getTime() local frameStart = love.timer.getTime()
local rockTexture = love.graphics.newImage( "tex/rock.png", { mipmaps = true } ) local rockTexture = love.graphics.newImage( "tex/rock.png", { mipmaps = true } )
rockTexture:setWrap( "repeat", "repeat" ) rockTexture:setWrap( "repeat", "repeat" )
function t.play() function t.play()
@ -15,12 +14,6 @@ function t.play()
player:setTurnRate( settings.mouseSensitivity.val ) player:setTurnRate( settings.mouseSensitivity.val )
player:setFOV( settings.FOV.val ) player:setFOV( settings.FOV.val )
world.start() world.start()
--[[local spike = require( "models/spike" )
spike:setTexture( rockTexture )
renderer.add( spike )
renderer.update( spike, mat.TRS( 0.3, 12, 0.3, 0, 0, 0, 4, 0, 3) )]]
local scene = require( "scene" ) local scene = require( "scene" )
return scene.load( t ) return scene.load( t )
end end
@ -28,15 +21,6 @@ end
function t.draw() function t.draw()
world.draw( player.view, player.proj, player.x, player.z ) world.draw( player.view, player.proj, player.x, player.z )
local y = 0
for k, v in pairs(love.graphics.getStats()) do
love.graphics.print( k, 0, y )
love.graphics.print( v, 200, y )
y = y + 16
end
love.graphics.print( player:tostring(), 0, y )
end end
@ -55,10 +39,10 @@ function t.update( dt )
updateTimeRemaining = updateTimeRemaining + dt updateTimeRemaining = updateTimeRemaining + dt
while updateTimeRemaining >= player.rate do while updateTimeRemaining >= player.rate do
updateTimeRemaining = updateTimeRemaining - player.rate updateTimeRemaining = updateTimeRemaining - player.rate
player:update() player:update( world.circles )
world.update( player )
end end
io.flush()
world.update( player )
end end
function t.mousepressed( x, y, button, isTouch, presses ) function t.mousepressed( x, y, button, isTouch, presses )
@ -72,24 +56,8 @@ function t.keypressed( key, code, isrepeat )
love.mouse.setVisible( true ) love.mouse.setVisible( true )
end end
if code == settings.keyUse.val then if code == settings.keyUse.val then
if world.bell.near then return world.bell.ringAll( world.bell.near ) end
end if world.phone.canPickup then return world.phone.pickup() end
if code == "2" then
local strings = require( "i18n" )
local slideshow = require( "scenes.slideshow" )
return slideshow.play( strings.win, love.event.quit, "tex/win.jpg" )
end
if code == "3" then
return world.targetLight( math.random( 1, 7 ) )
end
if code == "4" then
return world.pickupPhone()
end
if code == "1" then
return world.transposeBells( 2, 7 )
end
if code == "5" then
return world.ring( 2 )
end end
end end

View File

@ -1,6 +1,28 @@
local love = love
local sfx = {} local sfx = {}
function sfx.playFootstep() love.audio.setDistanceModel( "linear" )
--print( "step" )
local footsteps = {}
for i, file in pairs( love.filesystem.getDirectoryItems( "sfx/footsteps" ) ) do
footsteps[i] = love.audio.newSource( "sfx/footsteps/"..file, "static" )
footsteps[i]:setVolume( 0.02 )
end end
local stepIdx = 1
function sfx.playFootstep()
footsteps[ stepIdx ]:stop()
stepIdx = math.random( 1, #footsteps )
footsteps[ stepIdx ]:play()
end
function sfx.setPosition( x, y, z )
return love.audio.setPosition( x, y, z )
end
function sfx.setOrientation( yaw )
local x, z = math.cos( yaw ), math.sin( yaw )
return love.audio.setOrientation( x, 0, z, 0, 1, 0 )
end
return sfx return sfx

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
src/sfx/phoneMessage.ogg Normal file

Binary file not shown.

BIN
src/sfx/phoneRing.ogg Normal file

Binary file not shown.

BIN
src/sfx/wind.mp3 Normal file

Binary file not shown.

View File

@ -1,5 +1,5 @@
return love.graphics.newShader[[ return love.graphics.newShader[[
#define fog vec4( 0.85, 0.85, 1.0, 1.0 ) #define fog vec4( 0.9, 0.9, 1.0, 1.0 )
#define fogHigh vec4( 1.0, 1.0, 0.85, 1.0 ) #define fogHigh vec4( 1.0, 1.0, 0.85, 1.0 )
#define sunDir 0.1 * vec3( 0.9, 0.2, 0.5 ) #define sunDir 0.1 * vec3( 0.9, 0.2, 0.5 )
varying float depth; varying float depth;

View File

@ -1,6 +1,6 @@
return love.graphics.newShader[[ return love.graphics.newShader[[
#define fog vec4( 0.85, 0.85, 1.0, 1.0 ) #define fog vec4( 0.9, 0.9, 1.0, 1.0 )
#define fogHigh vec4( 1.0, 1.0, 0.9, 1.0 ) #define fogHigh vec4( 1.0, 1.0, 0.85, 1.0 )
varying float depth; varying float depth;
varying vec3 normal; varying vec3 normal;
varying vec4 world; varying vec4 world;
@ -24,10 +24,10 @@ return love.graphics.newShader[[
vec3 toLight = normalize( light - world.xyz ); vec3 toLight = normalize( light - world.xyz );
float diff = max( dot( norm, light ), 0.1 ); float diff = max( dot( norm, light ), 0.1 );
vec4 mainColor = vec4( diff * color.rgb, color.a ); vec4 mainColor = vec4( diff * color.rgb * world.y, color.a );
return mix( mix( mainColor, fog, return mix( mix( mainColor, fog,
clamp( depth / 80.0, 0.0, 1.0)), fogHigh, clamp( depth / 50.0, 0.0, 1.0)), fogHigh,
clamp( world.y / 20.0, 0.0, 1.0)) ; clamp( world.y / 20.0, 0.0, 1.0)) ;
} }
#endif #endif

View File

@ -14,10 +14,13 @@ varying vec3 viewDir;
#ifdef PIXEL #ifdef PIXEL
uniform vec3 light; uniform vec3 light;
vec4 effect( vec4 color, Image _, vec2 __, vec2 ___) { vec4 effect( vec4 color, Image _, vec2 __, vec2 ___) {
float d = dot( normalize( viewDir ), light ); vec3 view = normalize( viewDir );
d = 0.5+0.5*d; float d = dot( view, light );
d = pow(d, 45); float e = 0.504 +0.5*d;
return mix( blue, mix( yellow, color, d * 2 ) , d ); e = pow(e, 40);
float b = d < 0.995 ? 1.0 : 0.0;
vec4 black = vec4(b,b,b,1.0);
return black * mix( blue, mix( yellow, color, d * 2 ) , e ) + 0.2 * pow( (1.0 - dot( view, vec3( 0, 1, 0 ) )), 7 );
} }
#endif #endif
]] ]]

View File

@ -1,6 +1,6 @@
return love.graphics.newShader[[ return love.graphics.newShader[[
#define fog vec4( 0.6, 0.6, 0.7, 1.0 ) #define fog vec4( 0.9, 0.9, 1.0, 1.0 )
#define fogHigh vec4( 0.7, 0.7, 0.6, 1.0 ) #define fogHigh vec4( 1.0, 1.0, 0.85, 1.0 )
#define sunDir 0.1 * vec3( 0.9, 0.2, 0.5 ) #define sunDir 0.1 * vec3( 0.9, 0.2, 0.5 )
varying float depth; varying float depth;
varying vec3 normal; varying vec3 normal;
@ -8,15 +8,14 @@ return love.graphics.newShader[[
#ifdef VERTEX #ifdef VERTEX
//per instance: (uniform) x, y, z, height //per instance: (uniform) x, y, z, height
attribute vec4 spikeInstance; attribute vec4 spikeInstance;
attribute float spikeOrientation;
attribute vec3 VertexNormal; attribute vec3 VertexNormal;
uniform mat4 view; uniform mat4 view;
uniform mat4 proj; uniform mat4 proj;
vec4 position( mat4 _, vec4 pos ){ vec4 position( mat4 _, vec4 pos ){
normal = VertexNormal; normal = VertexNormal;
pos.xz *= 0.25;
pos.y *= spikeInstance.w; pos.y *= spikeInstance.w;
pos.xyz += spikeInstance.xyz; pos.xy += spikeInstance.xy;
pos.z -= spikeInstance.z;
world = pos; world = pos;
vec4 eye = view * pos; vec4 eye = view * pos;
@ -39,7 +38,7 @@ return love.graphics.newShader[[
return color * mix( mix( mainColor, return color * mix( mix( mainColor,
fog, clamp( depth / 80.0, 0.0, 1.0)), fog, clamp( depth * 0.03 , 0.0, 1.0)),
fogHigh, clamp(world.y / 20.0, 0.0, 1.0)); fogHigh, clamp(world.y / 20.0, 0.0, 1.0));
} }
#endif #endif