5 changed files with 1 additions and 299 deletions
			
			
		- 
					3main.lua
 - 
					89src/extra.lua
 - 
					23src/geometry.lua
 - 
					162src/gui.lua
 - 
					23src/memory.lua
 
@ -1,89 +0,0 @@ | 
				
			|||
 | 
				
			|||
-- utility functions that don't below elsewhere go here, | 
				
			|||
-- especially if they would be at home on the global 'math' or 'table' variables, or are otherwise extensions of standard lua features | 
				
			|||
-- try to avoid *too* much amulet specific stuff, but vector types are probably ok. | 
				
			|||
 | 
				
			|||
function fprofile(f, ...) | 
				
			|||
    local t1 = am.current_time() | 
				
			|||
    local result = { f(...) } | 
				
			|||
    local time = am.current_time() - t1 | 
				
			|||
    --log("%f", time) | 
				
			|||
    return time, unpack(result) | 
				
			|||
end | 
				
			|||
 | 
				
			|||
function math.wrapf(float, range) | 
				
			|||
    return float - range * math.floor(float / range) | 
				
			|||
end | 
				
			|||
 | 
				
			|||
function math.lerp(v1, v2, t) | 
				
			|||
    return v1 * t + v2 * (1 - t) | 
				
			|||
end | 
				
			|||
 | 
				
			|||
-- don't use this with sparse arrays | 
				
			|||
