math.randomseed(os.time()) local WINDOW_WIDTH, WINDOW_HEIGHT = 800, 400 local TALK_FONT = love.graphics.newFont(18) local OPTIONS_FONT = love.graphics.newFont(10) local markov = require "markov" --- Colors local COLOR_WHITE = {1,1,1} local COLOR_BLACK = {0,0,0} local COLOR_CLOCK_FRAME = {200/255,200/255,200/255,} local COLOR_CLOCK_INNER = COLOR_WHITE local COLOR_CLOCK_HAND = {50/255,50/255,50/255} local COLOR_BOARDS = {(240 + math.random() * 10)/255, (200 + math.random() * 10)/255, (120 + math.random() * 30)/255} local COLOR_PROJECTOR_CONTENTS = {82/255, 106/255, 108/255, 30/255} local COLOR_WHITEBOARD = {200/255, 200/255, 200/255} local COLOR_BOLTS = {149/255, 141/255, 128/255} local COLOR_CRACKS = {28/255, 19/255, 20/255} local COLOR_BEAMS = {127/255, 94/255, 61/255} local COLOR_PROJECTOR_AREA = {210/25/2555, 210/255, 210/255} local COLOR_WHITEBOARD_BORDERS = {149/255, 141/255, 128/255} local COLOR_HAIR = {59/255, 37/255, 24/255} local COLOR_SUIT = {87/255, 107/255, 56/255} local COLOR_HEAD = {163/255, 118/255, 100/255} -------------------------------------------------------------------------------- -- Background local function randomize_projector_color () for i = 1, 3 do COLOR_PROJECTOR_CONTENTS[i] = (math.random(80) + 100)/255 end end local function draw_clock (x, y, r, t) love.graphics.setColor(COLOR_CLOCK_FRAME) love.graphics.circle('fill', x, y, r) love.graphics.setColor(COLOR_CLOCK_INNER) love.graphics.circle('fill', x, y, r - 2) love.graphics.setColor(COLOR_CLOCK_HAND) love.graphics.setLineWidth(3) love.graphics.line(x, y, x + math.cos(t * (2*math.pi) / 42000 - math.pi / 2) * r * 0.4, y + math.sin(t * (2*math.pi) / 42000 - math.pi / 2) * r * 0.4) love.graphics.setLineWidth(2) love.graphics.line(x, y, x + math.cos(t * (2*math.pi) / 3600 - math.pi / 2) * r * 0.6, y + math.sin(t * (2*math.pi) / 3600 - math.pi / 2) * r * 0.6) love.graphics.setLineWidth(1) love.graphics.line(x, y, x + math.cos(math.floor(t) * (2*math.pi) / 60 - math.pi / 2) * r * 0.8, y + math.sin(math.floor(t) * (2*math.pi) / 60 - math.pi / 2) * r * 0.8) end local function draw_background () -- FLOOR -- love.graphics.setColor(COLOR_BOARDS) love.graphics.rectangle('fill',0, 0, WINDOW_WIDTH, WINDOW_HEIGHT) -- TODO -- WALL -- -- Color of cracks love.graphics.setColor(COLOR_CRACKS) love.graphics.rectangle('fill',0, 0, WINDOW_WIDTH, 250 + 10) -- "Beams" love.graphics.setColor(COLOR_BEAMS) for xi = 0.25, 100 do love.graphics.rectangle('fill',xi*8, 0, 4, 250) end -- "Bolts" love.graphics.setColor(COLOR_BOLTS) for xi = 0.25, 100 do for yi = 0.7, 5 do love.graphics.rectangle('fill',xi*8+1, yi*50, 2, 2) end end -- Whiteboards and projector area -- -- Whiteboard love.graphics.setColor(COLOR_WHITEBOARD) love.graphics.rectangle('fill', 100, 100, WINDOW_WIDTH - 100*2, 100) -- Projector Area love.graphics.setColor(COLOR_PROJECTOR_AREA) love.graphics.rectangle('fill', 100, 0, WINDOW_WIDTH - 100*2, 100) -- Whiteboard and projector borders love.graphics.setColor(COLOR_WHITEBOARD_BORDERS) love.graphics.rectangle('fill', (WINDOW_WIDTH-2)/2, 100, 2, 100) love.graphics.rectangle('fill', 100, 100, WINDOW_WIDTH - 100*2, 2) love.graphics.rectangle('fill', 100, 100+100-2, WINDOW_WIDTH - 100*2, 2) love.graphics.rectangle('fill', 100, 0, 2, 100+100) love.graphics.rectangle('fill', 100+WINDOW_WIDTH-100*2-2, 0, 2, 100+100) -- Projector contents love.graphics.setColor(COLOR_PROJECTOR_CONTENTS) for i = 5, 20, 2 do love.graphics.rectangle('fill', (100+i), 0, WINDOW_WIDTH - (100+i)*2, 100 - i) end -- OTHER PEOPLE -- -- TODO -- FOREGROUND -- TODO -- TEMP: love.graphics.setColor(COLOR_WHITE) love.graphics.rectangle('fill',0, 400, WINDOW_WIDTH, WINDOW_HEIGHT) end -------------------------------------------------------------------------------- -- Teacher local TEACHER = { x = WINDOW_WIDTH/2, y = WINDOW_HEIGHT - 100, h = 60, w = 30, head_r = 12} TEACHER.tx = TEACHER.x TEACHER.ty = TEACHER.y function TEACHER:draw () -- Hair love.graphics.setColor(COLOR_HAIR) love.graphics.circle('fill', self.x, self.y - self.h - self.head_r - 4, self.head_r+1) love.graphics.rectangle('fill', self.x - 10, self.y - self.h - self.head_r, 10 * 2, self.head_r) -- Suite love.graphics.setColor(COLOR_SUIT) love.graphics.polygon('fill', self.tx, self.ty, self.x - self.w / 2, self.y - self.h, self.x + self.w / 2, self.y - self.h ) -- Head love.graphics.setColor(COLOR_HEAD) love.graphics.circle('fill', self.x, self.y - self.h - self.head_r, self.head_r) end function TEACHER:update (dt) TEACHER.tx = TEACHER.tx + ( TEACHER.x - TEACHER.tx ) * 6 * dt TEACHER.ty = TEACHER.ty + ( TEACHER.y - TEACHER.ty ) * 10 * dt end function TEACHER:move (dx, dy) self.x = math.max(50, math.min(self.x + dx, WINDOW_WIDTH - 50)) self.y = math.max(250 + 30, math.min(self.y + dy, WINDOW_HEIGHT - 10)) end -------------------------------------------------------------------------------- -- Text Bobble local TEXT_BUBBLE = { tracking = TEACHER, x = 100, y = 100, text = "Hej Markov Chains! ;)", w = 300, h = 100 } TEXT_BUBBLE.text = 'God morgen alle sammen, velkommen til interaktiones-design forelæsningen.' function TEXT_BUBBLE:draw () -- Draw textbobble love.graphics.setColor(COLOR_WHITE) love.graphics.rectangle('fill', self.x, self.y, self.w, self.h, 10) love.graphics.polygon('fill', self.x, self.y + self.h / 2, self.tracking.x, self.tracking.y - 100, self.x + self.w, self.y + self.h / 2) -- Draw text love.graphics.setFont(TALK_FONT) love.graphics.setColor(COLOR_BLACK) local text_height = TALK_FONT:getHeight() * #select(2, TALK_FONT:getWrap(self.text, self.w - 10*2)) local text_x, text_y = math.floor(self.x + 10 + 0.5), math.floor(self.y + (self.h - text_height) / 2 + 0.5) love.graphics.printf(self.text, text_x, text_y, self.w - 10*2, 'center') end function TEXT_BUBBLE:update (dt) local tx, ty = self:getTargetPos() local cx, cy = self.x + (tx - self.x) * dt, self.y + (ty - self.y) * dt self.x = math.max(10, math.min(cx, WINDOW_WIDTH - 10 - self.w)) if ty < cy then cy = self.y + (ty - self.y) * dt * 6 end self.y = cy end function TEXT_BUBBLE:getTargetPos () local y_distance = self.h + self.tracking.h + self.tracking.head_r * 2 + 30 local tx, ty = self.tracking.x - self.w * 0.5, self.tracking.y - y_distance return tx, ty end local TEXT_BUBBLE_MARKOV_CHAIN do local ALPHABET = {"a","b","c","d","e","f","g","h","i","j","k","l","m", "n","o","p","q","r","s","t","u","v","w","x","y","z",'æ','ø','å', '?',',', '.', ' ','0', '1','2','3','4','5','6','7','8','9'} local chain = markov.VoMarkovChain.new(ALPHABET, 6) TEXT_BUBBLE_MARKOV_CHAIN = markov.StringWrapper.new(chain) local t = {} local lines = love.filesystem.lines('/sentences.txt') TEXT_BUBBLE_MARKOV_CHAIN:train(lines, true) end local function randomize_text_bubble_text () local text repeat text = TEXT_BUBBLE_MARKOV_CHAIN:generate(100) until text:len() > 80 local first_space_index = text:find(' ') local final_space_index = text:find' [^ ]-$' TEXT_BUBBLE.text = ('.' .. text:sub(first_space_index, final_space_index)):gsub("(%. *)(%l)(%w*)", function(c, a,b) return c .. ' ' .. string.upper(a) .. b end):gsub('%s+', ' '):sub(2) end -------------------------------------------------------------------------------- -- Callbacks local TEACHER_TARGET = { x = 0, y = 0 } local function randomize_teacher_target () repeat TEACHER_TARGET.x = math.random() * (WINDOW_WIDTH - 50*2) + 50 TEACHER_TARGET.y = math.random() * 100 + 280 until math.sqrt((TEACHER_TARGET.x-TEACHER.x)^2 + (TEACHER_TARGET.y-TEACHER.y)^2) > 200 end function love.load () end local TIMER_PROJECTOR, TIMER_TEXT, TIMER_MOVE = 0, 10, 0 local TIMER_FULL = 15 * 60 function love.update (dt) TEACHER:update(dt) TEXT_BUBBLE:update(dt) -- Update timers TIMER_PROJECTOR, TIMER_TEXT, TIMER_MOVE = TIMER_PROJECTOR - dt, TIMER_TEXT - dt, TIMER_MOVE - dt TIMER_FULL = TIMER_FULL + dt -- Quit game if TIMER_FULL > 60 * 60 + 5 then love.event.quit() end if TIMER_FULL > 60 * 60 then TEXT_BUBBLE.text = 'Hov, den er vist 13:00. Tak for i dag, og vi ses næste uge!'; return end -- Events occur if TIMER_PROJECTOR < 0 then TIMER_PROJECTOR = math.random() * 10 + 5; randomize_projector_color() end if TIMER_TEXT < 0 then TIMER_TEXT = math.random() * 2 + 6; randomize_text_bubble_text() end if TIMER_MOVE < 0 then TIMER_MOVE = math.random() * 10 + 5; randomize_teacher_target() end -- Move teacher local dist_x, dist_y = TEACHER_TARGET.x - TEACHER.x, TEACHER_TARGET.y - TEACHER.y local dist = math.sqrt(dist_x*dist_x + dist_y*dist_y) local speed = 60 if dist < 2 then return end TEACHER:move(speed*dt*dist_x/dist, speed*dt*dist_y/dist) end function love.keypressed (key) if key == 'f' then love.event.quit() end end function love.draw () draw_background() draw_clock(WINDOW_WIDTH - 50 + 2, 60, 14, TIMER_FULL) TEACHER:draw() TEXT_BUBBLE:draw() love.graphics.setFont(OPTIONS_FONT) love.graphics.print('Muligheder: \n- F: Du lærer intet fra det her, du kan lige så godt bare gå!', 20, WINDOW_HEIGHT - 40) end