mdecourse / vecp2018

車輛工程系大一計算機程式 (課程已經結束)
GNU Affero General Public License v3.0
0 stars 0 forks source link

vecp-week4 #6

Closed mdecourse closed 6 years ago

mdecourse commented 6 years ago

window.localStorage 的應用

http://mde.tw/vecp2018/lua/SchoolProject 之所以能讓使用者能夠直接在瀏覽器中執行簡單的 Lua 程式範例, 是因為利用 Javascript 重寫 Lua 解譯器, , 因此具有 Javascript 程式語言的特性, 其中包括 https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage

所謂的 localStorage, 是能讓使用者透過 Javascript 程式, 將資料存在近端的瀏覽器中, 也能取出利用.

localStorage 典型的應用之一, 就是當使用者在 http://mde.tw/vecp2018/lua/SchoolProject 的編輯器中輸入 Lua 程式碼後, 按下執行時, editor.lua 就會將編輯器中的 Lua 程式碼放入與 "lua_src_id" 字串對應的 localStorage 儲存空間中, 且在載入頁面時就啟動執行的 ace/FileSaver.min.js 與 ace/filereader.js 及設定將程式碼存在近端的 Javascript, 就可儲存所執行的 Lua 程式內容.

index.html 內容如下:

<!DOCTYPE html>
<html>
    <head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<link rel="stylesheet" href="style.css">
<title>How to program in Lua</title>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<!-- 導入 FileSaver 與 filereader -->
<script type="text/javascript" src="ace/FileSaver.min.js"></script>

<script type="text/javascript" src="ace/filereader.js"></script>
<script type="text/javascript">
function doSave(storage_id, filename){
    var blob = new Blob([localStorage[storage_id]], {type: "text/plain;charset=utf-8"});
    filename = document.getElementById(filename).value
    saveAs(blob, filename+".lua");
}
</script>
    </head>
    <body>
<header>
        <h1 class="center">Hello Lua!</h1>

        <div class="repl-container">
            <div class="row editor-container">
                <div class="col-sm editor">print("Lua is fun!")</div>
                <div class="col-sm output"></div>
            </div>
            <div class="row">
                <button type="button" class="btn btn-primary btn-execute">Execute</button>
            </div>
    <form>
    <label>Filename: <input type="text" id="lua_filename" placeholder="input file name"/>.lua</label>
    <input type="submit" value="Save" onclick="doSave('lua_src_id', 'lua_filename');"/>
</form>
            <br />
        </div>
<script src="ace/ace.js"></script>
<script src="ace/mode-lua.js"></script>
<script src="fengari-web.js"></script>
<script src="editor.lua" type="application/lua" async></script>
<script src="editor.js"></script>
<br /><br />
<canvas id="canvas" width="600" height="600"></canvas>
    </body>
</html>

editor.lua 內容如下:

local js = require "js"
local __G = _G
local load = load
local pack, unpack = table.pack, table.unpack
local tostring = tostring
local traceback = debug.traceback
local insert = table.insert
local document = js.global.document
local xpcall = xpcall
storage = js.global.localStorage

M = {} --All of the user globals

local newenv = setmetatable({}, {
        __index = function(t, k)
            local v = M[k]
            if v == nil then return __G[k] end
            return v;
        end,
        __newindex = M
    })

function js.global.runLua(window, code, outputElm) 
    --Reset user global table to a clean state
    --M = {}
    M["_G"] = M
    --Redirect print and error to output box
    M.print = function(text)
        local msgElm = document:createTextNode(text)
        msgElm.className = "console-msg"
        outputElm:appendChild(msgElm)
        outputElm:appendChild(document:createElement("br"))
    end

    M.error = function(text)
        local msgElm = document:createTextNode(text)
        msgElm.className = "console-error"
        outputElm:appendChild(msgElm)
        outputElm:appendChild(document:createElement("br"))
    end

    --Clean output window
    while (outputElm:hasChildNodes()) do
        outputElm:removeChild(outputElm.firstChild);
    end 

    --Finally load and run the code
    storage:setItem("lua_src_id", tostring(code))
    local fn, err = load(tostring(code), "sandbox", "bt", newenv)

    if fn then
        local results = pack(xpcall(fn, traceback))
        if results[1] then
            if results.n > 1 then
                M.print(unpack(results, 2, results.n))
            end
        else
            M.print(results[2])
        end
    else
       M.error(err)
    end
