1
0

Added games from 2017

This commit is contained in:
Jon Michael Aanes 2024-09-23 20:10:56 +02:00
parent 1790e2eaa8
commit 23a4114be5
Signed by: Jmaa
SSH Key Fingerprint: SHA256:Ab0GfHGCblESJx7JRE4fj4bFy/KRpeLhi41y4pF3sNA
21 changed files with 1834 additions and 0 deletions

42
2017-uge1/conf.lua Normal file
View File

@ -0,0 +1,42 @@
function love.conf(t)
t.identity = "dildo"
t.version = "11.1"
t.console = false
t.accelerometerjoystick = false
t.externalstorage = false
t.gammacorrect = false
t.window.title = "Dildo Collector"
t.window.icon = nil--'images/icon.png'
t.window.width = 500
t.window.height = 500
t.window.borderless = false
t.window.resizable = false
t.window.minwidth = 500
t.window.minheight = 300
t.window.fullscreen = false
t.window.fullscreentype = "desktop"
t.window.vsync = true
t.window.msaa = 0
t.window.display = 1
t.window.highdpi = false
t.window.x = nil
t.window.y = nil
t.modules.audio = true
t.modules.event = true
t.modules.graphics = true
t.modules.image = true
t.modules.joystick = false
t.modules.keyboard = true
t.modules.math = false
t.modules.mouse = true
t.modules.physics = false
t.modules.sound = true
t.modules.system = true
t.modules.timer = true
t.modules.touch = false
t.modules.video = false
t.modules.window = true
t.modules.thread = false
end

BIN
2017-uge1/dildo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 B

153
2017-uge1/main.lua Normal file
View File

@ -0,0 +1,153 @@
-- State
local DILDO_COST = 199
local DILDOES = {
}
local LIFE = 100
local MONEY = 0
local WORK_WAIT = 0
local function resetGame ()
LIFE = 100
MONEY = 0
WORK_WAIT = 0
DILDOES = {}
end
--------------------------------------------------------------------------------
-- Colors
local COLOR_BG = {26/255, 26/255, 26/255}
--------------------------------------------------------------------------------
-- DILDO WORK
local IMG = love.graphics.newImage('dildo.png')
IMG:setFilter('nearest', 'nearest', 1)
local QUADS = {}
for i = 0, 15 do
QUADS[#QUADS+1] = love.graphics.newQuad( (i % 4) * 8, math.floor(i / 4) * 8, 8, 8, IMG:getWidth(), IMG:getHeight() )
end
local POSSIBLE_DILDOES = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
}
local function get_new_dildo ()
local l = {}
for _, dildo in ipairs(POSSIBLE_DILDOES) do
l[dildo] = true
end
for dildo, _ in pairs(DILDOES) do
l[dildo] = nil
end
return next(l, nil)
end
local function has_all_dildoes ()
return not get_new_dildo()
end
local function set_has_dildo (dildo_id)
DILDOES[dildo_id] = true
end
--------------------------------------------------------------------------------
local function can_do_work ()
return WORK_WAIT <= 0
end
local function do_work ()
MONEY = MONEY + 150 + math.floor( 0.3*(100-LIFE))
LIFE = LIFE - 17
WORK_WAIT = 5
end
local function can_survive ()
return MONEY >= 100 and LIFE <= 70
end
local function do_survive ()
MONEY = MONEY - 100
LIFE = 100
end
local function can_buy_dildo ()
return MONEY >= DILDO_COST and not has_all_dildoes()
end
local function buy_dildo ()
MONEY = MONEY - DILDO_COST
local dildo_id = get_new_dildo()
set_has_dildo(dildo_id)
end
--------------------------------------------------------------------------------
local BUTTONS = {
{ x = 50, y = 020, width = 100, height = 20, text = 'Work', appear = can_do_work, func = do_work },
{ x = 50, y = 120, width = 100, height = 20, text = 'Survive', appear = can_survive, func = do_survive },
{ x = 50, y = 220, width = 100, height = 20, text = 'Buy Dildo', appear = can_buy_dildo, func = buy_dildo },
}
--------------------------------------------------------------------------------
function love.load ()
resetGame()
end
function love.update (dt)
WORK_WAIT = WORK_WAIT - dt
LIFE = LIFE - dt * 5
if LIFE <= 0 then
resetGame()
end
end
function love.mousepressed (x, y)
for _, button in ipairs(BUTTONS) do
if button.x <= x and x <= button.x+button.width and button.y <= y and y <= button.y+button.height and button.appear() then
button.func(button)
break
end
end
end
function love.keypressed(key)
if key == 'escape' then
love.event.quit()
end
end
function love.draw ()
love.graphics.setBackgroundColor(COLOR_BG)
-- Draw buttons
for _, button in ipairs(BUTTONS) do
if button.appear() then
love.graphics.rectangle('line', button.x - 0.5, button.y - 0.5, button.width + 1, button.height + 1)
love.graphics.printf(button.text, button.x, button.y + 5, button.width, 'center')
end
end
-- Draw survive bar
love.graphics.rectangle('line', 200-0.5, 120-0.5, 101, 21)
love.graphics.rectangle('fill', 200, 120, LIFE, 20)
-- Draw dollarydooes
love.graphics.print(MONEY..' $', 200, 20)
-- Draw Didloes
if next(DILDOES, nil) then
--love.graphics.rectangle('line', 200 - 0.5, 220 - 0.5, 3*70+64, 3*70+64)
end
for dildo_id, _ in ipairs(DILDOES) do
local x, y = 200 + 70 * ((dildo_id - 1) % 4), 220 + 70 * math.floor((dildo_id - 1) / 4)
love.graphics.draw( IMG, QUADS[dildo_id], x, y, 0, 4, 4 )
--love.graphics.rectangle('fill', x, y, 64, 64)
end
end

BIN
2017-uge2/All_Reverb.mp3 Normal file

Binary file not shown.

Binary file not shown.

42
2017-uge2/conf.lua Normal file
View File

@ -0,0 +1,42 @@
function love.conf(t)
t.identity = "allstar"
t.version = "11.1"
t.console = false
t.accelerometerjoystick = false
t.externalstorage = false
t.gammacorrect = false
t.window.title = "All Star"
t.window.icon = nil--'images/icon.png'
t.window.width = 800
t.window.height = 600
t.window.borderless = false
t.window.resizable = false
t.window.minwidth = 800
t.window.minheight = 600
t.window.fullscreen = false
t.window.fullscreentype = "desktop"
t.window.vsync = true
t.window.msaa = 0
t.window.display = 1
t.window.highdpi = false
t.window.x = nil
t.window.y = nil
t.modules.audio = true
t.modules.event = true
t.modules.graphics = true
t.modules.image = true
t.modules.joystick = false
t.modules.keyboard = true
t.modules.math = false
t.modules.mouse = true
t.modules.physics = false
t.modules.sound = true
t.modules.system = true
t.modules.timer = true
t.modules.touch = false
t.modules.video = false
t.modules.window = true
t.modules.thread = false
end

244
2017-uge2/main.lua Normal file
View File

