PlayBASIC LIVE: How to Make a 320 by 200 16 colour Palette Mapped Screen

Started by kevin, November 22, 2017, 09:12:17 AM

Previous topic - Next topic

kevin


PlayBASIC LIVE:   How to Make a 320 by 200 16 colour Palette Mapped Screen  (22 Nov 2017)

   In this video we take a look at how we could use the Palette mapping library to create a classic 8 bit styled screen that's 320 by 200 pixels with only 16 colours.    Which is something like the  type of graphic hardware you'd find in that classic 8bit / 16 bit computers.  In this example the programmer can use any of the 16 colours anyway on the the screen at any time,  this was generally not the case for classic  8Bit systems, which tend to have various limitations on how many colours can appears within a bitmap,  which makes some of the old artists even more impressive. 

Anyway, you can find the source code on our forums of course with thousands of other examples..  Have fun !

Video:


Example Code:
PlayBASIC Code: [Select]
// Include the palette Mapping library
#include "paletteMapping"


// Define
Dim Palette(256)


SetPalette(Palette())


for lp =0 to 15
palette(lp) =rndrgb()
next

Palette(0) = $0000ff
Palette(1) = $ffffff



constant ScreenWidth = 320
constant ScreenHeight = 200

PaletteSCreenImage=GetFreeImage()
CreateFXImageEx PaletteScreenImage,ScreenWidth,ScreenHeight, 16

FxScreen = newfximage(SCreenWidth,ScreenHeight)



x1=rnd(ScreenWidth)
y1=rnd(ScreenHeight)


do
rendertoimage PaletteScreenImage


x2=rnd(ScreenWidth)
y2=rnd(ScreenHeight)

linec x1,y1,x2,y2,indextorgb(rnd(15))

circlec mousex(),mousey(),30,true, indextorgb(CurrentColour)

if mousebutton()=1 and ButtonDown=false
CurrentColour = (CurrentColour+1 ) and $f
ButtonDown=true
else
ButtonDown=false
endif


x1=x2
y1=y2

RenderPaletteMappedScreen(PaletteScreenImage,0,0,FxScreen)

rendertoscreen

drawrotatedimage FxScreen,0,0,0,2,2,0,0,false

drawimage PaletteScreenImage,400,0,false

sync

loop spacekey()
end



function RenderPaletteMappedScreen(SrcPalettedImage,Xpos,Ypos,DestImage=0)

if GetImageDepth(SrcPalettedImage) = 16

local OldSurface = getSurface()

rendertoimage DestImage

lockbuffer
local ThisRGB = point(0,0)
local ImagePtr = GetImagePtr(SrcPalettedImage)
local ImageModulo = GetImagePitch(SrcPalettedImage)

local Width = GetImageWidth(SrcPalettedImage)

For ylp=0 to GetImageHeight(SrcPalettedImage)-1
DrawPaletteMappedStrip16 Xpos, Ypos+ylp, ImagePtr, Width, $000f
ImagePtr+=ImageModulo
next

unlockbuffer

rendertoimage OldSurface
endif
EndFunction






baggey

Quote from: kevin on November 22, 2017, 09:12:17 AM

PlayBASIC LIVE:   How to Make a 320 by 200 16 colour Palette Mapped Screen  (22 Nov 2017)

   In this video we take a look at how we could use the Palette mapping library to create a classic 8 bit styled screen that's 320 by 200 pixels with only 16 colours.    Which is something like the  type of graphic hardware you'd find in that classic 8bit / 16 bit computers.  In this example the programmer can use any of the 16 colours anyway on the the screen at any time,  this was generally not the case for classic  8Bit systems, which tend to have various limitations on how many colours can appears within a bitmap,  which makes some of the old artists even more impressive. 

Anyway, you can find the source code on our forums of course with thousands of other examples..  Have fun !

Video:


Example Code:
PlayBASIC Code: [Select]
// Include the palette Mapping library
#include "paletteMapping"


