Skip to content

The Main Loop

JoeStrout edited this page Oct 23, 2026 · 1 revision

Almost every raylib-miniscript program is built around a main loop that runs once per frame: check input, update the game, draw, and yield. On the desktop it hardly matters where in the loop each of those goes. On the web, it matters where the yield goes.

The rule: yield right after EndDrawing

Make yield the very next statement after raylib.EndDrawing, with nothing in between:

while true
	if raylib.IsKeyPressed(raylib.KEY_ESCAPE) then break
	// ... update the game ...

	raylib.BeginDrawing
	raylib.ClearBackground raylib.BLACK
	// ... draw stuff ...
	raylib.EndDrawing
	yield
end while

Input checks can then go anywhere else in the loop, and they work the same on desktop and web.

A loop that yields at the top is fine too, as long as EndDrawing is the last thing at the bottom. Then the yield still comes right after the EndDrawing from the previous time around:

while true
	yield
	if raylib.IsKeyPressed(raylib.KEY_ESCAPE) then break
	raylib.BeginDrawing
	// ... draw stuff ...
	raylib.EndDrawing
end while

What to avoid is this:

	raylib.EndDrawing
	if raylib.IsKeyPressed(raylib.KEY_ESCAPE) then break   // never true on the web!
	yield

It works on the desktop, but on the web that check never sees the key.

Why

Functions like IsKeyPressed report what changed this frame, and EndDrawing is where one frame ends and the next begins: everything that was "pressed" becomes old news.

  • On the desktop, EndDrawing also collects the input that arrived since the last frame, so a new key press shows up right after it, and stays "pressed" until the next EndDrawing.
  • On the web, the browser can only deliver input (and show the frame you drew) while your script is yielded. So a new key press shows up when yield returns, and the next EndDrawing makes it old news. Code between EndDrawing and yield never sees it.

Yielding right after EndDrawing closes that gap, so each press is seen once, anywhere in the loop, on both platforms.

This affects everything that reports a change since the last frame:

  • IsKeyPressed, IsKeyPressedRepeat, IsKeyReleased, GetKeyPressed and GetCharPressed
  • IsMouseButtonPressed, IsMouseButtonReleased, GetMouseWheelMove, GetMouseWheelMoveV and GetMouseDelta
  • touch and gesture functions

Functions that report the current state, such as IsKeyDown, IsMouseButtonDown and GetMousePosition, work anywhere.

Coming from Mini Micro

In Mini Micro the display and input are always up to date, so it never mattered whether you yielded at the top of the loop or the bottom, or where you checked the keyboard. Old habits are fine here too; just make sure nothing comes between EndDrawing and the yield.

Ending the loop

raylib.WindowShouldClose always returns false on the web, since there's no window to close. If your game should end on a key press, check for the key yourself, as in the examples above, rather than relying on WindowShouldClose.

It's still worth calling on the desktop, where it notices the window's close button, and it's harmless on the web, so a loop like this works on both:

while not raylib.WindowShouldClose
	if raylib.IsKeyPressed(raylib.KEY_ESCAPE) then break
	// ... update the game ...
	raylib.BeginDrawing
	// ... draw stuff ...
	raylib.EndDrawing
	yield
end while

(If you've used raylib from C on the web, you may know that its WindowShouldClose pauses for about 12 milliseconds there, to let the browser catch up. raylib-miniscript's doesn't: your yield already does that job.)

Clone this wiki locally