function table.rchoice(t) | 
				
			|||
    return t[math.floor(math.random() * #t) + 1] | 
				
			|||
end | 
				
			|||
 | 
				
			|||
function table.count(t) | 
				
			|||
    local count = 0 | 
				
			|||
    for i,v in pairs(t) do | 
				
			|||
        if v ~= nil then | 
				
			|||
            count = count + 1 | 
				
			|||
        end | 
				
			|||
    end | 
				
			|||
    return count | 
				
			|||
end | 
				
			|||
 | 
				
			|||
function table.highest_index(t) | 
				
			|||
    local highest = nil | 
				
			|||
    for i,v in pairs(t) do | 
				
			|||
        if i and not highest then | 
				
			|||
            highest = i | 
				
			|||
        end | 
				
			|||
 | 
				
			|||
        if i > highest then | 
				
			|||
            highest = i | 
				
			|||
        end | 
				
			|||
    end | 
				
			|||
    return highest | 
				
			|||
end | 
				
			|||
 | 
				
			|||
function table.find(t, predicate) | 
				
			|||
    for i,v in pairs(t) do | 
				
			|||
        if predicate(v) then | 
				
			|||
            return i,v | 
				
			|||
        end | 
				
			|||
    end | 
				
			|||
    return nil | 
				
			|||
end | 
				
			|||
 | 
				
			|||
function quicksort(t, low_index, high_index, comparator) | 
				
			|||
    local function partition(t, low_index, high_index) | 
				
			|||
        local i = low_index - 1 | 
				
			|||
        local pivot = t[high_index] | 
				
			|||
 | 
				
			|||
        for j = low_index, high_index - 1 do | 
				
			|||
            if comparator(t[j], t[pivot]) <= 0 then | 
				
			|||
                i = i + 1 | 
				
			|||
                t[i], t[j] = t[j], t[i] | 
				
			|||
            end | 
				
			|||
        end | 
				
			|||
 | 
				
			|||
        t[i + 1], t[high_index] = t[high_index], t[i + 1] | 
				
			|||
        return i + 1 | 
				
			|||
    end | 
				
			|||
 | 
				
			|||
    if #t == 1 then | 
				
			|||
        return t | 
				
			|||
    end | 
				
			|||
 | 
				
			|||
    if comparator(t[low_index], t[high_index]) < 0 then | 
				
			|||
        local partition_index = partition(t, low_index, high_index) | 
				
			|||
 | 
				
			|||
        quicksort(t, low_index, partition_index - 1, comparator) | 
				
			|||
        quicksort(t, partition_index + 1, high_index, comparator) | 
				
			|||
    end | 
				
			|||
 | 
				
			|||
    return t | 
				
			|||
end | 
				
			|||
 | 
				
			|||
@ -1,23 +0,0 @@ | 
				
			|||
 | 
				
			|||
function circles_intersect(center1, center2, radius1, radius2) | 
				
			|||
    local c1, c2, r1, r2 = center1, center2, radius1, radius2 | 
				
			|||
    local d = math.distance(center1, center2) | 
				
			|||
    local radii_sum = r1 + r2 | 
				
			|||
                                    -- touching | 
				
			|||
    if d == radii_sum then          return 1 | 
				
			|||
 | 
				
			|||
                                    -- not touching or intersecting | 
				
			|||
    elseif d > radii_sum then       return false | 
				
			|||
 | 
				
			|||
                                    -- intersecting | 
				
			|||
    else                            return 2 | 
				
			|||
    end | 
				
			|||
end | 
				
			|||
 | 
				
			|||
function point_in_rect(point, rect) | 
				
			|||
    return point.x > rect.x1 | 
				
			|||
       and point.x < rect.x2 | 
				
			|||
       and point.y > rect.y1 | 
				
			|||
       and point.y < rect.y2 | 
				
			|||
end | 
				
			|||
 | 
				
			|||
@ -1,162 +0,0 @@ | 
				
			|||
 | 
				
			|||
-- text popup in the middle of the screen that dissapates | 
				
			|||
function gui_alert(message, color, decay_time) | 
				
			|||
    win.scene:append( | 
				
			|||
        am.scale(3) ^ am.text(message, color or COLORS.WHITE) | 
				
			|||
        :action(coroutine.create(function(self) | 
				
			|||
            am.wait(am.tween(self, decay_time or 1, { color = vec4(0) }, am.ease_in_out)) | 
				
			|||
            win.scene:remove(self) | 
				
			|||
        end)) | 
				
			|||
    ) | 
				
			|||
end | 
				
			|||
 | 
				
			|||
function gui_numberfield(dimensions, opts) | 
				
			|||
 | 
				
			|||
end | 
				
			|||
 | 
				
			|||
function gui_textfield(position, dimensions, max, disallowed_chars) | 
				
			|||
    local width, height = dimensions.x, dimensions.y | 
				
			|||
    local disallowed_chars = disallowed_chars or {} | 
				
			|||
    local max = max or 10 | 
				
			|||
 | 
				
			|||
    local outer_rect = am.rect( | 
				
			|||
        -width/2, | 
				
			|||
        -height/2, | 
				
			|||
        width/2, | 
				
			|||
        height/2, | 
				
			|||
        COLORS.VERY_DARK_GRAY | 
				
			|||
    ) | 
				
			|||
    local inner_rect = am.rect( | 
				
			|||
        -width/2 + 1, | 
				
			|||
        -height/2 + 1, | 
				
			|||
        width/2 - 2, | 
				
			|||
        height/2 - 2, | 
				
			|||
        COLORS.PALE_SILVER | 
				
			|||
    ) | 
				
			|||
 | 
				
			|||
    local group = am.group{ | 
				
			|||
        outer_rect, | 
				
			|||
        inner_rect, | 
				
			|||
        am.translate(-width/2 + 5, 0) ^ am.scale(2) ^ am.text("", COLORS.BLACK, "left"), | 
				
			|||
        am.translate(-width/2 + 5, -8) ^ am.line(vec2(0, 0), vec2(16, 0), 2, COLORS.BLACK) | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    group:action(function(self) | 
				
			|||
        local keys = win:keys_pressed() | 
				
			|||
        if #keys == 0 then return end | 
				
			|||
 | 
				
			|||
        local chars = {} | 
				
			|||
        local shift = win:key_down("lshift") or win:key_down("rshift") | 
				
			|||
        for i,k in pairs(keys) do | 
				
			|||
            if k:len() == 1 then -- @HACK alphabetical or digit characters | 
				
			|||
                if string.match(k, "%a") then | 
				
			|||
                    if shift then | 
				
			|||
                        table.insert(chars, k:upper()) | 
				
			|||
                    else | 
				
			|||
                        table.insert(chars, k) | 
				
			|||
                    end | 
				
			|||
                elseif string.match(k, "%d") then | 
				
			|||
                    if shift then | 
				
			|||
                        if k == "1" then table.insert(chars, "!") | 
				
			|||
                        elseif k == "2" then table.insert(chars, "@") | 
				
			|||
                        elseif k == "3" then table.insert(chars, "#") | 
				
			|||
                        elseif k == "4" then table.insert(chars, "$") | 
				
			|||
                        elseif k == "5" then table.insert(chars, "%") | 
				
			|||
                        elseif k == "6" then table.insert(chars, "^") | 
				
			|||
                        elseif k == "7" then table.insert(chars, "&") | 
				
			|||
                        elseif k == "8" then table.insert(chars, "*") | 
				
			|||
                        elseif k == "9" then table.insert(chars, "(") | 
				
			|||
                        elseif k == "0" then table.insert(chars, ")") | 
				
			|||
                        end | 
				
			|||
                    else | 
				
			|||
                        table.insert(chars, k) | 
				
			|||
                    end | 
				
			|||
                end | 
				
			|||
            -- begin non-alphabetical/digit | 
				
			|||
            elseif k == "minus" then | 
				
			|||
                if shift then table.insert(chars, "_") | 
				
			|||
                else          table.insert(chars, "-") end | 
				
			|||
            elseif k == "equals" then | 
				
			|||
                if shift then table.insert(chars, "=") | 
				
			|||
                else          table.insert(chars, "+") end | 
				
			|||
            elseif k == "leftbracket" then | 
				
			|||
                if shift then table.insert(chars, "{") | 
				
			|||
                else          table.insert(chars, "[") end | 
				
			|||
            elseif k == "rightbracket" then | 
				
			|||
                if shift then table.insert(chars, "}") | 
				
			|||
                else          table.insert(chars, "]") end | 
				
			|||
            elseif k == "backslash" then | 
				
			|||
                if shift then table.insert(chars, "|") | 
				
			|||
                else          table.insert(chars, "\\") end | 
				
			|||
            elseif k == "semicolon" then | 
				
			|||
                if shift then table.insert(chars, ":") | 
				
			|||
                else          table.insert(chars, ";") end | 
				
			|||
            elseif k == "quote" then | 
				
			|||
                if shift then table.insert(chars, "\"") | 
				
			|||
                else          table.insert(chars, "'") end | 
				
			|||
            elseif k == "backquote" then | 
				
			|||
                if shift then table.insert(chars, "~") | 
				
			|||
                else          table.insert(chars, "`") end | 
				
			|||
            elseif k == "comma" then | 
				
			|||
                if shift then table.insert(chars, "<") | 
				
			|||
                else          table.insert(chars, ",") end | 
				
			|||
            elseif k == "period" then | 
				
			|||
                if shift then table.insert(chars, ">") | 
				
			|||
                else          table.insert(chars, ".") end | 
				
			|||
            elseif k == "slash" then | 
				
			|||
                if shift then table.insert(chars, "?") | 
				
			|||
                else          table.insert(chars, "/") end | 
				
			|||
 | 
				
			|||
            -- control characters | 
				
			|||
            elseif k == "backspace" then | 
				
			|||
                -- @NOTE this doesn't preserve the order of chars in the array so if | 
				
			|||
                -- someone presses a the key "a" then the backspace key in the same frame, in that order | 
				
			|||
                -- the backspace occurs first | 
				
			|||
                self"text".text = self"text".text:sub(1, self"text".text:len() - 1) | 
				
			|||
 | 
				
			|||
            elseif k == "tab" then | 
				
			|||
                -- @TODO | 
				
			|||
 | 
				
			|||
            elseif k == "space" then | 
				
			|||
                table.insert(chars, " ") | 
				
			|||
 | 
				
			|||
            elseif k == "capslock" then | 
				
			|||
                -- @OTOD | 
				
			|||
            end | 
				
			|||
        end | 
				
			|||
 | 
				
			|||
        for _,c in pairs(chars) do | 
				
			|||
            if not disallowed_chars[c] then | 
				
			|||
                if self"text".text:len() <= max then | 
				
			|||
                    self"text".text = self"text".text .. c | 
				
			|||
                end | 
				
			|||
            end | 
				
			|||
        end | 
				
			|||
    end) | 
				
			|||
 | 
				
			|||
    return group | 
				
			|||
end | 
				
			|||
 | 
				
			|||
function gui_slider(position, dimensions, bar_color, circle_color, min, max, default_value, action) | 
				
			|||
    local position = position or vec2(0) | 
				
			|||
    local width = dimensions.x | 
				
			|||
    local height = dimensions.y | 
				
			|||
    local bar_color = bar_color or COLORS.WHITE | 
				
			|||
    local circle_color = circle_color or COLORS.GREEN_YELLOW | 
				
			|||
    local min = min or 0 | 
				
			|||
    local max = max or 100 | 
				
			|||
    local default_value = math.clamp(default_value or 50, min, max) | 
				
			|||
 | 
				
			|||
    local slider = pack_texture_into_sprite(TEXTURES.GUI_SLIDER, width, height, bar_color) | 
				
			|||
    local circle = am.circle(vec2(-width/2 + (default_value/max) * (width/2), 0), height, circle_color) | 
				
			|||
 | 
				
			|||
    local node = am.translate(position) ^ am.group{ | 
				
			|||
        slider, | 
				
			|||
        circle | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    if action then node:action(action) end | 
				
			|||
 | 
				
			|||
    return node | 
				
			|||
end | 
				
			|||
 | 
				
			|||
@ -1,23 +0,0 @@ | 
				
			|||
 | 
				
			|||
local garbage_collector_cycle_timing_history = {} | 
				
			|||
local garbage_collector_average_cycle_time = 0 | 
				
			|||
function run_garbage_collector_cycle() | 
				
			|||
    local time, result = fprofile(collectgarbage, "collect") | 
				
			|||
 | 
				
			|||
    table.insert(garbage_collector_cycle_timing_history, time) | 
				
			|||
    -- re-calc average gc timing | 
				
			|||
    local total = 0 | 
				
			|||
    for _,v in pairs(garbage_collector_cycle_timing_history) do | 
				
			|||
        total = total + v | 
				
			|||
    end | 
				
			|||
    garbage_collector_average_cycle_time = total / #garbage_collector_cycle_timing_history | 
				
			|||
end | 
				
			|||
 | 
				
			|||
function check_if_can_collect_garbage_for_free(frame_start_time, min_fps) | 
				
			|||
    -- often this will be polled at the end of a frame to see if we're running fast or slow, | 
				
			|||
    -- and if we have some time to kill before the start of the next frame, we could maybe run gc. | 
				
			|||
    if (am.current_time() - frame_start_time) < (1 / (min_fps or 60) + garbage_collector_average_cycle_time) then | 
				
			|||
        run_garbage_collector_cycle() | 
				
			|||
    end | 
				
			|||
end | 
				
			|||
 | 
				
			|||
						Write
						Preview
					
					
					Loading…
					
					Cancel
						Save
					
		Reference in new issue