end

瀏覽器端設定

在 Firefox 中, 以 Preferences - General - Downloads 選擇"Always ask me where to save files"

在 Chrome 中, 以 Settings - Advanced - Downloads 選擇 Ask where to save each file before downloading

a40628404 commented 6 years ago

local window = require "js".global a = math.random(1,100) i = tonumber(window:prompt()) for j =1,5 do if (i>a)then i = tonumber(window:prompt("太大啦")) elseif(i<a)then i = tonumber(window:prompt("太小啦")) end if(i==a)then print("答對了 答案就是"..a) return end end print("你是魯蛇")

40328410 commented 6 years ago

js = require "js" window = js.global abc = math.random(1,100) min=1 max=100 cmp="請從" repeat n = window:prompt(""..cmp..""..min.."~"..max.."猜一數字:") if tonumber(n)>abc then max=tonumber(n) print("您猜的太大了,請在"..min.."~"..max.."再猜:") cmp="您的太大了,請再由" elseif tonumber(n)<abc then min=tonumber(n) print("您猜的太小了,請在"..min.."~"..max.."再猜:") cmp="您猜的太小了,請再由" end until tonumber(n)==abc print("答案是"..abc.."恭喜您猜對了!") print("遊戲結束")

40628402 commented 6 years ago

-- 導入 "js" 模組 local js = require "js" -- global 就是 javascript 的 window local global = js.global local document = global.document -- html 檔案中 canvas id 設為 "canvas" local canvas = document:getElementById("canvas") -- 將 ctx 設為 canvas 2d 繪圖畫布變數 local ctx = canvas:getContext("2d")

-- 屬性呼叫使用 . 而方法呼叫使用 : -- 設定填圖顏色 ctx.fillStyle = "rgb(200,0,0)" -- 設定畫筆顏色 ctx.strokeStyle = "rgb(0,0,200)"

-- 乘上 deg 可轉為徑度單位 deg = math.pi / 180

-- 建立多邊形定點位置畫線函式 function star(radius,yc,xc , n) --radius = 100 --xc = 200 --yc = 200 xi = xc + radiusmath.cos((360/n)deg+90deg) yi = yc - radiusmath.sin((360/n)deg+90deg) ctx:beginPath() ctx:moveTo(xi,yi) for i = 2, n+1 do x = xc + radiusmath.cos((360/n)degi+90deg) y = yc - radiusmath.sin((360/n)degi+90deg) ctx:lineTo(x,y) end end

-- 以下利用多邊形畫線函式呼叫執行畫框線或填入顏色 -- 畫五邊形框線 star(100, 200, 200, 5) ctx:closePath() ctx:stroke()

-- 填三角形色塊 star(50, 350, 200, 3) ctx:closePath() ctx:fill()

-- 改變畫線顏色後, 畫七邊形框線 ctx.strokeStyle = "rgb(0,200,20)" star(50, 450, 200, 7) ctx:closePath() ctx:stroke()

mdecourse commented 6 years ago

week 5 繪圖

-- 導入 "js" 模組
local js = require "js"
-- global 就是 javascript 的 window
local global = js.global
local document = global.document
-- html 檔案中 canvas id 設為 "canvas"
local canvas = document:getElementById("canvas")
-- 將 ctx 設為 canvas 2d 繪圖畫布變數
local ctx = canvas:getContext("2d")

-- 屬性呼叫使用 . 而方法呼叫使用 :
-- 設定填圖顏色
ctx.fillStyle = "rgb(200,0,0)"
-- 設定畫筆顏色
ctx.strokeStyle = "rgb(0,0,200)"

-- 乘上 deg 可轉為徑度單位
deg = math.pi / 180

-- 建立多邊形定點位置畫線函式
function star(radius, xc, yc, n, fors)
    radius = radius or 50
    xc = xc or 100
    yc = yc or 100
    n = n or 5
    fors = fors or "fill"
    xi = xc + radius*math.cos((360/n)*deg+90*deg)
    yi = yc - radius*math.sin((360/n)*deg+90*deg)
    ctx:beginPath()
    ctx:moveTo(xi,yi)
    for i = 2, n+1 do
        x = xc + radius*math.cos((360/n)*deg*i+90*deg)
        y = yc - radius*math.sin((360/n)*deg*i+90*deg)
        ctx:lineTo(x,y)
    end
    ctx:closePath()
    if fors == "fill" then
        ctx:fill()
    else
        ctx:stroke()
    end
