Log In  

I've been trying ways to take a specific sprite and replace all of them on the map with another sprite.

Here are two methods I figured out.

Cart #set_all1-0 | 2023-02-24 | Code ▽ | Embed ▽ | No License
1


This here is the first method and the one I use in my Pico-8 game "Marley The Adventurer". Probably the most simple and reliable method. It just scans all tiles one by one every time it wants to swap and immediatly replaces it by the other tile if the tile matches the one specified. It uses almost no extra RAM, but a lot of CPU usage. And if one of the tiles gets removed or if one gets added it will still react properly and replace the new tiles as well.
The function takes two parameters: set_all1(current_tile_sprite, new_tile_sprite)

Now for the next one

Cart #set_all2-0 | 2023-02-24 | Code ▽ | Embed ▽ | No License
1


This method works by scanning the whole map when you run the cart (which may lead to longer loading times) and stores the sprites coordinates into a variable. The tile replacing function simply reads the coordinates that were in memory and replaces them with a given sprite. This method is good when you have few tiles to replace, as it takes just a bit more RAM to save a lot of CPU, but if you want to replace a sprite that is drawn almost all over the map, this method will save a tiny bit of CPU and take a lot more RAM. It also takes more code and has the downside of not responding to map changes: it will still try to replace the coordinates in memory even if you made changes to the map.

The function that puts the sprites in memory:
sprites_in_memory = get_all2(sprite)

The function that sets a new sprite:
set_all2(sprites_in_memory, new_sprite)

What other ways do you have in mind? I'm kind of new to Pico-8 and I'd like to know what you would come up with.

P.S. There seems to be a bug with the amount of memory shown on the browser

P#126257 2023-02-24 23:47 ( Edited 2023-02-24 23:54)

@bilodau:

Consider changing only what the player can see. That would run faster. If you need help coding that, let me know and I will be happy to assist.

P#126259 2023-02-25 01:35

@dw817 I've been thinking about that too. And I'd really appreciate your help to help me code it.

P#126260 2023-02-25 01:38

Alright, lemme think for a second, @bilodau ...

First off be aware that if you use mapper that exceeds or is at 32 vertical, that cuts into your 128-255 sprites.

I'm not going to use that space. I'll just use the 0-127 horizontally and 0-15 vertically.

Cart #scms_02_24_23-0 | 2023-02-25 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

P#126262 2023-02-25 02:10 ( Edited 2023-02-25 02:10)

I prefer using an array for the map. This makes it easy to add various properties for tiles, and change them dynamically.

Cart #mezudaduso-0 | 2023-02-25 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

P#126266 2023-02-25 05:11

@binaryeye:

The map doesn't scroll to new data ... pretty sure that's a requisite.

P#126270 2023-02-25 05:23
1

bilodau: instead of looping over the map and using mset, have you thought of changing the sprite data with sset?
https://www.lexaloffle.com/dl/docs/pico-8_manual.html#SSET

P#126284 2023-02-25 17:47

That's a very good suggestion, @merwok !

@bilodau, can you see how to do that on your own - or would you like to see code for it ?

P#126288 2023-02-25 20:51

@dw817 @binaryeye @merwok I feel overwhelmed by all this information and don't understand much.

P#126293 2023-02-25 22:36
1

Hi @bilodau:

Well I think @merwok is definitely on to something. Here now, try out this code and examine the sprites. This is probably the first map in Pico-8 that takes advantage of 256-colors. :)

Here, I'll also document this one completely. Check the source-code for details.

Cart #hemumiyeso-0 | 2023-02-25 | Code ▽ | Embed ▽ | No License
1

Check the CPU usage. Using MEMCPY() for many sprites is actually faster than manually using SSET() for a single 8x8 sprite.

Runs best offline where it does not flicker at all - at least for me.

P#126294 2023-02-25 22:45 ( Edited 2023-02-25 23:52)

@dw817 I made this according to what @merwok said. Is that what you meant, @merwok?

Warning: contains flashing images

Cart #setall_v3-1 | 2023-02-25 | Code ▽ | Embed ▽ | No License

P#126296 2023-02-25 23:10 ( Edited 2023-02-25 23:23)

yes, that’s using sset to change sprites used in the map.
the demo could be improved by changing the sprites when a button is pressed ;)

