# How would one make these screen effects?

**URL:** <https://forum.makecode.com/t/how-would-one-make-these-screen-effects/12341>\
**Category:** Help\
**Tags:** graphics-and-math\
**Created:** [February 22, 2022, 11:08pm UTC](https://forum.makecode.com/t/how-would-one-make-these-screen-effects/12341 "2022-02-22T23:08:43Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![hasanchik](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.makecode.com/hasanchik/32/5885_2.png) [@hasanchik](https://forum.makecode.com/u/hasanchik)\
**Post date:** [February 22, 2022, 11:08pm UTC](https://forum.makecode.com/t/how-would-one-make-these-screen-effects/12341/1 "2022-02-22T23:08:43Z")

</div>

This is not an actual request, but if someone does knoe how to do it, please do make a demo.  
Also please watch this video first: [https://www.youtube.com/watch?v=zjQik7uwLIQ](https://www.youtube.com/watch?v=zjQik7uwLIQ)

I have made some screen effects, like a water screen effect  
 ![skillissuegemtree](https://us1.discourse-cdn.com/flex020/uploads/makecode/original/2X/b/b8ad4894a91908286e703fb7a5ebe4734ca56160.gif)  
and a heat screen effect  
 ![skillissuegemtree](https://us1.discourse-cdn.com/flex020/uploads/makecode/original/2X/e/eb7b44e1991e67da19126090c35fbbf557a37736.gif)  
But how would one make wavy effects like this?

> **[GitHub - r3trodev/earthbound-backgrounds-shaders-godot: This shader is...](https://github.com/r3trodev/earthbound-backgrounds-shaders-godot)**
>
> This shader is inspired by the battle backgrounds of Earthbound. I tried to incorporate in this shader as many effects used in Earthbound to create the battle backgrounds. - GitHub - r3trodev/eart...

Or a ghost-like effect like this?

 ![image](https://us1.discourse-cdn.com/flex020/uploads/makecode/original/2X/0/0ad8232a01438bdeb7ed8bbd2aed65582ee7a3c0.jpeg)  
Or a weird squishing effect like this??  
([https://thumbs.gfycat.com/UnevenConventionalLeafbird-max-1mb.gif](https://thumbs.gfycat.com/UnevenConventionalLeafbird-max-1mb.gif))

---

<div class="post-metadata">

**Author:** ![hasanchik](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.makecode.com/hasanchik/32/5885_2.png) [@hasanchik](https://forum.makecode.com/u/hasanchik)\
**Post date:** [February 23, 2022, 6:07pm UTC](https://forum.makecode.com/t/how-would-one-make-these-screen-effects/12341/2 "2022-02-23T18:07:53Z")

</div>

Success! Although this is one effect, its still really cool to see:  
 ![skillissuegemtree](https://us1.discourse-cdn.com/flex020/uploads/makecode/original/2X/6/60886f31116b19b6721eb0a20d6b62583dd39f6d.gif)  
I plan it to be a extension.  
Heres the github link:  
[https://github.com/gasanchik/pxt-imgfx](https://github.com/gasanchik/pxt-imgfx)

---

<div class="post-metadata">

**Author:** ![hasanchik](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.makecode.com/hasanchik/32/5885_2.png) [@hasanchik](https://forum.makecode.com/u/hasanchik)\
**Post date:** [February 23, 2022, 6:07pm UTC](https://forum.makecode.com/t/how-would-one-make-these-screen-effects/12341/3 "2022-02-23T18:07:59Z")

</div>

Now with setColumn and getColumn done, even vertical screen fx like this can be done!  
 ![skillissuegemtree](https://us1.discourse-cdn.com/flex020/uploads/makecode/original/2X/b/be518d64e898e3739ceb0914f8f8e8628739f48f.gif)

---

<div class="post-metadata">

**Author:** ![hasanchik](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.makecode.com/hasanchik/32/5885_2.png) [@hasanchik](https://forum.makecode.com/u/hasanchik)\
**Post date:** [February 23, 2022, 7:08pm UTC](https://forum.makecode.com/t/how-would-one-make-these-screen-effects/12341/4 "2022-02-23T19:08:00Z")

</div>

The setColumn and getColumn is pretty laggy on hardware. setRow and getRow isn’t. How come that?  
Heres the code:

```auto
   export function getColumns(img: Image, y : number, dst: Buffer): void {
        let dp = 0
        let sp = 0
        let w = img.width
        let h = img.height
        if (y >= h || y < 0) {
            return
        }

        dst.setUint8(dp, img.getPixel(0, y))
        let n = Math.min(dst.length, (w - y) * h)
        //uint8_t * dp = dst.data;
        //let n = min(dst.length, (w - x) * h) >> 1;

        while (n--) {
            dst.setUint8(sp, img.getPixel(sp, y))
            sp++;
        }
        return
    }

    export function setColumns(img: Image, y: number, src: Buffer): void {
        let dp = 0
        let sp = 0
        let w = img.width
        let h = img.height
        if (y >= h || y < 0) {
            return
        }

        let n = Math.min(src.length, (w - y) * h)
        //uint8_t * dp = dst.data;
        //let n = min(dst.length, (w - x) * h) >> 1;

        while (n--) {
            img.setPixel(sp, y, src[sp])
            sp += 1
        }
        return
    }

```

---

<div class="post-metadata">

**Author:** ![richard](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.makecode.com/richard/32/5417_2.png) [@richard](https://forum.makecode.com/u/richard)\
**Post date:** [February 23, 2022, 7:40pm UTC](https://forum.makecode.com/t/how-would-one-make-these-screen-effects/12341/5 "2022-02-23T19:40:23Z")

</div>

Good question!

There are two reasons why this is slower on hardware:

1. getRows and setRows is implemented in C++. Our compiled TypeScript code is pretty fast, but C++ is just a bit faster
2. The images are stored in memory column by column rather than row by row.

To clarify the second point, here’s a more detailed explanation:

You can think of the memory of the device as one long array of numbers. Since it’s a 1d array and images are 2d, we need to “flatten” the image to store it in memory. This is done by storing all of the columns one after another end to end. For a 2x2 image, it looks something like this:

```auto
Memory address: 0x0 0x1 0x2 0x3
Pixel: (0,0) (0,1) (1,0) (1,1)

```

(this isn’t quite accurate because each pixel is actually half a byte, but it’s good enough for this example)

When we want to access a specific pixel, we’d do so like this:

```auto
color = memory[x * height + y]

```

Because all of the pixels in a given column are stored next to each other, reading/writing an entire column is fast because it’s all in one contiguous piece of memory.

Now why does being a contiguous piece of memory matter?

Well, computers have several layers of memory that they use to store data. You’re probably familiar with two of these: the hard drive and RAM. RAM is way faster than the hard drive, so when the computer needs to access something often it will move the section of memory it lives in into RAM. It’s expensive to put something into RAM, but it ends up being way, way, faster in the long run if it’s being accessed multiple times. This strategy works best when things being accessed are next to each other in memory, because then only one chunk of data needs to be moved into RAM at a time.

When you access a lot of memory addresses far away from each other, the computer needs to keep moving more stuff into RAM every time something is missing. That’s why it’s better to access stuff in the order it’s stored.

In reality, most computers have more than just two layers of memory. Each one gets smaller and faster the closer it is to the top.

---

<div class="post-metadata">

**Author:** ![hasanchik](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.makecode.com/hasanchik/32/5885_2.png) [@hasanchik](https://forum.makecode.com/u/hasanchik)\
**Post date:** [February 23, 2022, 9:55pm UTC](https://forum.makecode.com/t/how-would-one-make-these-screen-effects/12341/6 "2022-02-23T21:55:54Z")

</div>

I only expected it to be because of the c++ it was written in!  
But, do you know how to make a blitColumn function?  
I cant seem to convert your c++ code into ts. Its a bit complicated for me since i donw know c++.

---

<div class="post-metadata">

**Author:** ![richard](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.makecode.com/richard/32/5417_2.png) [@richard](https://forum.makecode.com/u/richard)\
**Post date:** [February 23, 2022, 11:08pm UTC](https://forum.makecode.com/t/how-would-one-make-these-screen-effects/12341/7 "2022-02-23T23:08:14Z")

</div>

Can you give me a link to the code you’re using get/set columns on? I’m wondering if maybe it can be rewritten to use get/set rows.

---

<div class="post-metadata">

**Author:** ![hasanchik](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.makecode.com/hasanchik/32/5885_2.png) [@hasanchik](https://forum.makecode.com/u/hasanchik)\
**Post date:** [February 24, 2022, 4:42pm UTC](https://forum.makecode.com/t/how-would-one-make-these-screen-effects/12341/8 "2022-02-24T16:42:27Z")

</div>

![Screenshot_2022-02-24-07-58-59-11_3aea4af51f236e4932235fdada7d1643](https://us1.discourse-cdn.com/flex020/uploads/makecode/original/2X/7/743208072d0f526380fb19b9e17cddae2d0b67fa.jpeg)

---

<div class="post-metadata">

**Author:** ![hasanchik](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.makecode.com/hasanchik/32/5885_2.png) [@hasanchik](https://forum.makecode.com/u/hasanchik)\
**Post date:** [February 24, 2022, 4:42pm UTC](https://forum.makecode.com/t/how-would-one-make-these-screen-effects/12341/9 "2022-02-24T16:42:31Z")

</div>

Code that uses blitrow (could use getrows and setrows but I don’t know how to do that)

 ![Screenshot_2022-02-24-08-07-50-30_3aea4af51f236e4932235fdada7d1643](https://us1.discourse-cdn.com/flex020/uploads/makecode/original/2X/4/4dd1dd24d37905bfd54aab122650c4a8e883561f.jpeg)

---

<div class="post-metadata">

**Author:** ![AqeeAqee](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.makecode.com/aqeeaqee/32/5424_2.png) [@AqeeAqee](https://forum.makecode.com/u/AqeeAqee)\
**Post date:** [February 24, 2022, 4:42pm UTC](https://forum.makecode.com/t/how-would-one-make-these-screen-effects/12341/10 "2022-02-24T16:42:39Z")

</div>

Hi @hasanchik @richard

Very interesting topic for me, thought I am not good at it.

For in each time screen effect applying, get/setColumn will be called many times(100~160 I guess).  
So just supposed:

- create a cache image which transposed screen(x\<–\>y) at begin of apply()
- then call get/setRow in C++
- and write back to screen at the end tranposed again

Is that a efficient way?

---

<div class="post-metadata">

**Author:** ![richard](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.makecode.com/richard/32/5417_2.png) [@richard](https://forum.makecode.com/u/richard)\
**Post date:** [February 24, 2022, 6:01pm UTC](https://forum.makecode.com/t/how-would-one-make-these-screen-effects/12341/11 "2022-02-24T18:01:31Z")

</div>

@AqeeAqee that would certainly speed things up, but the screen is rather large (10kb) and keeping around an extra copy might cause memory issues.

@hasanchik have you tried using image.blit (not blitRow). Not sure how the perf will compare, but it might work for your needs

---

<div class="post-metadata">

**Author:** ![hasanchik](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.makecode.com/hasanchik/32/5885_2.png) [@hasanchik](https://forum.makecode.com/u/hasanchik)\
**Post date:** [February 24, 2022, 6:02pm UTC](https://forum.makecode.com/t/how-would-one-make-these-screen-effects/12341/12 "2022-02-24T18:02:02Z")

</div>

Could you also help me with a new function im creating? It basically loops an image with no seams in a canvas of w width and h height. It looks really janky and bad and i dont know how to make it. Its like the scrolling background extension you made but with support for any size image.

The right and bottom part is cut out, that is what i mean with “looping a image with no seams in a canvas”. Here are the scripts:

```auto
namespace Math {
    export function mod(a: number, n: number): number {
        if (n == 0) {
            return a
        }
        return (((a % n) + n) % n);
    }
}
////////////////////////////
    export function repeatImage(img: Image, scrollx: number, scrolly: number, maxwidth: number, maxheight: number, scrollable : boolean = false) {
        let w = img.width
        let h = img.height
        maxwidth = maxwidth + w
        let og = img.clone()
        let out = image.create(maxwidth,maxheight)
        let modx = maxwidth
        let mody = maxheight
        if (scrollable == true) {
            modx = 0
            mody = 0
        }
        for (let y = 0; y < Math.ceil(maxheight / h); y++) {
            let y2 = Math.mod(h * y + scrolly, mody + Math.mod(maxheight, h))
            for (let x = 0; x < Math.ceil(maxwidth / w); x++) {
                let x2 = Math.mod((w * x + scrollx), modx + Math.mod(maxwidth, w))
                out.drawTransparentImage(og, x2, y2,)
            }
        }
        return out
    }

```

![skillissuegemtree](https://us1.discourse-cdn.com/flex020/uploads/makecode/original/2X/a/a78f06e37590ff40fcb9660037f726ffcf360993.gif)

---

<div class="post-metadata">

**Author:** ![hasanchik](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.makecode.com/hasanchik/32/5885_2.png) [@hasanchik](https://forum.makecode.com/u/hasanchik)\
**Post date:** [February 24, 2022, 6:02pm UTC](https://forum.makecode.com/t/how-would-one-make-these-screen-effects/12341/13 "2022-02-24T18:02:07Z")

</div>

> [@AqeeAqee](#):
>
> transposed

i dont think that would work, because the screen is a rectangle. If you transposed the screen you would lose alot of image data.

---

<div class="post-metadata">

**Author:** ![richard](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.makecode.com/richard/32/5417_2.png) [@richard](https://forum.makecode.com/u/richard)\
**Post date:** [February 24, 2022, 6:02pm UTC](https://forum.makecode.com/t/how-would-one-make-these-screen-effects/12341/14 "2022-02-24T18:02:32Z")

</div>

@hasanchik you could transpose it to an image with the height/width swapped

---

<div class="post-metadata">

**Author:** ![richard](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.makecode.com/richard/32/5417_2.png) [@richard](https://forum.makecode.com/u/richard)\
**Post date:** [February 24, 2022, 6:27pm UTC](https://forum.makecode.com/t/how-would-one-make-these-screen-effects/12341/15 "2022-02-24T18:27:03Z")

</div>

@hasanchik give this a shot:

> **[scroll image](https://arcade.makecode.com/48795-66191-15053-47608)**
>
> Made with ❤️ in Microsoft MakeCode Arcade.

---

<div class="post-metadata">

**Author:** ![hasanchik](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.makecode.com/hasanchik/32/5885_2.png) [@hasanchik](https://forum.makecode.com/u/hasanchik)\
**Post date:** [February 24, 2022, 6:38pm UTC](https://forum.makecode.com/t/how-would-one-make-these-screen-effects/12341/16 "2022-02-24T18:38:13Z")

</div>

Thanks alot! This will be a really good extension thanks to you!

---

<div class="post-metadata">

**Author:** ![AqeeAqee](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.makecode.com/aqeeaqee/32/5424_2.png) [@AqeeAqee](https://forum.makecode.com/u/AqeeAqee)\
**Post date:** [February 24, 2022, 9:33pm UTC](https://forum.makecode.com/t/how-would-one-make-these-screen-effects/12341/17 "2022-02-24T21:33:47Z")

</div>

> [@richard](#):
>
> @AqeeAqee that would certainly speed things up, but the screen is rather large (10kb) and keeping around an extra copy might cause memory issues.

Yes, indeed. I ignored 10kb memery is so critical for embeded devices.  
Maybe some simple project could use it for preformence, absolutely bad idea for extensions.  
Thanks.

---

<div class="post-metadata">

**Author:** ![AqeeAqee](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.makecode.com/aqeeaqee/32/5424_2.png) [@AqeeAqee](https://forum.makecode.com/u/AqeeAqee)\
**Post date:** [February 24, 2022, 9:33pm UTC](https://forum.makecode.com/t/how-would-one-make-these-screen-effects/12341/18 "2022-02-24T21:33:56Z")

</div>

> [@richard](#):
>
> you could transpose it to an image with the height/width swapped

@hasanchik That’s what I mean.  
Sorry for my English, it’s not my native language.

---

<div class="post-metadata">

**Author:** ![hasanchik](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.makecode.com/hasanchik/32/5885_2.png) [@hasanchik](https://forum.makecode.com/u/hasanchik)\
**Post date:** [February 24, 2022, 9:34pm UTC](https://forum.makecode.com/t/how-would-one-make-these-screen-effects/12341/19 "2022-02-24T21:34:31Z")

</div>

Hi again,  
I’ve never mentioned this image effect i made: Its a dithering effect. It can dither from one image to another, from an image to a color, or simply fade. Its like that morph extension. Take a look:  
 ![skillissuegemtree](https://us1.discourse-cdn.com/flex020/uploads/makecode/original/2X/b/b6230d5186958d4c5c8b7f18a55b11ee3c165a29.gif)  
Problem is, this is incredibly laggy!!! On my xtron pro, when i applied this effect to a 16 by 16 sprite, fps drops to 20. Then i applied it to a 32 by 32 sprite, it drops to 10 fps!! And when i apply it to the whole screen like the gif it drops to 0.4 fps!!! Maybe because im setting every pixel, but that cant be it alone. I really dont know how to optimize this.

Code:

```auto
    //Thanks to kwx for the basis of this effect! (From 3d rendering demo)
    const Dither = img`
        1 1 1 1 . 1 1 1 . 1 1 1 . 1 1 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . . . 1 . . . 1 . . . 1 . . . .
        1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 . 1 1 1 . 1 1 1 . 1 1 1 . 1 . . . 1 . . . 1 . . . 1 . . . . . . . . . . . . . . . . . . . . .
        1 1 1 1 1 1 1 1 1 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . 1 . . . . . . . . . .
        1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 . 1 . 1 . 1 . 1 . 1 . 1 . . . 1 . . . . . . . . . . . . . . . . . . . . . . . . .
    `
    export function dither(img: Image, threshold: number, color: number = 0, img2: Image = null, offx: number = 0, offy: number = 0) {
        let w = img.width
        let h = img.height
        //let imageData : number[] = []
        let og = img.clone()
        for (let y = 0; y < h; y++) {
            const screeny = (h >> 1) + (y | 0) - 1 + Math.abs(offy)
            for (let x = 0; x < w; x++) {
                const ditherOffset = Math.floor(Math.mod(threshold, 17)) * 4;
                let screenx = (w >> 1) + (x | 0) + Math.abs(offx)
                let ditherX = ditherOffset + (screenx % 4);
                let ditherY = screeny % 4;
                let ditherPixel = Dither.getPixel(ditherX, ditherY);
                let shaded = ditherPixel ? 1 : 0;
                if (shaded>=1) {
                    og.setPixel(x, y, color)
                    if (img2 != null) {
                        og.setPixel(x, y, img2.getPixel(x,y))
                    }
                }
            }
        }
        return og
    }

```

---

<div class="post-metadata">

**Author:** ![kwx](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.makecode.com/kwx/32/1545_2.png) [@kwx](https://forum.makecode.com/u/kwx)\
**Post date:** [February 24, 2022, 11:25pm UTC](https://forum.makecode.com/t/how-would-one-make-these-screen-effects/12341/20 "2022-02-24T23:25:06Z")

</div>

Some quick suggestions:

- Move as much code as possible out of the inner loop. For example, `ditherOffset` only depends on `threshold`, and can be calculated once at the start of the function.

- Use buffer functions (image.getRows/setRows) instead of accessing individual pixels

- Try unrolling loops. For example, here’s a function from the Space Rocks 3D renderer that draws an alternating-colors dither pattern in chunks of 8 pixels, then doing the leftover pixels in chunks of 4/2/1 pixels as needed to get the exact pixel count needed. This is a lot faster than a per-pixel loop since it avoids the overhead from jumping around.

[Next page](https://forum.makecode.com/t/how-would-one-make-these-screen-effects/12341.md?page=2)