end

-- 以下利用多邊形畫線函式呼叫執行畫框線或填入顏色
-- 畫五邊形框線
--[[
star(100, 200, 200, 5, "stroke")
star(100, 200, 200, 3, "fill")
]]
-- star()
star(25, 300, 50, 3, "fill")
mdecourse commented 6 years ago

Lua 程式雖然不要求縮排, 但是要貼上 Issue, 若可以先在近端編輯器全部內縮四個 spaces, 然後再放上來, 應該會比較容易閱讀.

mdecourse commented 6 years ago

繪圖函式修改

將填色與畫筆顏色設為函式參數

-- 導入 "js" 模組
local js = require "js"
-- global 就是 javascript 的 window
local global = js.global
local document = global.document
-- html 檔案中 canvas id 設為 "canvas"
local canvas = document:getElementById("canvas")
-- 將 ctx 設為 canvas 2d 繪圖畫布變數
local ctx = canvas:getContext("2d")

-- 乘上 deg 可轉為徑度單位
deg = math.pi / 180

-- 建立多邊形定點位置畫線函式
function star(radius, xc, yc, n, fs, ss, fors)
    radius = radius or 50
    xc = xc or 100
    yc = yc or 100
    n = n or 5
    -- 屬性呼叫使用 . 而方法呼叫使用 :
    -- 填色屬性
    fs = fs or "rgb(200,0,0)"
    -- 畫筆顏色屬性
    ss = ss or "rgb(0,0,200)"
    -- 內定為填色
    fors = fors or "fill"
    ctx.fillStyle = fs
    ctx.strokeStyle = ss
    xi = xc + radius*math.cos((360/n)*deg+90*deg)
    yi = yc - radius*math.sin((360/n)*deg+90*deg)
    ctx:beginPath()
    ctx:moveTo(xi,yi)
    for i = 2, n+1 do
        x = xc + radius*math.cos((360/n)*deg*i+90*deg)
        y = yc - radius*math.sin((360/n)*deg*i+90*deg)
        ctx:lineTo(x,y)
    end
    ctx:closePath()
    if fors == "fill" then
        ctx:fill()
    else
        ctx:stroke()
    end
end

star(200, 300, 300, 12, "rgb(100,100,0)", "rgb(100,100,0)", "stroke")

求兩直線的交點

-- https://rosettacode.org/wiki/Find_the_intersection_of_two_lines#Lua
-- http://mathworld.wolfram.com/Line-LineIntersection.html
function intersection (s1, e1, s2, e2)
  local d = (s1.x - e1.x) * (s2.y - e2.y) - (s1.y - e1.y) * (s2.x - e2.x)
  local a = s1.x * e1.y - s1.y * e1.x
  local b = s2.x * e2.y - s2.y * e2.x
  local x = (a * (s2.x - e2.x) - (s1.x - e1.x) * b) / d
  local y = (a * (s2.y - e2.y) - (s1.y - e1.y) * b) / d
  return x, y
end

local line1start, line1end = {x = 4, y = 0}, {x = 6, y = 10}
local line2start, line2end = {x = 0, y = 3}, {x = 10, y = 7}
print(intersection(line1start, line1end, line2start, line2end))
40628428 commented 6 years ago

-- 導入 "js" 模組 local js = require "js" -- global 就是 javascript 的 window local global = js.global local document = global.document -- html 檔案中 canvas id 設為 "canvas" local canvas = document:getElementById("canvas") -- 將 ctx 設為 canvas 2d 繪圖畫布變數 local ctx = canvas:getContext("2d")

-- 屬性呼叫使用 . 而方法呼叫使用 : -- 設定填圖顏色 ctx.fillStyle = "rgb(0,0,100)" -- 設定畫筆顏色 ctx.strokeStyle = "rgb(0,0,200)"

-- 乘上 deg 可轉為徑度單位 deg = math.pi / 180

