Microsoft MakeCode

Is it possible to write directly to screen (pixels) on the Arcade?

As the title says; I do not want to use sprites, but want to write pixels directly to the screen.

Welcome, @gbraad!

Take a look at the reference documentation for image manipulation:

One way to do what you’re asking is to create an image the size of the screen, set the background to that image, and then manipulate that image as you’d like (by setting individual pixels, drawing lines and rectangles, etc.). In TypeScript, it’d look something like this:

let bg: Image = image.create(screen.width, screen.height)
scene.setBackgroundImage(bg)
// Any manipulations now done to bg will be shown on the screen
bg.printCenter('Hi, there!', 0, 5, image.font8)
bg.drawRect(0, 20, 40, 40, 1)
bg.fillRect(0, 70, 30, 30, 5)

In Blocks, you’d do something like this:

1 Like

Actually, I found the following:

ScreenImage.setPixel()                        

Ref: set Pixel

It seems it is possible to use a blitter in the beta with:

ScreenImage.blitRow()

Interesting stuff … although no documentation?

If you are in JavaScript, there are two ways to do it:

// This callback will run every frame after the sprites have been drawn
// so you can draw to the screen and not be overwritten
game.onShade(() => {
    screen.setPixel(0, 0, 1)
})

// Creates a "sprite-ish" object where you implement the draw method
// (only available in beta beta)
scene.createRenderable(0, (target: Image, camera: scene.Camera) => {
    target.setPixel(0, 0, 1)
})

The renderable approach is nice because it handles sorting for you (the first argument is the z-index). It’s currently only available in beta beta (https://arcade.makecode.com/beta)

1 Like

Also, the background image approach also works but it will consume a lot of memory on hardware.

If an image is editable (i.e. you are writing pixels to it), then it is stored in RAM. The setBackgroundImage API is really meant to be used with static images that are stored in the flash and not memory.

2 Likes

Sorry … should have mentioned that! The background image approach certainly is not the most memory-efficient method. :slight_smile: You’ll only be able to keep one or two in memory on hardware because of the limited RAM. Since it’s kept in memory, though, it’s a bit simpler, as the image doesn’t need to be redrawn in code each frame. It’s also the only available method for use in Blocks.

For more traditional game developers, onShade() and createRenderable() definitely are what you want.

If you want to dig around the internals, take a look at the source code in GitHub. The code is very well documented, and you may find additional routines that are of use to you. Things change, of course, so be careful about using undocumented APIs, but most of the “playing” that the devs do is done outside of the master branches. Aside from the main repository,[1] you’ll want to check out the common packages repo, as well.[2]

[1] https://github.com/microsoft/pxt-arcade
[2] https://github.com/Microsoft/pxt-common-packages

3 Likes

Thanks Alex! Thanks especially for calling the code well documented :smile:

1 Like

Screen.blitRow(x, y, src, sx, h) will draw a row of pixels from position Sx in src image. It will draw at x,y on screen and the resulting row will be h pixels high (that is it will scale src.height to h).

It’s mostly useful for ray casting, but you could also use it for general scaling.

3 Likes

I was looking at the sources at pxt-arcade, but wasn’t able to find this. Hence my follow-up message.

You can find the function header here:

It’s implemented here:

1 Like

Was looking in all the wrong places; common-packages it was :wink: