Frequently Asked Questions

Here are some of the more frequently asked questions we've received, linking to different parts of this document where you can get more information. Be sure to also check out the cookbook examples if you haven't, as those can teach you some of the basic concepts of Retro Gadgets. If you still have any questions, feel free to ask in our Discord server!

How do I get started building a gadget?

We show how to build a gadget from scratch that takes button inputs and outputs sound in our Sound Board cookbook example. It also serves as teaching you the very basics to follow later cookbook examples.

Additionally, you can look at the built-in gadgets under the Tutorial button in the main menu to see how they were made.

The camera or the wi-fi modules don't work!

Check that your gadget permissions are set correctly. Additionally, there is currently no way to switch between camera sources in computers with multiple sources, so the game might not be detecting your webcam correctly.

I'm trying to use a function, but it seems to ask for the wrong number of arguments!

Check that you are using : (colon) for object methods, and . (period) for properties. Check out the glossary for more information on methods and properties.

How do I load assets to use in my code? GetAudioSample and GetSpriteSheet don't work!

Between the Next Fest demo and the Early Access release, some of the syntax was changed with new features and some supplemental material might not reflect that. To use assets currently, you must drag a ROM chip onto your gadget from the Misc drawer, and replace calls such as:

local sprites:SpriteSheet = GetSpriteSheet("filename.png")

with:

local sprites:SpriteSheet = gdt.ROM.User.SpriteSheets["filename.png"]

For built-in assets such as "StandardFont", replace User with System. For audio assets, replace SpriteSheets with AudioSamples. See the ROM page for more information.

How can I protect my gadget's assets or code from copying when I publish it into the Workshop?

You can include a SecurityChip in your gadget to lock its assets. Check out the module page for more information.

How do I tell what size a screen is?

A Screen module will have Width and Height properties that you can read to get the size of each individual screen. If you connect multiple screens to the same VideoChip, the drawing buffer grows in order to accommodate all the connected screens, so you can use the Width and Height properties of the VideoChip instead to get the full resolution of your combined screen. If you want to know what size each screen in the drawer is, that information is also in the Screen module's page in this document.

How do I make a code delay, or how do I make my code wait some time?

Since Retro Gadgets is aimed at being programmed like any other basic computer would need to be, you need to code everything from scratch. The CPU gives you a couple of time properties that allow you to do this.

First, understand your code runs in ticks. That means for each tick, your entire update() function will have run through in its entirety. Retro Gadgets aims to run at 60 ticks per second, that is your update() will run 60 times every second. This is fine for logic and for parsing inputs.

Second, we need a way to determine how much time has passed. We can do this by reading gdt.CPU0.Time to get the total time in seconds since the gadget has turned on, or gdt.CPU0.DeltaTime to get the time in seconds that passed since the last tick.

Say we want something to happen 2 seconds after a trigger, like a button. You could write it like so:

-- we start with an unset timer as nil, meaning null or unset
local timeToTrigger = nil
function update()
    if gdt.LedButton0.ButtonDown then
        -- we set the timer for 2 seconds from the current time
        timeToTrigger = gdt.CPU0.Time + 2
    end

    -- this if first checks if the timer is set, then if the time is right
    if timeToTrigger and gdt.CPU.Time >= timeToTrigger then
        timeToTrigger = nil
        -- this will execute once when the time is right
        -- and will not execute again since we unset the timer
        -- you can put your code to be triggered here
    end
end

There are other ways to keep track of time than individual timers however. If you want something to happen every half second, for example:

-- let's call our repeating timer "frames", meaning every half second we
-- advance one frame
local frameDuration = 0.5
-- this will keep track of DeltaTime
local deltaCounter = 0

function frame()
    -- this will get called every 0.5 seconds
end

function update()
    -- increase the counter by the CPU's DeltaTime
    deltaCounter += gdt.CPU0.DeltaTime

    -- we run a while loop for however many times the delta counter is greater
    -- than the duration of one frame, such that if for some reason the counter
    -- has gone past over one frame duration, we run our frame loop however many
    -- times necessary to keep the logic tied to the timer.
    while (deltaCounter >= frameDuration) do
        deltaCounter -= frameDuration
        frame()
    end
end

This last method is useful for repeating timers such as one to run a drum machine or a game's animation logic cycle.

How do I check collision between two sprites?

Like the delay question above, there is no built-in simple way to do this, and you have to make your own from scratch. The simplest type of collision checking you can write is called AABB collision, which checks if 2 rectangles are overlapping.

AABB collision between two boxes

To tell if the two boxes are overlapping, you need to know the position of each box (X and Y), and their sizes (Width and Height). However you store these values depends on your own code. Then, it's a matter of comparing those values like such:

function is_colliding(x1, y1, w1, h1, x2, y2, w2, h2)
    return x1 < x2 + w2 and x1 + w1 > x2 and
        y1 < y2 + h2 and y1 + h1 > y2
end

...where x1 and y1 are the top-left coordinates of the first box, w1 and h1 are the width and height of the first box, x2 and y2 are the top-left coordinates of the second box, and w2 and h2 are the width and height of the second box. The function will return true if there is a collision between those coordinates, or false otherwise.