-- 建立多邊形定點位置畫線函式 function star(radius, xc, yc, n) --radius = 100 --xc = 200 --yc = 200 xi = xc + radiusmath.cos((360/n)deg+180deg) yi = yc - radiusmath.sin((360/n)deg+180deg) ctx:beginPath() ctx:moveTo(xi,yi) for i = 2, n+1 do x = xc + radiusmath.cos((360/n)degi+180deg) y = yc - radiusmath.sin((360/n)degi+180deg) ctx:lineTo(x,y) end end

-- 以下利用多邊形畫線函式呼叫執行畫框線或填入顏色 -- 畫外面六邊形框線 ctx.fillStyle= '#191970' star(135, 200, 200, 6) ctx:closePath() ctx:fill() --劃裡面白色六邊型 ctx.fillStyle = '#fff' star(90, 200, 200, 6) ctx:closePath() ctx:fill() -- 以下採用 canvas 原始座標繪圖 flag_w = 600 flag_h = 400 circle_x = flag_w/4 circle_y = flag_h/4

--上方空白 ctx.fillStyle= '#fff' ctx:fillRect(0, 0, flag_w/2, flag_h/3)

--中間圓 ctx.fillStyle= '#191970' star(40, 200, 200, 40) ctx:closePath() ctx:fill()

--中間白色 ctx.fillStyle= '#fff' star(15, 180, 180, 4) ctx:closePath() ctx:fill() --中間白色 ctx.fillStyle= '#fff' star(15, 190, 190, 4) ctx:closePath() ctx:fill() --中間白色 ctx.fillStyle= '#fff' star(15, 200, 200, 4) ctx:closePath() ctx:fill() --中間白色 ctx.fillStyle= '#fff' star(15, 210, 210, 4) ctx:closePath() ctx:fill() --中間白色 ctx.fillStyle= '#fff' star(15, 220, 220, 4) ctx:closePath() ctx:fill()

--中間白色 ctx.fillStyle= '#fff' star(15, 170, 170, 4) ctx:closePath() ctx:fill()

--中間白色 ctx.fillStyle= '#fff' star(15, 230, 230, 4) ctx:closePath() ctx:fill()

40628407 commented 6 years ago

-- 導入 "js" 模組 local js = require "js" -- global 就是 javascript 的 window local global = js.global local document = global.document -- html 檔案中 canvas id 設為 "canvas" local canvas = document:getElementById("canvas") -- 將 ctx 設為 canvas 2d 繪圖畫布變數 local ctx = canvas:getContext("2d")

-- 屬性呼叫使用 . 而方法呼叫使用 : -- 設定填圖顏色 ctx.fillStyle = "rgb(0,0,200)" -- 設定畫筆顏色 ctx.strokeStyle = "rgb(0,0,200)"

-- 乘上 deg 可轉為徑度單位 deg = math.pi / 180

-- 建立多邊形定點位置畫線函式 function star(radius, xc, yc, n) --radius = 100 --xc = 200 --yc = 200 xi = xc + radiusmath.sin((360/n)deg+90deg) yi = yc - radiusmath.cos((360/n)deg+90deg) ctx:beginPath() ctx:moveTo(xi,yi) for i = 2, n+1 do x = xc + radiusmath.sin((360/n)degi+90deg) y = yc - radiusmath.cos((360/n)degi+90deg) ctx:lineTo(x,y) end end

-- 以下利用多邊形畫線函式呼叫執行畫框線或填入顏色 -- 畫五邊形框線 star(250, 300, 300, 6) ctx:closePath() ctx:stroke() ctx:fill()

star(100, 300, 300, 1000) ctx:closePath() ctx:stroke() ctx:fill()

ctx.fillStyle = "white" star(160, 300, 300, 6) ctx:closePath() ctx:stroke() ctx:fill()

ctx.fillStyle = "rgb(0,0,200)" star(80, 300, 300, 1000) ctx:closePath() ctx:stroke() ctx:fill()

ctx.fillStyle = "white" star(27, 300, 300, 4) ctx:closePath() ctx:stroke() ctx:fill()

ctx.fillStyle = "white" star(27, 278, 278, 4) ctx:closePath() ctx:fill()

ctx.fillStyle = "white" star(27, 255, 255, 4) ctx:fill()

ctx.fillStyle = "white" star(27, 323, 323, 4) ctx:fill()

