3D voxel rendering engine

@richard

I’m not sure which of those is faster, but I would go with the class approach since it will make your code way easier to understand.

MakeCode does compile differently than other JavaScript runtimes. JavaScript is normally an interpreted language, meaning it is run using a program called an interpreter that takes in the source code and executes the program without compiling it (that’s a bit of an oversimplification, modern JavaScript interpreters do some compiling at runtime but that’s not important for this explanation).

MakeCode doesn’t interpret your program, it compiles it, which is very different than other JavaScript runtimes. On hardware, this allows us to be way more efficient than something like MicroPython (an interpreted language). Interpreters take a lot of memory and CPU cycles which are both at a premium on microcontrollers.

In the browser, we compile down to JavaScript but it’s a form of JavaScript that closely matches the code we compile for hardware. This allows MakeCode programs in our simulator to behave roughly the same was as programs on microcontrollers. The downside is that it’s usually less efficient than just running pure JavaScript in the browser since browsers are heavily optimized to run code written by people, not the code our compiler spits out.

That’s why it’s always important to use the builtin functions whenever possible in MakeCode programs. For example, always use Image.fillRect instead of using two for-loops to loop over a rectangle and set all the pixels. Similarly, you should use Image.blit or Image.blitRow when mapping textures to areas. These “native” implementations bypass our compiler and run as pure JavaScript, so they are way faster.

As for ray tracing, it’s always going to be faster to do bulk operations with Image.setRows than calling Image.setPixel a million times. That being said, if you’re just painting all the pixels to be the same color, or copying pixels from one image to another, then use Image.fillRect or Image.blitRow.

Finally, I would not recommend putting it in game.onPaing. Instead, use scene.createRenderable() so that your engine draws at a set z index. That way people can make UI elements that go over whatever you’re doing

2 Likes

@WoofWoof can you try to fix the blocks for the current update? For some reason they are crashing and all being in the same spot in the block window to the left. I think it may just be a typo for one of the //% things (e.g. block, var.shadow, vat.defl), but I don’t think it’s a variable type. For example, I probably had something like:

//% block="add %a0 and %B and return the sum"
//% A.defl=true
//% b1.defl=4
function add(a: number, b: number): number {
	return a + b
}
1 Like

There’s a rather simple way to figure out which block is problematic.

  1. Remove all of the code for your blocks. (Paste it somewhere else to keep it safe, of course.)
  2. Add code back one block at a time. Check the rendering after adding each block.
  3. As soon as it breaks, you’ve at least found the problematic block.

Once you find the problematic block(s), if you need help diagnosing, then share the code for the problematic block definition.

2 Likes

this is REALLY trippy

1 Like

ah thanks @AlexK. I fixed the issue, its that makecode dislikes it when the input/output to a block is any (why though). Now, I will fix a few defls and shadows, then i will add walls (similar to the walls in a tilemap) and event listeners. I will also make the player a class, allowing multiple players.

I know basically this entire topic is about debugging the extension now, but why whenever someone creates some 3D thing, I SWEAR the demo is ALWAYS based off of minecraft.

3 Likes

i half forgot about this but hopefully ill find a faster way to make makecode run soon! (im already onto something)

2 Likes

How fast can you get?
My best (im expecting nobody to get less than 45 seconds, maybe even a whole minute):

4 Likes

This is amazing! Maybe you could make the turn speed a tad bit faster, or maybe the screen size a little larger? I don’t know what you could do, but adding those would be nice! Also I still have no idea how to get up there.

Im probably going to send a video of what im doing if people want me to! (but first a hint)

by the way, I’ve added support for hardware (and mobile but it’s slow)!

PC (keyboard) = everthing (assuming you are using the keyboard)

One hardware device = move forward + backwards, turn left + right, A + B

Two hardware devices (2 player) = everthing

The fps for the screen size right now (100x100) gives me around 30 fps, doing 110x110 gives like 15, so I’ll probably have to work on optimizing the raytracer again. Also my phone was 5 fps.

@YamJam if you did want the screen size to be larger, then you could edit the code, and at the top you should see:

namespace userconfig { 
    export const ARCADE_SCREEN_WIDTH = 100
    export const ARCADE_SCREEN_HEIGHT = 100
}

you can make those 100s bigger to make the screen resolution larger!

1 Like

oh about the turn speed you can also change that. press [edit protect] at the top-right, then after it loads, there should be a [file explorer] at the left. expand it, and look for cam.js. Towards the top, you should find a line that looks like:

    turnsSpeed = ...

increase that number, and the turn speed should be faster.

1 Like

rq can you give me an explanation of what voxels are and how this works.

voxels are cubes that all have the exact same size, and have integer coordanites. This is a video of what inspired me, and can help understand voxels: https://www.youtube.com/watch?v=ztkh1r1ioZo