From 62d2b1085d2cc5f2dc45b55b62e723b9a98cc9d9 Mon Sep 17 00:00:00 2001 From: "Jill \"oatmealine\" Monoids" Date: Mon, 19 Sep 2022 16:42:33 +0300 Subject: [PATCH] init commit, i think --- .gitconfig | 1 + .gitignore | 52 + .vscode/extensions.json | 6 + .vscode/settings.json | 6 + MANUAL.md | 641 +++++++++++ Song.sm | 2010 ++++++++++++++++++++++++++++++++++ docs/uranium.png | Bin 0 -> 31686 bytes docs/uranium_full.png | Bin 0 -> 74394 bytes jillo_png.png | Bin 0 -> 7402 bytes silence.ogg | Bin 0 -> 4316 bytes src/main.lua | 41 + template/actors.xml | 6 + template/main.xml | 482 ++++++++ template/stdlib/bitop.lua | 343 ++++++ template/stdlib/color.lua | 299 +++++ template/stdlib/easable.lua | 80 ++ template/stdlib/easable2.lua | 90 ++ template/stdlib/ease.lua | 338 ++++++ template/stdlib/index.lua | 10 + template/stdlib/input.lua | 39 + template/stdlib/rng.lua | 172 +++ template/stdlib/util.lua | 157 +++ template/stdlib/uwuify.lua | 23 + template/stdlib/vector2D.lua | 142 +++ template/typings.lua | 81 ++ 25 files changed, 5019 insertions(+) create mode 100644 .gitconfig create mode 100644 .gitignore create mode 100644 .vscode/extensions.json create mode 100644 .vscode/settings.json create mode 100644 MANUAL.md create mode 100644 Song.sm create mode 100644 docs/uranium.png create mode 100644 docs/uranium_full.png create mode 100644 jillo_png.png create mode 100644 silence.ogg create mode 100644 src/main.lua create mode 100644 template/actors.xml create mode 100644 template/main.xml create mode 100644 template/stdlib/bitop.lua create mode 100644 template/stdlib/color.lua create mode 100644 template/stdlib/easable.lua create mode 100644 template/stdlib/easable2.lua create mode 100644 template/stdlib/ease.lua create mode 100644 template/stdlib/index.lua create mode 100644 template/stdlib/input.lua create mode 100644 template/stdlib/rng.lua create mode 100644 template/stdlib/util.lua create mode 100644 template/stdlib/uwuify.lua create mode 100644 template/stdlib/vector2D.lua create mode 100644 template/typings.lua diff --git a/.gitconfig b/.gitconfig new file mode 100644 index 0000000..fee9b8b --- /dev/null +++ b/.gitconfig @@ -0,0 +1 @@ +pull.rebase=true \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a177d5a --- /dev/null +++ b/.gitignore @@ -0,0 +1,52 @@ +# Old SM files +*.sm.auto +*.sm.old + +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Folder config file +[Dd]esktop.ini + +# Windows shortcuts +*.lnk + +# MacOS +.DS_Store +.AppleDouble +.LSOverride + +# Thumbnails +._* + +# VSCode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Linux +*~ + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# Cache files for Sublime Text +*.tmlanguage.cache +*.tmPreferences.cache +*.stTheme.cache + +# Sublime-github package stores a github token in this file +# https://packagecontrol.io/packages/sublime-github +GitHub.sublime-settings \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..7fee640 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,6 @@ +{ + "recommendations": [ + "sumneko.lua", + "fms-cat.xml-stepmania" + ], +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..fd81e19 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "Lua.runtime.path": [ + "?.lua" + ], + "Lua.runtime.version": "Lua 5.1" +} \ No newline at end of file diff --git a/MANUAL.md b/MANUAL.md new file mode 100644 index 0000000..3b6f55f --- /dev/null +++ b/MANUAL.md @@ -0,0 +1,641 @@ + +If you're viewing this in VSCode, it's recommended that you open it in a preview with `Ctrl+Shift+V`! + + +--- + +
+ +
+

+ + Uranium Template α +