@ -0,0 +1,244 @@
-- Colors
local COLOR_WHITE = {1,1,1}
local COLOR_BG = {26/255,26/255,26/255}
local COLOR_PLAYER = {0, 1, 0}
-- Resources
local MUSIC_1 = love.audio.newSource('/All_Star_NoIntro.mp3', 'stream')
local MUSIC_2 = love.audio.newSource('/All_Reverb.mp3', 'stream')
local FONT = love.graphics.newFont('/star_font.ttf', 70)
--------------------------------------------------------------------------------
math.randomseed(os.time())
love.graphics.setFont(FONT)
local plat = require "plat"
local system = plat.PlatformSystem.new()
system:addPlatform(000, 400, 800, 300)
system:addPlatform(-50, -200000, 50, 400000)
system:addPlatform(800, -200000, 50, 400000)
system:addPlatform(450, 200, 100, 50)
system:addPlatform(200, 50, 100, 50)
system:addPlatform(450, -50, 100, 50)
system:addPlatform(200, -150, 100, 50)
system:addPlatform(200, -350, 100, 50)
system:addPlatform(100, -550, 100, 50)
system:addPlatform(300, -750, 250, 50)
system:addPlatform(50, -700, 100, 50)
system:addPlatform(550, -950, 150, 50)
system:addPlatform(300, -1100, 100, 50)
system:addPlatform(500, -1300, 100, 50)
system:addPlatform(150, -1400, 100, 50)
system:addPlatform(650, -1500, 100, 50)
system:addPlatform(300, -1550, 100, 50)
system:addPlatform(500, -1700, 100, 50)
system:addPlatform(250, -1850, 100, 50)
system:addPlatform(100, -2050, 50, 250)
system:addPlatform(400, -2200, 50, 200)
system:addPlatform(650, -2200, 50, 200)
system:addPlatform(650, -2500, 50, 200)
system:addPlatform(700, -2200, 100, 50)
system:addPlatform(700, -2450, 50, 50)
system:addPlatform(700, -2450, 50, 50)
system:addPlatform(600, -2450, 50, 50)
system:addPlatform(550, -2400, 50, 50)
system:addPlatform(450, -2700, 150, 50)
system:addPlatform(350, -2750, 150, 50)
system:addPlatform(300, -2900, 50, 150)
system:addPlatform(300, -2950, 100, 50)
system:addPlatform(650, -3250, 50, 200)
system:addPlatform(500, -3150, 150, 50)
system:addPlatform(600, -3400, 150, 50)
system:addPlatform(250, -3300, 150, 50)
system:addPlatform(450, -3700, 50, 300)
system:addPlatform(300, -3550, 150, 50)
system:addPlatform(100, -3500, 50, 100)
system:addPlatform(450, -3750, 150, 50)
system:addPlatform(350, -4100, 50, 250)
system:addPlatform(400, -4000, 150, 100)
system:addPlatform(700, -3900, 50, 150)
system:addPlatform(500, -4250, 300, 50)
system:addPlatform(0, -4450, 350, 50)
system:addPlatform(150, -4650, 50, 50)
system:addPlatform(250, -4850, 50, 50)
system:addPlatform(400, -4850, 50, 50)
system:addPlatform(550, -4850, 50, 50)
system:addPlatform(700, -5050, 50, 50)
system:addPlatform(450, -5250, 50, 50)
system:addPlatform(750, -5450, 50, 50)
system:addPlatform(0, -5500, 50, 50)
system:addPlatform(0, -5650, 50, 150)
system:addPlatform(750, -5800, 50, 150)
system:addPlatform(300, -6100, 200, 50)
system:addPlatform(250, -6050, 300, 50)
system:addPlatform(200, -6000, 400, 50)
system:addPlatform(350, -6150, 100, 50)
system:addPlatform(550, -6350, 200, 50)
system:addPlatform(50, -6350, 200, 50)
system:addPlatform(300, -6550, 200, 50)
system:addPlatform(350, -6750, 50, 50)
system:addPlatform(400, -6950, 50, 50)
system:addPlatform(350, -7150, 50, 50)
system:addPlatform(400, -7300, 50, 50)
system:addPlatform(550, -7500, 150, 50)
system:addPlatform(300, -7500, 150, 50)
system:addPlatform(350, -7850, 50, 250)
system:addPlatform(200, -7750, 150, 50)
system:addPlatform(0, -7650, 100, 50)
system:addPlatform(500, -8000, 200, 50)
system:addPlatform(250, -8200, 200, 50)
system:addPlatform(500, -8400, 50, 50)
system:addPlatform(200, -8600, 50, 50)
system:addPlatform(550, -8800, 50, 50)
system:addPlatform(350, -8950, 50, 50)
system:addPlatform(300, -9150, 150, 50)
system:addPlatform(300, -9350, 150, 50)
system:addPlatform(300, -9550, 150, 50)
system:addPlatform(150, -9750, 150, 50)
system:addPlatform(450, -9750, 150, 50)
system:addPlatform(300, -9950, 150, 50)
system:addPlatform(400, -10150, 50, 50)
system:addPlatform(300, -10350, 50, 50)
system:addPlatform(400, -10550, 50, 50)
system:addPlatform(450, -10750, 100, 50)
system:addPlatform(200, -10750, 100, 50)
system:addPlatform((800-250)/2, -10950, 250, 50)
local BEST_SCORE = math.huge
local PREVIOUS_SCORE = {}
local START_OF_GAME, END_OF_GAME = 0, 0
local player = system:addPlayer((800-50)/2, 350, 50, 50, {jump = 'up', left = 'left', right = 'right'})
player.color = COLOR_PLAYER
local stars = {}
for i = 1, 1000 do
stars[i] = { math.random() * 800, math.random() * 600 * 4 - 1800 }
end
local function set_score (score)
PREVIOUS_SCORE = score
local SCORE_L = tostring(math.floor(BEST_SCORE*100)/100)
PREVIOUS_SCORE[#PREVIOUS_SCORE+1] = ' '
for i = 1, #SCORE_L do PREVIOUS_SCORE[#PREVIOUS_SCORE+1] = SCORE_L:sub(i,i) end
for i = 1, #score do
score[i] = { score[i] }
score[i].x = math.random() * 10 - 5
score[i].y = math.random() * 10 - 5
score[i].r = math.random() * math.pi/2 - math.pi/4
end
end
--------------------------------------------------------------------------------
local reset_game = nil
local goto_highscore = function ()
local new_score = END_OF_GAME - START_OF_GAME
local old_draw, text = love.draw, {}
if new_score < BEST_SCORE then
BEST_SCORE = new_score
love.keypressed = function (key)
if key == 'escape' then
love.event.quit()
elseif key == 'return' and #text >= 1 then
set_score(text)
reset_game()
elseif key == 'backspace' then
text[#text] = nil
elseif #key == 1 and #text < 3 then
text[#text+1] = key:upper()
end
end
love.draw = function () old_draw(); love.graphics.printf('New High Score!\nEnter name:\n'..table.concat(text), 0, 200, 800, 'center') end
else
love.keypressed = function ()
if key == 'escape' then
love.event.quit()
else
reset_game()
end
end
love.draw = function () old_draw(); love.graphics.printf(':(', 0, 200, 800, 'center') end
end
love.update = function () end
player.movable = false
end
--------------------------------------------------------------------------------
local update_game = function (dt)
system:update(dt)
if player.y < -800 and not MUSIC_1:isPlaying() then MUSIC_1:play(); MUSIC_2:play(); START_OF_GAME = love.timer.getTime(); print("start") end
if player.y < -10950 then player.dy = player.dy - 1000 * dt end
if player.y < -10950 and not END_OF_GAME then END_OF_GAME = love.timer.getTime() end
if player.y < -200000 then goto_highscore() end
if love.keyboard.isDown('f2') then player.dy = player.dy - 1000 * dt end
COLOR_PLAYER[1], COLOR_PLAYER[3] = (player.y+800)/-100000, (player.y+800)/-100000
MUSIC_1:setVolume((player.y+800)/-12000)
MUSIC_2:setVolume((1-(player.y+800)/-12000))
end
local draw_previous_score = function (bx, by, inconsitency)
for i, b in ipairs(PREVIOUS_SCORE) do
love.graphics.print(b[1], b.x * inconsitency + bx + (i-1) * 80, by + b.y * inconsitency, b.r * inconsitency )
end
end
local draw_game = function ()
love.graphics.setBackgroundColor(COLOR_BG)
-- Draw score
love.graphics.setColor(COLOR_WHITE)
draw_previous_score(100, 200*player.y/-10000 + 200, player.y/-3000)
-- Draw Stars
love.graphics.setColor(COLOR_WHITE)
if player.y < 10000 then
for i = 1, #stars do
love.graphics.points(stars[i][1], - 600 + stars[i][2] - player.y/100)
end
end
-- Draw System
system:draw(player.x, player.y - (800-50)/2 - ((player.y < -11000) and (player.y+11000)/400 or 0))
end
function reset_game ( set_score )
player.x, player.y = (800-50)/2, 250
--player.x, player.y = (800-50)/2, -10000
player.dy, player.dx = 0, 0
player.movable = true
MUSIC_1:stop(); MUSIC_2:stop()
love.update = update_game
love.draw = draw_game
love.keypressed = function (key)
if key == 'escape' then
love.event.quit()
elseif key == 'r' then
reset_game()
end
end
END_OF_GAME = nil
end
--------------------------------------------------------------------------------
love.load = reset_game

131
2017-uge2/plat.lua Normal file
View File

@ -0,0 +1,131 @@
local DEFAULT_PLATFORM_COLOR = {255,255,255}
local GRAVITY_CONSTANT = 300
local AIR_RES_CONSTANT = 1
local VERY_SMALL_NUM = 0.01
local function platform_below_platform (platform, system)
return system:isPointOccupied(platform.x, platform.y + platform.h + VERY_SMALL_NUM, platform) or system:isPointOccupied(platform.x + platform.w, platform.y + platform.h + VERY_SMALL_NUM, platform)
end
--------------------------------------------------------------------------------
local PlayerController = {}
PlayerController.__index = PlayerController
function PlayerController.new (target, controls)
assert(controls.jump and controls.left and controls.right )
local self = setmetatable({}, PlayerController)
self.target = target
self.controls = controls
return self
end
function PlayerController:update (dt, system)
local not_jumping = platform_below_platform(self.target, system)
if love.keyboard.isDown( self.controls.jump ) then
self.target.dy = self.target.dy + (not_jumping and -260 or (-280 * dt))
end
if love.keyboard.isDown( self.controls.left ) then
self.target.dx = self.target.dx - 15
end
if love.keyboard.isDown( self.controls.right ) then
self.target.dx = self.target.dx + 15
end
end
--------------------------------------------------------------------------------
local Platform = {}
Platform.__index = Platform
function Platform.new (t)
local self = setmetatable(t, Platform)
assert(self.x and self.y and self.w and self.y)
self.color = self.color or DEFAULT_PLATFORM_COLOR
return self
end
--------------------------------------------------------------------------------
local PlatformSystem = {}
PlatformSystem.__index = PlatformSystem
function PlatformSystem.new ()
local self = setmetatable({}, PlatformSystem)
self.platforms = {}
self.controllers = {}
return self
end
function PlatformSystem:addPlatform (x, y, w, h)
self.platforms[#self.platforms + 1] = Platform.new {
x = x, y = y, w = w, h = h
}
end
function PlatformSystem:addPlayer ( x, y, w, h, controls )
local platform = Platform.new {
x = x, y = y, w = w, h = h,
movable = true, dx = 0, dy = 0
}
self.platforms[#self.platforms + 1] = platform
self.controllers[#self.controllers + 1] = PlayerController.new(platform, controls)
return platform
end
function PlatformSystem:isPointOccupied (x, y, except)
for _, platform in ipairs(self.platforms) do
if platform.x <= x and x <= platform.x + platform.w and platform.y <= y and y <= platform.y + platform.h and platform ~= except then
return platform
end
end
return false
end
function PlatformSystem:updatePlatform (platform, dt)
local ndx, ndy = platform.dx * (1 - AIR_RES_CONSTANT * dt), platform.dy + GRAVITY_CONSTANT * dt
local nx, ny = platform.x + ndx * dt, platform.y + ndy * dt
if true then
if not self:isPointOccupied(platform.x, ny, platform) and not self:isPointOccupied(platform.x + platform.w, ny, platform) and not self:isPointOccupied(platform.x, ny + platform.h, platform) and not self:isPointOccupied(platform.x + platform.w, ny + platform.h, platform) then
platform.y, platform.dy = ny, ndy
else
ndx = ndx * (1 - AIR_RES_CONSTANT * dt)
platform.dy = 0
end
if not self:isPointOccupied(nx, platform.y, platform) and not self:isPointOccupied(nx + platform.w, platform.y, platform) and not self:isPointOccupied(nx, platform.y + platform.h, platform) and not self:isPointOccupied(nx + platform.w, platform.y + platform.h, platform) then
platform.x, platform.dx = nx, ndx
else
platform.dx = 0
end
end
end
function PlatformSystem:update (dt)
-- Update movable platforms
for _, platform in ipairs(self.platforms) do
if platform.movable then
platform.moved = self:updatePlatform(platform, dt) or self:updatePlatform(platform, dt * 0.5) or self:updatePlatform(platform, dt * 0.25)
end
end
-- Update controllers
for _, controller in ipairs(self.controllers) do
controller:update(dt, self)
end
end
function PlatformSystem:draw (dt, offset_x, offset_y)
local offset_x, offset_y = offset_x or 0, offset_y or 0
for _, platform in ipairs(self.platforms) do
love.graphics.setColor(platform.color)
love.graphics.rectangle('fill', platform.x - offset_y, platform.y - offset_x, platform.w, platform.h)
end
end
--------------------------------------------------------------------------------
return {
PlatformSystem = PlatformSystem,
Player = Player,
}

BIN
2017-uge2/star_font.ttf Normal file

Binary file not shown.

Binary file not shown.

BIN
2017-uge3/all_stars.love Normal file

Binary file not shown.

120
2017-uge3/color_tools.lua Normal file
View File

@ -0,0 +1,120 @@
--[[
This is a collection of functions for performing color operations,
designed to work with the LÖVE game engine.
See `README_COLOR_TOOLS.md` for full documentation.
LICENSE is BEER-WARE.
]]
local color_tools = {}
--------------------------------------------------------------------------------
-- Conversion
color_tools.rgb_to_hsl = function (color)
local r = (color[1] == 255 and 1 or color[1]/256)
local g = (color[2] == 255 and 1 or color[2]/256)
local b = (color[3] == 255 and 1 or color[3]/256)
local max, min = math.max(r, g, b), math.min(r, g, b)
local h, s, l = (max+min)/2, (max+min)/2, (max+min)/2
if min == max then
return {0, 0, l}
end
local d = max - min
s = l > 0.5 and d / (2 - max - min) or d / (max + min)
if max == r then
h = ((g - b) / d + (g < b and 6 or 0)) / 6
elseif max == g then
h = ((b - r) / d + 2) / 6
elseif max == b then
h = ((r - g) / d + 4) / 6
end
return {h, s, l}
end
local function hue_to_rgb (p, q, t)
if t < 0 then
t = t + 1
end
if t > 1 then
t = t - 1
end
if t < 1/6 then
return p + (q - p) * 6 * t
elseif t < 1/2 then
return q
elseif t < 2/3 then
return p + (q - p) * 6 * (2/3 - t)
end
return p
end
color_tools.hsl_to_rgb = function (color)
local h, s, l = color[1], color[2], color[3]
local r, g, b
if s == 0 then
r, g, b = l, l, l
else
local q = l < 0.5 and l * (1+s) or l+s - l*s
local p = 2 * l - q
r, g, b = hue_to_rgb(p,q,h+1/3), hue_to_rgb(p,q,h), hue_to_rgb(p,q,h-1/3)
end
r, g, b = math.floor(math.min(255,r*256)+0.5), math.floor(math.min(255,g*256)+0.5), math.floor(math.min(255,b*256)+0.5)
return { r, g, b }
end
--------------------------------------------------------------------------------
-- Interpolation
color_tools.interpolate_rgb = function (c1, c2, t)
return { c1[1]+(c2[1]-c1[1])*t, c1[2]+(c2[2]-c1[2])*t, c1[3]+(c2[3]-c1[3])*t }
end
local function angle_delta (a1, a2)
local r1, r2 = (a1-a2)%1, (a2-a1)%1
return r1 < r2 and -r1 or r2
end
color_tools.interpolate_hsl = function (c1, c2, t)
local h = c1[1] + angle_delta(c1[1], c2[1]) * t
local s = c1[2] + (c2[2] - c1[2]) * t
local l = c1[3] + (c2[3] - c1[3]) * t
return { h, s, l }
end
color_tools.interpolate_rgb_by_way_of_hsl = function (c1, c2, t)
local c1_hsl = color_tools.rgb_to_hsl(c1)
local c2_hsl = color_tools.rgb_to_hsl(c2)
local c3_hsl = color_tools.interpolate_hsl(c1_hsl, c2_hsl, t)
return color_tools.hsl_to_rgb(c3_hsl)
end
--------------------------------------------------------------------------------
-- Inversion
color_tools.invert_rgb = function (color)
return { 255 - color[1], 255 - color[2], 255 - color[3] }
end
--------------------------------------------------------------------------------
-- Parsing
color_tools.parse_rgb = function (str)
local r, g, b
local o = (str:sub(1,1) == '#') and 1 or 0 -- Offset
if #str == 3 or #str == 4 then
r, g, b = str:sub(o+1,o+1):rep(2), str:sub(o+2,o+2):rep(2), str:sub(o+3,o+3):rep(2)
else
r, g, b = str:sub(o+1,o+2), str:sub(o+3,o+4), str:sub(o+5,o+6)
end
return {tonumber('0x'..r), tonumber('0x'..g), tonumber('0x'..b)}
end
--------------------------------------------------------------------------------
return color_tools

42
2017-uge3/conf.lua Normal file
View File

@ -0,0 +1,42 @@
function love.conf(t)
t.identity = "all_stars"
t.version = "11.1"
t.console = false
t.accelerometerjoystick = false
t.externalstorage = false
t.gammacorrect = false
t.window.title = "All Stars"
t.window.icon = nil--'images/icon.png'
t.window.width = 800
t.window.height = 600
t.window.borderless = false
t.window.resizable = false
t.window.minwidth = 800
t.window.minheight = 600
t.window.fullscreen = false
t.window.fullscreentype = "desktop"
t.window.vsync = true
t.window.msaa = 0
t.window.display = 1
t.window.highdpi = false
t.window.x = nil
t.window.y = nil
t.modules.audio = true
t.modules.event = true
t.modules.graphics = true
t.modules.image = true
t.modules.joystick = false
t.modules.keyboard = true
t.modules.math = false
t.modules.mouse = true
t.modules.physics = false
t.modules.sound = true
t.modules.system = true
t.modules.timer = true
t.modules.touch = false
t.modules.video = false
t.modules.window = true
t.modules.thread = false
end

195
2017-uge3/main.lua Normal file
View File

@ -0,0 +1,195 @@
--------------------------------------------------------------------------------
-- Colors
local COLOR_PLAYER_1 = {200/255, 255/255, 200/255}
local COLOR_PLAYER_2 = {200/255, 200/255, 255/255}
local COLOR_WHITE = {255/255,255/255,255/255}
local COLOR_LOWER = {230/255, 230/255, 255/255}
local COLOR_BG = {26/255,26/255,26/255}
--------------------------------------------------------------------------------
WINDOW_WIDTH, WINDOW_HEIGTH = 800, 600
local SOMEBODY_ONCE = false
local SOMEBODY_MUSC = love.audio.newSource('/All_Star_NoIntro.mp3', 'stream')
SOMEBODY_MUSC:setLooping(true)
SOMEBODY_MUSC:play()
local SOMEBODIES = {}
local plat = require "plat"
local color = require "color_tools"
local FONT = love.graphics.newFont('star_font.ttf', 60)
love.graphics.setFont(FONT)
local system, player_1, player_2, reset_timer
-- Stars
local Stars = {}
function Stars:generate (nr_stars)
for i = 1, 200 do
self[#self+1] = math.random() * WINDOW_WIDTH
self[#self+1] = math.random() ^ 2 * WINDOW_HEIGTH
end
end
function Stars:update (dt, scores)
local star_speed = dt * (scores[2] - scores[1])
if star_speed == 0 then return end
for i = 1, #self, 2 do
self[i] = (self[i] + star_speed * self[i+1]/WINDOW_HEIGTH) % WINDOW_WIDTH
end
end
function Stars:draw ()
love.graphics.points(self)
end
-- Scores
local SCORES = { 0, 0 }
local function draw_scores ()
love.graphics.printf(SCORES[1], 50, 600 - 80, 700, 'left')
love.graphics.printf(SCORES[2], 50, 600 - 80, 700, 'right')
end
function reset_game ()
system = plat.PlatformSystem.new()
system:addPlatform(50, 400, 100, 50)
system:addPlatform(800-50-100, 400, 100, 50)
system:addPlatform(300, 200, 200, 50)
local lower = system:addPlatform(300, 550, 200, 50)
lower.resistance = -0.4
lower.color = COLOR_LOWER
player_1 = system:addPlayer(100, 50, 50, 50, {jump = 'w', left = 'a', right = 'd'})
player_1.start_t = 0
player_1.controller.last_dir = 1
player_2 = system:addPlayer(800 - 100 - 50, 50, 50, 50, {jump = 'up', left = 'left', right = 'right'})
player_2.start_t = 0
player_2.controller.last_dir = -1
reset_timer = nil
if SOMEBODY_ONCE then
local somb = SOMEBODY_MUSC:clone()
somb:play()
somb:setLooping(true)
SOMEBODIES[#SOMEBODIES+1] = somb
end
end
local function is_player_outside_bounds (player)
return player.x + player.w < -100 or 900 < player.x or player.y > 700
end
--------------------------------------------------------------------------------
function love.load ()
math.randomseed(os.time())
Stars:generate(1000)
reset_game()
end
local PLAYER_1_SHOOT = 's'
local PLAYER_2_SHOOT = 'down'
function love.update (dt)
Stars:update(dt, SCORES)
system:update(dt)
-- Update color
player_1.color = color.interpolate_rgb(COLOR_PLAYER_1, COLOR_WHITE, love.keyboard.isDown(PLAYER_1_SHOOT) and math.max(0, math.min(1, love.timer.getTime() - player_1.start_t)) or 0)
player_2.color = color.interpolate_rgb(COLOR_PLAYER_2, COLOR_WHITE, love.keyboard.isDown(PLAYER_2_SHOOT) and math.max(0, math.min(1, love.timer.getTime() - player_2.start_t)) or 0)
if reset_timer then
reset_timer = reset_timer - dt
if reset_timer < 0 then
reset_game()
end
end
if is_player_outside_bounds(player_1) and player_1.movable then
SCORES[2] = SCORES[2] + 1
player_1.movable = false
reset_timer = 1
end
if is_player_outside_bounds(player_2) and player_2.movable then
SCORES[1] = SCORES[1] + 1
player_2.movable = false
reset_timer = reset_timer or 1
end
end
local function shoot_bullet_at_player (player)
-- TODO: Add Timeout when shooting bullets shorter than 0.2
local time = love.timer.getTime() - player.start_t
local size = math.max(math.min( 1, time ), 0.2)
local dx = player.controller.last_dir * (1.2 - size) * 600 + player.dx
if dx ~= 0 then
local bw, bh = math.floor(40*size + 0.5), math.floor(20*size + 0.5)
local bx, by = player.x + player.w/2 - bw/2, player.y + player.h/2 - bh/2
system:addBullet(bx, by, bw, bh, dx, player)
end
end
function love.keyreleased (key)
if key == PLAYER_1_SHOOT then shoot_bullet_at_player(player_1) end
if key == PLAYER_2_SHOOT then shoot_bullet_at_player(player_2) end
end
function love.keypressed (key)
if key == 'escape' then
love.event.quit()
end
if key == 's' and player_1.start_t < love.timer.getTime() then
player_1.start_t = love.timer.getTime()
end
if key == 'down' and player_2.start_t < love.timer.getTime() then
player_2.start_t = love.timer.getTime()
end
if key == 'f2' then
SOMEBODY_MUSC:stop()
end
if key == 'f1' then
SOMEBODY_ONCE = not SOMEBODY_ONCE
if not SOMEBODY_ONCE then
for _, track in ipairs(SOMEBODIES) do
track:stop()
end
SOMEBODIES = {}
end
end
end
function love.draw ()
love.graphics.setBackgroundColor(COLOR_BG)
love.graphics.setColor(COLOR_WHITE)
-- Draw score
draw_scores()
-- Draw Stars
Stars:draw()
-- Draw System
system:draw()
if is_player_outside_bounds(player_1) then
love.graphics.setColor(COLOR_PLAYER_1)
love.graphics.rectangle('fill', player_1.x-4000, player_1.y, 8000, 50)
love.graphics.rectangle('fill', player_1.x, player_1.y-4000, 50, 8000)
end
if is_player_outside_bounds(player_2) then
love.graphics.setColor(COLOR_PLAYER_2)
love.graphics.rectangle('fill', player_2.x-4000, player_2.y, 8000, 50)
love.graphics.rectangle('fill', player_2.x, player_2.y-4000, 50, 8000)
end
end

241
2017-uge3/plat.lua Normal file
View File

@ -0,0 +1,241 @@
local DEFAULT_PLATFORM_COLOR = {255,255,255}
local GRAVITY_CONSTANT = 700
local AIR_RES_CONSTANT = 0.5
local DEFAULT_PLATFORM_RES = 0.7
local VERY_SMALL_NUM = 0.01
local PLAYER_MOVE_SPEED = 20
local PUSH_RESISTANCE = math.huge -- Should be >=2, set to math.huge to disable pushing
local BOUNCE_CONSTANT_X = 0
local BOUNCE_CONSTANT_Y = 0
local function platform_below_platform (platform, system)
local tmp
tmp, platform.collided_on_y_axis = platform.collided_on_y_axis, false
return tmp
end
--------------------------------------------------------------------------------
local BulletController
local PlayerController = {}
PlayerController.__index = PlayerController
function PlayerController.new (target, controls)
assert(controls.jump and controls.left and controls.right )
local self = setmetatable({}, PlayerController)
self.target = target
self.controls = controls
self.last_dir = 0
return self
end
function PlayerController:update (dt, system)
local not_jumping = platform_below_platform(self.target, system)
if love.keyboard.isDown( self.controls.jump ) then
self.target.dy = self.target.dy + (not_jumping and -400 or (-400 * dt))
end
if love.keyboard.isDown( self.controls.left ) then
self.target.dx = self.target.dx - PLAYER_MOVE_SPEED
self.last_dir = -1
end
if love.keyboard.isDown( self.controls.right ) then
self.target.dx = self.target.dx + PLAYER_MOVE_SPEED
self.last_dir = 1
end
end
function PlayerController:canCollide (platform, collided_with)
return platform ~= collided_with
and (not collided_with.controller or collided_with.controller.__index ~= BulletController)
end
function PlayerController:onCollide (platform, collided_with, system)
end
--------------------------------------------------------------------------------
BulletController = {}
BulletController.__index = BulletController
function BulletController.new (target, owner)
local self = setmetatable({}, BulletController)
self.target = target
self.owner = owner
self.owner_im = 0.5
return self
end
function BulletController:update (dt, system)
self.target.x = (self.target.x + self.target.w + (WINDOW_WIDTH + self.target.w)) % (WINDOW_WIDTH + self.target.w) - self.target.w
self.owner_im = self.owner_im - dt
end
function BulletController:canCollide (platform, collided_with)
return collided_with ~= platform and (collided_with ~= self.owner or self.owner_im <= 0) and (collided_with.controller and collided_with.controller.__index ~= BulletController)
end
function BulletController:onCollide (platform, collided_with, system)
local dir = platform.dx / math.abs(platform.dx)
local force = dir * ((platform.w / (40*0.2) )^1.5) * (40*0.2)
local ndx, ndy = collided_with.dx + force * 15, collided_with.dy + -platform.h * 12
if ndx == ndx and ndy == ndy then -- Prevent nan values
collided_with.dx, collided_with.dy = ndx, ndy
system:removeController(self)
system:removePlatform(self.target)
end
end
--------------------------------------------------------------------------------
local Platform = {}
Platform.__index = Platform
function Platform.new (t)
local self = setmetatable(t, Platform)
assert(self.x and self.y and self.w and self.y)
self.color = self.color or DEFAULT_PLATFORM_COLOR
self.resistance = DEFAULT_PLATFORM_RES
return self
end
--------------------------------------------------------------------------------
local PlatformSystem = {}
PlatformSystem.__index = PlatformSystem
function PlatformSystem.new ()
local self = setmetatable({}, PlatformSystem)
self.platforms = {}
self.controllers = {}
return self
end
function PlatformSystem:addPlatform (x, y, w, h)
local platform = Platform.new {
x = x, y = y, w = w, h = h
}
self.platforms[platform] = true
return platform
end
function PlatformSystem:removeController( controller )
self.controllers[controller] = nil
end
function PlatformSystem:removePlatform( platform )
self.platforms[platform] = nil
end
function PlatformSystem:addPlayer ( x, y, w, h, controls )
local platform = Platform.new {
x = x, y = y, w = w, h = h,
movable = true, dx = 0, dy = 0
}
platform.controller = PlayerController.new(platform, controls)
self.platforms[platform] = true
self.controllers[platform.controller] = true
return platform
end
function PlatformSystem:addBullet (x, y, w, h, dx, owner)
local platform = Platform.new {
x = x, y = y, w = w, h = h,
movable = true, dx = dx, dy = 0, constant = true
}
platform.controller = BulletController.new(platform, owner)
self.platforms[platform] = true
self.controllers[platform.controller] = true
return platform
end
function PlatformSystem:isPointOccupied (x, y, who_is_asking)
for platform, _ in pairs(self.platforms) do
if platform.x <= x and x <= platform.x + platform.w and platform.y <= y and y <= platform.y + platform.h and who_is_asking.controller:canCollide(who_is_asking, platform) then
return platform
end
end
return nil
end
local function is_movement_on_collision_course (platform, nx, ny, platforms, func)
for other in pairs(platforms) do
if func(platform, nx, ny, other) then
return other
end
end
end
local function check_move_x (platform, nx, ny, other)
return platform ~= other and nx < other.x + other.w and other.x < nx + platform.w and other.y < platform.y + platform.h and platform.y < other.y + other.h and platform.controller:canCollide(platform, other)
end
local function check_move_y (platform, nx, ny, other)
return platform ~= other and ny < other.y + other.h and other.y < ny + platform.h and other.x < platform.x + platform.w and platform.x < other.x + other.w and platform.controller:canCollide(platform, other)
end
function PlatformSystem:updatePlatform (platform, dt)
local ndx, ndy = platform.dx * (platform.constant and 1 or (1 - AIR_RES_CONSTANT) ^ dt), platform.dy + (platform.constant and 0 or (GRAVITY_CONSTANT * dt))
local nx, ny = platform.x + ndx * dt, platform.y + ndy * dt
-- Moving down
do
local collided_with = is_movement_on_collision_course(platform, nx, ny, self.platforms, check_move_y)
if not collided_with then
platform.y, platform.dy = ny, ndy
else
platform.collided_on_y_axis = collided_with and (ndy >= 0)
platform.controller:onCollide(platform, collided_with, self)
ndx = ndx * (platform.constant and 1 or (1 - collided_with.resistance) ^ dt)
platform.y = collided_with.y + ( (ndy >= 0) and -platform.h or collided_with.h)
platform.dy = -platform.dy * BOUNCE_CONSTANT_Y
end
end
-- Moving on x axis
do
local collided_with = is_movement_on_collision_course(platform, nx, ny, self.platforms, check_move_x)
if not collided_with then
platform.x, platform.dx = nx, ndx
else
platform.controller:onCollide(platform, collided_with, self)
platform.x = collided_with.x + ( (ndx >= 0) and -platform.w or collided_with.w)
if platform.movable and collided_with.movable and self.platforms[platform] and PUSH_RESISTANCE ~= math.huge then
platform.dx, collided_with.dx = (platform.dx + collided_with.dx)/PUSH_RESISTANCE, (platform.dx + collided_with.dx)/PUSH_RESISTANCE
elseif BOUNCE_CONSTANT_X == 0 then
platform.dx = 0
end
platform.dx = -platform.dx * BOUNCE_CONSTANT_X
end
end
end
function PlatformSystem:update (dt)
-- Update movable platforms
for platform, _ in pairs(self.platforms) do
if platform.movable then
self:updatePlatform(platform, dt)
end
end
-- Update controllers
for controller, _ in pairs(self.controllers) do
controller:update(dt, self)
end
end
function PlatformSystem:draw (dt, offset_x, offset_y)
local offset_x, offset_y = offset_x or 0, offset_y or 0
for platform, _ in pairs(self.platforms) do
love.graphics.setColor(platform.color)
love.graphics.rectangle('fill', platform.x - offset_y, platform.y - offset_x, platform.w, platform.h)
end
end
--------------------------------------------------------------------------------
return {
PlatformSystem = PlatformSystem,
Player = Player,
}

BIN
2017-uge3/star_font.ttf Normal file

Binary file not shown.

42
2017-uge4/conf.lua Normal file
View File

@ -0,0 +1,42 @@
function love.conf(t)
t.identity = "En Forelæsning"
t.version = "11.1"
t.console = false
t.accelerometerjoystick = false
t.externalstorage = false
t.gammacorrect = false
t.window.title = "En Forelæsning"
t.window.icon = nil--'images/icon.png'
t.window.width = 800
t.window.height = 400
t.window.borderless = false
t.window.resizable = false
t.window.minwidth = 800
t.window.minheight = 400
t.window.fullscreen = false
t.window.fullscreentype = "desktop"
t.window.vsync = true
t.window.msaa = 0
t.window.display = 1
t.window.highdpi = false
t.window.x = nil
t.window.y = nil
t.modules.audio = true
t.modules.event = true
t.modules.graphics = true
t.modules.image = true
t.modules.joystick = false
t.modules.keyboard = true
t.modules.math = false
t.modules.mouse = true
t.modules.physics = false
t.modules.sound = true
t.modules.system = true
t.modules.timer = true
t.modules.touch = false
t.modules.video = false
t.modules.window = true
t.modules.thread = false
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 611 B

267
2017-uge4/main.lua Normal file
View File

@ -0,0 +1,267 @@
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

247
2017-uge4/markov.lua Normal file
View File

@ -0,0 +1,247 @@
--[[
Markov Chain module of the luaFortune library.
Documentation and License can be found here:
https://bitbucket.org/Jmaa/luafortune
--]]
local markov = {
version = 0.5
}
--------------------------------------------------------------------------------
-- Constants
local ENGLISH_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"}
--------------------------------------------------------------------------------
-- Misc functios
local function reverse_alphabet (alphabet)
local reverse = {}
for index, letter in ipairs(alphabet) do
reverse[letter] = index
end
reverse[""] = 0
return reverse
end
--------------------------------------------------------------------------------
local function new_chain (alphabet, order)
local alphabet = alphabet or ENGLISH_ALPHABET
return {
alphabet = alphabet,
reverse_alphabet = reverse_alphabet(alphabet),
nr_symbols = #alphabet,
order = order,
}
end
--------------------------------------------------------------------------------
-- first-order markov chains
local MarkovChain = {}
MarkovChain.__index = MarkovChain
markov.MarkovChain = MarkovChain
function MarkovChain.new (alphabet)
return setmetatable(new_chain(alphabet), MarkovChain)
end
function MarkovChain:trainMany (list_of_words)
for _, word in ipairs(list_of_words) do
self:trainSingle(word)
end
end
function MarkovChain:getTotalWeight (loc)
local total_weight = 0
for i=1, self.nr_symbols do
total_weight = total_weight + (self[loc+i] or 0)
end
return total_weight
end
function MarkovChain:translateToFinal (id_word)
local word = {}
for i=#id_word, 1, -1 do
word[i] = self.alphabet[id_word[i]]
end
return word
end
function MarkovChain:translateToRaw (str_word)
local id_word = {}
for i=#str_word, 1, -1 do
id_word[i] = self.reverse_alphabet[str_word[i]]
end
return id_word
end
function MarkovChain:trainSingle (word)
for i=1, #word do
local cur_id =
self.reverse_alphabet[word[i-1] or ""] * self.nr_symbols +
self.reverse_alphabet[word[i ]]
self[cur_id] = (self[cur_id] or 0) + 1
end
end
function MarkovChain:getNextRaw (word, index)
local index = index or #word
local loc = index==0 and 0 or word[index]*self.nr_symbols
local weight_random = math.random(self:getTotalWeight(loc))
for j=1, self.nr_symbols do
weight_random = weight_random - (self[loc+j] or 0)
if weight_random <= 0 then
return j
end
end
end
function MarkovChain:getNext (word, index)
local id_word = {}
for i=1, #word do
id_word[i] = self.reverse_alphabet[word[i]]
end
return self.alphabet[self:getNextRaw(id_word, index)]
end
--------------------------------------------------------------------------------
-- nth-order markov chains
local NoMarkovChain = {
trainMany = MarkovChain.trainMany,
getTotalWeight = MarkovChain.getTotalWeight,
translateToFinal = MarkovChain.translateToFinal,
translateToRaw = MarkovChain.translateToRaw
}
NoMarkovChain.__index = NoMarkovChain
markov.NoMarkovChain = NoMarkovChain
function MarkovChain.new (alphabet, order)
return setmetatable(new_chain(alphabet, order), NoMarkovChain)
end
function NoMarkovChain:trainSingle (word)
local word_len = #word
local markov_order = self.order
local nr_symbols = self.nr_symbols
for i = markov_order + 1, markov_order + word_len do
local cur_id = 0
for j=i-markov_order, math.min(word_len,i+markov_order) do
self[cur_id] = (self[cur_id] or 0) + 1
cur_id = cur_id*nr_symbols+self.reverse_alphabet[word[j]]
end
self[cur_id] = (self[cur_id] or 0) + 1
end
end
function NoMarkovChain:getLoc (word, this_i)
local loc = 0
for i = math.max(1, this_i-self.order+1), this_i do
loc = loc*self.nr_symbols + word[i]
end
return loc
end
function NoMarkovChain:getNextRaw (word, index)
local index = index or #word
local loc = self:getLoc(word, index) * self.nr_symbols
local total_weight = self:getTotalWeight(loc)
if total_weight == 0 then return nil end
local weight_random = math.random(total_weight)
for j=1, self.nr_symbols do
weight_random = weight_random - (self[loc+j] or 0)
if weight_random <= 0 then
return j
end
end
end
--------------------------------------------------------------------------------
-- Variable-order markov chains
local VoMarkovChain = {
trainSingle = NoMarkovChain.trainSingle,
trainMany = NoMarkovChain.trainMany,
getLoc = NoMarkovChain.getLoc,
getTotalWeight = NoMarkovChain.getTotalWeight,
translateToFinal = NoMarkovChain.translateToFinal,
translateToRaw = NoMarkovChain.translateToRaw,
getNext = NoMarkovChain.getNext,
}
VoMarkovChain.__index = VoMarkovChain
markov.VoMarkovChain = VoMarkovChain
function VoMarkovChain.new (alphabet, order)
return setmetatable(new_chain(alphabet, order), VoMarkovChain)
end
function VoMarkovChain:getLoc (word, this_i, min_i)
local loc = 0
for i = math.max(1, min_i+this_i-self.order+1), this_i do
loc = loc*self.nr_symbols + word[i]
end
return loc
end
function VoMarkovChain:getNextRaw (word, index)
local index = index or #word
for i=0, index do
local loc = self:getLoc(word, index, i)
local total_weight = self[loc]
if total_weight then
local weight_random = math.random(total_weight)
loc = loc * self.nr_symbols
for j=1, self.nr_symbols do
weight_random = weight_random - (self[loc+j] or 0)
if weight_random <= 0 then
return j
end
end
end
end
end
--------------------------------------------------------------------------------
-- String-based markov wrapper
local StringWrapper = {}
StringWrapper.__index = StringWrapper
markov.StringWrapper = StringWrapper
function StringWrapper.new (chain)
return setmetatable({chain = chain}, StringWrapper)
end
function StringWrapper:train (list_of_words, is_iterator)
local char_match = "[\01-\127\192-\255][\128-\191]*"
for _, word in is_iterator and list_of_words or ipairs(list_of_words) do
word = word or _
local word_table = {}
for char in word:gmatch(char_match) do
table.insert(word_table, char)
end
self.chain:trainSingle(word_table)
end
end
function StringWrapper:generate (word_len)
local word = {}
for i=1, word_len do
local next_char = self.chain:getNextRaw(word)
word[i] = next_char
if next_char == nil then
break
end
end
return table.concat(self.chain:translateToFinal(word))
end
--------------------------------------------------------------------------------
return markov

68
2017-uge4/sentences.txt Normal file
View File

@ -0,0 +1,68 @@
vi har en meget tydelig design sprog, og det er selve definitionen af brandet.
du vil aldrig se noget popsmart i et bang og olufsen produkt, hvis vi har gjort vores arbejde ordentligt brugeren vil kunna forstå, hvad historien er.
en af vores regler er to kun skabe produkter med en stærk grund til at være og designet følger.
du vil aldrig fange en af vores designers tegne en skitse af, hvordan et produkt ser ud på papir og derefter forsøger at passe elektronikken ind i det, vi arbejder indefra og ud, so formular virkelig følger funktion.
vores signatur design has fokus på kvalitet, på essentialisme, på at skære tingene tilbage til kernen og enklere alt.
vi also have en stærk forståelse af materiale, ingen form for metal eller træ anvendt because er attraktiv, det hele dræbe et formål.
vores kunder er omdrejningspunktet i vores konceptuelle arbejde. hvert stykke stammer med vores brugere.
det gør vi gennem forskning og tilbringe tid sammen med kunderne to få en forståelse af de smertestillende punkter associeret med teknologi, og hvordan denne tech væver ind i folks liv.
vi finder mønstre i folks adfærd og fra dette, levere meningsfuld løsninger.
vi har ikke designe produkter med kort levetid, og vi forsøger at gøre det muligt for folk, der har købt ind i brand lang tid siden, siger en gammel pladespiller, for at bringe disse produkter i den nye verden med dem.
vi kan kombinere vores klassiske ikoner med de produkter, vi frigiver nu, at sikre de arbejder sammen.
men hvis disse produkter kommer til at vare, de har brug for at blive godt.
vi er en highend brand, og vi går ikke på kompromis med kvaliteten.
fra komponenterne i højttalerne til det materiale, de er indkapslet i, bruger vi de allerbedste materialer.
vi bruger aluminium højttalere, fordi det overfører varme meget godt, og dette virker for god lydkvalitet, og fordi det er holdbart, ikke fordi det er smukt.
en anden måde sørger vi for vores produkter er tidløse i de figurer, vi udfører.
vi starter med en geometrisk design og bruge disse grundlæggende former hele, fordi disse former findes i naturen, øjnene ikke trætte af dem.
hvor mange interaktiv produkter er der i daglig brug?
tænk et øjeblik over, hvad du bruger i en typisk dag, mobil telefon, computer, fjernbetjening, kaffemaskine, atm, billetautomat, printer, ipod, lommeregner, gps, dvd, computerspil.
listen er endeløs.
nu tænker et øjeblik om, hvordan brugbar de er.
hvor mange er faktisk nemt, ubesværet, og sjovt at bruge?
nogle kan lide ipod er en fornøjelse at bruge.
andre, ligesom data projektor, der ikke ser en persons laptop, når du tilslutter det, kan være meget frustrerende.
hvorfor er der en forskel?
et hovedformål interaktionsdesign er at reducere de negative aspekter af brugeroplevelsen og samtidig øge de positive.
i det væsentlige, det handler om at udvikle interaktiv produkter 1, der er nemme, effektive, og behagelig at bruge, fra brugernes perspektiv.
i dette kapitel starter vi med at undersøge hvad interaktionsdesign er.
vi ser på forskellen mellem god og dårlig design, fremhæver, hvordan produkterne kan afvige radikalt i hvordan brugbare og fornøjelig de er.
vi derefter beskrive hvad og hvem der er involveret i processen med interaktionsdesign.
brugeren erfaring, som er et centralt anliggende for interaktionsdesign, indføres derefter.
endelig har vi skitsere, hvordan at karakterisere brugeroplevelsen i form af usability, brugeroplevelse mål, og design principper.
en opgave præsenteres i slutningen af kapitlet, hvor du har mulighed for at omsætte til praksis, hvad du har læst ved at evaluere udformningen af et interaktivt produkt.
et centralt anliggende for interaktionsdesign er at udvikle interaktive produkter, der er anvendelige.
med dette er generelt menes let at lære, effektivt at bruge, og giver en fornøjelig bruger erfaring.
et godt sted at begynde at tænke over, hvordan man designer brugbare interaktive produkter er at sammenligne eksempler på godt og dårligt designede dem.
gennem identificere specifikke svagheder og styrker forskellige interaktive systemer, kan vi begynde at forstå, hvad det betyder for noget at være brugbart eller ej.
her beskriver vi to eksempler på dårligt designede produkter, en telefonsvarer, system anvendes på hoteller og allestedsnærværende fjernbetjening enhed, og kontrast disse med to veldesignede eksempler på produkter, der udfører den samme funktion.
verden bliver gennemtrængt af teknologier, der understøtter mere forskelligartede aktiviteter.
tænk et øjeblik, hvad du kan i øjeblikket ved hjælp af edb systemer. sende beskeder, indsamle oplysninger, skrive essays, styre kraftværker, program, tegne, planlægge, beregne, overvåge andre, spille spil for at nævne nogle få.
nu tænker de typer af grænseflader og interaktive enheder, der er til rådighed.
også de er lige så forskellige. multirøre skærme, tale baserede systemer, håndholdte enheder, og store interaktive skærme til nævne nogle få.
der er også mange måder at designe, hvordan brugerne kan interagere med et system, f.eks.
ved brug af menuer, kommandoer, formularer, ikoner, gestik osv desuden stadigt mere innovative dagligdags artefakter bliver skabt, ved hjælp af nye materialer, såsom e tekstiler og wearables.
grænsefladerne for dagligvarer, ligesom kameraer, mikrobølgeovne og vask ing maskiner, der plejede at være fysisk og rige produktdesign, er nu predomi overvejende digitalt baseret, kræver interaktion design.
flytningen mod omdanne menneske menneske transaktioner i udelukkende grænseflade baserede dem har også indført en ny type kunde interaktion.
self kasserne på købmandsforretninger, lufthavne, og biblioteker er ved at blive normen, hvor kunderne selv skal kontrollere i deres egen varer, bagage eller bøger.
i stedet for et venligt ansigt hjælpe dem ud, grænseflader bark ordrer på dem.
mens mere omkostningseffektiv, det lægger byrden på brugerne at interagere med systemet.
trykke utilsigtet på den forkerte knap kan resultere i en frustrerende, og undertiden mortifying, oplevelse, især for førstegangsbrugere.
en række udtryk er blevet anvendt til at fremhæve forskellige aspekter af det, der designet, herunder brugergrænseflade design, software design, brugercentreret design, produkt design, webdesign, oplevelsesdesign, og interaktivt system design.
interaktionsdesign bliver i stigende grad accepteret som paraplyen sigt, der dækker alle disse aspekter.
ja, mange praktiserende læger og designere, som i 1990erne ville have beskrevet, hvad de var gør som interface design eller interaktivt system design, nu fremme, hvad de gør som interaktionsdesign.
fokus i interaktionsdesign er meget meget bekymret med praksis, dvs.
hvordan man designer brugeroplevelser.
det er ikke gift med en bestemt måde at gøre design, men er mere eklektisk, fremme brugen af en række metoder, teknikker og rammer.
hvilket er givet prom inence eller er i øjeblikket på mode, vil i høj grad afhænge af den tid og kontekst.
hvorledes interaktionsdesign adskiller sig fra andre tilgange til design af computerbaserede systemer, såsom software engineering?
en simpel analogi til en anden profession, con berørt med skabe bygninger, tydeliggøre denne forskel.
i sin redegørelse for interaktion design, winograd spørger, hvordan arkitekter og ingeniører er forskellige, når de står med problemet med at bygge et hus.
arkitekter er bekymrede med de mennesker og deres interac tioner med hinanden og med huset bliver bygget.
for eksempel er der den rette blanding af familie og private rum?
er rum til madlavning og spisning i umiddelbar nærhed?
vilje mennesker lever i rummet er udformet på den måde, det var beregnet til at blive brugt?
i modsætning, ingeniører interesseret i spørgsmål at gøre med at realisere projektet.
disse omfatter praktisk bekymringer som omkostninger, holdbarhed, strukturelle aspekter, miljømæssige aspekter, brandkrav, og byggemetoder.
ligesom der er en forskel mellem at designe og bygge en hus, så er også der en skelnen mellem at designe et interaktivt produkt og ingeniør ing softwaren til det.