// Define
Dim Palette(256)


SetPalette(Palette())


for lp =0 to 15
palette(lp) =rndrgb()
next

Palette(0) = $0000ff
Palette(1) = $ffffff



constant ScreenWidth = 320
constant ScreenHeight = 200

PaletteSCreenImage=GetFreeImage()
CreateFXImageEx PaletteScreenImage,ScreenWidth,ScreenHeight, 16

FxScreen = newfximage(SCreenWidth,ScreenHeight)



x1=rnd(ScreenWidth)
y1=rnd(ScreenHeight)


do
rendertoimage PaletteScreenImage


x2=rnd(ScreenWidth)
y2=rnd(ScreenHeight)

linec x1,y1,x2,y2,indextorgb(rnd(15))

circlec mousex(),mousey(),30,true, indextorgb(CurrentColour)

if mousebutton()=1 and ButtonDown=false
CurrentColour = (CurrentColour+1 ) and $f
ButtonDown=true
else
ButtonDown=false
endif


x1=x2
y1=y2

RenderPaletteMappedScreen(PaletteScreenImage,0,0,FxScreen)

rendertoscreen

drawrotatedimage FxScreen,0,0,0,2,2,0,0,false

drawimage PaletteScreenImage,400,0,false

sync

loop spacekey()
end



function RenderPaletteMappedScreen(SrcPalettedImage,Xpos,Ypos,DestImage=0)

if GetImageDepth(SrcPalettedImage) = 16

local OldSurface = getSurface()

rendertoimage DestImage

lockbuffer
local ThisRGB = point(0,0)
local ImagePtr = GetImagePtr(SrcPalettedImage)
local ImageModulo = GetImagePitch(SrcPalettedImage)

local Width = GetImageWidth(SrcPalettedImage)

For ylp=0 to GetImageHeight(SrcPalettedImage)-1
DrawPaletteMappedStrip16 Xpos, Ypos+ylp, ImagePtr, Width, $000f
ImagePtr+=ImageModulo
next

unlockbuffer

rendertoimage OldSurface
endif
EndFunction






How do i get the library and install it?
Jesus was only famous because of his dad

baggey

Okay, I just jumped to code and saw library.
Watched the video absoloutly superb!

Would love to see a video of making a program thats slow say bit banging pixels on screen and the compiling and converting with the machine code tool!

Kind Regards Baggey ;D
Jesus was only famous because of his dad

kevin


Quote
Would love to see a video of making a program thats slow say bit banging pixels on screen and the compiling and converting with the machine code tool!

  Yep that's on the TO DO list..

baggey

Hi,

Ive modified the code abit. I can't get fastdot to work? but dotc does?
I need to make this full screen or no window streched!
Heres the code.

Example Code:
PlayBASIC Code: [Select]
; PROJECT : zx81

; CREATED : 25/05/2018
; ---------------------------------------------------------------------

// Include the palette Mapping library
#include "paletteMapping"
openscreen 256,192,16,2

// Define
Dim Palette(256)
dim inkindex(15)

SetPalette(inkindex())


; for lp =0 to 15
; inkindex(lp) =rndrgb()
;next
initColorArrays()

;inkindex(0) = $0000ff
; inkindex(1) = $ffffff



constant ScreenWidth = 256
constant ScreenHeight = 192

PaletteSCreenImage=GetFreeImage()
CreateFXImageEx PaletteScreenImage,ScreenWidth,ScreenHeight, 16

FxScreen = newfximage(SCreenWidth,ScreenHeight)



; x1=rnd(ScreenWidth)
; y1=rnd(ScreenHeight)


do
;rendertoimage PaletteScreenImage

rendertoimage PaletteScreenImage
lockbuffer
for x= 0 to 256
for y= 0 to 192
;fastdot x,y,palette((rnd(15)))
dotc x,y,inkindex(rnd(15))
next
next

unlockbuffer

RenderPaletteMappedScreen(PaletteScreenImage,0,0,FxScreen)