+ Official manual!!!! +
+
+ +**Uranium Template** is a Love2D-inspired NotITG game development template, focusing on keeping things as **Lua-pure** as possible with enough abstractions to make you feel like you're not dealing with Stepmania jank at all. + +Uranium Template originally formed during the creation of a currently unreleased project, and since then I've went ahead and refined and polished it up to be usable on its own. Most of the design decisions came from experience using prototype versions of it! + +- [Testimonies](#testimonies) +- [Installation](#installation) +- [Distribution](#distribution) +- [How do I start writing code?](#how-do-i-start-writing-code) +- [Defining actors](#defining-actors) + - [Initializing actors](#initializing-actors) +- [Callback usage](#callback-usage) + - [Default callbacks](#default-callbacks) + - [`uranium.update(dt: number)`](#uraniumupdatedt-number) + - [`uranium.init()`](#uraniuminit) + - [`uranium.press(direction: string)`](#uraniumpressdirection-string) + - [`uranium.release(direction: string)`](#uraniumreleasedirection-string) + - [Custom callbacks](#custom-callbacks) +- [Standard library](#standard-library) + - [`vector2D`](#vector2d) + - [`vector2D(x: number | nil, y: number | nil): vector2D`](#vector2dx-number--nil-y-number--nil-vector2d) + - [`vectorFromAngle(ang: number | nil, amp: number | nil): vector2D`](#vectorfromangleang-number--nil-amp-number--nil-vector2d) + - [`vector2D:length(): number`](#vector2dlength-number) + - [`vector2D:lengthSquared(): number`](#vector2dlengthsquared-number) + - [`vector2D:angle(): number`](#vector2dangle-number) + - [`vector2D:normalize(): vector2D`](#vector2dnormalize-vector2d) + - [`vector2D:resize(length: number): vector2D`](#vector2dresizelength-number-vector2d) + - [`vector2D:unpack(): number, number`](#vector2dunpack-number-number) + - [`vector2D:distance(vect: vector2D): number`](#vector2ddistancevect-vector2d-number) + - [`vector2D:distanceSquared(vect: vector2D): number`](#vector2ddistancesquaredvect-vector2d-number) + - [Operations](#operations) + - [`color`](#color) + - [`rgb(r: number, g: number, b: number, a: number | nil): color`](#rgbr-number-g-number-b-number-a-number--nil-color) + - [`hsl(h: number, s: number, l: number, a: number | nil): color`](#hslh-number-s-number-l-number-a-number--nil-color) + - [`hsv(h: number, s: number, v: number, a: number | nil): color`](#hsvh-number-s-number-v-number-a-number--nil-color) + - [`shsv(h: number, s: number, v: number, a: number | nil): color`](#shsvh-number-s-number-v-number-a-number--nil-color) + - [`hex(hex: string): color`](#hexhex-string-color) + - [`color:unpack(): number, number, number, number`](#colorunpack-number-number-number-number) + - [`color:rgb(): number, number, number`](#colorrgb-number-number-number) + - [`color:hsl(): number, number, number`](#colorhsl-number-number-number) + - [`color:hsv(): number, number, number`](#colorhsv-number-number-number) + - [`color:hex(): string`](#colorhex-string) + - [`color:hue(h: number): color`](#colorhueh-number-color) + - [`color:huesmooth(h: number): color`](#colorhuesmoothh-number-color) + - [`color:alpha(a: number): color`](#coloralphaa-number-color) + - [`color:malpha(a: number): color`](#colormalphaa-number-color) + - [`color:invert(): color`](#colorinvert-color) + - [`color:grayscale(): color`](#colorgrayscale-color) + - [`color:hueshift(a: number): color`](#colorhueshifta-number-color) + - [Operations](#operations-1) + - [`input`](#input) + - [A note about keyboard inputs](#a-note-about-keyboard-inputs) + - [`bitop`](#bitop) + - [`rng`](#rng) + - [`rng.init(seed: number[] | nil): rng`](#rnginitseed-number--nil-rng) + - [`rng(a: number | nil, b: number | nil): number`](#rnga-number--nil-b-number--nil-number) + - [`rng:int(min: number, max: number | nil): number`](#rngintmin-number-max-number--nil-number) + - [`rng:float(max: number | nil): number`](#rngfloatmax-number--nil-number) + - [`rng:bool(): boolean`](#rngbool-boolean) + - [`rng:seed(seed: number): void`](#rngseedseed-number-void) + - [`rng:next(): number`](#rngnext-number) + - [`rng:jump(): void`](#rngjump-void) + - [`rng:longJump(): void`](#rnglongjump-void) + - [`uwuify`](#uwuify) +- [Examples](#examples) + - [Default Uranium Template code](#default-uranium-template-code) + - [Simple platformer base](#simple-platformer-base) +- [Credits](#credits) + +## Testimonies + +- "this template really adds some spice to your modfiles. think industrial glitter in your next chilli!" _- Mayflower_ +- "a good template that i have definitely used! jill can i go now. jill please i just want to see my family" _- Aura_ + +## Installation + +Installation is the exact same as any other NotITG template: + +1. Unzip your installation zip, as you would a modfile +2. Edit `Song.sm` in your editor of choice (ArrowVortex, NotITG) to include necessary metadata; replace `silence.ogg` with an actual track, if necessary +3. Edit `main.lua` to do whatever you wish to do with it! The entirety of the `src/` folder is yours! +4. _(Recommended)_ Install [sumneko's Lua LSP](https://marketplace.visualstudio.com/items?itemName=sumneko.lua) and grab the latest NotITG typings [here](https://gitlab.com/CraftedCart/notitg_docs/-/archive/master/notitg_docs-master.zip?path=lua) (put them in a folder like `.typings`!) + +## Distribution + +After you're done with writing your file, be sure to take these steps to reduce the filesize and get your game ready for zipping up! + +- Remove `MANUAL.md`, `jillo_png.png`, `docs/`, `.vscode/`, `.gitconfig`, `.gitignore` and `template/typings.lua`. These are files that aren't necessary outside of a development environment! +- Optionally, remove `Song.sm.auto` and `Song.sm.old`. These files may not exist depending on certain factors. +- If you've followed step 4 during [Installation](#installation), be sure to remove your typings folder (likely `.typings`) +- If you're using Git, **PLEASE REMOVE YOUR `.git/` FOLDER!!!** + +Afterwards, it should be safe to zip everything up and send it over! + +## How do I start writing code? + +`main.lua` is the entry-point for your code! From there, you can do the following: + +- [Define some actors](#defining-actors), and [call initialization methods on those actors](#initializing-actors) to set them up +- [Define callbacks](#callback-usage), such as the [update](#uraniumupdatedt-number) callback +- Require more files in! Splitting your code into neat little modules is always good practice. +- Make use of the expansive standard library, like the vector or color classes + +If you're still a bit clueless, why not check out the [Examples](#examples) section? + +## Defining actors + +Actors are defined in Uranium Template before any other callback runs, and are defined by a single function of their type: + +```lua +local quad = Quad() +local sprite = Sprite('file/location.png') +local text = BitmapText('common', 'hello, world!') +``` + +### Initializing actors + +Once you have an actor defined, you can run whatever methods you want. + +> **Note** +> Even though you get a fully functional actor, what you actually get is a _proxied actor_! What this means for you is that you really shouldn't call any getters on the actor, as it'll just return `nil`. + +```lua +local text = BitmapText('common', 'hello, world!') +text:xy(scx, scy) +text:zoom(2.3) +text:rotationz(30) +text:diffuse(1, 0.8, 0.8, 1) +``` + +All methods that you run upon definition will be ran again at the start of every frame: + +```lua +local quad = Quad() +quad:xy(scx, scy) +quad:zoomto(60, 60) +quad:diffusealpha(1) + +function uranium.update() + -- doesn't need a reset! it'll automatically zoomto 60, 60 and set its alpha to 1 + quad:Draw() + quad:zoomto(120, 120) + quad:diffusealpha(0.5) + quad:Draw() +end +``` + +If you want to avoid this, or otherwise call getter methods, use the [`uranium.init`](#uraniuminit) callback: + +```lua +local sprite = Sprite() + +function uranium.init() + someTexture = sprite:GetTexture() +end +``` + +Alternatively, you can also use the actors' individual `InitCommand`s: +```lua +local sprite = Sprite() +sprite:addcommand('Init', function(self) + someTexture = self:GetTexture() +end) +``` + +## Callback usage + +Uranium uses a unique callback system - to define a callback, you define a function under `uranium.` with your desired callback name: + +```lua +function uranium.update(dt) + -- runs every frame +end +``` + +You can do this as many times as you like - it'll call every single function that's defined as `uranium.update`, not just the last! + +If you return a non-falsy value in a callback, however, it'll cancel every other callback after it. This can be useful for, eg. capturing inputs and ensuring they don't get passed through to other callbacks on accident. + +### Default callbacks + +These are the callbacks that are built into Uranium: + +#### `uranium.update(dt: number)` +Called every frame. `dt` is the time passed since the last frame, the "deltatime". + +#### `uranium.init()` +Called once on `OnCommand`. Every actor has been created, and the game should be starting shortly. + +#### `uranium.press(direction: string)` +Called when the player presses on a certain key. **Currently only supports arrow keys!!** `direction` can be `Left`, `Down`, `Up` or `Right` (TODO: change this to an enum). + +#### `uranium.release(direction: string)` +Same as [`uranium.press`](#uraniumpressdirection-string), except for releasing a key. + +### Custom callbacks + +Custom callbacks require no extra setup. Define your callback like usual: + +```lua +function uranium.somethingHappened(value) + -- ... +end +``` + +Then all you need to do to call it is: + +```lua +uranium:call('somethingHappened', extra, values, go, here) +``` + +Callbacks support as many extra values as Lua supports arguments in a function - so let's just say you won't be running out of them any time soon. + +## Standard library + +The Uranium Template standard library is split up into a few convinient modules. This section aims to comprehensively document them all. + +### `vector2D` + +`vector2D` is a simple 2D vector class system. For example, to define a vector: +```lua +local vec = vector2D(0, 0) +-- or +local vec = vector(0, 0) +-- or +local vec = vector(0) +-- or +local vec = vector() +``` + +Then add another vector to it: +```lua +vec = vec + vector(1) +print(vec) --> (1, 1) +``` + +Then measure its length: +```lua +local len = vec:length() +print(len) --> 1.4142135623730951 + -- (sqrt of 2) +``` + +Then rotate it and index it: +```lua +vec:rotate(180) + +local x = vec.x +-- or +local x = vec[1] + +print(x) --> -1 +``` + +#### `vector2D(x: number | nil, y: number | nil): vector2D` + +Creates a new vector. If only `x` is passed in, `y` = `x`. If no arguments are passed, `x` = `y` = `0`. + +#### `vectorFromAngle(ang: number | nil, amp: number | nil): vector2D` + +Creates a new vector pointing in a specific angle. **Specify `ang` in degrees.** `ang` defaults to 0, `amp` defaults to 1. + +#### `vector2D:length(): number` + +Returns the vector's length. Equal to `vector:distance(vector())`. + +#### `vector2D:lengthSquared(): number` + +Returns the vector's length, squared. Here mainly for optimization purposes; this is a cheaper version of [`length()`](#vectorlength-number) that's less accurate. + +#### `vector2D:angle(): number` + +Returns the vector's angle in radians. + +#### `vector2D:normalize(): vector2D` + +Normalizes the vector, setting its length to 1 but keeping its angle. Equal to `vector:resize(1)` + +#### `vector2D:resize(length: number): vector2D` + +Resizes the vector, setting its length but keeping its angle. + +#### `vector2D:unpack(): number, number` + +Unpacks the vector into its X and Y coordinates. Useful for quickly unpacking it into a function call: +```lua +local quad = Quad() +quad:xy(center:unpack()) +``` + +#### `vector2D:distance(vect: vector2D): number` + +Gets the distance between one vector and another. + +#### `vector2D:distanceSquared(vect: vector2D): number` + +Gets the distance between one vector and another, squared. Here mainly for optimization purposes; this is a cheaper version of [`distance()`](#vectordistancevect-vector-number) that's less accurate. + +#### Operations + +Here are all valid operations for vectors: + +- `vector2D + number`: equal to `vector2D + vector2D(number)` +- `vector2D + vector2D`: adds the vectors' X and Y coordinates together, respectively, forming a new vector +- `vector2D - number`: equal to `vector2D - vector2D(number)` +- `vector2D - vector2D`: subtracts the vectors' X and Y coordinates, respectively, forming a new vector +- `vector2D * number`: equal to `vector2D * vector2D(number)` +- `vector2D * vector2D`: multiplies the vectors' X and Y coordinates together, respectively, forming a new vector +- `vector2D / number`: equal to `vector2D / vector2D(number)` +- `vector2D / vector2D`: divides the vectors' X and Y coordinates, respectively, forming a new vector +- `vector2D == vector2D`: checks if the two vectors' X and Y coordinates are equivalent; returns false with any other type +- `-vector2D`: negates the X and Y coordinates of the vector + +### `color` + +`color` is a simple wrapper around all things color-related. + +#### `rgb(r: number, g: number, b: number, a: number | nil): color` + +Constructs a new color using the `r`, `g`, `b` and `a` values. Assumes all values are contained in the set [0, 1]. `a` defaults to 1. + +#### `hsl(h: number, s: number, l: number, a: number | nil): color` + +Constructs a new color using the `h`, `s`, `l` and `a` values using the [HSL color model](https://en.wikipedia.org/wiki/HSL_and_HSV). Assumes all values are contained in the set [0, 1]. `a` defaults to 1; `h` wraps around. + +#### `hsv(h: number, s: number, v: number, a: number | nil): color` + +Constructs a new color using the `h`, `s`, `v` and `a` values using the [HSV color model](https://en.wikipedia.org/wiki/HSL_and_HSV). Assumes all values are contained in the set [0, 1]. `a` defaults to 1; `h` wraps around. + +#### `shsv(h: number, s: number, v: number, a: number | nil): color` + +Equal to [`hsv()`](#hsvh-number-s-number-v-number-a-number--nil), except the hue value is smoothed using cubic smoothing. Not accurate, but produces neater-looking color blends for rainbow-shifting colors. + +```lua +local rainbow = shsv(t, 1, 0.5) +``` + +#### `hex(hex: string): color` + +Reads in a hex string and parses it into a `color`. Accepted hex string formats are `#ffffff`, `ffffff`, `#fff` and `fff`. + +#### `color:unpack(): number, number, number, number` + +Unpacks the color into its R, G, B and A values. Useful for `diffuse`: +```lua +local quad = Quad() +quad:diffuse(col:unpack()) +``` + +#### `color:rgb(): number, number, number` + +Returns the color's R, G and B values. + +#### `color:hsl(): number, number, number` + +Returns the color's H, S and L values in the [HSL color model](https://en.wikipedia.org/wiki/HSL_and_HSV). + +#### `color:hsv(): number, number, number` + +Returns the color's H, S and V values in the [HSV color model](https://en.wikipedia.org/wiki/HSL_and_HSV). + +#### `color:hex(): string` + +Returns the color's hex string representation in the format `ffffff`. + +#### `color:hue(h: number): color` + +Sets the color's hue value in the [HSL/HSV color model](https://en.wikipedia.org/wiki/HSL_and_HSV). + +#### `color:huesmooth(h: number): color` + +Equivalent to [`color:hue()`](#colorhueh-number-color), except the hue value is smoothed using cubic smoothing. Not accurate, but produces neater-looking color blends for rainbow-shifting colors. + +#### `color:alpha(a: number): color` + +Sets the color's alpha channel. + +#### `color:malpha(a: number): color` + +Sets the color's alpha channel, multiplying the previous value with `a`. + +#### `color:invert(): color` + +Inverts the color. + +#### `color:grayscale(): color` + +Makes the color grayscale using a more accurate formula than just multiplying every value by `0.5`. + +#### `color:hueshift(a: number): color` + +Shifts the color's hue by `a`. + +#### Operations + +Here are all valid operations for colors: + +- `color + number`: equal to `color + rgb(number, number, number)` +- `color + color`: adds the colors' R, G and B values together, respectively, forming a new color +- `color - number`: equal to `color - rgb(number, number, number)` +- `color - color`: subtracts the colors' R, G and B values, respectively, forming a new color +- `color * number`: equal to `color * rgb(number, number, number)` +- `color * color`: multiplies the colors' R, G and B values together, respectively, forming a new color +- `color / number`: equal to `color / rgb(number, number, number)` +- `color / color`: divides the colors' R, G and B values, respectively, forming a new color +- `color == color`: checks if the two colors' R, G and B values are equivalent; returns false with any other type + +### `input` + +`input` is the library that handles everything input-related. Its main feature is providing the `press` and `release` callbacks, but you can also access the raw inputs with the `inputs` table (each value is `-1` if the key is not pressed and the time at which it was pressed, estimated with `t` if it is pressed) and the _raw_ inputs (ignoring callback returns) with `rawInputs`. Additionally, for your convinience, it provides a `directions` enum: +```lua +directions = { + Left = {-1, 0}, + Down = {0, 1}, + Up = {0, -1}, + Right = {1, 0} +} +``` + +#### A note about keyboard inputs + +Working with left/down/up/right inputs can be tiring at times and it's hard to always fit designs to work with them. However, if you're willing to take a little compromise, you can also _access all keyboard inputs_. However, it's worth noting that this **depends on NotITG's Simply Love** (any forks will work fine too) both for your development environment and for all players. That being said, if you want to access the keyboard API, this is how you do it: + +```lua +-- check if the user is using simply love at all +if not stitch then error('This modfile requires the Simply Love theme! https://github.com/TaroNuke/Simply-love-NotITG-ver.-') end + +keyboard = stitch('lua.keyboard') + +-- table that contains every keyboard key as the key and a boolean as the value +local buffer = keyboard.buffer +-- for example: +local isDebugKeyHeld = buffer['F3'] + +-- contains booleans for shift, ctrl, alt, win and altgr +local special = keyboard.special +local isDebugKeyAndShiftHeld = isDebugKeyHeld and special.shift +``` + +### `bitop` + +A Lua 5.0 port of [bitop-lua](https://github.com/AlberTajuelo/bitop-lua). See their repository for documentation. + +### `rng` + +A xoshiro128** reimplementation in Lua. + +#### `rng.init(seed: number[] | nil): rng` + +Initializes a new RNG class. `seed` must be a table of size 4; if it is not provided, `os.time()` is used in its place. + +#### `rng(a: number | nil, b: number | nil): number` + +Acts identical to `math.random()`. Pass in no arguments to get a random float from 0 to 1, pass in one argument to get a random inclusive integer from 1 to `a`, pass in two arguments to get a random integer from `a` to `b`. + +#### `rng:int(min: number, max: number | nil): number` + +Generates an inclusive random integer. Pass in one argument to get a random integer from 1 to `a`, pass in two arguments to get a random integer from `a` to `b`. + +#### `rng:float(max: number | nil): number` + +Generates a random fractional number from `0` to `max`. `max` defaults to 1. + +#### `rng:bool(): boolean` + +Generates either a `true` or a `false` randomly. + +#### `rng:seed(seed: number): void` + +Sets the seed and advances the state. + +#### `rng:next(): number` + +Gets the next pseudo-random value. Recommended to use [`int`](#rngintmin-number-max-number-number), [`float`](#rngfloatmax-number--nil-number), etc. over this. + +#### `rng:jump(): void` + +The jump function: + +> This is the jump function for the generator. It is equivalent +> to 2^64 calls to next(); it can be used to generate 2^64 +> non-overlapping subsequences for parallel computations. + +#### `rng:longJump(): void` + +The long-jump function: + +> This is the long-jump function for the generator. It is equivalent to +> 2^96 calls to next(); it can be used to generate 2^32 starting points, +> from each of which jump() will generate 2^32 non-overlapping +> subsequences for parallel distributed computations. + +### `uwuify` + +```lua +print(uwuify('hello, world!')) --> hewwo, wowwd! +``` + +_A very important library I don't see enough game engines include in their standard libraries._ + +## Examples + +Here are a couple of examples. All of these are standalone `main.lua` files that you can plug in and view the results of! + +### Default Uranium Template code +```lua +-- define a basic quad +local quad = Quad() +quad:xy(scx, scy) +quad:zoomto(120, 120) +quad:diffuse(0.8, 1, 0.7, 1) +quad:skewx(0.2) + +-- define a sprite +local sprite = Sprite('../docs/uranium.png') +sprite:xy(scx, scy) +sprite:zoom(0.4) + +-- let's add some text aswell +local text = BitmapText('common', 'hello, uranium template!') +text:xy(scx, scy + 100) + +-- update gets called every frame +-- dt here refers to deltatime - the time that has passed since the last frame! +function uranium.update(dt) + -- let's rotate our quad + quad:rotationz(t * 80) + -- then shove it to the screen - similar to a drawfunction! + quad:Draw() + -- and you can do this multiple times of course! + quad:zoomto(180, 180) + quad:rotationz(t * 100) + quad:diffusealpha(0.4) + quad:skewx(0.1) + quad:Draw() + -- no need to reset properties - uranium resets all properties that you set upon definition! + + -- throw in the logo aswell, because why not + sprite:Draw() + + -- for the text, get a rainbow color + local col = rgb(1, 0.4, 0.4):huesmooth(t * 0.6) + text:diffuse(col:unpack()) -- the :unpack() is necessary when passing into :diffuse() + -- wag the text + text:rotationz(math.sin(t * 2) * 10) + text:Draw() +end +``` + +### Simple platformer base +```lua +-- constants are just those that felt nice to me. this is completely valid to do in gamedev +local DAMPING = 1/9500 +local SPEED = 2 +local JUMP_FORCE = 32 +local GRAVITY = 2.3 +local PLAYER_SIZE = 50 + +local groundY = sh * 0.8 + +local protagActor = Quad() +protagActor:zoomto(PLAYER_SIZE, PLAYER_SIZE) +local ground = Quad() +ground:zoomto(sw, 4) +ground:xy(scx, groundY + PLAYER_SIZE/2 + 4/2) + +local pos = vector(scx, groundY) +local vel = vector(0, 0) +local hasHitGround = true -- let's define this so that you can't jump mid-air + +-- called whenever the player recieves an input +function uranium.press(direction) + if direction == 'Up' and hasHitGround then + vel.y = vel.y - JUMP_FORCE + hasHitGround = false + return true -- input eaten! further callbacks won't recieve this + end +end + +function uranium.update(dt) + -- respond to l/r inputs + if inputs.Left ~= -1 then + vel.x = vel.x - SPEED + end + if inputs.Right ~= -1 then + vel.x = vel.x + SPEED + end + + -- apply gravity + vel.y = vel.y + GRAVITY + + -- update position, apply damping to velocity + pos = pos + vel + vel = vel * math.pow(DAMPING, dt) + + -- make sure the player can't clip through the ground + if pos.y >= groundY then + pos.y = groundY + if vel.y >= 0 then vel.y = 0 end + hasHitGround = true + end + + -- make sure the player can't leave the screen on accident + pos.x = math.min(pos.x, sw - PLAYER_SIZE/2) + pos.x = math.max(pos.x, 0 + PLAYER_SIZE/2) + + -- draw them! + protagActor:xy(pos.x, pos.y) + protagActor:Draw() + + -- draw the ground + ground:Draw() +end +``` + +## Credits + +**XeroOl** - Mirin Template was a massive design inspiration; early stages of this template borrowed lots of code from it
+**Mayflower**, **Aura** - Testing, design help
+**mangoafterdawn** - The Uranium Template logo!
+ +


+
+ You didn't delete the included image of Jillo, did you? +
\ No newline at end of file diff --git a/Song.sm b/Song.sm new file mode 100644 index 0000000..6884fd5 --- /dev/null +++ b/Song.sm @@ -0,0 +1,2010 @@ +#TITLE:Uranium Template; +#SUBTITLE:; +#ARTIST:oatmealine; +#TITLETRANSLIT:; +#SUBTITLETRANSLIT:; +#ARTISTTRANSLIT:; +#GENRE:; +#CREDIT:oatmealine; +#BANNER:; +#BACKGROUND:; +#LYRICSPATH:; +#CDTITLE:; +#MUSIC:silence.ogg; +#OFFSET:0.000; +#SAMPLESTART:0.000; +#SAMPLELENGTH:12.000; +#SELECTABLE:YES; +#BPMS:0.000=100.000; +#STOPS:; +#TIMESIGNATURES:0.000=4=4; +#BGCHANGES:; + +//The majority of simfile scripts and visual effects are stored here. +#FGCHANGES:-10.000=template/main.xml=-10.000=0=0=1=====, +; + +#KEYSOUNDS:; + +//---------------dance-single - ---------------- +#NOTES: + dance-single: + Medium: + Challenge: + 1: + 0.000,0.000,0.000,0.000,0.000: +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +0000 +0000 +0000 +0000 +, +M000 +0M00 +00M0 +000M +; \ No newline at end of file diff --git a/docs/uranium.png b/docs/uranium.png new file mode 100644 index 0000000000000000000000000000000000000000..26cd73ca3057764fe8a22f1da08a124f9d7dc8c8 GIT binary patch literal 31686 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 Q1~*7fN=dRx+&JWa0LS9PGynhq literal 0 HcmV?d00001 diff --git a/docs/uranium_full.png b/docs/uranium_full.png new file mode 100644 index 0000000000000000000000000000000000000000..a4d6015648134801d26303274728c1225762310b GIT binary patch literal 74394 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
JKd4YioCc#S6 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 literal 0 HcmV?d00001 diff --git a/silence.ogg b/silence.ogg new file mode 100644 index 0000000000000000000000000000000000000000..ac9071d037820b3a9b5e1653d1fd27af7a11ac5a GIT binary patch literal 4316 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 + + + + + \ No newline at end of file diff --git a/template/main.xml b/template/main.xml new file mode 100644 index 0000000..06fd83c --- /dev/null +++ b/template/main.xml @@ -0,0 +1,482 @@ + + + + \ No newline at end of file diff --git a/template/stdlib/bitop.lua b/template/stdlib/bitop.lua new file mode 100644 index 0000000..a40b31c --- /dev/null +++ b/template/stdlib/bitop.lua @@ -0,0 +1,343 @@ +local M = {_TYPE='module', _NAME='bitop.funcs', _VERSION='1.0-0'} + +local floor = math.floor + +local MOD = math.pow(2, 32) +local MODM = MOD-1 + +local function memoize(f) + + local mt = {} + local t = setmetatable({}, mt) + + function mt:__index(k) + local v = f(k) + t[k] = v + return v + end + + return t +end + +local function make_bitop_uncached(t, m) + local function bitop(a, b) + local res,p = 0,1 + while a ~= 0 and b ~= 0 do + local am, bm = a%m, b%m + res = res + t[am][bm]*p + a = (a - am) / m + b = (b - bm) / m + p = p*m + end + res = res + (a+b) * p + return res + end + return bitop +end + +local function make_bitop(t) + local op1 = make_bitop_uncached(t, math.pow(2, 1)) + local op2 = memoize(function(a) + return memoize(function(b) + return op1(a, b) + end) + end) + return make_bitop_uncached(op2, math.pow(2, (t.n or 1))) +end + +-- ok? probably not if running on a 32-bit int Lua number type platform +function M.tobit(x) + return x % math.pow(2, 32) +end + +M.bxor = make_bitop {[0]={[0]=0,[1]=1},[1]={[0]=1,[1]=0}, n=4} +local bxor = M.bxor + +function M.bnot(a) return MODM - a end +local bnot = M.bnot + +function M.band(a,b) return ((a+b) - bxor(a,b))/2 end +local band = M.band + +function M.bor(a,b) return MODM - band(MODM - a, MODM - b) end +local bor = M.bor + +local lshift, rshift -- forward declare + +function M.rshift(a,disp) -- Lua5.2 insipred + if disp < 0 then return lshift(a,-disp) end + return floor(a % math.pow(2, 32) / math.pow(2, disp)) +end +rshift = M.rshift + +function M.lshift(a,disp) -- Lua5.2 inspired + if disp < 0 then return rshift(a,-disp) end + return (a * math.pow(2, disp)) % math.pow(2, 32) +end +lshift = M.lshift + +function M.tohex(x, n) -- BitOp style + n = n or 8 + local up + if n <= 0 then + if n == 0 then return '' end + up = true + n = - n + end + x = band(x, math.pow(16, n-1)) + return ('%0'..n..(up and 'X' or 'x')):format(x) +end +local tohex = M.tohex + +function M.extract(n, field, width) -- Lua5.2 inspired + width = width or 1 + return band(rshift(n, field), math.pow(2, width-1)) +end +local extract = M.extract + +function M.replace(n, v, field, width) -- Lua5.2 inspired + width = width or 1 + local mask1 = math.pow(2, width-1) + v = band(v, mask1) -- required by spec? + local mask = bnot(lshift(mask1, field)) + return band(n, mask) + lshift(v, field) +end +local replace = M.replace + +function M.bswap(x) -- BitOp style + local a = band(x, 0xff); x = rshift(x, 8) + local b = band(x, 0xff); x = rshift(x, 8) + local c = band(x, 0xff); x = rshift(x, 8) + local d = band(x, 0xff) + return lshift(lshift(lshift(a, 8) + b, 8) + c, 8) + d +end +local bswap = M.bswap + +function M.rrotate(x, disp) -- Lua5.2 inspired + disp = disp % 32 + local low = band(x, math.pow(2, disp-1)) + return rshift(x, disp) + lshift(low, 32-disp) +end +local rrotate = M.rrotate + +function M.lrotate(x, disp) -- Lua5.2 inspired + return rrotate(x, -disp) +end +local lrotate = M.lrotate + +M.rol = M.lrotate -- LuaOp inspired +M.ror = M.rrotate -- LuaOp insipred + + +function M.arshift(x, disp) -- Lua5.2 inspired + local z = rshift(x, disp) + if x >= 0x80000000 then z = z + lshift(math.pow(2, disp-1), 32-disp) end + return z +end +local arshift = M.arshift + +function M.btest(x, y) -- Lua5.2 inspired + return band(x, y) ~= 0 +end + +-- +-- Start Lua 5.2 "bit32" compat section. +-- + +M.bit32 = {} -- Lua 5.2 'bit32' compatibility + + +local function bit32_bnot(x) + return (-1 - x) % MOD +end +M.bit32.bnot = bit32_bnot + +-- something here causes a syntax error so im just commenting out since i dont need it anyways +--[[ +local function bit32_bxor(a, b, c, ...) + local z + if b then + a = a % MOD + b = b % MOD + z = bxor(a, b) + if c then + z = bit32_bxor(z, c, ...) + end + return z + elseif a then + return a % MOD + else + return 0 + end +end +M.bit32.bxor = bit32_bxor + +local function bit32_band(a, b, c, ...) + local z + if b then + a = a % MOD + b = b % MOD + z = ((a+b) - bxor(a,b)) / 2 + if c then + z = bit32_band(z, c, ...) + end + return z + elseif a then + return a % MOD + else + return MODM + end +end +M.bit32.band = bit32_band + +local function bit32_bor(a, b, c, ...) + local z + if b then + a = a % MOD + b = b % MOD + z = MODM - band(MODM - a, MODM - b) + if c then + z = bit32_bor(z, c, ...) + end + return z + elseif a then + return a % MOD + else + return 0 + end +end +M.bit32.bor = bit32_bor + +function M.bit32.btest(...) + return bit32_band(...) ~= 0 +end + +function M.bit32.lrotate(x, disp) + return lrotate(x % MOD, disp) +end + +function M.bit32.rrotate(x, disp) + return rrotate(x % MOD, disp) +end + +function M.bit32.lshift(x,disp) + if disp > 31 or disp < -31 then return 0 end + return lshift(x % MOD, disp) +end + +function M.bit32.rshift(x,disp) + if disp > 31 or disp < -31 then return 0 end + return rshift(x % MOD, disp) +end + +function M.bit32.arshift(x,disp) + x = x % MOD + if disp >= 0 then + if disp > 31 then + return (x >= 0x80000000) and MODM or 0 + else + local z = rshift(x, disp) + if x >= 0x80000000 then z = z + lshift(math.pow(2, disp-1), 32-disp) end + return z + end + else + return lshift(x, -disp) + end +end + +function M.bit32.extract(x, field, ...) + local width = ... or 1 + if field < 0 or field > 31 or width < 0 or field+width > 32 then error 'out of range' end + x = x % MOD + return extract(x, field, ...) +end + +function M.bit32.replace(x, v, field, ...) + local width = ... or 1 + if field < 0 or field > 31 or width < 0 or field+width > 32 then error 'out of range' end + x = x % MOD + v = v % MOD + return replace(x, v, field, ...) +end + + +-- +-- Start LuaBitOp "bit" compat section. +-- + +M.bit = {} -- LuaBitOp "bit" compatibility + +function M.bit.tobit(x) + x = x % MOD + if x >= 0x80000000 then x = x - MOD end + return x +end +local bit_tobit = M.bit.tobit + +function M.bit.tohex(x, ...) + return tohex(x % MOD, ...) +end + +function M.bit.bnot(x) + return bit_tobit(bnot(x % MOD)) +end + +local function bit_bor(a, b, c, ...) + if c then + return bit_bor(bit_bor(a, b), c, ...) + elseif b then + return bit_tobit(bor(a % MOD, b % MOD)) + else + return bit_tobit(a) + end +end +M.bit.bor = bit_bor + +local function bit_band(a, b, c, ...) + if c then + return bit_band(bit_band(a, b), c, ...) + elseif b then + return bit_tobit(band(a % MOD, b % MOD)) + else + return bit_tobit(a) + end +end +M.bit.band = bit_band + +local function bit_bxor(a, b, c, ...) + if c then + return bit_bxor(bit_bxor(a, b), c, ...) + elseif b then + return bit_tobit(bxor(a % MOD, b % MOD)) + else + return bit_tobit(a) + end +end +M.bit.bxor = bit_bxor + +function M.bit.lshift(x, n) + return bit_tobit(lshift(x % MOD, n % 32)) +end + +function M.bit.rshift(x, n) + return bit_tobit(rshift(x % MOD, n % 32)) +end + +function M.bit.arshift(x, n) + return bit_tobit(arshift(x % MOD, n % 32)) +end + +function M.bit.rol(x, n) + return bit_tobit(lrotate(x % MOD, n % 32)) +end + +function M.bit.ror(x, n) + return bit_tobit(rrotate(x % MOD, n % 32)) +end + +function M.bit.bswap(x) + return bit_tobit(bswap(x % MOD)) +end +]] + +return M diff --git a/template/stdlib/color.lua b/template/stdlib/color.lua new file mode 100644 index 0000000..4855741 --- /dev/null +++ b/template/stdlib/color.lua @@ -0,0 +1,299 @@ + +--[[ + * Converts an HSL color value to RGB. Conversion formula + * adapted from http://en.wikipedia.org/wiki/HSL_color_space. + * Assumes h, s, and l are contained in the set [0, 1] and + * returns r, g, and b in the set [0, 1]. +]] +local function hslToRgb(h, s, l) + local r, g, b + + if s == 0 then + r, g, b = l, l, l -- achromatic + else + function hue2rgb(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 end + if t < 1/2 then return q end + if t < 2/3 then return p + (q - p) * (2/3 - t) * 6 end + return p + end + + local q + if l < 0.5 then q = l * (1 + s) else q = l + s - l * s end + local p = 2 * l - q + + r = hue2rgb(p, q, h + 1/3) + g = hue2rgb(p, q, h) + b = hue2rgb(p, q, h - 1/3) + end + + return r, g, b +end + +--[[ + * Converts an HSL color value to RGB. Conversion formula + * adapted from http://en.wikipedia.org/wiki/HSL_color_space. + * Assumes h, s, and l are contained in the set [0, 1] and + * returns r, g, and b in the set [0, 1]. +]] +local function rgbToHsl(r, g, b) + local max, min = math.max(r, g, b), math.min(r, g, b) + local h, s, l + + l = (max + min) / 2 + if max == 0 then s = 0 else s = (max - min) / max end + + if max == min then + h, s = 0, 0 -- achromatic + else + local d = max - min + local s + if l > 0.5 then s = d / (2 - max - min) else s = d / (max + min) end + if max == r then + h = (g - b) / d + if g < b then h = h + 6 end + elseif max == g then h = (b - r) / d + 2 + elseif max == b then h = (r - g) / d + 4 + end + h = h / 6 + end + + return h, s, l +end + + +--[[ + * Converts an RGB color value to HSV. Conversion formula + * adapted from http://en.wikipedia.org/wiki/HSV_color_space. + * Assumes r, g, and b are contained in the set [0, 1] and + * returns h, s, and v in the set [0, 1]. +]] +local function rgbToHsv(r, g, b) + local max, min = math.max(r, g, b), math.min(r, g, b) + local h, s, v + v = max + + local d = max - min + if max == 0 then s = 0 else s = d / max end + + if max == min then + h = 0 -- achromatic + else + if max == r then + h = (g - b) / d + if g < b then h = h + 6 end + elseif max == g then h = (b - r) / d + 2 + elseif max == b then h = (r - g) / d + 4 + end + h = h / 6 + end + + return h, s, v +end + +--[[ + * Converts an HSV color value to RGB. Conversion formula + * adapted from http://en.wikipedia.org/wiki/HSV_color_space. + * Assumes h, s, and v are contained in the set [0, 1] and + * returns r, g, and b in the set [0, 1]. +]] +local function hsvToRgb(h, s, v) + local r, g, b + + local i = math.floor(h * 6); + local f = h * 6 - i; + local p = v * (1 - s); + local q = v * (1 - f * s); + local t = v * (1 - (1 - f) * s); + + i = i % 6 + + if i == 0 then r, g, b = v, t, p + elseif i == 1 then r, g, b = q, v, p + elseif i == 2 then r, g, b = p, v, t + elseif i == 3 then r, g, b = p, q, v + elseif i == 4 then r, g, b = t, p, v + elseif i == 5 then r, g, b = v, p, q + end + + return r, g, b +end + +---@class color +---@field r number @red, 0.0 - 1.0 +---@field g number @green, 0.0 - 1.0 +---@field b number @blue, 0.0 - 1.0 +---@field a number @alpha, 0.0 - 1.0 +---@operator add(color): color +---@operator add(number): color +---@operator sub(color): color +---@operator sub(number): color +---@operator mul(color): color +---@operator mul(number): color +---@operator div(color): color +---@operator div(number): color +local col = {} + +--- for use in actor:diffuse(col:unpack()) +---@return number, number, number, number +function col:unpack() + return self.r, self.g, self.b, self.a +end + +-- conversions + +---@return number, number, number +function col:rgb() + return self.r, self.g, self.b +end + +---@return number, number, number +function col:hsl() + return rgbToHsl(self.r, self.g, self.b) +end + +---@return number, number, number +function col:hsv() + return rgbToHsv(self.r, self.g, self.b) +end + +---@return string +function col:hex() + return string.format('%02x%02x%02x', + math.floor(self.r * 255), + math.floor(self.g * 255), + math.floor(self.b * 255)) +end + +-- setters + +---@return color +function col:hue(h) + local _, s, v = self:hsv() + return hsv(h % 1, s, v, self.a) +end + +---@return color +function col:huesmooth(h) + local _, s, v = self:hsv() + return shsv(h % 1, s, v, self.a) +end + +---@return color +function col:alpha(a) + return rgb(self.r, self.g, self.b, a) +end + +--- multiplies current alpha by provided value +---@return color +function col:malpha(a) + return rgb(self.r, self.g, self.b, self.a * a) +end + +-- effects + +---@return color +function col:invert() + return rgb(1 - self.r, 1 - self.g, 1 - self.b, self.a) +end + +---@return color +function col:grayscale() + return rgb(self.r * 0.299 + self.g * 0.587 + self.b * 0.114, self.a) +end + +---@return color +function col:hueshift(a) + local h, s, v = self:hsv() + return hsv((h + a) % 1, s, v, self.a) +end + +local colmeta = {} + +function colmeta:__index(i) + if i == 1 then return self.r end + if i == 2 then return self.g end + if i == 3 then return self.b end + if i == 4 then return self.a end + return col[i] +end + +local function typ(a) + return (type(a) == 'table' and a.r and a.g and a.b and a.a) and 'color' or type(a) +end + +local function genericop(a, b, f, name) + local typea = typ(a) + local typeb = typ(b) + if typea == 'number' then + return rgb(f(b.r, a), f(b.g, a), f(b.b, a), b.a) + elseif typeb == 'number' then + return rgb(f(a.r, b), f(a.g, b), f(a.b, b), a.a) + elseif typea == 'color' and typeb == 'color' then + return rgb(f(a.r, b.r), f(a.g, b.g), f(a.b, b.b), f(a.a, b.a)) + end + error('cant apply ' .. name .. ' to ' .. typea .. ' and ' .. typeb, 3) +end + +function colmeta.__add(a, b) + return genericop(a, b, function(a, b) return a + b end, 'add') +end +function colmeta.__sub(a, b) + return genericop(a, b, function(a, b) return a - b end, 'sub') +end +function colmeta.__mul(a, b) + return genericop(a, b, function(a, b) return a * b end, 'mul') +end +function colmeta.__div(a, b) + return genericop(a, b, function(a, b) return a / b end, 'div') +end + +function colmeta.__eq(a, b) + return (typ(a) == 'color' and typ(b) == 'color') and (a.r == b.r and a.g == b.g and a.b == b.b and a.a == b.a) +end + +function colmeta:__tostring() + return '#' .. self:hex() +end +colmeta.__name = 'color' + +-- constructors + +---@return color +function rgb(r, g, b, a) + a = a or 1 + return setmetatable({r = r, g = g, b = b, a = a or 1}, colmeta) +end + +---@return color +function hsl(h, s, l, a) + a = a or 1 + local r, g, b = hslToRgb(h % 1, s, l) + return setmetatable({r = r, g = g, b = b, a = a or 1}, colmeta) +end + +---@return color +function hsv(h, s, v, a) + a = a or 1 + local r, g, b = hsvToRgb(h % 1, s, v) + return setmetatable({r = r, g = g, b = b, a = a or 1}, colmeta) +end + +--- smoother hsv. not correct but looks nicer +---@return color +function shsv(h, s, v, a) + return hsv(h * h * (3 - 2 * h), s, v, a) +end + +---@param hex string +---@return color +function hex(hex) + hex = string.gsub(hex, '#', '') + if string.len(hex) == 3 then + return rgb((tonumber('0x' .. string.sub(hex, 1, 1)) * 17) / 255, (tonumber('0x' .. string.sub(hex, 2, 2)) * 17) / 255, (tonumber('0x' .. string.sub(hex, 3, 3)) * 17) / 255) + else + return rgb(tonumber('0x' .. string.sub(hex, 1, 2)) / 255, tonumber('0x' .. string.sub(hex, 3, 4)) / 255, tonumber('0x' .. string.sub(hex, 5, 6)) / 255) + end +end \ No newline at end of file diff --git a/template/stdlib/easable.lua b/template/stdlib/easable.lua new file mode 100644 index 0000000..fbf07c9 --- /dev/null +++ b/template/stdlib/easable.lua @@ -0,0 +1,80 @@ +---@class easable +---@field public a number @the eased value +---@field public toa number @the target, uneased value +---@field protected onUpdateFuncs fun():nil[] +local eas = {} + +---@param new number @New value to ease to +---@return void +function eas:set(new) + self.toa = new +end + +---@param new number @New value +---@return void +function eas:reset(new) + self.toa = new + self.a = new +end + +---@param new number @How much to add to current value to ease to +---@return void +function eas:add(new) + self.toa = self.toa + new +end + +---@param func fun(a: number):void @Adds a callback function that will run each time the eased value changes +---@return void +function eas:onUpdate(func) + table.insert(self.onUpdateFuncs, func) +end + +local easmeta = {} + +easmeta.__index = eas +easmeta.__name = 'easable' + +function easmeta.__add(a, b) + return ((type(a) == 'table' and a.a) and a.a or a) + ((type(b) == 'table' and b.a) and b.a or b) +end +function easmeta.__sub(a, b) + return ((type(a) == 'table' and a.a) and a.a or a) - ((type(b) == 'table' and b.a) and b.a or b) +end +function easmeta.__mul(a, b) + return ((type(a) == 'table' and a.a) and a.a or a) * ((type(b) == 'table' and b.a) and b.a or b) +end +function easmeta.__div(a, b) + return ((type(a) == 'table' and a.a) and a.a or a) / ((type(b) == 'table' and b.a) and b.a or b) +end +function easmeta.__mod(a, b) + return ((type(a) == 'table' and a.a) and a.a or a) % ((type(b) == 'table' and b.a) and b.a or b) +end +function easmeta.__eq(a, b) + return ((type(a) == 'table' and a.a) and a.a or a) == ((type(b) == 'table' and b.a) and b.a or b) +end +function easmeta.__lt(a, b) + return ((type(a) == 'table' and a.a) and a.a or a) < ((type(b) == 'table' and b.a) and b.a or b) +end +function easmeta.__le(a, b) + return ((type(a) == 'table' and a.a) and a.a or a) <= ((type(b) == 'table' and b.a) and b.a or b) +end + +function easmeta:__call(dt) + self.a = mix(self.a, self.toa, dt) + for _, callback in ipairs(self.onUpdateFuncs) do + callback(self.a) + end +end +function easmeta:__tostring() + return tostring(self.a) +end +function easmeta:__unm(self) + return -self.a +end + +---@param default number +---@return easable +function easable(default) + default = default or 0 + return setmetatable({a = default, toa = default, onUpdateFuncs = {}}, easmeta) +end \ No newline at end of file diff --git a/template/stdlib/easable2.lua b/template/stdlib/easable2.lua new file mode 100644 index 0000000..31f64d2 --- /dev/null +++ b/template/stdlib/easable2.lua @@ -0,0 +1,90 @@ +---@class easable2 +---@field public a number @the eased value +---@field public toa number @the target, uneased value +---@field public ease fun(a:number):number @the ease to use +---@field protected onUpdateFuncs fun(a:number):nil[] +---@field protected _a number @the internal value, linearly eased +local eas = {} + +---@param new number @New value to ease to +---@return void +function eas:set(new) + self.toa = new +end + +---@param new number @New value +---@return void +function eas:reset(new) + self.toa = new + self._a = new +end + +---@param new number @How much to add to current value to ease to +---@return void +function eas:add(new) + self.toa = self.toa + new +end + +---@param func fun(a: number):void @Adds a callback function that will run each time the eased value changes +---@return void +function eas:onUpdate(func) + table.insert(self.onUpdateFuncs, func) +end + +local easmeta = {} + +easmeta.__index = eas +easmeta.__name = 'easable2' + +function easmeta.__add(a, b) + return ((type(a) == 'table' and a.a) and a.a or a) + ((type(b) == 'table' and b.a) and b.a or b) +end +function easmeta.__sub(a, b) + return ((type(a) == 'table' and a.a) and a.a or a) - ((type(b) == 'table' and b.a) and b.a or b) +end +function easmeta.__mul(a, b) + return ((type(a) == 'table' and a.a) and a.a or a) * ((type(b) == 'table' and b.a) and b.a or b) +end +function easmeta.__div(a, b) + return ((type(a) == 'table' and a.a) and a.a or a) / ((type(b) == 'table' and b.a) and b.a or b) +end +function easmeta.__mod(a, b) + return ((type(a) == 'table' and a.a) and a.a or a) % ((type(b) == 'table' and b.a) and b.a or b) +end +function easmeta.__eq(a, b) + return ((type(a) == 'table' and a.a) and a.a or a) == ((type(b) == 'table' and b.a) and b.a or b) +end +function easmeta.__lt(a, b) + return ((type(a) == 'table' and a.a) and a.a or a) < ((type(b) == 'table' and b.a) and b.a or b) +end +function easmeta.__le(a, b) + return ((type(a) == 'table' and a.a) and a.a or a) <= ((type(b) == 'table' and b.a) and b.a or b) +end + +function easmeta:__call(dt) + if self._a == self.toa then + -- do nothing + elseif self._a < self.toa then + self._a = self._a + math.min(dt, math.abs(self._a - self.toa)) + else + self._a = self._a - math.min(dt, math.abs(self._a - self.toa)) + end + self.a = self.ease(self._a) + + for _, callback in ipairs(self.onUpdateFuncs) do + callback(self.a) + end +end +function easmeta:__tostring() + return tostring(self.a) +end +function easmeta:__unm(self) + return -self.a +end + +---@param default number +---@return easable2 +function easable2(default, ease) + default = default or 0 + return setmetatable({a = default, toa = default, onUpdateFuncs = {}, ease = ease or outSine, _a = default}, easmeta) +end \ No newline at end of file diff --git a/template/stdlib/ease.lua b/template/stdlib/ease.lua new file mode 100644 index 0000000..6a98a28 --- /dev/null +++ b/template/stdlib/ease.lua @@ -0,0 +1,338 @@ +-- nabbed straight from mirin template: +-- https://github.com/XeroOl/notitg-mirin/blob/d1e9a8e71026aeabe81c682a114ce265cbd6362a/template/ease.lua + +local sqrt = math.sqrt +local sin = math.sin +local asin = math.asin +local cos = math.cos +local pow = math.pow +local exp = math.exp +local pi = math.pi +local abs = math.abs + +-- ===================================================================== -- + +-- Utility functions + +--- Flip any easing function, making it go from 1 to 0 +-- Example use: +-- ```lua +-- ease {0, 20, flip(outQuad), 50, 'modname'} +-- ``` +flip = setmetatable({}, { + __call = function(self, fn) + self[fn] = self[fn] or function(x) return 1 - fn(x) end + return self[fn] + end +}) + +-- Mix two easing functions together into a new ease +-- the new ease starts by acting like the first argument, and then ends like the second argument +-- Example: ease {0, 20, blendease(inQuad, outQuad), 100, 'modname'} +blendease = setmetatable({}, { + __index = function(self, key) + self[key] = {} + return self[key] + end, + __call = function(self, fn1, fn2) + if not self[fn1][fn2] then + local transient1 = fn1(1) <= 0.5 + local transient2 = fn2(1) <= 0.5 + if transient1 and not transient2 then + error('blendease: the first argument is a transient ease, but the second argument doesn\'t match') + end + if transient2 and not transient1 then + error('blendease: the second argument is a transient ease, but the first argument doesn\'t match') + end + self[fn1][fn2] = function(x) + local mixFactor = 3*x^2-2*x^3 + return (1 - mixFactor) * fn1(x) + mixFactor * fn2(x) + end + end + return self[fn1][fn2] + end +}) + +local function param1cache(self, param1) + self.cache[param1] = self.cache[param1] or function(x) + return self.fn(x, param1) + end + return self.cache[param1] +end + +local param1mt = { + __call = function(self, x, param1) + return self.fn(x, param1 or self.dp1) + end, + __index = { + param = param1cache, + params = param1cache, + } +} + +-- Declare an easing function taking one custom parameter +function with1param(fn, defaultparam1) + return setmetatable({ + fn = fn, + dp1 = defaultparam1, + cache = {}, + }, param1mt) +end + +local function param2cache(self, param1, param2) + self.cache[param1] = self.cache[param1] or {} + self.cache[param1][param2] = self.cache[param1][param2] or function(x) + return self.fn(x, param1, param2) + end + return self.cache[param1][param2] +end + +local param2mt = { + __call = function(self, x, param1, param2) + return self.fn(x, param1 or self.dp1, param2 or self.dp2) + end, + __index = { + param=param2cache, + params=param2cache, + } +} + +-- Declare an easing function taking two custom parameters +function with2params(fn, defaultparam1, defaultparam2) + return setmetatable({ + fn = fn, + dp1 = defaultparam1, + dp2 = defaultparam2, + cache = {}, + }, param2mt) +end + +-- ===================================================================== -- + +-- Easing functions + +function bounce(t) return 4 * t * (1 - t) end +function tri(t) return 1 - abs(2 * t - 1) end +function bell(t) return inOutQuint(tri(t)) end +function pop(t) return 3.5 * (1 - t) * (1 - t) * sqrt(t) end +function tap(t) return 3.5 * t * t * sqrt(1 - t) end +function pulse(t) return t < .5 and tap(t * 2) or -pop(t * 2 - 1) end + +function spike(t) return exp(-10 * abs(2 * t - 1)) end +function inverse(t) return t * t * (1 - t) * (1 - t) / (0.5 - t) end + +local function popElasticInternal(t, damp, count) + return (1000 ^ -(t ^ damp) - 0.001) * sin(count * pi * t) +end + +local function tapElasticInternal(t, damp, count) + return (1000 ^ -((1 - t) ^ damp) - 0.001) * sin(count * pi * (1 - t)) +end + +local function pulseElasticInternal(t, damp, count) + if t < .5 then + return tapElasticInternal(t * 2, damp, count) + else + return -popElasticInternal(t * 2 - 1, damp, count) + end +end + +popElastic = with2params(popElasticInternal, 1.4, 6) +tapElastic = with2params(tapElasticInternal, 1.4, 6) +pulseElastic = with2params(pulseElasticInternal, 1.4, 6) + +impulse = with1param(function(t, damp) + t = t ^ damp + return t * (1000 ^ -t - 0.001) * 18.6 +end, 0.9) + +function instant() return 1 end +function linear(t) return t end +function inQuad(t) return t * t end +function outQuad(t) return -t * (t - 2) end +function inOutQuad(t) + t = t * 2 + if t < 1 then + return 0.5 * t ^ 2 + else + return 1 - 0.5 * (2 - t) ^ 2 + end +end +function outInQuad(t) + t = t * 2 + if t < 1 then + return 0.5 - 0.5 * (1 - t) ^ 2 + else + return 0.5 + 0.5 * (t - 1) ^ 2 + end +end +function inCubic(t) return t * t * t end +function outCubic(t) return 1 - (1 - t) ^ 3 end +function inOutCubic(t) + t = t * 2 + if t < 1 then + return 0.5 * t ^ 3 + else + return 1 - 0.5 * (2 - t) ^ 3 + end +end +function outInCubic(t) + t = t * 2 + if t < 1 then + return 0.5 - 0.5 * (1 - t) ^ 3 + else + return 0.5 + 0.5 * (t - 1) ^ 3 + end +end +function inQuart(t) return t * t * t * t end +function outQuart(t) return 1 - (1 - t) ^ 4 end +function inOutQuart(t) + t = t * 2 + if t < 1 then + return 0.5 * t ^ 4 + else + return 1 - 0.5 * (2 - t) ^ 4 + end +end +function outInQuart(t) + t = t * 2 + if t < 1 then + return 0.5 - 0.5 * (1 - t) ^ 4 + else + return 0.5 + 0.5 * (t - 1) ^ 4 + end +end +function inQuint(t) return t ^ 5 end +function outQuint(t) return 1 - (1 - t) ^ 5 end +function inOutQuint(t) + t = t * 2 + if t < 1 then + return 0.5 * t ^ 5 + else + return 1 - 0.5 * (2 - t) ^ 5 + end +end +function outInQuint(t) + t = t * 2 + if t < 1 then + return 0.5 - 0.5 * (1 - t) ^ 5 + else + return 0.5 + 0.5 * (t - 1) ^ 5 + end +end +function inExpo(t) return 1000 ^ (t - 1) - 0.001 end +function outExpo(t) return 1.001 - 1000 ^ -t end +function inOutExpo(t) + t = t * 2 + if t < 1 then + return 0.5 * 1000 ^ (t - 1) - 0.0005 + else + return 1.0005 - 0.5 * 1000 ^ (1 - t) + end +end +function outInExpo(t) + if t < 0.5 then + return outExpo(t * 2) * 0.5 + else + return inExpo(t * 2 - 1) * 0.5 + 0.5 + end +end +function inCirc(t) return 1 - sqrt(1 - t * t) end +function outCirc(t) return sqrt(-t * t + 2 * t) end +function inOutCirc(t) + t = t * 2 + if t < 1 then + return 0.5 - 0.5 * sqrt(1 - t * t) + else + t = t - 2 + return 0.5 + 0.5 * sqrt(1 - t * t) + end +end +function outInCirc(t) + if t < 0.5 then + return outCirc(t * 2) * 0.5 + else + return inCirc(t * 2 - 1) * 0.5 + 0.5 + end +end +function outBounce(t) + if t < 1 / 2.75 then + return 7.5625 * t * t + elseif t < 2 / 2.75 then + t = t - 1.5 / 2.75 + return 7.5625 * t * t + 0.75 + elseif t < 2.5 / 2.75 then + t = t - 2.25 / 2.75 + return 7.5625 * t * t + 0.9375 + else + t = t - 2.625 / 2.75 + return 7.5625 * t * t + 0.984375 + end +end +function inBounce(t) return 1 - outBounce(1 - t) end +function inOutBounce(t) + if t < 0.5 then + return inBounce(t * 2) * 0.5 + else + return outBounce(t * 2 - 1) * 0.5 + 0.5 + end +end +function outInBounce(t) + if t < 0.5 then + return outBounce(t * 2) * 0.5 + else + return inBounce(t * 2 - 1) * 0.5 + 0.5 + end +end +function inSine(x) return 1 - cos(x * (pi * 0.5)) end +function outSine(x) return sin(x * (pi * 0.5)) end +function inOutSine(x) + return 0.5 - 0.5 * cos(x * pi) +end +function outInSine(t) + if t < 0.5 then + return outSine(t * 2) * 0.5 + else + return inSine(t * 2 - 1) * 0.5 + 0.5 + end +end + +function outElasticInternal(t, a, p) + return a * pow(2, -10 * t) * sin((t - p / (2 * pi) * asin(1/a)) * 2 * pi / p) + 1 +end +local function inElasticInternal(t, a, p) + return 1 - outElasticInternal(1 - t, a, p) +end +function inOutElasticInternal(t, a, p) + return t < 0.5 + and 0.5 * inElasticInternal(t * 2, a, p) + or 0.5 + 0.5 * outElasticInternal(t * 2 - 1, a, p) +end +function outInElasticInternal(t, a, p) + return t < 0.5 + and 0.5 * outElasticInternal(t * 2, a, p) + or 0.5 + 0.5 * inElasticInternal(t * 2 - 1, a, p) +end + +inElastic = with2params(inElasticInternal, 1, 0.3) +outElastic = with2params(outElasticInternal, 1, 0.3) +inOutElastic = with2params(inOutElasticInternal, 1, 0.3) +outInElastic = with2params(outInElasticInternal, 1, 0.3) + +function inBackInternal(t, a) return t * t * (a * t + t - a) end +function outBackInternal(t, a) t = t - 1 return t * t * ((a + 1) * t + a) + 1 end +function inOutBackInternal(t, a) + return t < 0.5 + and 0.5 * inBackInternal(t * 2, a) + or 0.5 + 0.5 * outBackInternal(t * 2 - 1, a) +end +function outInBackInternal(t, a) + return t < 0.5 + and 0.5 * outBackInternal(t * 2, a) + or 0.5 + 0.5 * inBackInternal(t * 2 - 1, a) +end + +inBack = with1param(inBackInternal, 1.70158) +outBack = with1param(outBackInternal, 1.70158) +inOutBack = with1param(inOutBackInternal, 1.70158) +outInBack = with1param(outInBackInternal, 1.70158) \ No newline at end of file diff --git a/template/stdlib/index.lua b/template/stdlib/index.lua new file mode 100644 index 0000000..7ca0a96 --- /dev/null +++ b/template/stdlib/index.lua @@ -0,0 +1,10 @@ +require('input') +bitop = require('bitop') -- TODO: tons of this is commented out because of '...'. FIX. IT. +require('rng') +require('easable') +require('easable2') +require('color') +require('vector2D') +require('ease') +uwuify = require('uwuify') +require('util') \ No newline at end of file diff --git a/template/stdlib/input.lua b/template/stdlib/input.lua new file mode 100644 index 0000000..3b4c9ee --- /dev/null +++ b/template/stdlib/input.lua @@ -0,0 +1,39 @@ +inputs = { -- -1 for not pressed, time for time of press + Left = -1, + Down = -1, + Up = -1, + Right = -1 +} +rawInputs = { + Left = -1, + Down = -1, + Up = -1, + Right = -1 +} + +directions = { + Left = {-1, 0}, + Down = {0, 1}, + Up = {0, -1}, + Right = {1, 0} +} + +function uranium.init() + for pn = 1, 2 do + for i,j in ipairs({'Left', 'Down', 'Up', 'Right'}) do + local i = i -- lua scope funnies + local j = j + + _main:addcommand('StepP' .. pn .. j .. 'PressMessage', function() + rawInputs[j] = t + if uranium:call('press', j) then return end + inputs[j] = t + end) + _main:addcommand('StepP' .. pn .. j .. 'LiftMessage', function() + if uranium:call('release', j) then return end + inputs[j] = -1 + rawInputs[j] = -1 + end) + end + end +end \ No newline at end of file diff --git a/template/stdlib/rng.lua b/template/stdlib/rng.lua new file mode 100644 index 0000000..dad337c --- /dev/null +++ b/template/stdlib/rng.lua @@ -0,0 +1,172 @@ +-- xoshiro128** 1.1 by David Blackman and Sebastiano Vigna (vigna@acm.org) https://prng.di.unimi.it/xoshiro128starstar.c +-- Lua implementation by Jill "oatmealine" Monoids +-- Licensed under CC-BY-SA + +local RAND_MAX = 4294967295 + +---@param x int +---@param k int +local function rotl(x, k) + return bitop.bor(bitop.lshift(x, k), bitop.rshift(x, (32 - k))) +end + +---@param state int[] @array of size 4; will be mutated +local function next(state) + local result = rotl(state[2] * 5, 7) * 9 + local t = bitop.lshift(state[2], 9) + + state[3] = bitop.bxor(state[3], state[1]) + state[4] = bitop.bxor(state[4], state[2]) + state[2] = bitop.bxor(state[2], state[3]) + state[1] = bitop.bxor(state[1], state[4]) + + state[2] = bitop.bxor(state[3], t) + + state[3] = rotl(state[4], 11) + + return result +end + +local JUMP = { 0x8764000b, 0xf542d2d3, 0x6fa035c3, 0x77f2db5b } + +---@param state int[] @array of size 4; will be mutated +local function jump(state) + local s0 = 0 + local s1 = 0 + local s2 = 0 + local s3 = 0 + + for _, j in ipairs(JUMP) do + for b = 0, 31 do + if bitop.band(j, bitop.lshift(1, b)) ~= 0 then + s0 = bitop.bxor(s0, state[1]) + s1 = bitop.bxor(s1, state[2]) + s2 = bitop.bxor(s2, state[3]) + s3 = bitop.bxor(s3, state[4]) + end + next(state) + end + end + + state[1] = s0 + state[2] = s1 + state[3] = s2 + state[4] = s3 +end + +local LONG_JUMP = { 0xb523952e, 0x0b6f099f, 0xccf5a0ef, 0x1c580662 } + +---@param state int[] @array of size 4; will be mutated +local function long_jump(state) + local s0 = 0 + local s1 = 0 + local s2 = 0 + local s3 = 0 + + for _, j in ipairs(LONG_JUMP) do + for b = 0, 31 do + if bitop.band(j, bitop.lshift(1, b)) ~= 0 then + s0 = bitop.bxor(s0, state[1]) + s1 = bitop.bxor(s1, state[2]) + s2 = bitop.bxor(s2, state[3]) + s3 = bitop.bxor(s3, state[4]) + end + next(state) + end + end + + state[1] = s0 + state[2] = s1 + state[3] = s2 + state[4] = s3 +end + +---@class rng a xoshiro128** pseudorandom implementation +---@field public state int[] the current state, size of 4 +rng = {} + +--- gets the next pseudo-random value; recommended to use abstractions (like __call) over this +---@return int +function rng:next() + return next(self.state) +end + +--- This is the jump function for the generator. It is equivalent +--- to 2^64 calls to next(); it can be used to generate 2^64 +--- non-overlapping subsequences for parallel computations. +---@return void +function rng:jump() + return jump(self.state) +end + +--- This is the long-jump function for the generator. It is equivalent to +--- 2^96 calls to next(); it can be used to generate 2^32 starting points, +--- from each of which jump() will generate 2^32 non-overlapping +--- subsequences for parallel distributed computations. +---@return void +function rng:longJump() + return long_jump(self.state) +end + +--- if `max` is not given, `min` will be used as the maximum and the minimum will be 1 +--- if min is 1 and max is 4, the returned value can be 1, 2, 3 or 4 +---@param min int +---@param max int +---@return int +function rng:int(min, max) + if not max then + local m = min + min = 1 + max = m + end + + local _min = min + local _max = max + min = math.min(_min, _max) + max = math.max(_min, _max) + + return min + (self:next() % (max - min + 1)) +end + +--- if `max` is not given, it will be 1 +---@param max float +---@return float +function rng:float(max) + return ((self:next() % RAND_MAX) / RAND_MAX) * (max or 1) +end + + +---@return boolean +function rng:bool() + return self:next() % 2 == 0 +end + +function rng:seed(seed) + self.state = {seed, seed, seed, seed} + self:next() +end + +local rngmeta = {} + +--- acts identical to math.random() +function rngmeta:__call(a, b) + if a then + return self:int(a, b) + end + return self:float() +end + +rngmeta.__index = rng + +--- creates a new RNG object +---@param seed int[] @array of size 4, will default to os.time() if not given +---@return rng +function rng.init(seed) + seed = seed or os.time() + local state = {seed, seed, seed, seed} + local this = setmetatable({state = state}, rngmeta) + this:next() -- just to prevent the state from being all the same number; i dont know a cleaner way of doing this + return this +end + +return rng \ No newline at end of file diff --git a/template/stdlib/util.lua b/template/stdlib/util.lua new file mode 100644 index 0000000..7f1dbd7 --- /dev/null +++ b/template/stdlib/util.lua @@ -0,0 +1,157 @@ +---@param a number +---@param b number +---@param x number +---@return number +function mix(a, b, x) + return a * (1 - x) + b * x +end +lerp = mix + +---@param x number +---@return number +function sign(x) + if x > 0 then return 1 end + if x < 0 then return -1 end + return 0 +end + +function deepcopy(obj) + if type(obj) ~= 'table' then return obj end + local res = {} + for k, v in pairs(obj) do res[deepcopy(k)] = deepcopy(v) end + return res +end + +---@param a number +---@param x number +---@param y number +---@return number +function clamp(a, x, y) + return math.max(math.min(a, math.max(x, y)), math.min(x, y)) +end + +---@param tab any[] +---@param elem any +function includes(tab, elem) + if not tab then error('bad argument #1 (expected table, got nil)', 2) end + for _, v in pairs(tab) do + if elem == v then return true end + end + return false +end + +---@param text string +---@param length int +function truncate(text, length) + local addellipses = false + + local firstLine = nil + for line in string.gfind(text, '([^\n]*)\n?') do + if not firstLine then + firstLine = line + elseif line ~= '' then + addellipses = true + break + end + end + + text = firstLine + if string.len(text) > length then + text = string.sub(text, 1, length) + addellipses = true + end + + if addellipses then text = text .. '...' end + return text +end + +function padLeft(str, num, fill) + local s = {} + for i = 1, num - #str do + table.insert(s, fill) + end + table.insert(s, str) + return table.concat(s, '') +end + +function padLeft(str, num, fill) + local s = {} + table.insert(s, str) + for i = 1, num - #str do + table.insert(s, fill) + end + return table.concat(s, '') +end + +local whitespaces = {' ', '\n', '\r'} + +---@param str string +function trimLeft(str) + while includes(whitespaces, string.sub(str, 1, 1)) do + str = string.sub(str, 2) + end + return str +end + +---@param str string +function trimRight(str) + while includes(whitespaces, string.sub(str, -1, -1)) do + str = string.sub(str, 1, -2) + end + return str +end + +---@param str string +function trim(str) + return trimRight(trimLeft(str)) +end + +---@param o any +---@return string +--- stringify an object +function fullDump(o, r) + if type(o) == 'table' and (not r or r > 0) then + local s = '{' + local first = true + for k,v in pairs(o) do + if not first then + s = s .. ', ' + end + local nr = nil + if r then + nr = r - 1 + end + if type(k) ~= 'number' then + s = s .. tostring(k) .. ' = ' .. fullDump(v, nr) + else + s = s .. fullDump(v, nr) + end + first = false + end + return s .. '}' + elseif type(o) == 'string' then + return '"' .. o .. '"' + else + return tostring(o) + end +end + +---@param t1 any[] +---@param t2 any[] +---@return any[] +function tableConcat(t1, t2) + for i = 1, #t2 do + t1[#t1 + 1] = t2[i] + end + return t1 +end + +---@param tab table +function clearMetatables(tab) + setmetatable(tab, nil) + for _, obj in pairs(tab) do + if type(obj) == 'table' then + clearMetatables(obj) + end + end +end \ No newline at end of file diff --git a/template/stdlib/uwuify.lua b/template/stdlib/uwuify.lua new file mode 100644 index 0000000..acc933a --- /dev/null +++ b/template/stdlib/uwuify.lua @@ -0,0 +1,23 @@ +local endings = {'rawr x3', 'OwO', 'UwU', 'o.O', '-.-', '>w<', '(˘ω˘)', 'σωσ', 'ʘwʘ', ':3', 'XD', 'nyaa~~', 'mya', '>_<', 'rawr', '^^', '^^;;', '(^•ω•^)'} + +return function(str) + str = string.lower(str) + + str = string.gsub(str, 'small', 'smol') + str = string.gsub(str, 'cute', 'kawaii~') + str = string.gsub(str, 'fluff', 'floof') + str = string.gsub(str, 'love', 'luv') + str = string.gsub(str, 'stupid', 'baka') + str = string.gsub(str, 'meow', 'nya~') + + str = string.gsub(str, 'l', 'w') + str = string.gsub(str, 'r', 'w') + + str = string.gsub(str, 'n([aeiou])', 'ny%1') + + str = string.gsub(str, '[.!?]%s', function(e) return e .. endings[math.random(1, #endings)] .. ' ' end) + + str = string.gsub(str, '(%s)(%a)(%a)', function(space, rep, other) if math.random() < 0.05 then return space .. rep .. '-' .. rep .. other else return space .. rep .. other end end) + + return str +end \ No newline at end of file diff --git a/template/stdlib/vector2D.lua b/template/stdlib/vector2D.lua new file mode 100644 index 0000000..29dce1c --- /dev/null +++ b/template/stdlib/vector2D.lua @@ -0,0 +1,142 @@ +---@class vector2D A vector can be defined as a set of 2 coordinates. They can be obtained by doing either vect.x and vect.y or vect[1] and vect[2], for compatibility purposes. +---The reason such a simple class exists is to do simplified math with it - math abstracted as :length(), :angle(), etc is much easier to read. +---@field public x number @x coordinate +---@field public y number @y coordinate +---@operator add(vector2D): vector2D +---@operator add(number): vector2D +---@operator sub(vector2D): vector2D +---@operator sub(number): vector2D +---@operator mul(vector2D): vector2D +---@operator mul(number): vector2D +---@operator div(vector2D): vector2D +---@operator div(number): vector2D +---@operator unm: vector2D +local vect = {} + +---@return number +function vect:length() + return math.sqrt(self.x * self.x + self.y * self.y) +end + +---@return number +function vect:lengthSquared() + return self.x * self.x + self.y * self.y +end + +---@return number +function vect:angle() + return math.atan2(self.y, self.x) +end + +---@return vector2D +function vect:normalize() + local len = self:length() + if len ~= 0 and len ~= 1 then + return vector2D(self.x / len, self.y / len) + else + return self + end +end + +---@return vector2D +function vect:resize(x) + local n = self:normalize() + return vector2D(n.x * x, n.y * x) +end + +---@return vector2D +function vect:rotate(ang) + local a = self:angle() + local len = self:length() + return vectorFromAngle(a + ang, len) +end + +---@return number, number +function vect:unpack() + return self.x, self.y +end + +---@param v2 vector2D +---@return number +function vect:distance(v2) + return (self - v2):length() +end + +---@param v2 vector2D +---@return number +function vect:distanceSquared(v2) + return (self - v2):lengthSquared() +end + +local vectmeta = {} + +local function typ(a) + return (type(a) == 'table' and a.x and a.y) and 'vector' or type(a) +end + +local function genericop(a, b, f, name) + local typea = typ(a) + local typeb = typ(b) + if typea == 'number' then + return vector2D(f(b.x, a), f(b.y, a)) + elseif typeb == 'number' then + return vector2D(f(a.x, b), f(a.y, b)) + elseif typea == 'vector' and typeb == 'vector' then + return vector2D(f(a.x, b.x), f(a.y, b.y)) + end + error('cant apply ' .. name .. ' to ' .. typea .. ' and ' .. typeb, 3) +end + +function vectmeta.__add(a, b) + return genericop(a, b, function(a, b) return a + b end, 'add') +end +function vectmeta.__sub(a, b) + return genericop(a, b, function(a, b) return a - b end, 'sub') +end +function vectmeta.__mul(a, b) + return genericop(a, b, function(a, b) return a * b end, 'mul') +end +function vectmeta.__div(a, b) + return genericop(a, b, function(a, b) return a / b end, 'div') +end + +function vectmeta.__eq(a, b) + return (typ(a) == 'vector' and typ(b) == 'vector') and (a.x == b.x and a.y == b.y) +end + +function vectmeta:__unm() + return vector2D(-self.x, -self.y) +end + +function vectmeta:__tostring() + return '(' .. self.x .. ', ' .. self.y .. ')' +end +vectmeta.__name = 'vector' + +function vectmeta:__index(i) + if i == 1 then return self.x end + if i == 2 then return self.y end + return vect[i] +end + +--- create a new vector +---@param x number | nil +---@param y number | nil +---@return vector2D +function vector2D(x, y) + x = x or 0 + y = y or x + return setmetatable({x = x, y = y}, vectmeta) +end + +--- create a new vector from an angle +---@param ang number | nil @angle in degrees +---@param amp number | nil +---@return vector2D +function vectorFromAngle(ang, amp) + ang = math.rad(ang or 0) + amp = amp or 1 + return vector2D(math.cos(ang) * amp, math.sin(ang) * amp) +end + +vector = vector2D \ No newline at end of file diff --git a/template/typings.lua b/template/typings.lua new file mode 100644 index 0000000..22950f7 --- /dev/null +++ b/template/typings.lua @@ -0,0 +1,81 @@ +---@meta + +-- cleaning up some notitg typing jank... ehe +---@alias int number +---@alias float number +---@alias Quad Actor +---@alias void nil + +---@return Quad +--- Defines a Quad actor. +function Quad() end +---@return ActorProxy +--- Defines an ActorProxy actor. +function ActorProxy() end +---@return Polygon +--- Defines a Polygon actor. +function Polygon() end +---@param file string +---@return Sprite +--- Defines a Sprite actor. +function Sprite(file) end +---@param file string +---@return Model +--- Defines a Model actor. +function Model(file) end +---@param font string? +---@param text string? +---@return BitmapText +--- Defines a BitmapText actor. +function BitmapText(font, text) end +---@param file string +---@return ActorSound +--- Defines an ActorSound actor. +function ActorSound(file) end + +---@type number +--- A simple timer. Ticks upwards at a rate of 1/sec. +--- +--- **The start time is undefined!** This uses `os.clock()`, meaning this will be inconsistent between modfile starts. +--- +--- It's recommended to only use this for eg. `math.sin`, rotations, and other similar visual effects. If you want a proper timer, see `b`. +t = 0 + +---@type number +--- The amount of beats that have passed since the start of the file. +b = 0 + +---@type ActorFrame +--- The root ActorFrame. Use this for `addcommand` and similar! +_main = {} + +---@type number +--- The center of the screen on the X axis. Equal to `SCREEN_CENTER_X`. +scx = 0 +---@type number +--- The center of the screen on the Y axis. Equal to `SCREEN_CENTER_Y`. +scy = 0 +---@type number +--- The screen width. Equal to `SCREEN_WIDTH`. +sw = 0 +---@type number +--- The screen height. Equal to `SCREEN_HEIGHT`. +sh = 0 + +--- The Uranium Template table! Mostly callback-related stuff goes here. +uranium = {} + +--- A callback for initialization. Called on `OnCommand`. +uranium.init = function() end +--- A callback for updates. Called every frame. Draw stuff here! +uranium.update = function() end + +---@param event string +---@param ... any +---@return any +--- Call a defined callback. +function uranium:call(event, ...) end + +--- Equivalent to a modfile-sandboxed `_G`, similar to Mirin's `xero`. You shouldn't need this; and if you do, *what are you doing?* +---@type table +oat = {} \ No newline at end of file