
Ââåäåíèå
Òû æ ïðîãðàììèñò!!Èëè êòî?!
Òàê äàâàé, ñîçäàé óæå ñàì ñåáå ñâîè èíñòðóìåíòû. Ýòî ëåã÷å, ÷åì òû äóìàåøü.
 ýòîé ñòàòüå ÿ òåáå ïîêàæó ïàðó ñâîèõ èíñòðóìåíòîâ. Íî åñëè òåáå â ïðîöåññå ñîçäàíèÿ ìîäà ïîíàäîáèòñÿ ñïåöèôè÷åñêèé èíñòðóìåíò, òî íå ñòåñíÿéñÿ è äåëàé ñàì.
ÎãëàâëåíèåÓðîê 1. Ñêïðèòû Lua äëÿ TTS
Óðîê 2. Èíñòðóìåíòû
iHelper - ïàëèì êîîðäèíàòû è ñâîéñòâà
Ýòî ìàëåíüêèé êóáèê äëÿ èçìåðåíèÿ òî÷íûõ êîîðäèíàò. Ñîçäàé îáû÷íûé êóá. Óìåíüøè åãî äî ìèíèìóìà - òàê èçìåðåíèÿ áóäóò òî÷íåå. Òåïåðü äîáàâü ê íåìó òàêîé ñêðèïò:local my_counter = 100 --Ñ÷¸ò÷èê ôðåéìîâ. local obj --Òåêóùèé îáúåêò, êîòîðîãî ìû êîñíóëèñü. local ON_TABLE_Y -- "Óðîâåíü" ïîâåðõíîñòè ñòîëà. --Óäîáíàÿ ôóíêöèÿ äëÿ îêðóãëåíèÿ. local function r(x) --round return math.floor(x * 10000 + 0.5)/10000 end local TABLES_TYPES = { --Âñå âèäû ñòîëîâ â èãðå Table_Custom_Square=1, Table_Custom=1, Table_Circular=1, Table_Square=1, Table_Octagon=1, Table_Poker=1, Table_RPG=1, Table_Glass=1, Table_Hexagon=1 } --Ïîêàçûâàåò èíòåðåñíóþ èíôîðìàöèþ î êîîðäèíàòàõ. local function ShowCoords() local self_coords = self:getPosition() local level = self_coords.y - 0.125 --Íèæíÿÿ ãðàíü êóáèêà (â òåîðèè). print("self ",r(self_coords.x),', ',r(self_coords.y),', ',r(self_coords.z)) print("LEVEL = ",level) if TABLES_TYPES[obj.name] then --Êàñàíèå ñòîëà. ON_TABLE_Y = level --Çàïîìèíàåì óðîâåíü (âûñîòó) ñòîëà. return --Ïðî ñòîë íàì íå èíòåðåñíî çíàòü, âûõîäèì. end if ON_TABLE_Y then --Åñëè çíàåì óðîâåíü ñòîëà, òî âû÷èñëÿåì âûñîòó íàä ñòîëîì. print("over table = ",level - ON_TABLE_Y) end local obj_coords = obj:getPosition() --Êîîðäèíàòû îáúåêòà. print("obj = ",r(obj_coords.x),', ',r(obj_coords.y),', ',r(obj_coords.z)) --Âûñîòà = (ðàññòîÿíèå îò íèæíåé ãðàíè êóáèêà äî ñåðåäû îáúåêòà) õ2. print("height = ", (level - obj_coords.y) * 2 ) local rot = obj:getRotation() print("rot = ",r(rot.x), ', ', r(rot.y), ', ', r(rot.z)) local scale = obj:getScale() print("scale = ",r(scale.x), ', ', r(scale.y), ', ', r(scale.z)) end --Ñîáûòèå ïðè ñîïðèêîñíîâåíèè ñ îáúåêòîì. function onCollisionEnter(info) --info - ýòî ñòðóêòóðà ñ èíôîðìàöèåé (ñì. äîêè). obj = info.collision_object --Çàïîìèíàåì îáúåêò äëÿ ôóíêöèè ShowCoords(). print(obj.name) --Âûâîäèì èìÿ (òèï) îáúåêòà â ìîìåíò ñòîëêíîâåíèÿ. my_counter = 0 --Íàâ÷èíàåì îòñ÷¸ò âðåìåíè. end function update() my_counter = my_counter + 1 if my_counter == 50 then --Æä¸ì, êîãäà âñ¸ óòðÿñ¸òñÿ. ShowCoords() end end
×òî îí ìîæåò? Ñàì ïîñìîòðè. Îí âûâîäèò ñâîè êîîðäèíàòû, ýòî ñàìîå áàíàëüíîå. À òàêæå îí âûâîäèò êîîðäèíàòû îáúåêòà ïîä ñîáîé.  ñêðèïò ìîæíî äîáàâèòü ïðî÷èå ñâîéñòâà ïî íåîáõîäèìîñòè.
Ïîèãðàé ñ êóáèêîì. Ïîïðîáóé ïîíÿòü, â êàêóþ ñòîðîíó íàïðàâëåíû îñü X, îñü Y è îñü Z. Åñëè ëåíü, òî ñðàçó íàïèøó îòâåò. Îñè X è Z ëåæàò â ãîðèçîíòàëüíîé ïëîñêîñòè, à îñü Y (âûñîòà) íàïðàâëåíà ââåðõ. Òî åñòü ÷åì áîëüøå Y, òåì öåíòð ïðåäìåòà âûøå.
ÈíôàÎïûòíûì ïóò¸ì âûÿñíÿåòñÿ, ÷òî ðàçìåðû êóáà èçíà÷àëüíî 1õ1õ1, à ìàêñèìàëüíàÿ ñòåïåíü óìåíüøåíèÿ - â 4 ðàçà. Òàêèì îáðàçîì, äëèíà ðåáðà ïîëó÷èâøåãîñÿ iHelper ðàâíà 0.25, à ýòî â ñâîþ î÷åðåäü çíà÷èò, ÷òî ðàññòîÿíèå îò öåíòðà äî ëþáîé ãðàíè ðàâíî 0.125.
Ìû óæå çíàåì âûñîòó íèæíåé ãðàíè! Îíà âûâîäèòñÿ â ñòðîêå "LEVEL =", òî åñòü ýòî êàê áû óðîâåíü òîãî, íà ÷åì ëåæèò êóáèê.
Íå ôàêò, ÷òî ìåæäó ïðåäìåòàìè íåò "âîçäóøíîãî" çàçîðà, íî òû ìîæåøü ýòî ëåãêî ïðîâåðèòü. Óçíàé âûñîòó äðóãîãî êóáèêà. Åñëè ýòî 1, òî çàçîðà íåò.
Äàëåå, ýòî ïîçâîëÿåò íàì âû÷èñëèòü êîîðäèíàòó ïîâåðõíîñòè ñòîëà, êîãäà êóáèê ëåæèò íà ñòîëå. Íàäî ëè íàïîìèíàòü, íàñêîëüêî ýòî ïîëåçíî?! Íàïðèìåð, äëÿ êàæäîãî ïðåäìåòà òåïåðü ìîæíî ïîíÿòü, ëåæèò îí èëè âèñèò.
Y ïîâåðõíîñòè ñòîëà = 0.96
Åñëè ïîëîæèòü iHelper íà äðóãîé ïðåäìåò, òî ó íàñ áóäåò äîñòóï ê åãî êîîðäèíàòàì. Òàê ÷òî ìû ìîæåì âû÷èñëèòü åãî ïðåäïîëàãàåìóþ âûñîòó. Èìåííî ýòî êóá è äåëàåò. Õîòÿ òû ìîæåøü "ñ÷èòåðèòü" è êîñíóòüñÿ áîêîì, è ïîëó÷èòñÿ ëîæíàÿ âûñîòà, íî ýòî òâîè ïðîáëåìû - èíñòðóìåíò-òî òâîé.
Ðåø¸ííûå ïðîáëåìû ïðîöåññå ñîçäàíèÿ äàæå òàêîãî ïðîñòîãî ñêðèïòà ÿ ñòîëêíóëñÿ ñ ïàðî÷êîé ïðîáëåì, îò êîòîðûõ íèêòî íå çàñòðàõîâàí. Òû òîæå íå ðàç ñòîëêí¸øüñÿ ñ ÷åì-òî ïîäîáíûì.
Ïðè ïàäåíèè íà ñòîë èëè äðóãîé ïðåäìåò, êóáèê ìîæåò ñëåãêà ïîäïðûãíóòü. Òàêèì îáðàçîì, ñòîëêíîâåíèé ìîæåò áûòü íåñêîëüêî çà êîðîòêîå âðåìÿ. Ïëþñ, êîîðäèíàòû â ìîìåíò êàñàíèÿ ìîãóò áûòü (îøèáî÷íî) ïîëó÷åíû, êîãäà êóáèê åù¸ â ïîë¸òå (ò.å. âîò-âîò êîñí¸òñÿ îáúåêòà). Ðåøåíèå ïðîñòîå - íàäî ïîäîæäàòü íåìíîãî, ïîêà êóáèê íå óëÿæåòñÿ. Êàæäîå êàñàíèå ñ äðóãèì îáúåêòîì ñáðàñûâàåò òàéìåð îòñ÷¸òà, òàê ÷òî íåñêîëüêî êîðîòêèõ ñòîëêíîâåíèé íå ïðèâåäóò ê âûâîäó êó÷è èíôîðìàöèè.
Äàëåå, ñòîë îêàçàëñÿ î÷åíü ïîïóëÿðíîé ïîâåðõíîñòüþ. Òàê ÷òî ïðèøëîñü èñêëþ÷èòü åãî èç èíòåðåñíûõ îáúåêòîâ, ÷òîáû íå çàõëàìëÿòü ëîã. Êó÷à íåíóæíîé èíôîðìàöèè íàì ñîâñåì íè ê ÷åìó.
Òî÷íîñòüÎíà îñòàâëÿåò æåëàòü ëó÷øåãî. Êàê âèäèøü, êîîðäèíàòà ìîæåò ïðåâðàòèòüñÿ â 1.0000000789 èëè â 0.9999999789. Ïîýòîìó òî÷íîå ñðàâíåíèå êîîðäèíàò îïåðàòîðîì "==" - ïëîõàÿ èäåÿ. Òî æå êàñàåòñÿ îñòàëüíûõ äàííûõ - ïîâîðîò, óñêîðåíèå, óãëîâîå óñêîðåíèå. Ïðèõîäèòñÿ èñïîëüçîâàòü îïåðàòîðû "áîëüøå" è "ìåíüøå" (">", "<", ">=", "<=").
Äðóãîé âàðèàíò - îêðóãëåíèå ÷èñåë. Ïðàêòèêà ïîêàçûâàåò, ÷òî ñòðàííîñòè íà÷èíàþòñÿ íà øåñòîì çíàêå ïîñëå çàïÿòîé. Äëÿ íà䏿íîñòè ëó÷øå ðàññ÷èòûâàòü ëèøü íà 4 çíàêà ïîñëå çàïÿòîé (â ìîèõ ýêñïåðèìåíòàõ áûëè ñëó÷àè, êîãäà íà 5-ì çíàêå òîæå òâîðèëèñü ÷óäåñà).
Ôóíêöèè îêðóãëåíèÿ òèïà math.round â Ëóà - ÍÅÒ! Óâû è àõ. Íî åñòü ôóíêöèÿ îòáðàñûâàíèÿ äðîáíîé ÷àñòè - math.floor(). À îêðóãëåíèå ëåãêî äåëàåòñÿ íà å¸ îñíîâå:
local function round(x) return math.floor(x + 0.5) end Âîò òàê ïðîñòî. Òàê ÷òî äàæå 0.99999789 ïðåâðàòèòñÿ â 1.49999789, à ïîñëå îòáðàñûâàíèÿ äðîáíîé ÷àñòè ñòàíåò 1.
ÎïòèìèçàöèÿÒàêæå íà çàìåòêó. Äåëåíèå ñóùåñòâåííî äîðîæå óìíîæåíèÿ. Òàê ÷òî âìåñòî x / 10000 ëó÷øå çàïèñàòü x * 0.0001. Ïî ñóòè ðàçíèöû íèêàêîé, çàòî áûñòðåå. Äëÿ íàøåãî iHelper ýòî íå êðèòè÷íî, íî â âûñîêî íàãðóæåííîì ñêðèïòå ëó÷øå îáðàòèòü íà ýòî âíèìàíèå.
iRect - èçìåðÿåì ïëîùàäü
Êîíå÷íî, ìîæíî èñïîëüçîâàòü äëÿ ýòîãî iHelper - è ïåðåïèñûâàòü êîîðäèíàòû êàæäîé òî÷êè âðó÷íóþ èç ëîãà. À ÷òî åñëè çîí ìíîãî? Çàìó÷àåøüñÿ æå! Òàê ñäåëàåì æå äëÿ ýòîé ñïåöèôè÷åñêîé öåëè ñïåöèôè÷åñêèé èíñòðóìåíò è íàçîâ¸ì åãî "iRect"!
Ñîçäàé êóá, ïîêðàñü åãî â ñèíèé (÷òîáû îòëè÷àòü îò iHelper) è ñäåëàé ìàêñèìàëüíî ìàëåíüêèì. Çàòåì äîáàâü ê íåìó ñêðèïò:
--Èíñòðóìåíò äëÿ èçìåðåíèÿ ïðÿìîóãîëüíèêîâ. --Ïåðâûé ðàç çàïîìèíàåò âåðøèíó, âòîðîé ðàç çàïîìèíàåò âòîðóþ âåðøèíó. local params = { --Äëÿ âçàèìîäåéñòâèÿ ñ òåòðàäüþ. index = 0, title = "iRect", body = "", } local point --Ýòî ñîõðàí¸ííàÿ ïåðâàÿ òî÷êà (èëè nil, åñëè ïåðâîé åù¸ íåò). --Íîâîå êàñàíèå. Ïåðâîå èëè âòîðîå - îïðåäåëÿåòñÿ ÷åðåäîâàíèåì. local function UpdateCollision() local coords = self:getPosition() for j=1,3 do --Îêðóãëÿåì êîîðäèíàòû ñðàçó. coords[j] = math.floor(coords[j] * 1000000 + 0.5)/1000000 end --Ïîëó÷àåì â ïåðåìåííóþ txt òåêóùåå ñîäåðæèìîå òåòðàäè. local p = getNotebookTabs(); local txt = p[1].body; if point then --Åñëè ïåðâàÿ òî÷êà óæå åñòü, òî ýòà âòîðàÿ. print("SECOND point") --Óïîðÿäî÷èâàåì êîîðäèíàòû. Äîëæíî áûòü: x1 < x2 è y1 < y2. if point[1] > coords[1] then local tmp = point[1] point[1] = coords[1] coords[1] = tmp end if point[3] > coords[3] then local tmp = point[3] point[3] = coords[3] coords[3] = tmp end --Äîïèñûâàåì ëóà-ñòðóêòóðó â òåòðàäü. txt = txt .. " { " .. point[1] .. ", " ..point[3] .. ", " .. coords[1] .. ", " ..coords[3] .. "},n" --Âû÷èñëÿåì êîîðäèíàòû öåíòðà. --local cx = (point[1] + coords[1]) / 2 --local cz = (point[2] + coords[2]) / 2 --txt = txt .. " { " --??? Òèïà çàãîòîâêà. point = nil --Çàáûâàåì âñ¸. else --Åñëè ïåðâîé òî÷êè íåò, òî ýòà áóäåò ïåðâîé. print("FIRST POINT") point = coords --Ïðîñòî çàïîìèíàåì êîîðäèíàòû. Âñå ðàñ÷¸òû íà âòîðîé òî÷êå. end --Èçìåíÿåì òåòðàäü. params.body = txt editNotebookTab(params) end local my_counter = 51 function onCollisionEnter(info) if my_counter < 200 then --Åñëè ïðîøëî ñëèøêîì ìàëî âðåìåíè, òî èãíîðèì. return -- ÷àñòíîñòè, ïðè çàãðóçêå ñêðèïòà èãíîðèì ïåðâîå êàñàíèå. end --local obj = info.collision_object --Îáúåêò íàì íå èíòåðåñåí. Äîñòàòî÷íî self --print(obj.name) my_counter = 0 end function update() my_counter = my_counter + 1 if my_counter == 50 then UpdateCollision() end end
Íå÷òî ïîäîáíîå òàêæå ìîæåøü äîïèñàòü è äëÿ iHelper, åñëè òåáå â ñêðèïòå íóæíû êîîðäèíàòû îòäåëüíûõ òî÷åê. À òàêæå òû ìîæåøü èçìåðÿòü áîëåå ñëîæíûå çîíû.
Êîðî÷å, â áîëüøèíñòâå ñëó÷àåâ ýòîãî äîñòàòî÷íî. Íî åñëè íåò, òî âñ¸ â òâîèõ ðóêàõ! Åñòü ïðîáëåìà - ðåøàé. ×åãî-òî íå õâàòàåò - ñäåëàé. Íå óäîáíî - äîáàâü óäîáñòâ. È òàê äàëåå.
Òû æ ïðîãðàììèñò, â êîíöå êîíöîâ!