rendertoscreen

drawrotatedimage FxScreen,0,0,0,10,10,0,0,false


;drawimage PaletteScreenImage,400,0,false

sync

loop spacekey()
end



function RenderPaletteMappedScreen(SrcPalettedImage,Xpos,Ypos,DestImage=0)

if GetImageDepth(SrcPalettedImage) = 16

local OldSurface = getSurface()

rendertoimage DestImage

lockbuffer
local ThisRGB = point(0,0)
local ImagePtr = GetImagePtr(SrcPalettedImage)
local ImageModulo = GetImagePitch(SrcPalettedImage)

local Width = GetImageWidth(SrcPalettedImage)

For ylp=0 to GetImageHeight(SrcPalettedImage)-1
DrawPaletteMappedStrip16 Xpos, Ypos+ylp, ImagePtr, Width, $000f
ImagePtr+=ImageModulo
next

unlockbuffer

rendertoimage OldSurface
endif
EndFunction


PSub InitColorArrays()

// Ive set the colors up here in RGB but using the palletindex(0)
// We have standard colors so we can make our own pallets!
// select color

// Standard Spectrum colors

// Normal
inkindex(0) = $0000ff ;rgb(0, 0, 0); Black
inkindex(1) = rgb(0,0,192); Blue
inkindex(2) = rgb(192,0,0); Red
inkindex(3) = rgb(192,0,192); Magenta
inkindex(4) = rgb(0,192,0); Green
inkindex(5) = rgb(0,192,192); Cyan
inkindex(6) = rgb(192,192,0); Yellow
inkindex(7) = rgb(192,192,192); White

// Bright
inkindex(8) = rgb(0, 0, 0); Black
inkindex(9) = rgb(0,0,255); Blue
inkindex(10) = rgb(255,0,0); Red
inkindex(11) = rgb(255,0,255); Magenta
inkindex(12) = rgb(0,255,0); Green
inkindex(13) = rgb(0,255,255); Cyan
inkindex(14) = rgb(255,255,0); Yellow
inkindex(15) = rgb(255,255,255); White

EndpSub


Jesus was only famous because of his dad

kevin



this loop has a couple of errors in it

PlayBASIC Code: [Select]
rendertoimage PaletteScreenImage
lockbuffer
for x= 0 to 256
for y= 0 to 192
;fastdot x,y,palette((rnd(15)))
dotc x,y,inkindex(rnd(15))
next
next

unlockbuffer





   Any of the FAST named commands such FastDot / FastPoint (and a few others) others require the surface to pre-seeded prior to calling.   These commands dont have any of them built into them, nor do they generally have clipping..   You can do this via using the DOT/POINT() commands on them.  Generally it's gest to use POINT as it doesn't change the surface.

Quote
      Note: Before you can use FastDot correctly. After you lock the draw surface, it's highly recommended you read a pixel from this surface using Point(). This will ensure the address of the surface is seeded for FASTDOT and FastPoint.



  so it should be

PlayBASIC Code: [Select]
rendertoimage PaletteScreenImage
lockbuffer
ThisRGB=Point(0,0) ; read a null pixel to make sure the current surface is seeded..

for x= 0 to 256
for y= 0 to 192
fastdot x,y,inkindex(rnd(15))
next
next

unlockbuffer




   not sure if know this but if the image it's drawing onto is 256 * 192 then the previous loops are writinf outside of the image memory, as Image sizes are Inclusive / Exclusive so pixels on the X axis range from 0 to 255 and the same for the Y axis.

PlayBASIC Code: [Select]
rendertoimage PaletteScreenImage
lockbuffer
ThisRGB=Point(0,0) ; read a null pixel to make sure the current surface is seeded..

for x= 0 to 256-1
for y= 0 to 192-1
fastdot x,y,inkindex(rnd(15))
next
next

unlockbuffer









baggey

Hi Again,

