Trying to Learn How Richard Builds Engine-Level Code like controller.ts

Short Introduction:

I’ve been studying the real logic behind controller.ts and sprite.ts, trying to learn how to code like Richard — not just writing game logic, but building real systems with deep connections and structure.

What I Tried:

I started writing my own function like moveSprite() to understand how velocity and input connect in the engine. Here’s a small version:

namespace war {
    export function move(spr: Sprite, vx: number, vy: number) {
        spr.vx = vx
        spr.vy = vy

        if (vx === 0) spr.vx *= 0.9
        if (vy === 0) spr.vy *= 0.9

        const maxSpeed = 100
        if (Math.abs(spr.vx) > maxSpeed) spr.vx = maxSpeed * Math.sign(spr.vx)
        if (Math.abs(spr.vy) > maxSpeed) spr.vy = maxSpeed * Math.sign(spr.vy)
    }
}
You can find the full code and more of my attempt on GitHub:
🔗 https://github.com/DeveloperTryingToCodeLikeOtherOfThem/war2/blob/master/main.ts

What I’m Trying to Learn:
Richard’s code has structure. He doesn’t just make utility functions — he builds real systems. Like how controller.ts connects button input, velocity, and updates so the whole thing feels like an engine feature, not just vx = 100.

Here’s what I’m hoping to understand:

How do I structure my engine-level code like Richard?

When should logic become a class, not just functions?

How do his files reach 200–500 lines but still feel clean and reusable?

How do you design input and velocity logic to plug into sprite behavior like the real engine?

One Last Thing:
Anyone reading this can fork, edit, or suggest improvements directly on my GitHub repo. I'm treating this like a real extension and want to build it right from the ground up — not just remixing, but learning to design like the MakeCode team.

Thanks for reading!
2 Likes

if Richard or others know how to code the controller.ts come here and help me if you want. If not, it is fine too, but if you do, it is great too.

1 Like

or :megaphone: If Richard or anyone from the MakeCode team knows how controller.ts was really built, and you’re open to helping me understand it — I’d really appreciate it.
But if you’re busy or can’t right now, that’s completely okay too. I’m just trying my best to learn how the real engine-level systems work, like how input connects to velocity and sprite behavior.

Thanks again, whether you reply or not — I’m here to learn from how the real system was made. :folded_hands:

1 Like

Hi everyone! I’ve been diving deep into the real engine-level code behind MakeCode Arcade — especially files like controller.ts, sprite.ts, and prompt.ts.

:brain: What I’m Trying to Learn:

I’m not here to remix or write quick game logic — I’m here to learn how to build actual systems, the way Richard and the team did. I’m treating this project like a real extension — just like how you’d structure controller.moveSprite() from scratch.

Here are a few questions I’ve been focusing on:

1. How do you structure your code to feel like real engine systems?

  • Not just utility functions, but reusable, connected systems.

  • When should I use classes vs plain functions?

  • How do you keep files clean even when they reach 300–500+ lines?

2. How does the real controller.ts connect input to velocity and update logic?

I’ve been trying to write my own version of moveSprite() just to understand this:

ts

CopyEdit

namespace war { export function move(spr: Sprite, vx: number, vy: number) { spr.vx = vx spr.vy = vy if (vx === 0) spr.vx *= 0.9 if (vy === 0) spr.vy *= 0.9 const maxSpeed = 100 if (Math.abs(spr.vx) > maxSpeed) spr.vx = maxSpeed * Math.sign(spr.vx) if (Math.abs(spr.vy) > maxSpeed) spr.vy = maxSpeed * Math.sign(spr.vy) } }

Full source is here:
:link: https://github.com/DeveloperTryingToCodeLikeOtherOfThem/war2/blob/master/main.ts

I’d love advice on how to make this evolve into something that behaves more like controller.moveSprite() — something that feels truly built-in and structured.


:desktop_computer: Split Screen Logic (Advanced Project)

I’m also experimenting with recreating Richard’s split screen demo — but with 8 players, not just 4.

My goal is to deeply understand:

  • How to assign cameras to different players

  • How to combine scene.setCamera() and screen.setClip() correctly

  • How the screen rendering loop was customized to draw multiple views per frame

I’m not looking for a shortcut — I want to learn how the real engine did this so I can build from the real logic, like how Richard and the team designed it internally.


:folded_hands: Final Thoughts:

If Richard or anyone from the MakeCode team sees this and has time to share tips, I’d really appreciate it.

But if not — no worries at all. I’m just trying my best to understand how everything works under the hood and build real, engine-level extensions that feel native.

Thank you!

1 Like

Thanks again! I’m also currently studying how scene.cameraFollowSprite() was built — not just how to call it, but how Richard and the team actually implemented it inside the engine.

I found the real source and I’m learning how it connects the camera to a sprite internally. It’s starting to make sense: before the camera can follow anything, there needs to be a real Sprite instance — and the logic begins from how sprites are created, stored in the scene, and updated during the game loop.

I’m not just using the API — I’m studying how Richard built the system that makes camera following work at the engine level.

Here’s what I’m focusing on right now:

  • How cameraFollowSprite() assigns a camera to a sprite

  • How the camera updates its position based on the sprite during the game loop

  • What files and systems handle camera logic behind the scenes (like scene.ts)

  • How the screen respects the camera’s position while rendering

  • How to structure this logic cleanly, like Richard does in his 200+ line files

:magnifying_glass_tilted_left: I also found the real camera file here:
pxt-common-packages/libs/game/camera.ts

If anyone — especially Richard — can explain how he designed this whole system (not just the function call), I’d love to understand more about the internal structure, flow, and real logic that powers it. I’m trying to learn how to design systems like this from scratch.

Thanks! :folded_hands:

1 Like

Hi Richard (and team),

I’m continuing my deep study into how the core engine systems were built in MakeCode Arcade — especially things like the physicsEngine, scene.cameraFollowSprite(), and how Sprite x and y positions are updated and managed internally.

I’m not asking how to use these APIs — I’m trying to understand how you actually implemented them, the way you would when building the engine itself.

Right now, I’m learning:

  • How sprite x and y are calculated during physics (gravity, collisions, etc.)

  • How physics applies velocity and acceleration to change position

  • How your files sometimes grow to 30+ pages of real logic — not just helper functions — and how you keep it all structured, consistent, and logical

I want to be able to build my own physicsEngine.ts, including slopes and collisions, not to win a game jam — but to go beyond that and become an engine builder like you.

Can you share any thoughts on:

  • How you structured the original physicsEngine for sprites

  • How you update the sprite’s position every frame based on physics

  • Any tips for building a real collision and slope engine from scratch?

I’m already studying the files like sprite.ts, physicsEngine.ts, and camera.ts, and I want to finish what I’ve started — learning how to build systems like you did.

Thank you so much for the inspiration and code — it means a lot.

1 Like

Also, can you confirm if sprite.vx is applied before collision or after?

1 Like