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:[pbcode]
// 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
[/pbcode]
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:
[pbcode]
// 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
[/pbcode]
How do i get the library and install it?
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
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..
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:
[pbcode]
; 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
[/pbcode]
this loop has a couple of errors in it
[pbcode]
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
[/pbcode]
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
[pbcode]
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
[/pbcode]
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.
[pbcode]
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
[/pbcode]
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:
[pbcode]
; 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
[/pbcode]
So yeah ive done some messing around and have changed the command fastdot for this line of code.
Example Code:
[pbcode]
fastdot x,y,rgb(rnd(255),rnd(255),rnd(255))
[/pbcode]
Im now getting random colours. Ive made a schoolboy error somewhere or theres some other reason?
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
[pbcode]
// 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
[/pbcode]
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)
If only i new how to program well!