Im trying to understand this Palette buffer Stuff and struggling. I see Direct buffer writing is FAST!
So If we have a palette screen. We need the Pallette reference to set the colour of the Pixel Sprite part in memory.

I get the part were we find the address pointer of the colour part of the image and work down in a timely fashon from left to right.
So in a 8bit screen the pitch is one Byte. So the number it can hold is 255. This is linked to the Pallette map index. This holeds the index to the RGB(value)

In my code for some reason only inkindex(0) is working!!? I can't get the rnd selection to work is this something to do with GLOBAL variables.

Or does the Pallette Mapper routine not see my Dim array for some reason?

Baggey

Example Code:
PlayBASIC Code: [Select]
; PROJECT : Project2
; AUTHOR : Microsoft
; CREATED : 29/05/2018
; ---------------------------------------------------------------------

; PROJECT : zx81

; CREATED : 25/05/2018
; ---------------------------------------------------------------------

// Include the palette Mapping library
#include "paletteMapping"
openscreen 256,192,16,2

// Define
Dim Palette(256)
dim inkindex(15)

SetPalette(inkindex())
initColorArrays()

;inkindex(0) = $0000ff
inkindex(10) = $ff0000



constant ScreenWidth = 256
constant ScreenHeight = 192

PaletteSCreenImage=GetFreeImage()
CreateFXImageEx PaletteScreenImage,ScreenWidth,ScreenHeight, 16

FxScreen = newfximage(SCreenWidth,ScreenHeight)

do

rendertoimage PaletteScreenImage
lockbuffer
ThisRGB=Point(0,0) ; read a null pixel to make sure the current surface is seeded..

for x= 0 to 256-1
for y= 0 to 192-1
fastdot x,y,inkindex(rnd(15))
next
next

unlockbuffer

RenderPaletteMappedScreen(PaletteScreenImage,0,0,FxScreen)

rendertoscreen

drawrotatedimage FxScreen,0,0,0,4,4,0,0,false

sync

loop spacekey()
end



function RenderPaletteMappedScreen(SrcPalettedImage,Xpos,Ypos,DestImage=0)

if GetImageDepth(SrcPalettedImage) = 16

local OldSurface = getSurface()

rendertoimage DestImage

lockbuffer
local ThisRGB = point(0,0)
local ImagePtr = GetImagePtr(SrcPalettedImage)
local ImageModulo = GetImagePitch(SrcPalettedImage)

local Width = GetImageWidth(SrcPalettedImage)

For ylp=0 to GetImageHeight(SrcPalettedImage)-1
DrawPaletteMappedStrip16 Xpos, Ypos+ylp, ImagePtr, Width, $000f
ImagePtr+=ImageModulo
next

unlockbuffer

rendertoimage OldSurface
endif
EndFunction


PSub InitColorArrays()

// Ive set the colors up here in RGB but using the palletindex(0)
// We have standard colors so we can make our own pallets!
// select color

// Standard Spectrum colors

// Normal
inkindex(0) = rgb(0,192,192) ;rgb(0, 0, 0); Black
inkindex(1) = rgb(0,0,192); Blue
inkindex(2) = rgb(192,0,0); Red
inkindex(3) = rgb(192,0,192); Magenta
inkindex(4) = rgb(0,192,0); Green
inkindex(5) = rgb(0,192,192); Cyan
inkindex(6) = rgb(192,192,0); Yellow
inkindex(7) = rgb(192,192,192); White

// Bright
inkindex(8) = rgb(0, 0, 0); Black
inkindex(9) = rgb(0,0,255); Blue
inkindex(10) = rgb(255,0,0); Red
inkindex(11) = rgb(255,0,255); Magenta
inkindex(12) = rgb(0,255,0); Green
inkindex(13) = rgb(0,255,255); Cyan
inkindex(14) = rgb(255,255,0); Yellow
inkindex(15) = rgb(255,255,255); White

EndpSub



So yeah ive done some messing around and have changed the command fastdot for this line of code.


