Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Changing palettes

Hello!
In my program I need to draw an image, which is only 128x128, to the screen often but I also need to occasionally change the palette. For example, I may need to make all of the white pixels black. I’m not sure how to do this though. I do not understand meshes, would I need a vertex for each pixel? Any help is greatly appreciated!

Comments

  • dave1707dave1707 Mod
    Posts: 7,838

    @SaladFingers If that’s an image you’re creating by assigning colors before you draw, the you can assign colors to a variable. For instance you can say White=color(255,255,255). Then when you want to change to black you can assign White=color(0,0,0). I’d need to see some of your code to better understand how you’re drawing your image.

  • edited September 28 Posts: 18

    @dave1707 I forgot to mention that I manipulate the image frequently by using setContext(), and I draw the image to the screen using sprite()
    Edit: I see what you are saying but I would not be able to to that because the image that I am drawing to the screen, has sprites drawn to it. My only idea of how to do this would be to iterate over all the pixels in the image and change the colors that way but it would be slow

  • edited September 28 Posts: 1,354
    @SaladFingers - sounds like you are drawing a background and then superimposing sprites. Do you need to change the colours of the background or sprites?

    If it's sprites a shader is the best way. If it's the background an array of palettes would do the job.

    In the bad old days, on a defunct computer (a BBC micro) a simple VDU command would have cycled sprite colours very easily.
  • edited September 28 Posts: 18

    @Bri_G Yes, essentially I have a screen buffer that is an image, and I use various built-in functions to draw to it: rect, sprite, line, etc... and I need to change the colors of all the pixels in the screen buffer image. I hope that makes sense. I draw the buffer using the sprite function. And I am not sure I understand your question about the backgrounds.
    Thanks so much for your help!

  • dave1707dave1707 Mod
    Posts: 7,838

    @SaladFingers I’m still not sure of everything you’re trying to do but here’s an example where I draw a 128x128 background and then draw a rect, ellipse, line, and a sprite. Then each time I tap the screen I alter the color. What do you need to do differently.

    displayMode(FULLSCREEN)
    
    function setup()
        img=image(128,128)
        setContext(img)
        background(0, 255, 0, 255)
        fill(255,0,0)
        rect(50,50,20,20)
        fill(0,0,255)
        ellipse(100,100,40,40)
        stroke(255)
        strokeWidth(5)
        line(0,0,128,128)
        sprite("Planet Cute:Character Princess Girl",50,100,50)
        setContext()
    end
    
    function draw()
        background(0)
        sprite(img,WIDTH/2,HEIGHT/2)   
        fill(255)
        text("tap screen to alter color",WIDTH/2,HEIGHT-100)
    end
    
    function touched(t)
        if t.state==BEGAN then
            for x=1,128 do
                for y=1,128 do
                    r,g,b,a=img:get(x,y)
                    r,b=b,r
                    g,r=r,g
                    img:set(x,y,r,g,b,a)
                end
            end
        end
    end
    
  • Posts: 1,354
    @SaladFingers - all the pixels probably needs a shader. If it's an effect like flashing explosion you could consider layering the background and coupling cycling images with transparency values you could fade one out and fade one in. Do it other multiple backgrounds could be quite effective.

    In a similar way you could cycle round different coloured sprites in the foreground (just as you do with animations).
  • edited September 28 Posts: 18

    @dave1707 Although this accomplishes what I need, it would be incredibly slow and not practical.

    To give more context (which I should have done to start with), is I am trying to reimplement PICO-8 in Codea. Most problematically, so far, is the PAL() function which modifies palettes. So I have a 'screen' variable, which is a 128x128 image that uses RGB for color. PICO-8 has 16 colors in its palette, which accepts as an index to the RGB representation of that color. But in PICO-8, you can change the color that is shown for a specific index. For example, the 7th color is white and the 1st color is black, by calling PAL(1,0), any color on the screen that has the index of 1 (black), becomes displayed as index 0 (white). So all black pixels become white. Hope I explained that well...

  • dave1707dave1707 Mod
    edited September 28 Posts: 7,838

    @SaladFingers Here’s something that might be close to what you’re after, I think. Slide the from and to parameters then tap PAL to switch colors. Press reset to get back to the original image. This only has 8 colors, but that can be expanded to as many as you want.

    displayMode(STANDARD)
    
    function setup()
        tabs1()
        parameter.integer("fromCol",1,8,1)
        parameter.integer("toCol",1,8,1)
        parameter.action("PAL",pal)
        parameter.action("reset",reset)
        create()
    end
    
    function draw()
        background(0)
        sprite(img,WIDTH/2,HEIGHT/2)  
        stroke(255)
        strokeWidth(2)
        for z=1,8 do
            fill(tab1[z])
            rect(z*60,HEIGHT-100,50,50)
        end
        fill(255)
        text("from",fromCol*60+25,HEIGHT-120)
        text("to",toCol*60+25,HEIGHT-140)
    
        text(string.format("PAL(%d,%d)",fromCol,toCol),WIDTH/2,HEIGHT-180)
    end
    
    function pal()
        for z=1,#col do
            if col[z]==fromCol then
                col[z]=toCol
            end
        end
        tabs2()
        create() 
    end
    
    function reset()
        tabs1()
        create()
    end
    
    function tabs1()
        tab1={  color(0,0,0),
                color(0,0,255),
                color(0,255,0),
                color(0,255,255),
                color(255,0,0),
                color(255,0,255),
                color(255,255,0),
                color(255,255,255)
            }
        col={1,2,3,4,5,6,7,8}
        tabs2()
    end
    
    function tabs2()
        black=tab1[col[1]]
        blue=tab1[col[2]]
        green=tab1[col[3]]
        cyan=tab1[col[4]]
        red=tab1[col[5]]
        magenta=tab1[col[6]] 
        yellow=tab1[col[7]] 
        white=tab1[col[8]]
    end
    
    function create()
        noStroke()    
    
        img=image(128,128)    
        setContext(img)
    
        background(green)   
    
        fill(red)
        rect(20,60,20,60)   
    
        fill(blue)
        ellipse(100,50,40,40)   
    
        stroke(magenta)
        strokeWidth(5)
        line(0,0,128,128) 
    
        setContext()
    end
    
  • Posts: 1,354
    @SaladFingers - that's precisely what one of the bbc micros VDU commands did. Could you post an image as an example of what you are trying to colour cycle.

    I'm not hot on shaders but in principle you could build up a palette, pass it to the shader which could cycle through the palette exchanging pixel colours. It was used in lots of demos with moving text and line/colour scrolling often with sine waves for effect
  • @dave1707 That would work, and is currently what I’m doing, but the issue is that I would be also drawing images onto “img” and those sprites would need their colors changed too.

    @Bri_G The first is what it currently looks like and the second is what it should look like. The difference is the colors underneath the “hello world.” The white colors are modified. Here is the PICO-8 program:

    function _update()
    
     t+=1
    
    end
    
    
    
    function _draw()
    
     cls()
     i,j0 = 0,0
    
    
     for i=1,11 do
    
      for j0=0,7 do
    
      j = 7-j0
    
      col = 7+j
    
      t1 = t + i*4 - j*2
    
      x = cos(t0)*5
    
      y = 38 + j + cos(t1/50)*5
    
      pal(7,col)
    
      spr(16+i, 8+i*8 + x, y)
    
      end
    
     end
    
    
    
      print("this is pico-8",
    
        37, 70, 14) --8+(t/4)%8)
    
    
    
     print("nice to meet you",
    
        34, 80, 12) --8+(t/4)%8)
    
    
    
      spr(1, 64-4, 90)
    
    end
    
  • dave1707dave1707 Mod
    edited September 30 Posts: 7,838

    @SaladFingers I’m totally confused about what you’re trying to do. At the start you said you want to draw something on a 128x128 image and to be able to change a color on the image. Then above you show 2 images and the second image is quite different than the first. You’re not just altering a color, but you’re adding a lot of other things. So if you’re doing that, then just alter the colors before redrawing on the 2nd image. If you want a color palette, then you can put a bunch of colors in a table and refer to them by number.

    displayMode(FULLSCREEN)
    
    function setup()
        str="Hello World "
        col={   color(0,0,0),
                color(0,0,255),
                color(0,255,0),
                color(0,255,255),
                color(255,0,0),
                color(255,0,255),
                color(255,255,0),
                color(255,255,255) }
        create()   
    end
    
    function draw()
        background(0, 0, 0, 255)
        sprite(img,WIDTH/2,HEIGHT/2)
    end
    
    function create()
        img=image(WIDTH,HEIGHT)
        setContext(img)
        background(0)
        fontSize(140)    
        c=1
        for a=-3,3 do
            c=c+1
            for i=1,#str do
                x=i*70
                v=string.sub(str,i,i)
                y=math.sin(math.rad(i*180/#str))*60*a+HEIGHT/1.8
                fill(col[c])
                text(v,x,y)
            end
        end
        fontSize(40)
        fill(col[2])
        text("this is pico-8",WIDTH/2,HEIGHT/4)
        fill(col[4])
        text("nice to meet you",WIDTH/2,HEIGHT/5)
        sprite("Planet Cute:Heart",WIDTH/2,HEIGHT/7,50)
        setContext()
    end
    
  • edited September 30 Posts: 1,354

    @SaladFingers, @dave1707 - first stab at getting you intro sorted. Only thing I am missing is getting each layer ‘Hello World’ to be offset vertically with the sine wave. Also seems to stick occasionally. Maybe one of you could add the offset scrolling?


    -- Pico-8-01 -- Bri_G first attempt displayMode(OVERLAY) function setup() -- cX,cY = WIDTH/2,HEIGHT/2 hello = "HELLO WORLD" font("Copperplate-Bold") fontSize(64) textMode(LEFT) offset,y,pt = 0,0,1 txt = {} piV = 2*math.pi/11 for lp = 1,11 do txt[lp] = string.sub(hello,lp,lp) end end function draw() -- background(4, 4, 4, 255) for layer = 1,7 do for x = 1,11 do posx = x*56 -- for y = 1,11 do fill(colrs[layer]) pos = math.sin(os.clock()) posy = cY + pos*piV/(0.02)*y+offset text(txt[x],posx,posy) offset = 32 end y = y+1 if y > 7 then y = 1 end end end colrs = { color(228, 210, 204, 255), color(216, 133, 216, 255), color(148, 223, 215, 255), color(143, 223, 149, 255), color(235, 234, 67, 255), color(250, 151, 11, 255), color(241, 44, 62, 255), }

    P.s. - thought the use of text letters would be easier than sprites - adding an eightH colour created havoc!!

  • dave1707dave1707 Mod
    Posts: 7,838

    @Bri_G @SaladFingers See my example above.

  • Posts: 1,354

    @dave1707 - very neat, I just thought it was an animated intro screen with more involved images(sprites). I tried to text and it worked but I became a little frustrated with trying to offset several scrolling strings - produced some interesting effects but not like those @SaladFingers was trying to imitate.

  • dave1707dave1707 Mod
    Posts: 7,838

    @Bri_G I’m not sure what it’s supposed to be. As I mentioned in my post above I don’t know what he wants to accomplish. I was just going by what he showed in the 2 images.

  • Posts: 1,354

    @dave1707 - same here, just looks like some of the early PC games with simple scrolling text. See what feedback comes back.

  • edited September 30 Posts: 18
    @Bri_G @dave1707
    I sincerely apologize for my lack of clarity. The idea of my project is to take a PICO-8 program and alter it to the point that it will run in Codea. PICO-8 is a fantasy console that uses Lua and has many other features such as built in graphics and sound. The program I attached was a PICO-8 demo program. It does not run natively in Codea. Functions like “cls,” “pal,” and “spr” have been rewritten by me to allow the code to run. The problem I am experiencing is with PICO-8’s ability to change palette colors. Codea uses a standard RGBA format for all image types. In PICO-8, I can have the color index 4 show up as white or as green or blue: it can be whatever color. In Codea, color(255,255,255,255) is always white. @dave1707 you suggested using tables which would work except for PICO-8’s “spr” function which draws a sprite to the screen. It would be very slow to copy each pixel one by one to my screen buffer rather than using Codea’s sprite function which copies all the pixels at once but doesn’t allow me to modify what those pixels look like.

    I hope I’ve explained this better, and I really appreciate your guys’ help!
  • dave1707dave1707 Mod
    Posts: 7,838

    @SaladFingers Thanks, that explains a lot. You can change the sprite color somewhat by using the tint command. Or you can create your own simple sprites and redraw them changing the color. It’s always hard to take a program from one system and convert it to another.

Sign In or Register to comment.