Problem with Map Transparency in Fullscreen Mode

Started by Rembrandt Q Einstein, July 02, 2007, 05:20:18 PM

Previous topic - Next topic

Rembrandt Q Einstein

Hey, I've never used maps before, so I'm hoping someone has some experience with this issue.

So I create a map, poke all it's tiles, tell it that all 3 levels are transparent with transparent block = 0.  Then I make map GFX telling it my transparent color is purple.

When I draw the map windowed, it works just fine.  When it's full screen, the purple shows.  When I tell the image that purple is the transparent color and then pass it to the MakeMapGFX, the purple turns to black, but it's not transparent black, it's solid black. 

The reason why I'm so confused is that it works fine windowed but not full screen.  What's the difference?

Thanks for any help

kevin


What version of PB ?

What colour depth ?

  Example code  ?


Rembrandt Q Einstein

V1.62

640x480x16, tile image is a .png

There's a lot of code that isn't relevent to the problem at hand, so I'm going to delete some of the stuff that looks superfluous.



Type Map
TileWidth
TileHeight
MapWidth
MapHeight
Tiles
Layers
CollisionLayer
Index
Dark
SandTileNumber
EndType



Function MakeMap(datafile$,MaxSlopedTiles)
Dim rMap As Map
rMap.Index = GetFreeMap()
FileChannel = GetFreeFile()
ReadFile datafile$,FileChannel
GraphicsFileName$ = ReadString$(FileChannel)

* * HERE I READ A BUNCH OF MAP INFO  * *

TransparentColor = RGB(255,0,255)
CreateMap rMap.Index,rMap.Layers
For a = 1 to rMap.Layers
CreateLevel rMap.Index,a,rMap.MapWidth-1,rMap.MapHeight-1
For b = 0 to rMap.MapHeight-1
Line$ = ReadString$(FileChannel)

* * GetValue() is a function that returns one number at a time from a line with numbers sperated by commas *  *

For c = 0 to rMap.MapWidth-1
Line$,TileValue = GetValue(Line$)
PokeLevelTile rMap.Index,a,c,b,TileValue
Next c
Next b
LevelTransparent rMap.Index,a,TransparentTile
Next a

CloseFile FileChannel
GfxIndex = GetFreeImage()
LoadImage GraphicsFilename$,GfxIndex
DrawImage GfxIndex,0,0,1
DeleteImage GfxIndex
CreateMapGFX rMap.Index,rMap.TileWidth,rMap.TileHeight,rMap.Tiles,TransparentColor
For a = 1 to GraphicsTileHeight
For b = 1 to GraphicsTileWidth
If (a-1)*GraphicsTileWidth+b-1 < rMap.Tiles then GetMapBlk rMap.Index,(a-1)*GraphicsTileWidth+b,(b-1)*rMap.TileWidth,(a-1)*rMap.TileHeight
Next b
Next a
PrepareFXMap rMap.Index

* * WORLD COLLISION STUFF ETC... *  *

EndFunction

Function GetValue(line$)
Length = 0
a$ = ""
While a$ <> "," and Length < Len(line$)
Inc(Length)
a$ = Mid$(Line$,Length,1)
EndWhile
If Length = Len(Line$) then Inc(Length)
Value = Val(Mid$(Line$,1,Length-1))
Line$ = Mid$(Line$,Length+1,Len(Line$)-Length)
EndFunction line$,Value

Function DrawWorldMap(WorldMap.Map)
For a = 1 to WorldMap.Layers
CaptureDepth a*50
DrawMap WorldMap.Index,a,0,0
Next a
EndFunction



Hope that helps.  If there's anything else I should have added, please tell me.  I'm really not sure where the problem lies.

kevin

#3
  In future, It'd be nice to able run a snippet.   

The issue is probably in the tile grab,  if you run a window and your desktop is 32bit, then you app is also running 32bit.