ctx.fillStyle = "white" star(27, 347, 347, 4) ctx:fill()

-- 建立多邊形定點位置畫線函式 function star(radius, xc, yc, n) --radius = 100 --xc = 200 --yc = 200 xi = xc + radiusmath.cos((360/n)deg+90deg) yi = yc - radiusmath.sin((360/n)deg+90deg) ctx:beginPath() ctx:moveTo(xi,yi) for i = 2, n+1 do x = xc + radiusmath.cos((360/n)degi+90deg) y = yc - radiusmath.sin((360/n)degi+90deg) ctx:lineTo(x,y) end end ctx.fillStyle = "white" star(250, 300, 45, 3) ctx:closePath() ctx:fill()

-- 填三角形色塊 --star(50, 350, 200, 3) --ctx:closePath() --ctx:fill()

-- 改變畫線顏色後, 畫七邊形框線 --ctx.strokeStyle = "rgb(0,200,20)" --star(50, 450, 200, 7) --ctx:closePath() --ctx:stroke()

bobXDC commented 6 years ago

-- 導入 "js" 模組 local js = require "js" -- global 就是 javascript 的 window local global = js.global local document = global.document -- html 檔案中 canvas id 設為 "canvas" local canvas = document:getElementById("canvas") -- 將 ctx 設為 canvas 2d 繪圖畫布變數 local ctx = canvas:getContext("2d")

-- 屬性呼叫使用 . 而方法呼叫使用 : -- 設定填圖顏色 ctx.fillStyle = "rgb(0,0,200)" -- 設定畫筆顏色 ctx.strokeStyle = "rgb(0,0,200)"

-- 乘上 deg 可轉為徑度單位 deg = math.pi / 180

-- 建立多邊形定點位置畫線函式 function star(radius, xc, yc, n) --radius = 100 --xc = 200 --yc = 200 xi = xc + radiusmath.sin((360/n)deg+90deg) yi = yc - radiusmath.cos((360/n)deg+90deg) ctx:beginPath() ctx:moveTo(xi,yi) for i = 2, n+1 do x = xc + radiusmath.sin((360/n)degi+90deg) y = yc - radiusmath.cos((360/n)degi+90deg) ctx:lineTo(x,y) end end

-- 以下利用多邊形畫線函式呼叫執行畫框線或填入顏色 -- 畫五邊形框線 star(250, 300, 300, 6) ctx:closePath() ctx:stroke() ctx:fill()

star(100, 300, 300, 1000) ctx:closePath() ctx:stroke() ctx:fill()

ctx.fillStyle = "white" star(160, 300, 300, 6) ctx:closePath() ctx:stroke() ctx:fill()

ctx.fillStyle = "rgb(0,0,200)" star(80, 300, 300, 1000) ctx:closePath() ctx:stroke() ctx:fill()

ctx.fillStyle = "white" star(27, 300, 300, 4) ctx:closePath() ctx:stroke() ctx:fill()

ctx.fillStyle = "white" star(27, 278, 278, 4) ctx:closePath() ctx:fill()

ctx.fillStyle = "white" star(27, 255, 255, 4) ctx:fill()

ctx.fillStyle = "white" star(27, 323, 323, 4) ctx:fill()

ctx.fillStyle = "white" star(27, 347, 347, 4) ctx:fill()

-- 建立多邊形定點位置畫線函式 function star(radius, xc, yc, n) --radius = 100 --xc = 200 --yc = 200 xi = xc + radiusmath.cos((360/n)deg+90deg) yi = yc - radiusmath.sin((360/n)deg+90deg) ctx:beginPath() ctx:moveTo(xi,yi) for i = 2, n+1 do x = xc + radiusmath.cos((360/n)degi+90deg) y = yc - radiusmath.sin((360/n)degi+90deg) ctx:lineTo(x,y) end end ctx.fillStyle = "white" star(250, 300, 45, 3) ctx:closePath() ctx:fill()

-- 填三角形色塊 --star(50, 350, 200, 3) --ctx:closePath() --ctx:fill()

-- 改變畫線顏色後, 畫七邊形框線 --ctx.strokeStyle = "rgb(0,200,20)" --star(50, 450, 200, 7) --ctx:closePath() --ctx:stroke()