1
0
Fork 0
mirror of https://github.com/Reuh/ubiquitousse.git synced 2025-10-27 17:19:31 +00:00

Add LDtk, update docs

This commit is contained in:
Étienne Fildadut 2021-12-24 23:50:03 +01:00
parent c793617ded
commit 582f592a79
13 changed files with 2733 additions and 39 deletions

View file

@ -1,8 +1,8 @@
# ubiquitousse # ubiquitousse
Set of various libraries I use for game development, mainly with LÖVE. Nothing that hasn't been done before, but these are tailored to what I need. Set of various libraries I use for game development, mainly with LÖVE. Nothing that hasn't been done before, but these are tailored to what I need. They can be used independently too.
Documentation is done in LDoc-like comments in source files, but LDoc doesn't really like how I structure my libraries so you can't really generate documentation with it. Documentation is done in LDoc-like comments in source files, but LDoc doesn't really like how I structure my libraries so you can't really generate documentation with it. I'm currently trying to fix this; some modules already have a working LDoc documentation in `doc/`.
Whatever is currently on the master branch should be working and usable. Changelog, including breaking changes, are documented in commit messages. Whatever is currently on the master branch should be working and usable. Changelog, including breaking changes, are documented in commit messages.

View file

@ -1,12 +1,18 @@
project = "Ubiquitousse" project = "Ubiquitousse"
description = "Ubiquitousse Game Engine" title = "Ubiquitousse reference"
full_description = "A simple Lua game framework, made to run everywhere. See the Ubiquitousse module for more information." description = "Ubiquitousse game development tools"
full_description = [[Set of Lua libraries to make game development easier using the [LÖVE](https://love2d.org/) game framework.
title = "Ubiquitousse Reference" See [main module](modules/init.html) for more information, or the [GitHub page](https://github.com/Reuh/ubiquitousse) for the source.
package = "ubiquitousse" ]]
--package = "ubiquitousse"
file = "./" format = "discount"
format = "markdown"
style = "!fixed" style = "!fixed"
no_summary = true
not_luadoc = true not_luadoc = true
custom_tags = { { "require", title="Requires" } }
topics = { "README.md", "LICENSE" }
file = { "init.lua", "ldtk/ldtk.can" }

85
doc/index.html Normal file
View file

@ -0,0 +1,85 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Ubiquitousse reference</title>
<link rel="stylesheet" href="ldoc_fixed.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Ubiquitousse</h1>
<h2>Modules</h2>
<ul class="nowrap">
<li><a href="modules/init.html">init</a></li>
<li><a href="modules/ldtk.html">ldtk</a></li>
</ul>
<h2>Topics</h2>
<ul class="">
<li><a href="topics/README.md.html">README</a></li>
<li><a href="topics/LICENSE.html">LICENSE</a></li>
</ul>
</div>
<div id="content">
<h2>Ubiquitousse game development tools</h2>
<p>Set of Lua libraries to make game development easier using the <a href="https://love2d.org/">LÖVE</a> game framework.</p>
<p>See <a href="modules/init.html">main module</a> for more information, or the <a href="https://github.com/Reuh/ubiquitousse">GitHub page</a> for the source.</p>
<h2>Modules</h2>
<table class="module_list">
<tr>
<td class="name" nowrap><a href="modules/init.html">init</a></td>
<td class="summary">Ubiquitousse main module.</td>
</tr>
<tr>
<td class="name" nowrap><a href="modules/ldtk.html">ldtk</a></td>
<td class="summary"><a href="https://ldtk.io/">LDtk</a> level importer for LÖVE.</td>
</tr>
</table>
<h2>Topics</h2>
<table class="module_list">
<tr>
<td class="name" nowrap><a href="topics/README.md.html">README.md</a></td>
<td class="summary"></td>
</tr>
<tr>
<td class="name" nowrap><a href="topics/LICENSE.html">LICENSE</a></td>
<td class="summary"></td>
</tr>
</table>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2021-12-24 23:49:41 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

311
doc/ldoc_fixed.css Normal file
View file

@ -0,0 +1,311 @@
/* BEGIN RESET
Copyright (c) 2010, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.com/yui/license.html
version: 2.8.2r1
*/
html {
color: #000;
background: #FFF;
}
body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td {
margin: 0;
padding: 0;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
fieldset,img {
border: 0;
}
address,caption,cite,code,dfn,em,strong,th,var,optgroup {
font-style: inherit;
font-weight: inherit;
}
del,ins {
text-decoration: none;
}
li {
margin-left: 20px;
}
caption,th {
text-align: left;
}
h1,h2,h3,h4,h5,h6 {
font-size: 100%;
font-weight: bold;
}
q:before,q:after {
content: '';
}
abbr,acronym {
border: 0;
font-variant: normal;
}
sup {
vertical-align: baseline;
}
sub {
vertical-align: baseline;
}
legend {
color: #000;
}
input,button,textarea,select,optgroup,option {
font-family: inherit;
font-size: inherit;
font-style: inherit;
font-weight: inherit;
}
input,button,textarea,select {*font-size:100%;
}
/* END RESET */
body {
margin-left: 1em;
margin-right: 1em;
font-family: arial, helvetica, geneva, sans-serif;
background-color: #ffffff; margin: 0px;
}
code, tt { font-family: monospace; font-size: 1.1em; }
span.parameter { font-family:monospace; }
span.parameter:after { content:":"; }
span.types:before { content:"("; }
span.types:after { content:")"; }
.type { font-weight: bold; font-style:italic }
body, p, td, th { font-size: .95em; line-height: 1.2em;}
p, ul { margin: 10px 0 0 0px;}
strong { font-weight: bold;}
em { font-style: italic;}
h1 {
font-size: 1.5em;
margin: 0 0 20px 0;
}
h2, h3, h4 { margin: 15px 0 10px 0; }
h2 { font-size: 1.25em; }
h3 { font-size: 1.15em; }
h4 { font-size: 1.06em; }
a:link { font-weight: bold; color: #004080; text-decoration: none; }
a:visited { font-weight: bold; color: #006699; text-decoration: none; }
a:link:hover { text-decoration: underline; }
hr {
color:#cccccc;
background: #00007f;
height: 1px;
}
blockquote { margin-left: 3em; }
ul { list-style-type: disc; }
p.name {
font-family: "Andale Mono", monospace;
padding-top: 1em;
}
pre {
background-color: rgb(245, 245, 245);
border: 1px solid #C0C0C0; /* silver */
padding: 10px;
margin: 10px 0 10px 0;
overflow: auto;
font-family: "Andale Mono", monospace;
}
pre.example {
font-size: .85em;
}
table.index { border: 1px #00007f; }
table.index td { text-align: left; vertical-align: top; }
#container {
margin-left: 1em;
margin-right: 1em;
background-color: #ffffff;
}
#product {
text-align: center;
border-bottom: 1px solid #cccccc;
background-color: #ffffff;
}
#product big {
font-size: 2em;
}
#main {
background-color:#FFFFFF; // #f0f0f0;
border-left: 1px solid #cccccc;
}
#navigation {
position: fixed;
top: 0;
left: 0;
float: left;
width: 14em;
vertical-align: top;
background-color:#FFFFFF; // #f0f0f0;
border-right: 2px solid #cccccc;
overflow: visible;
overflow-y: scroll;
height: 100%;
padding-left: 1em;
}
#navigation h2 {
background-color:#FFFFFF;//:#e7e7e7;
font-size:1.1em;
color:#000000;
text-align: left;
padding:0.2em;
border-bottom:1px solid #dddddd;
}
#navigation ul
{
font-size:1em;
list-style-type: none;
margin: 1px 1px 10px 1px;
}
#navigation li {
text-indent: -1em;
display: block;
margin: 3px 0px 0px 22px;
}
#navigation li li a {
margin: 0px 3px 0px -1em;
}
#content {
margin-left: 14em;
padding: 1em;
padding-left: 2em;
width: 700px;
border-left: 2px solid #cccccc;
// border-right: 2px solid #cccccc;
background-color: #ffffff;
}
#about {
clear: both;
padding-left: 1em;
margin-left: 14em; // avoid the damn sidebar!
border-top: 2px solid #cccccc;
border-left: 2px solid #cccccc;
background-color: #ffffff;
}
@media print {
body {
font: 12pt "Times New Roman", "TimeNR", Times, serif;
}
a { font-weight: bold; color: #004080; text-decoration: underline; }
#main {
background-color: #ffffff;
border-left: 0px;
}
#container {
margin-left: 2%;
margin-right: 2%;
background-color: #ffffff;
}
#content {
padding: 1em;
background-color: #ffffff;
}
#navigation {
display: none;
}
pre.example {
font-family: "Andale Mono", monospace;
font-size: 10pt;
page-break-inside: avoid;
}
}
table.module_list {
border-width: 1px;
border-style: solid;
border-color: #cccccc;
border-collapse: collapse;
}
table.module_list td {
border-width: 1px;
padding: 3px;
border-style: solid;
border-color: #cccccc;
}
table.module_list td.name { background-color: #f0f0f0; ; min-width: 200px; }
table.module_list td.summary { width: 100%; }
table.function_list {
border-width: 1px;
border-style: solid;
border-color: #cccccc;
border-collapse: collapse;
}
table.function_list td {
border-width: 1px;
padding: 3px;
border-style: solid;
border-color: #cccccc;
}
table.function_list td.name { background-color: #f6f6ff; ; min-width: 200px; }
table.function_list td.summary { width: 100%; }
dl.table dt, dl.function dt {border-top: 1px solid #ccc; padding-top: 1em;}
dl.table dd, dl.function dd {padding-bottom: 1em; margin: 10px 0 0 20px;}
dl.table h3, dl.function h3 {font-size: .95em;}
ul.nowrap {
overflow:auto;
whitespace:nowrap;
}
/* stop sublists from having initial vertical space */
ul ul { margin-top: 0px; }
ol ul { margin-top: 0px; }
ol ol { margin-top: 0px; }
ul ol { margin-top: 0px; }
/* make the target distinct; helps when we're navigating to a function */
a:target + * {
background-color: #FF9;
}
/* styles for prettification of source */
pre .comment { color: #558817; }
pre .constant { color: #a8660d; }
pre .escape { color: #844631; }
pre .keyword { color: #aa5050; font-weight: bold; }
pre .library { color: #0e7c6b; }
pre .marker { color: #512b1e; background: #fedc56; font-weight: bold; }
pre .string { color: #8080ff; }
pre .number { color: #f8660d; }
pre .operator { color: #2239a8; font-weight: bold; }
pre .preprocessor, pre .prepro { color: #a33243; }
pre .global { color: #800080; }
pre .user-keyword { color: #800080; }
pre .prompt { color: #558817; }
pre .url { color: #272fc2; text-decoration: underline; }

303
doc/modules/init.html Normal file
View file

@ -0,0 +1,303 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Ubiquitousse reference</title>
<link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Ubiquitousse</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Fields</h2>
<ul class="nowrap">
<li><a href="#version">version</a></li>
<li><a href="#asset">asset</a></li>
<li><a href="#ecs">ecs</a></li>
<li><a href="#input">input</a></li>
<li><a href="#ldtk">ldtk</a></li>
<li><a href="#scene">scene</a></li>
<li><a href="#signal">signal</a></li>
<li><a href="#timer">timer</a></li>
<li><a href="#util">util</a></li>
</ul>
<h2>Modules</h2>
<ul class="nowrap">
<li><strong>init</strong></li>
<li><a href="../modules/ldtk.html">ldtk</a></li>
</ul>
<h2>Topics</h2>
<ul class="">
<li><a href="../topics/README.md.html">README</a></li>
<li><a href="../topics/LICENSE.html">LICENSE</a></li>
</ul>
</div>
<div id="content">
<h1>Module <code>init</code></h1>
<p>Ubiquitousse main module.</p>
<p> Set of various Lua libraries to make game development easier, mainly made to be used alongside the <a href="https://love2d.org/">LÖVE</a> game framework.
Nothing that hasn&rsquo;t been done before, but these are tailored to what I need. They can be used independently too, and are relatively portable, even without LÖVE.</p>
<p> This is the main module, which will try to load every other Ubiquitousse module when required and may even provide a few convenience functions.</p>
<p> This also perform a quick LÖVE version check and show a warning in case of potential incompatibility.</p>
<p> <strong>Regarding Ubiquitousse&rsquo;s organization</strong></p>
<p> Ubiquitousse may or may not be used in its totality. You can delete the modules directories you don&rsquo;t need and Ubiquitousse
should adapt accordingly. You can also simply copy the modules directories you need and use them directly, without using this
file at all.
However, some modules may provide more feature when other modules are available.
These dependencies are written at the top of every main module file.</p>
<p> Ubiquitousse&rsquo;s original goal was to run everywhere with the least porting effort possible, so while the current version now mainly focus LÖVE, it
should still be easily modifiable to work with something else. Ubiquitousse is mainly tested on LuaJIT and Lua 5.3 but should also support Lua 5.1 and 5.2.
In order to keep a good idea of how portable this all is, other dependencies, including LÖVE, are explicited at the top of every module file and in specific
functions definition using the <code>@require</code> tag (e.g., <code>&mdash; @require love</code> for LÖVE).</p>
<p> Some modules are developped in <a href="https://github.com/Reuh/candran">Candran</a> (.can files), but can easily be compiled into regular Lua code.</p>
<p> Units used in the API documentation, unless written otherwise:</p>
<ul>
<li>All distances are expressed in pixels (px)</li>
<li>All durations are expressed in seconds (ms)</li>
</ul>
<p> These units are only used to make writing documentation easier; you can use other units if you want, as long as you're consistent.</p>
<p> Style:</p>
<ul>
<li>tabs for indentation, spaces for esthetic whitespace (notably in comments)</li>
<li>no globals</li>
<li>UPPERCASE for constants (or maybe not).</li>
<li>CamelCase for class names.</li>
<li>lowerCamelCase is expected for everything else.</li>
</ul>
<p> Regarding the documentation: Ubiquitousse used LDoc/LuaDoc styled-comments, but since LDoc hates me and my code, the
generated result is complete garbage, so please read the documentation directly in the comments here until fix this.
Stuff you're interested in starts with triple &ndash; (e.g., &ldquo;&mdash;&ndash; This functions saves the world&rdquo;).</p>
<p> <em>UPDATE</em>: I give up, currently in the process of admitting defat to LDoc and progressively porting all my documentation to it.
Though I had to modify a few things to get LDoc to like me, so the documentation is generated using <a href="https://github.com/Reuh/LDoc">my LDoc fork</a>.</p>
<h3>Usage:</h3>
<ul>
<pre class="example">local ubiquitousse = require(&quot;ubiquitousse&quot;)
</pre>
</ul>
<h2 class="section-header "><a name="Fields"></a>Fields</h2>
<dl class="function">
<dt>
<a name = "version"></a>
<strong>version</strong>
</dt>
<dd>
Ubiquitousse version string (currently <code>&quot;0.1.0&quot;</code>).
</ul>
</dd>
<dt>
<a name = "asset"></a>
<strong>asset</strong>
</dt>
<dd>
Asset manager module, if available.
</ul>
<h3>See also:</h3>
<ul>
<a href="../modules/init.html#asset">asset</a>
</ul>
</dd>
<dt>
<a name = "ecs"></a>
<strong>ecs</strong>
</dt>
<dd>
Entity Component System, if available.
</ul>
<h3>See also:</h3>
<ul>
<a href="../modules/init.html#ecs">ecs</a>
</ul>
</dd>
<dt>
<a name = "input"></a>
<strong>input</strong>
</dt>
<dd>
Input management, if available.
</ul>
<h3>See also:</h3>
<ul>
<a href="../modules/init.html#input">input</a>
</ul>
</dd>
<dt>
<a name = "ldtk"></a>
<strong>ldtk</strong>
</dt>
<dd>
LDtk level import, if available.
</ul>
<h3>See also:</h3>
<ul>
<a href="../modules/ldtk.html#">ldtk</a>
</ul>
</dd>
<dt>
<a name = "scene"></a>
<strong>scene</strong>
</dt>
<dd>
Scene management, if available.
</ul>
<h3>See also:</h3>
<ul>
<a href="../modules/init.html#scene">scene</a>
</ul>
</dd>
<dt>
<a name = "signal"></a>
<strong>signal</strong>
</dt>
<dd>
Signal management, if available.
</ul>
<h3>See also:</h3>
<ul>
<a href="../modules/init.html#signal">signal</a>
</ul>
</dd>
<dt>
<a name = "timer"></a>
<strong>timer</strong>
</dt>
<dd>
Timer utilities, if available.
</ul>
<h3>See also:</h3>
<ul>
<a href="../modules/init.html#timer">timer</a>
</ul>
</dd>
<dt>
<a name = "util"></a>
<strong>util</strong>
</dt>
<dd>
Various useful functions, if available.
</ul>
<h3>See also:</h3>
<ul>
<a href="../modules/init.html#util">util</a>
</ul>
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2021-12-24 23:49:41 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

1230
doc/modules/ldtk.html Normal file

File diff suppressed because it is too large Load diff

65
doc/topics/LICENSE.html Normal file
View file

@ -0,0 +1,65 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Ubiquitousse reference</title>
<link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Ubiquitousse</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Topics</h2>
<ul class="">
<li><a href="../topics/README.md.html">README</a></li>
<li><strong>LICENSE</strong></li>
</ul>
<h2>Modules</h2>
<ul class="nowrap">
<li><a href="../modules/init.html">init</a></li>
<li><a href="../modules/ldtk.html">ldtk</a></li>
</ul>
</div>
<div id="content">
Copyright 2021 Étienne &ldquo;Reuh&rdquo; Fildadut</p>
<p>Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.</p>
<p>THE SOFTWARE IS PROVIDED &ldquo;AS IS&rdquo; AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2021-12-24 23:49:41 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

70
doc/topics/README.md.html Normal file
View file

@ -0,0 +1,70 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Ubiquitousse reference</title>
<link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Ubiquitousse</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Topics</h2>
<ul class="">
<li><strong>README</strong></li>
<li><a href="../topics/LICENSE.html">LICENSE</a></li>
</ul>
<h2>Modules</h2>
<ul class="nowrap">
<li><a href="../modules/init.html">init</a></li>
<li><a href="../modules/ldtk.html">ldtk</a></li>
</ul>
</div>
<div id="content">
<h1>ubiquitousse</h1>
<p>Set of various libraries I use for game development, mainly with LÖVE. Nothing that hasn&rsquo;t been done before, but these are tailored to what I need. They can be used independently too.</p>
<p>Documentation is done in LDoc-like comments in source files, but LDoc doesn&rsquo;t really like how I structure my libraries so you can&rsquo;t really generate documentation with it. I'm currently trying to fix this; some modules already have a working LDoc documentation in <code>doc/</code>.</p>
<p>Whatever is currently on the master branch should be working and usable. Changelog, including breaking changes, are documented in commit messages.</p>
<p>Licensed under ISC (equivalent to MIT/Expat/Simplified BSD).</p>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2021-12-24 23:49:41 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

View file

@ -1,7 +1,14 @@
-- ubiquitousse -- ubiquitousse
--- Ubiquitousse Game Framework. --- Ubiquitousse main module.
-- Main module, which will try to load every other Ubiquitousse module when required and provide a few convenience functions. -- Set of various Lua libraries to make game development easier, mainly made to be used alongside the [LÖVE](https://love2d.org/) game framework.
-- Nothing that hasn't been done before, but these are tailored to what I need. They can be used independently too, and are relatively portable, even without LÖVE.
--
-- This is the main module, which will try to load every other Ubiquitousse module when required and may even provide a few convenience functions.
--
-- This also perform a quick LÖVE version check and show a warning in case of potential incompatibility.
--
-- **Regarding Ubiquitousse's organization**
-- --
-- Ubiquitousse may or may not be used in its totality. You can delete the modules directories you don't need and Ubiquitousse -- Ubiquitousse may or may not be used in its totality. You can delete the modules directories you don't need and Ubiquitousse
-- should adapt accordingly. You can also simply copy the modules directories you need and use them directly, without using this -- should adapt accordingly. You can also simply copy the modules directories you need and use them directly, without using this
@ -9,47 +16,67 @@
-- However, some modules may provide more feature when other modules are available. -- However, some modules may provide more feature when other modules are available.
-- These dependencies are written at the top of every main module file. -- These dependencies are written at the top of every main module file.
-- --
-- Ubiquitousse's goal is to run everywhere with the least porting effort possible, so while the current version mainly focus LÖVE, it -- Ubiquitousse's original goal was to run everywhere with the least porting effort possible, so while the current version now mainly focus LÖVE, it
-- should be easily modifiable to work with something else. Ubiquitousse should only require: -- should still be easily modifiable to work with something else. Ubiquitousse is mainly tested on LuaJIT and Lua 5.3 but should also support Lua 5.1 and 5.2.
-- * The backend needs to have access to some kind of main loop, or at least a function called very often (may or may not be the -- In order to keep a good idea of how portable this all is, other dependencies, including LÖVE, are explicited at the top of every module file and in specific
-- same as the redraw screen callback). -- functions definition using the `@require` tag (e.g., `-- @require love` for LÖVE).
-- * Some way of measuring time (preferably with millisecond-precision).
-- * Some kind of filesystem.
-- * Lua 5.1, 5.2, 5.3 or LuaJit.
-- * Other requirement for specific modules should be described in the module's documentation.
-- --
-- Functions that depends on LÖVE or anything that's not in the Lua standard libraries (and therefore the one you may want to port to -- Some modules are developped in [Candran](https://github.com/Reuh/candran) (.can files), but can easily be compiled into regular Lua code.
-- another framework) are indicated by a "-- @impl love" annotation. --
-- Units used in the API documentation, unless written otherwise:
-- --
-- Units used in the API documentation:
-- * All distances are expressed in pixels (px) -- * All distances are expressed in pixels (px)
-- * All durations are expressed in seconds (ms) -- * All durations are expressed in seconds (ms)
--
-- These units are only used to make writing documentation easier; you can use other units if you want, as long as you're consistent. -- These units are only used to make writing documentation easier; you can use other units if you want, as long as you're consistent.
-- --
-- Style: -- Style:
--
-- * tabs for indentation, spaces for esthetic whitespace (notably in comments) -- * tabs for indentation, spaces for esthetic whitespace (notably in comments)
-- * no globals -- * no globals
-- * UPPERCASE for constants (or maybe not). -- * UPPERCASE for constants (or maybe not).
-- * CamelCase for class names. -- * CamelCase for class names.
-- * lowerCamelCase is expected for everything else. -- * lowerCamelCase is expected for everything else.
-- --
-- For game writer:
-- Ubiquitousse works with Lua 5.1 to 5.3, including LuaJit, but doesn't provide any version checking or compatibility layer
-- between the different versions, so it's up to you to handle that in your game (or ignore the problem and sticks to your
-- main's backend Lua version).
--
-- Regarding the documentation: Ubiquitousse used LDoc/LuaDoc styled-comments, but since LDoc hates me and my code, the -- Regarding the documentation: Ubiquitousse used LDoc/LuaDoc styled-comments, but since LDoc hates me and my code, the
-- generated result is complete garbage, so please read the documentation directly in the comments here until fix this. -- generated result is complete garbage, so please read the documentation directly in the comments here until fix this.
-- Stuff you're interested in starts with triple - (e.g., "--- This functions saves the world"). -- Stuff you're interested in starts with triple - (e.g., "--- This functions saves the world").
-- --
-- *UPDATE*: I give up, currently in the process of admitting defat to LDoc and progressively porting all my documentation to it.
-- Though I had to modify a few things to get LDoc to like me, so the documentation is generated using [my LDoc fork](https://github.com/Reuh/LDoc).
--
-- @usage local ubiquitousse = require("ubiquitousse") -- @usage local ubiquitousse = require("ubiquitousse")
local p = ... -- require path local p = ... -- require path
local ubiquitousse local ubiquitousse
ubiquitousse = { ubiquitousse = {
--- Ubiquitousse version. --- Ubiquitousse version string (currently `"0.1.0"`).
version = "0.1.0" version = "0.1.0",
--- Asset manager module, if available.
-- @see asset
asset = nil,
--- Entity Component System, if available.
-- @see ecs
ecs = nil,
--- Input management, if available.
-- @see input
input = nil,
--- LDtk level import, if available.
-- @see ldtk
ldtk = nil,
--- Scene management, if available.
-- @see scene
scene = nil,
--- Signal management, if available.
-- @see signal
signal = nil,
--- Timer utilities, if available.
-- @see timer
timer = nil,
--- Various useful functions, if available.
-- @see util
util = nil
} }
-- Check LÖVE version -- Check LÖVE version
@ -70,7 +97,7 @@ end
package.loaded[p] = ubiquitousse package.loaded[p] = ubiquitousse
-- Require external submodules -- Require external submodules
for _, m in ipairs{"signal", "asset", "ecs", "input", "scene", "timer", "util"} do for _, m in ipairs{"signal", "asset", "ecs", "input", "scene", "timer", "util", "ldtk"} do
local s, t = pcall(require, p.."."..m) local s, t = pcall(require, p.."."..m)
if s then if s then
ubiquitousse[m] = t ubiquitousse[m] = t

View file

@ -47,7 +47,7 @@ input = {
-- The function may error if the identifier is incorrect. -- The function may error if the identifier is incorrect.
-- @tparam string button identifier, depends on the platform Ubiquitousse is running on -- @tparam string button identifier, depends on the platform Ubiquitousse is running on
-- @treturn the new button detector -- @treturn the new button detector
-- @impl love -- @require love
basicButtonDetector = function(str) end, basicButtonDetector = function(str) end,
--- Make a new button detector from a detector function, string, or list of buttons. --- Make a new button detector from a detector function, string, or list of buttons.
@ -85,7 +85,7 @@ input = {
-- The function may error if the identifier is incorrect. -- The function may error if the identifier is incorrect.
-- @tparam string axis identifier, depends on the platform Ubiquitousse is running on -- @tparam string axis identifier, depends on the platform Ubiquitousse is running on
-- @treturn the new axis detector -- @treturn the new axis detector
-- @impl love -- @require love
basicAxisDetector = function(str) end, basicAxisDetector = function(str) end,
--- Make a new axis detector from a detector function, string, or a couple of buttons. --- Make a new axis detector from a detector function, string, or a couple of buttons.
@ -117,13 +117,13 @@ input = {
-- This may also returns "axis threshold" buttons if an axis passes the threshold. -- This may also returns "axis threshold" buttons if an axis passes the threshold.
-- @tparam[opt=0.5] number threshold the threshold to detect axes as button -- @tparam[opt=0.5] number threshold the threshold to detect axes as button
-- @treturn string,... buttons identifiers list -- @treturn string,... buttons identifiers list
-- @impl love -- @require love
buttonUsed = function(threshold) end, buttonUsed = function(threshold) end,
--- Returns a list of the axes currently in use, identified by their string axis identifier --- Returns a list of the axes currently in use, identified by their string axis identifier
-- @tparam[opt=0.5] number threshold the threshold to detect axes -- @tparam[opt=0.5] number threshold the threshold to detect axes
-- @treturn string,... axes identifiers list -- @treturn string,... axes identifiers list
-- @impl love -- @require love
axisUsed = function(threshold) end, axisUsed = function(threshold) end,
--- Returns a nice name for the button identifier. --- Returns a nice name for the button identifier.
@ -131,7 +131,7 @@ input = {
-- May returns the raw identifier if you're lazy. -- May returns the raw identifier if you're lazy.
-- @tparam string... button identifier string(s) -- @tparam string... button identifier string(s)
-- @treturn string... the displayable names -- @treturn string... the displayable names
-- @impl love -- @require love
buttonName = function(...) end, buttonName = function(...) end,
--- Returns a nice name for the axis identifier. --- Returns a nice name for the axis identifier.
@ -139,7 +139,7 @@ input = {
-- May returns the raw identifier if you're lazy. -- May returns the raw identifier if you're lazy.
-- @tparam string... axis identifier string(s) -- @tparam string... axis identifier string(s)
-- @treturn string... the displayable names -- @treturn string... the displayable names
-- @impl love -- @require love
axisName = function(...) end, axisName = function(...) end,
------------------- -------------------
@ -152,7 +152,7 @@ input = {
-- any platform without having to configure the keys. -- any platform without having to configure the keys.
-- If some key function in your game match one of theses defaults, using it instead of creating a new -- If some key function in your game match one of theses defaults, using it instead of creating a new
-- input would be a good idea. -- input would be a good idea.
-- @impl love -- @require love
default = { default = {
pointer = nil, -- Pointer: used to move and select. Example binds: arrow keys, WASD, stick. pointer = nil, -- Pointer: used to move and select. Example binds: arrow keys, WASD, stick.
confirm = nil, -- Button: used to confirm something. Example binds: Enter, A button. confirm = nil, -- Button: used to confirm something. Example binds: Enter, A button.
@ -161,7 +161,7 @@ input = {
--- Get draw area dimensions. --- Get draw area dimensions.
-- Used for pointers. -- Used for pointers.
-- @impl love -- @require love
getDrawWidth = function() return 1 end, getDrawWidth = function() return 1 end,
getDrawHeight = function() return 1 end, getDrawHeight = function() return 1 end,

1
ldtk/init.lua Normal file
View file

@ -0,0 +1 @@
return require((...)..".ldtk")

596
ldtk/ldtk.can Normal file
View file

@ -0,0 +1,596 @@
--- [LDtk](https://ldtk.io/) level importer for LÖVE.
-- Support most LDtk features, and allow easy usage in LÖVE projects.
--
-- Every unit is in pixel in the API unless written otherwise.
--
-- This modules returns a single function @{LDtk}(path).
--
-- Requires LÖVE `love.graphics` (drawing Image, SpriteBatch, Quad).
--
-- @module ldtk
-- @require love
-- @usage
-- local ldtk = require("ubiquitousse.ldtk")
--
-- local project = ltdk("example.ldtk")
--
-- local callbacks = {
-- onAddEntity = function(entity)
-- -- handle entity...
-- end
-- }
--
-- -- load every level
-- for _, lvl in ipairs(project.levels) do lvl:load() end
--
-- function love.draw()
-- -- draw every level
-- for _, lvl in ipairs(project.levels) do lvl:draw() end
-- end
-- TODO: give associated tile & color with enum values, also give enum info
let lg = love.graphics
--- json helpers
let json_decode = require("json").decode
let readJson = (file)
let f = assert(io.open(file, "r"))
local t = json_decode(f:read("*a"))
f:close()
return t
end
--- color helpers
let parseColor = (str)
local r, g, b = str:match("^#(..)(..)(..)")
r, g, b = tonumber(r, 16), tonumber(g, 16), tonumber(b, 16)
return { r/255, g/255, b/255 }
end
let white = {1,1,1}
--- returns a lua table from some fieldInstances
let toLua = (type, val)
if val == nil then return val end
if type:match("^Array%<") then
local itype = type:match("^Array%<(.*)%>$")
for i, v in ipairs(val) do
val[i] = toLua(itype, v)
end
elseif type == "Color" then
return parseColor(val)
elseif type == "Point" then
return { x = val.cx, y = val.cy }
end
return val
end
let getFields = (f)
local t = {}
for _, v in ipairs(f) do
t[v.__identifier] = toLua(v.__type, v.__value)
end
return t
end
let tileset_mt
let make_cache = (new_fn)
return setmetatable({}, {
__mode = "v",
__call = (cache, id)
if not cache[id] then
cache[id] = new_fn(id)
end
return cache[id]
end
})
end
let cache = {
tileset = make_cache((tilesetDef)
return tileset_mt._init(tilesetDef)
end),
image = make_cache((path)
return lg.newImage(path)
end),
}
--- Tileset object.
-- Stores the image associated with the tileset; can be shared among several layers and levels.
-- @type Tileset
-- @require love
tileset_mt = {
_newQuad = :(x, y, width, height)
return lg.newQuad(x, y, width, height, @image)
end,
_getTileQuad = :(tileid, x, y, size)
if not @_tileQuads[tileid] then
@_tileQuads[tileid] = @_newQuad(x, y, size, size)
end
return @_tileQuads[tileid]
end,
_init = (tilesetDef)
local t = {
--- The tileset LÖVE image object.
image = cache.image(tilesetDef.path),
_tileQuads = {}
}
return setmetatable(t, tileset_mt)
end
}
tileset_mt.__index = tileset_mt
--- Layer object.
--
-- Part of a @{Level}.
--
-- @type Layer
-- @require love
let layer_mt = {
--- Draw the current layer.
-- Assumes we are currently in level coordinates (i.e. level top-left is at 0,0).
-- @require love
draw = :()
if @visible then
lg.push()
lg.translate(@offsetX, @offsetY)
if @spritebatch then
lg.setColor(1, 1, 1, @opacity)
lg.draw(@spritebatch)
elseif @intTiles then
for _, t in ipairs(@intTiles) do
lg.setColor(t.color)
lg.rectangle("fill", t.x, t.y, t.layer.gridSize, t.layer.gridSize)
end
elseif @entities then
for _, e in ipairs(@entities) do
if e.draw then e:draw() end
end
end
lg.pop()
end
end,
_unloadCallbacks = :(callbacks)
local onRemoveTile = callbacks.onRemoveTile
if @tiles and onRemoveTile then
for _, t in ipairs(@tiles) do
onRemoveTile(t)
end
end
local onRemoveIntTile = callbacks.onRemoveIntTile
if @intTiles and onRemoveIntTile then
for _, t in ipairs(@intTiles) do
onRemoveIntTile(t)
end
end
local onRemoveEntity = callbacks.onRemoveEntity
if @entities and onRemoveEntity then
for _, e in ipairs(@entities) do
onRemoveEntity(e)
end
end
end,
_init = (layer, level, order, callbacks)
let gridSize = layer.__gridSize
let t = {
--- @{Level} this layer belongs to.
level = level,
--- The layer name.
identifier = layer.__identifier,
--- Type of layer: IntGrid, Entities, Tiles or AutoLayer (string).
type = layer.__type,
--- Whether the layer is visible or not.
visible = layer.visible,
--- The layer opacity (0-1).
opacity = layer.opacity,
--- The layer order: smaller order means it is on top.
order = order,
--- X position of the layer relative to the level.
offsetX = layer.__pxTotalOffsetX,
--- Y position of the layer relative to the level.
offsetY = layer.__pxTotalOffsetY,
--- Size of the grid on this layer.
gridSize = gridSize,
--- Width of the layer, in grid units.
gridWidth = layer.__cWid,
--- Height of the layer, in grid units.
gridHeight = layer.__cHei,
--- _(Entities layer only)_ List of @{Entity} in the layer.
entities = nil,
--- _(Tiles, AutoLayer, or IntGrid with AutoLayer rules layers only)_ List of @{Tile}s in the layer.
tiles = nil,
--- _(Tiles, AutoLayer, or IntGrid with AutoLayer rules layers only)_ @{Tileset} object associated with the layer.
tileset = nil,
--- _(Tiles, AutoLayer, or IntGrid with AutoLayer rules layers only)_ [LÖVE SpriteBatch](https://love2d.org/wiki/SpriteBatch) containing the layer.
spritebatch = nil,
--- _(IntGrid without AutoLayer rules layer only)_ list of @{IntTile}s in the layer.
intTiles = nil,
}
-- Layers with an associated tileset (otherwise ignore as there is nothing to draw) (Tiles, AutoLayer & IntGrid with AutoLayer rules)
if layer.__tilesetDefUid then
t.tiles = {}
local tilesetData = level.project._tilesetData[layer.__tilesetDefUid]
t.tileset = cache.tileset(tilesetData)
local tiles = layer.__type == "Tiles" and layer.gridTiles or layer.autoLayerTiles
local onAddTile = callbacks.onAddTile
t.spritebatch = lg.newSpriteBatch(t.tileset.image)
for _, tl in ipairs(tiles) do
let quad = t.tileset:_getTileQuad(tl.t, tl.src[1], tl.src[2], gridSize)
let sx, sy = 1, 1
let x, y = tl.px[1], tl.px[2]
--- Tile object.
--
-- This represent the tiles from a Tiles, AutoLayer or IntGrid with AutoLayer rules layer.
--
-- Can be retrived from the @{tiles} list or `onAddTile` level load callback.
--
-- @type Tile
let tile = {
--- Layer the tile belongs to.
layer = t,
--- X position of the tile relative to the layer.
x = x,
--- Y position of the tile relative to the layer.
y = y,
--- Whether the tile is flipped horizontally.
flipX = false,
--- Whether the tile is flipped vertically.
flipY = false,
--- Tags associated with the tile: can be used either as a list of tags or a map of activated tags tags[name] == true.
tags = tilesetData[tl.t].tags,
--- Custom data associated with the tile, if any.
data = tilesetData[tl.t].data,
--- Quad associated with the tile (relative to the layer's tileset).
quad = quad
}
if tl.f == 1 or tl.f == 3 then
sx = -1
x += gridSize
tile.flipX = true
end
if tl.f == 2 or tl.f == 3 then
sy = -1
y += gridSize
tile.flipY = true
end
t.spritebatch:add(quad, x, y, 0, sx, sy)
table.insert(t.tiles, tile)
if onAddTile then onAddTile(tile) end
end
-- IntGrid
elseif layer.__type == "IntGrid" then
t.intTiles = {}
local onAddIntTile = callbacks.onAddIntTile
local values = level.project._layerDef[layer.layerDefUid].intGridValues
for i, tl in ipairs(layer.intGridCsv) do
if tl > 0 then
let y = math.floor((i-1) / t.gridWidth) * gridSize
let x = ((i-1) % t.gridWidth) * gridSize
--- IntTile object.
--
-- This represent the tiles from a IntGrid without AutoLayer rules layer.
--
-- Can be retrived from the @{intTiles} list or `onAddIntTile` level load callback.
--
-- @type IntTile
let tile = {
--- Layer the IntTile belongs to.
layer = t,
--- X position of the IntTile relative to the layer.
x = x,
--- Y position of the IntTile relative to the layer.
y = y,
--- Name of the IntTile.
identifier = values[tl].identifier,
--- Integer value of the IntTile.
value = tl,
--- Color of the IntTile.
color = values[tl].color
}
table.insert(t.intTiles, tile)
if onAddIntTile then onAddIntTile(tile) end
end
end
end
-- Entities layers
if layer.__type == "Entities" then
t.entities = {}
local onAddEntity = callbacks.onAddEntity
for _, e in ipairs(layer.entityInstances) do
let entityDef = level.project._entityData[e.defUid]
--- Entity object.
--
-- This represent an entity from an Entities layer.
--
-- Can be retrived from the @{entities} list or `onAddEntity` level load callback.
--
-- @type Entity
let entity = {
--- @{Layer} this entity belongs to.
layer = t,
--- The entity name.
identifier = e.__identifier,
--- X position of the entity relative to the layer.
x = e.px[1],
--- Y position of the entity relative to the layer.
y = e.px[2],
--- The entity width.
width = e.width,
--- The entity height.
height = e.height,
--- Scale factor on x axis relative to original entity size.
sx = e.width / entityDef.width,
--- Scale factor on y axis relative to original entity size.
sy = e.height / entityDef.height,
--- The entity pivot point x position relative to the entity.
pivotX = e.__pivot[1] * e.width,
--- The entity pivot point x position relative to the entity.
pivotY = e.__pivot[2] * e.height,
--- Entity color.
color = entityDef.color,
--- Entity tile, if any. Is a table { tileset = associated tileset object, quad = associated quad }.
tile = nil,
--- Map of custom fields of the entity.
fields = getFields(e.fieldInstances),
--- Called for the entity when drawing the associated entity layer (you will likely want to redefine it).
--
-- By default, this draws the tile associated with the entity if there is one, or a rectangle around the entity position otherwise.
-- @require love
draw = :()
if @tile then
let _, _, w, h = @tile.quad:getViewport()
lg.setColor(white)
lg.draw(@tile.tileset.image, @tile.quad, @x-@pivotX, @y-@pivotY, 0, @width / w, @height / h)
else
lg.setColor(@color)
lg.rectangle("line", @x-@pivotX, @y-@pivotY, @width, @height)
end
end
}
if e.__tile then
local tileset = cache.tileset(level.project._tilesetData[e.__tile.tilesetUid])
local srcRect = e.__tile.srcRect
local quad = tileset:_newQuad(srcRect[1], srcRect[2], srcRect[3], srcRect[4])
entity.tile = {
tileset = tileset,
quad = quad
}
end
table.insert(t.entities, entity)
if onAddEntity then onAddEntity(entity) end
end
end
return setmetatable(t, layer_mt)
end
}
layer_mt.__index = layer_mt
--- Level object.
--
-- Levels are not automatically loaded in order to not waste ressources if your project is large; so before drawing or operating on a level, you will need to call its @{Level:load} method.
--
-- Part of a @{Project}.
--
-- @type Level
-- @require love
let level_mt = {
--- Draw this level.
-- Assumes we are currently in world coordinates (i.e. world top-left is at 0,0).
-- The level must be loaded.
-- Will draw the eventual backgrounds and all the layers in the level.
-- @require love
draw = :()
assert(@loaded == true, "level not loaded")
lg.push()
lg.translate(@x, @y)
-- background color
lg.setColor(@_bgColor)
lg.rectangle("fill", 0, 0, @width, @height)
-- background image
lg.setColor(white)
if @_bgImage then
lg.draw(@_bgImage.image, @_bgImage.quad, @_bgImage.x, @_bgImage.y, 0, @_bgImage.sx, @_bgImage.sy)
end
-- layers
for _, l in ipairs(@layers) do
l:draw()
end
lg.pop()
end,
--- Load the level.
-- Will load every layer in the level and the associated images.
--
-- You can optionally specify some callbacks for the loading process:
--
-- * `onAddLayer(layer)` will be called for every new layer loaded, with the @{Layer} as sole argument
-- * `onAddTile(tile)` will be called for every new tile loaded, with the @{Tile} as sole argument
-- * `onAddIntTile(tile)` will be called for every new IntGrid tile loaded, with the @{IntTile} as sole argument
-- * `onAddEntity(entity)` will be called for every new entity loaded, with the @{Entity} as sole argument
--
-- These callbacks should allow you to capture all the important elements needed to use the level, so you can hopefully
-- integrate it into your current game engine easily.
--
-- @tab[opt] callbacks
-- @require love
load = :(callbacks={})
assert(@loaded == false, "level already loaded")
if @_json.bgRelPath then
let pos = @_json.__bgPos
let cropRect = pos.cropRect
let image = cache.image(@project._directory..@_json.bgRelPath)
@_bgImage = {
image = image,
quad = lg.newQuad(cropRect[1], cropRect[2], cropRect[3], cropRect[4], image),
x = pos.topLeftPx[1],
y = pos.topLeftPx[2],
sx = pos.scale[1],
sy = pos.scale[1]
}
end
let layerInstances
if @_json.externalRelPath then
layerInstances = readJson(@project._directory..@_json.externalRelPath).layerInstances
else
layerInstances = @_json.layerInstances
end
@layers = {}
let onAddLayer = callbacks.onAddLayer
for i=#layerInstances, 1, -1 do
local layer = layer_mt._init(layerInstances[i], @, i, callbacks)
table.insert(@layers, layer)
if onAddLayer then onAddLayer(layer) end
end
@loaded = true
end,
--- Unload the level.
-- Images loaded by the level will be freed on the next garbage collection cycle.
--
-- You can optionally specify some callbacks for the unloading process:
--
-- * `onAddLayer(layer)` will be called for every new layer unloaded, with the @{Layer} as sole argument
-- * `onAddTile(tile)` will be called for every new tile unloaded, with the @{Tile} as sole argument
-- * `onAddIntTile(tile)` will be called for every new IntGrid tile unloaded, with the @{IntTile} as sole argument
-- * `onAddEntity(entity)` will be called for every new entity unloaded, with the @{Entity} as sole argument
--
-- @tab[opt] callbacks
unload = :(callbacks={})
assert(@loaded == true, "level not loaded")
let onRemoveLayer = callbacks.onRemoveLayer
for _, l in ipairs(@layers) do
l:_unloadCallbacks(callbacks)
if onRemoveLayer then onRemoveLayer(l) end
end
@loaded = false
@_bgImage = nil
@_bgImageQuads = nil
@layers = nil
end,
_init = (level, project)
let t = {
--- @{Project} this level belongs to.
project = project,
--- Whether this level is currently loaded or not (boolean).
loaded = false,
--- The level name (string).
identifier = level.identifier,
--- The level x position (number).
x = level.worldX,
--- The level y position (number).
y = level.worldY,
--- The level width (number).
width = level.pxWid,
--- The level height (number).
height = level.pxHei,
--- Map of custom fields of the level (table).
fields = getFields(level.fieldInstances),
--- List of @{Layer}s in the level (table).
layers = nil,
-- private
_json = level,
_bgColor = parseColor(level.__bgColor),
_bgImage = nil
}
return setmetatable(t, level_mt)
end
}
level_mt.__index = level_mt
--- Project object.
--
-- Returned by @{LDtk}.
--
-- @type Project
let project_mt = {
_init = (project, directory)
assert(project.jsonVersion == "0.9.3", "map made for LDtk version %s":format(project.jsonVersion))
let t = {
--- List of @{Level}s in this project.
levels = nil,
-- private
_directory = directory,
_layerDef = nil,
_tilesetData = nil,
_entityData = nil,
}
t.levels = [
for _, lvl in ipairs(project.levels) do
push level_mt._init(lvl, t)
end
]
t._tilesetData = [
for _, ts in ipairs(project.defs.tilesets) do
@[ts.uid] = {
path = directory..ts.relPath
}
local tilesetData = @[ts.uid]
for gridx=0, ts.__cWid-1 do
for gridy=0, ts.__cHei-1 do
tilesetData[gridx + gridy * ts.__cWid] = {
tags = {},
data = nil
}
end
end
for _, custom in ipairs(ts.customData) do
tilesetData[custom.tileId].data = custom.data
end
for _, tag in ipairs(ts.enumTags) do
local value = tag.enumValueId
for _, tileId in ipairs(tag.tileIds) do
table.insert(tilesetData[tileId].tags, value)
tilesetData[tileId].tags[value] = true
end
end
end
]
t._layerDef = [
for _, lay in ipairs(project.defs.layers) do
@[lay.uid] = {
intGridValues = nil
}
local layerDef = @[lay.uid]
if lay.__type == "IntGrid" then
layerDef.intGridValues = [
for _, v in ipairs(lay.intGridValues) do
@[v.value] = {
color = parseColor(v.color),
identifier = v.identifier
}
end
]
end
end
]
t._entityData = [
for _, ent in ipairs(project.defs.entities) do
@[ent.uid] = {
color = parseColor(ent.color),
width = ent.width,
height = ent.height
}
end
]
return setmetatable(t, project_mt)
end
}
project_mt.__index = project_mt
--- Custom fields.
-- @section fields
--- Module.
-- `ubiquitousse.ldtk` returns a single function, @{LDtk}.
-- @section module
--- Load a LDtk project.
-- @string path to LDtk project file (.ldtk)
-- @treturn Project the loaded LDtk project
-- @function LDtk
return (file)
return project_mt._init(readJson(file), file:match("^(.-)[^%/%\\]+$"))
end

View file

@ -97,7 +97,7 @@ let signal = {
--- Call this function to hook signal.event signals to the current backend. --- Call this function to hook signal.event signals to the current backend.
-- For LÖVE, this means overriding every existing LÖVE callback. If a callback is already defined, the new one will call the old function along with the signal:emit. -- For LÖVE, this means overriding every existing LÖVE callback. If a callback is already defined, the new one will call the old function along with the signal:emit.
-- @impl love -- @require love
registerEvents = () registerEvents = ()
local callbacks = { -- everything except run, errorhandler, threaderror local callbacks = { -- everything except run, errorhandler, threaderror
"displayrotated", "draw", "load", "lowmemory", "quit", "update", "displayrotated", "draw", "load", "lowmemory", "quit", "update",