so this ..
/*
GfxIndex = GetFreeImage()
LoadImage GraphicsFilename$,GfxIndex
DrawImage GfxIndex,0,0,1
DeleteImage GfxIndex
MakeMapGFX rMap.Index,rMap.TileWidth,rMap.TileHeight,rMap.Tiles,TransparentColor
For a = 1 to GraphicsTileHeight
For b = 1 to GraphicsTileWidth
If (a-1)*GraphicsTileWidth+b-1 < rMap.Tiles
GetMapBlk rMap.Index,(a-1)*GraphicsTileWidth+b,(b-1)*rMap.TileWidth,(a-1)*rMap.TileHeight
endif
Next b
Next a
PrepareFXMap rMap.Index
*/

could prolly just be this.  Dunno, can't test it !

GfxIndex = LoadNewImage(GraphicsFilename$)
MakeMapGFX rMap.Index,GfxIndex, rMap.TileWidth,rMap.TileHeight,rMap.Tiles,TransparentColor
PrepareFXMap rMap.Index

   deleteimage GfxIndex



  Also, same goes for the Getvalue function. You should be able to replace it SplitToArray() it's unnecessary.  Which will split a string into an array.   


kevin

Split To Array example.


s$="1,2,3,4,5,6,7,8,9,1000"

Dim Table(1)
Items=SplitToArray(S$,",",Table(),1)
For lp=1 to Items
print Table(lp)
next
Sync
Waitkey


Rembrandt Q Einstein

Yes, you're right.  When I put it at 32 bit in settings it works fine.  Of course, this is a lot slower than 16 bit.  Is there a way I can get it to work in 16 bit?  Does it have to do with the png being 24 bit?

SplitToArray huh?  Thanks, that would have saved me the time of writing my own function.  You thought of everything. 

And yeah, MakeMapGFX is a helpful command, but I do other stuff with some tiles before I put it in the mapGFX, so I like to just do it all manually. 

Thanks for all the help.

kevin


QuoteYes, you're right.  When I put it at 32 bit in settings it works fine.  Of course, this is a lot slower than 16 bit.  Is there a way I can get it to work in 16 bit?

    After building an example (bellow)   it appears not.   There's an issue with tile blitter in this combination.  It's been addressed now, so you'll have to wait for the next round of updates.  Which i'm in the process of building atm. 

 
QuoteDoes it have to do with the png being 24 bit?

   The image format can effect things. But it shouldn't in this case.


Note: This is test code requires  PB1.62B demo or  V1.63h retail  (when released) to function correctly in 16bit modes.



OpenScreen 800,600,16,2
ScreenVsync on

MakeBitmapFont 1,$ffffff

; ================================
; Create Water Shape  ( WAVE :))
; ================================
WaterLineShape=NewShape(100,100)