as was pointed out, using memcpy will be more efficient than using sget, as memcpy can set 8 pixels in one call. it’s a bit more advanced but worth learning!

P#126329 2023-02-26 21:11

I really appreciate your help, guys. But I prefer not use anything fancy as I'm just a beginner.

P#126330 2023-02-26 21:31
1

Hi @bilodau. Let me write a cart using only SGET() and SSET() then if that is your preference.

Cart #dotidedayo-0 | 2023-02-26 | Code ▽ | Embed ▽ | No License
1

Examine the source-code. If that's not clear I can document each line.

P#126331 2023-02-26 22:06

I'll try to understand all of this tomorrow @dw817.
Thanks for the help.

P#126338 2023-02-26 22:50

@dw817 I understand now. I took the time to read and I understand. Thank you so much for the help you're an amazing community ❤

P#126386 2023-02-27 22:59

You are very welcome, @bilodau. I'm getting at the level I need to write comments in my code to help me keep my thoughts in order. :)

Glad to assist. Here's hoping your next cart is nothing short of awesome !

P#126387 2023-02-27 23:08 ( Edited 2023-02-27 23:09)

@dw817 Marley The Adventurer is not done yet! I imagine a new level, which will probably be a pain to code. But still, it's not over!

By the way... I also forget to write these comments a lot...

P#126388 2023-02-27 23:10 ( Edited 2023-02-27 23:12)

Hey, @dw817,

I made this function for the purpose of replacing a sprite with sset. Do you think you can make it work with memcpy and that the function still uses the same parameters?

function replace_sprite(os,ds,f)
    -- os: original sprite
    -- ds: destination sprite
    -- f: include flags

    local os_x = (os%16)*8
    local os_y = os \ 16 * 8
    local ds_x = (ds%16)*8
    local ds_y = ds \ 16 * 8
    for y = 0,7 do
        for x = 0,7 do
            sset(ds_x+x,ds_y+y,
            sget(os_x+x,os_y+y))
        end
    end

    if f then
        fset(ds,fget(os))
    end
end

Thanks in advance,

bilodau

P.S. According to my tests, each byte from 0x0 to 0x0fff represent two pixels on the sprite sheet. Am I right?

P#126688 2023-03-06 23:05 ( Edited 2023-03-07 01:07)

Hi @bilodau:

I am on the downstairs computer now. And ...

Nope, a single pixel for Pico-8 uses 4-bits of data, not 8. So if you were to poke 0x6000 or 24576 a value of 0xFF or 255 which is 8-bits then it would be two "Salmon" (color #15) pixels that appear in the top-left-hand corner of the screen.

If you poke something that is 3-bytes or more, it spills into the next horizontal frame. So MemCpy() doesn't really do you a big advantage unless you are shifting MORE THAN ONE sprite at a time.

Your best results for 16-sprites for instance will be to use the first row (#0 if you count them 0 to 15) - the first row would contain the sprite you want to have appear. The second row #1 to contain the image of the sprite 1st frame and the third row #2 to contain the image of the sprite 2nd frame.

Then simply use a timer to animate them in sequence. If you want to animate at different times, you can do this.

Suppose you want to have 8-sprites animated fairly quickly and the 8 after it to animate somewhat slower. You could have this for that:


Cart #sa2ss-4 | 2023-03-07 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

(v04 03-06-23)
TO LOAD THIS PICO-8 CART, in immediate mode, type: load #sa2ss


So here are 16-sprites that don't animate, the first is just a black square. Then you have 8 that do animate, slow, and 8-more that animate a bit faster. 2 frames per animation sprite cel in all. Uses a simple 128x16 drawing map field. Use LEFT and RIGHT arrow keys to scroll through it.

If you don't split the animation as I am doing now and in fact have 16-sprites across to animate at one speed and 16-more sprites to animate at a different speed, the code would run faster and cleaner and use less CPU overall.

P#126694 2023-03-07 02:21 ( Edited 2023-03-07 02:27)

a pixel is 4 bits, but a sprite is more than one pixel, so it’s still efficient to poke 4 bytes at a time to set 8 pixels, or memcpy 4 bytes (one would have to compare the token and cpu costs to pick either, or coding simplicity if one feels easier to understand)

P#126716 2023-03-07 15:38

[Please log in to post a comment]

Follow Lexaloffle:          
Generated 2024-03-28 19:57:33 | 0.068s | Q:63