Example Code:
PlayBASIC Code: [Select]
fastdot x,y,rgb(rnd(255),rnd(255),rnd(255))



Im now getting random colours. Ive made a schoolboy error somewhere or theres some other reason?

Jesus was only famous because of his dad

kevin


if want to use DOT/FASTDOT/ LINE / BOX etc etc on surface your going to render with a palette,  then check out the help files ->Palette Mapping -> IndexRoRGB  and RGBtoIndex

PlayBASIC Code: [Select]
// Include the palette Mapping library
#include "paletteMapping"
openscreen 256,192,16,2

// Define
dim inkindex(15)

initColorArrays()

SetPalette(inkindex())



constant ScreenWidth = 256
constant ScreenHeight = 192

PaletteSCreenImage=GetFreeImage()
CreateFXImageEx PaletteScreenImage,ScreenWidth,ScreenHeight, 16

FxScreen = newfximage(SCreenWidth,ScreenHeight)

do

rendertoimage PaletteScreenImage
lockbuffer
ThisRGB=Point(0,0) ; read a null pixel to make sure the current surface is seeded..
for y= 0 to 192-1
; do rows by cols since that's how image memory is laid out
for x= 0 to 256-1

; FastDOT renders RGB's so in order to write an INDEX
; it first needs to be converted to a RGB colour, others bits will be lost.
; Ie. All drawing assumed 32bit RGB, the lower 3 bits don't exist when drawing
; to a 16bit 565 / 555 surface
FastDot x,y,IndexToRGB(rnd(15))
next
next
unlockbuffer

RenderPaletteMappedScreen(PaletteScreenImage,0,0,FxScreen)

rendertoscreen

drawrotatedimage FxScreen,0,0,0,4,4,0,0,false

sync

loop spacekey()
end



function RenderPaletteMappedScreen(SrcPalettedImage,Xpos,Ypos,DestImage=0)

if GetImageDepth(SrcPalettedImage) = 16

local OldSurface = getSurface()

rendertoimage DestImage

lockbuffer
local ThisRGB = point(0,0)
local ImagePtr = GetImagePtr(SrcPalettedImage)
local ImageModulo = GetImagePitch(SrcPalettedImage)

local Width = GetImageWidth(SrcPalettedImage)

For ylp=0 to GetImageHeight(SrcPalettedImage)-1
DrawPaletteMappedStrip16 Xpos, Ypos+ylp, ImagePtr, Width, $000f
ImagePtr+=ImageModulo
next

unlockbuffer

rendertoimage OldSurface
endif
EndFunction


PSub InitColorArrays()

// Ive set the colors up here in RGB but using the palletindex(0)
// We have standard colors so we can make our own pallets!
// select color

// Standard Spectrum colors

// Normal
inkindex(0) = rgb(0,192,192) ;rgb(0, 0, 0); Black
inkindex(1) = rgb(0,0,192); Blue
inkindex(2) = rgb(192,0,0); Red
inkindex(3) = rgb(192,0,192); Magenta
inkindex(4) = rgb(0,192,0); Green
inkindex(5) = rgb(0,192,192); Cyan
inkindex(6) = rgb(192,192,0); Yellow
inkindex(7) = rgb(192,192,192); White

// Bright
inkindex(8) = rgb(0, 0, 0); Black
inkindex(9) = rgb(0,0,255); Blue
inkindex(10) = rgb(255,0,0); Red
inkindex(11) = rgb(255,0,255); Magenta
inkindex(12) = rgb(0,255,0); Green
inkindex(13) = rgb(0,255,255); Cyan
inkindex(14) = rgb(255,255,0); Yellow
inkindex(15) = rgb(255,255,255); White

EndpSub





    You can of course just poke the Bytes/ Words in directly into the image,  get pointer to the surface and pitch/modulo, then compute the addres of the dot and write to memory (PokeByte / PokeWord)


baggey

Jesus was only famous because of his dad