WaveHeight=20
Xpos=0
FirstVertex=10
Vertex=FirstVertex
For angle=0 To (360*4) Step 5
ypos=CosRadius(Baseangle#+angle,WaveHeight)
SetShapeVertex Waterlineshape,Vertex,xpos,ypos
xpos=xpos+20
Inc vertex
Next    
lastVertex=Vertex-1

x=GetShapeVertexX(Waterlineshape,FirstVertex)
y=GetShapeVertexY(Waterlineshape,FirstVertex)
SetShapeVertex Waterlineshape,1,x,y
SetShapeVertex Waterlineshape,2,x,1000

SetShapeVertex Waterlineshape,3,xpos,y
SetShapeVertex Waterlineshape,4,xpos,1000

EdgeINdex=1
SetShapeEdge WaterlineShape,EdgeINdex,1,2
Inc edgeindex
SetShapeEdge WaterlineShape,EdgeINdex,3,4

For Vertex=FirstVertex To lastVertex-1
Inc Edgeindex
SetShapeEdge WaterlineShape,EdgeINdex,Vertex,Vertex+1
Next




   ;=========================================================================
`CReate a Series of Tiles To make the blob Animation blocks.
   ;=========================================================================
 
Frames=10
BlockSize=64
; Create the Animated blocks
Block_Image=CreateBlocks(BlockSize,frames)


; Create a Map with provision For 2 level maps To be created using it's Blocks
Thismap=NewMap(2)

; Import the above Image created into our Map as BLocks
MakeMapGFX ThisMap,Block_image,BlockSize,BlockSize,frames+1,RGB(255,0,255)


; Prepare the Block graphics for FX rendering.  This Allows Maps to be
; drawn to the images in FX format. 
PrepareFXMap ThisMap




; =========================
; Create 3 Animations
; =========================

MaxAnims=6
Create_Map_Anims(ThisMap,MAxAnims,Frames)


; CREATE A LEVEL filled with ranomd blocks
Constant z=$80000000
Width=100
height=100
MyLevel=NewLevel(ThisMap,Width,height)
For ylp=0 To Width
For xlp=0 To height
PokeLevelTile ThisMap,MyLevel,xlp,ylp,z Or RndRange(1,MaxAnims)
Next xlp
Next ylp


; SET THIS LEVEL As Transparent + animated..
    LevelTransparent ThisMap,MyLevel,0
LevelAnimated ThisMap,MyLevel



   ;=========================================================================
   ; Create an FX Image the size of the screen.
   ;=========================================================================

; This image is used as render target.  So we render all our games
; elements to this image, then once were done we drawn it to the real screen.

sw=GetScreenWidth()
sh=GetScreenHeight()

FXScreen=NewFXImage(sw,sh)
RenderToImage FXscreen


; create a camera.  This camera will attach itself to the current image
; which will be the FX screen
CreateCamera 1
CameraCls 1,Off

   ShowControls =Timer()+10000


   ;=========================================================================
   ; MAIN LOOp
   ;=========================================================================

; Start of Main Loop
RenderToScreen
Do

; Redirect drawing to the FX screen image
RenderToImage FXScreen

Cls RGB(05,100,255)

; Tell PB to capture the following drawn items to the scene buffer
CaptureToScene

         ; clear the buffer
ClsScene


capturedepth 150

Circlec GetCameraX(1)+400,GetCameraY(1)+300,100,true,rgb(0,255,0)

capturedepth 50

         ; draw our map to the scene buffer
DrawMap thisMap,MyLevel,0,0

         ; draw the camera.  This will process the items in the scene buffer
         ; to the cameras position and render what it can see to the image
         ; it's attached to.  In this case it's attached to the FXscreen
         ; image
DrawCamera 1



; set the INK mode to Alpha 50%
InkMode 1+32

; set the ink colour to a bluey colour
Ink RGB(35,75,125)

; Calc the Y pos of the water
WaterY=SinNewValue((sh/4)*3,WaveAngle#,sh/6)
WaveAngle#=WrapAngle(WaveAngle#,1)

; draw the wave shape over the map
DrawShape WaterLineShape,0,WaterY,2

         ; restore the ink mode to normal
         InkMode 1

         ; restore rendering to the screen
RenderToScreen


; ================================================
; Cycle water vertex
; ================================================

Vertex=FirstVertex
Xpos=0
vertex=10
For angle=0 To (360*4) Step 10
ypos=Cos(baseAngle#+angle)*(WaveHeight*Sin(angle))
ypos=ypos+(Cos((baseAngle#)+(angle*3) )*(WaveHeight/2))
SetShapeVertex Waterlineshape,Vertex,xpos,ypos
xpos=xpos+20
Inc vertex
Next    

sh=GetScreenHeight()
x=GetShapeVertexX(Waterlineshape,FirstVertex)
y=GetShapeVertexY(Waterlineshape,FirstVertex)

SetShapeVertex Waterlineshape,1,x,y
SetShapeVertex Waterlineshape,2,x,sh+1
SetShapeVertex Waterlineshape,3,xpos,y
SetShapeVertex Waterlineshape,4,xpos,sh+1

Baseangle#=WrapAngle(Baseangle#,1)

; Draw the FX screen image to the actual screen, so we can see it.
DrawImage FXscreen,0,0,0

If UpKey() Then MoveCamera 1,0,-5
If DownKey() Then MoveCamera 1,0,5
If RightKey() Then MoveCamera 1,5,0
If LeftKey() Then MoveCamera 1,-5,0


CenterText GetScreenWidth()/2,0,"Rendering Water Effect Over FX Map"
Text 0,0,FPS()

; if the demo has been running for less than 10 second then show
; the controls message
    If ShowControls>Timer()
    CenterText sw/2,sh/2,"Use Arrows to Scroll Window"
    EndIf

; update the map animations
UpdateMapAnims Thismap


Xpos=100
Ypos=20

text GetScreenWidth()-100,Ypos,hex$(GetMapMaskColour(ThisMap))
text GetScreenWidth()-100,Ypos+30,hex$(PBPeekEngine(23))


; Loop through the blocks in this map
  For Blk=0 To GetMapBlockQuantity(ThisMap)
     
   ; Check if this block is transparent or not
     Transparent=GetMapBlockTransparent(ThisMap,blk)
     
     
   ; draw hhe block along side
     DrawMapBlk ThisMap,blk,Xpos,ypos,Transparent

   ; Display the block index and the transparent status of this block
     Text xpos+GetMapBlockWidth(ThisMap)+10,ypos, "blk: ("+Digits$(blk,2)+") Transparent=("+Str$(transparent)+")"

     
  ; bump the output y value
     ypos=ypos+GetMapBlockHeight(ThisMap)+2
Next



Sync
Loop

End


   ;=========================================================================
   ; Create the Colour Blocks
   ;=========================================================================


Function CreateBlocks(BlockSize,frames)
; Create a Image to Use to Store out Blob tiles upon
Map_Image=NewImage(BlockSize*(Frames+1),BlockSize)
; CReate the set of Blob
For lp=0 To frames
i=NewImage(BlockSize,BlockSize)
c=RndRGB()
rendertoimage i
cls Rgb(255,0,255)
imageviewport i,20,0,BlockSize,BlockSize
RenderPhongImage i,GetImageWidth(i)/2,GetImageHeight(i)/2,RGBFade(c,50+((40.0/frames)*lp)),200,255.0/(blocksize-lp)


RenderToImage Map_image
DrawImage i,blocksize*(lp+1),0,0 
DeleteImage i
Next
RenderToScreen
EndFunction Map_image


   ;=========================================================================
   ; Create the Mpa Animations
   ;=========================================================================



Function Create_Map_Anims(ThisMap,MAxAnims,Frames)
  ; Create provision For 3 Animations
MapAnimQuantity ThisMap,MaxAnims

For Anims=1 To MaxAnims
For lp=1 To frames
MapAnim_Add_Block ThisMap,Anims,lp
Next
For lp=frames To 1 Step -1
MapAnim_Add_Block ThisMap,Anims,lp
Next
MapAnimFrameRate ThisMap,Anims,anims
MapAnimType ThisMap,Anims,1
Next Anims
EndFunction


   ;=========================================================================
   ; Helper function to treat ading map anims like a que
   ;=========================================================================

Function MapAnim_Add_Block(ThisMap,ThisAnim,ThisBlock)
If GetMapAnimStatus(ThisMap,ThisAnim)=False
CreateMapAnim ThisMap,ThisAnim,1
PokeMapAnim ThisMap,ThisAnim,0,ThisBlock
Else
size=GetMapAnimSize(thisMap,thisAnim)
PokeMapAnim ThisMap,ThisAnim,Size,ThisBlock
ResizeMapAnim ThisMap,ThisAnim,Size+1
EndIf
EndFunction



Rembrandt Q Einstein


Rembrandt Q Einstein

Hey Kevin, the map solution worked.  Thank you.

I came across a new problem dealing with graphics this time.  When in full screen, I notice that colors (including mask colors) get changed and impossible to compare to.  Here's a simple example I whipped up to demonstrate the problem.  Run it in 32bit fullscreen or windowed and it's fine, but run in 16 bit full screen, and the values are simply wrong.

The problem takes shape in the game I'm making, this is just an example without the extraneous code.



; PROJECT : Project1
; AUTHOR  : Tyler
; CREATED : 8/2/2007
; ---------------------------------------------------------------------


CreateImage 1,50,50
ImageMaskColour 1,RGB(255,0,255)
RenderToImage 1
BoxC 0,0,50,50,True,RGB(255,0,255)
CircleC 25,25,25,True,RGB(255,255,0)
PrepareFXImage 1
RenderToScreen
CreateCamera 1

Do
CLSScene
CaptureToScene
DrawImage 1,0,0,1

RenderToImage 1
DrawGFXImmediate
Col = Point(MouseX(),MouseY())
If LeftMouseButton() = True then CircleC MouseX(),MouseY(),5,True,GetImageMaskColour(1)
CaptureToScene
RenderToScreen

WriteColors(Col,100,100)
WriteColors(GetImageMaskColour(1),200,100)

CircleC MouseX(),MouseY(),4,True,RGB(255,255,255)
DrawCamera 1
sync
Loop


Function WriteColors(Color,x,y)
ink RGB(255,255,255)
Text x,y,RGBR(Color)
Text x,y+30,RGBG(Color)
Text x,y+60,RGBB(Color)
EndFunction

Rembrandt Q Einstein

To save you the trouble of figuring out the code, i'll explain it:

It makes an image of a yellow circle with a purple mask color.  The image is drwan on the screen along with the RGBs of the color the mouse is on in the image on the left, and the mask color of the image on the right

You'll notice that in 16 bit mode fullscreen, both the purple color and the yellow color will have different RGBs than the colors they were drawn as.

kevin


   Which is correct.   When you're running in 16bit display mode then R,G,B channels will be represented in either a 5,6,5 (bits per channel) format or 5,5,5 format.    In 24bit & 32bit modes the pixel is represent in 8,8,8 mode, so there's 8bits to represent each R,G,B onj the surface.

   When a pixel is drawn in any mode the RGB values are remapped to suit the surface, when you read that surface then bits are exported and returned in a 32bit formatted color.   If you draw 32bit dot in 16bit mode of  the depending upon the video mode the target hardware supports,    each channel is truncated to fit the 16bit pixel format.  If you read the pixel back then the lower bits will be lost.
 

kevin

 
  You can detect the pixel format and build a mask like this.
 


OpenScreen 800,600,16,2

Global RGBFormatMask=GetSurfaceRGBMask(0)



Do
cls rgb(0,0,0)

BoxColour=Rgb(255,0,255) And RGBFormatMask
BoxC 200,200,300,300,true,BoxColour


Mx=mouseX()
My=mouseY()

MouseOverColour=Point(mx,my) And RGBFormatMask

; draw mouse pointer
Dotc MX,MY,RGB(255,255,255)


print Hex$(BoxColour)
print Hex$(MouseOverCOlour)


if MouseOverColour=BoxColour
Print "You hit the box"
endif

Sync
loop





Function GetSurfaceRGBMask(ThisSurface)
; surface 0 is the screen
Depth=GetImageDepth(ThisSurface)

If Depth=15 then Mask=$00f8f8f8
If Depth=16 then Mask=$00f8fcf8
If Depth=24 then Mask=$00ffffff
If Depth=32 then Mask=$00ffffff

EndFunction Mask


Rembrandt Q Einstein

Good good.  I hadn't really thought about it, but obviously the RGB values are 8 bits * 3 colors, so they couldn't fit in 16 bit. 

Full screen mode is pretty important, and 32 bit is hurting my frame rate, so I'll have to add these fixes before our next release