Thanks Otus, the problems is not with the lettebox specifically, since that seems to work fine, the problem is when i use it, somehow screws up some other code that seems to have nothing to do with it.
Thanks for the tip tonyg:
Heres a code i shrinked to show you my problem, it used 3 images wich are explained in the code, it has a function Create_Graphics() wich creates a vertical button, to see the problem just comment and uncomment the indicated lines at the begining of the code.
'--"Border-top.png" and "Border_bottom.png" are two images in 30x3 size, one used for the top of the button, and the other for the bottom
'--"Vertical.png" is a 30x3 image used for this vertical button"
Global Created_Image:TImage
Global Mouse_X:Float, Mouse_Y:Float
Global Mx#, My#
Local OriginX%, OriginY%
Local ScaleX#, ScaleY#
'Graphics 1024, 768, 32'-------- use this line to see the error
Graphics 800, 600, 0'-------- use this line to see how it should work
'ProjectionMatrix.SetLetterBox(800, 500)'-------- use this line to see the error
ProjectionMatrix.SetLetterBox(800, 600)'-------- use this line to see how it should work
ScaleX# = ProjectionMatrix.Width() / GraphicsWidth()
ScaleY# = ProjectionMatrix.Height() / GraphicsHeight()
OriginX = ProjectionMatrix.CenterX() - ProjectionMatrix.Width()/2
OriginY = ProjectionMatrix.CenterY() - ProjectionMatrix.Height()/2
SetOrigin OriginX, OriginY
Create_Graphics()
Repeat
SetClsColor 0, 0, 63
Cls
'VirtualMouseX = (MouseX() - OriginX) * ProjX
'VirtualMouseY = (MouseY() - OriginY) * ProjY
' Transform mouse coordinates from screen space to virtual space via scaling.
Mx# = MouseX()
My# = MouseY()
Mouse_X# = Mx#*ScaleX#
Mouse_Y# = My#*ScaleY#
DrawText Mx#, 16, 16*1
DrawText My#, 16, 16*2
DrawText Mouse_X#, 16, 16*4
DrawText Mouse_Y#, 16, 16*5
ProjectionMatrix.DrawLetterBox()
DrawImage(Created_Image, 400, 300)
Flip 1
Until KeyDown(KEY_ESCAPE) Or AppTerminate()
Function Create_Graphics() 'creates the graphic with grabimage
Local width0:Float = 100'size of the button
Local height0:Float = 200'size of the button
Local scaleH:Float'scale to be used to give shape to the button
Local scaleV:Float
Local NewImage:TImage'temporal image to grab image of the button
Local border:TImage'used to store the border top and bottom images
Local bordesAlto:Float'height of the boder images
'loads border
border = LoadImage("Border-top.png")
bordesAlto = border.Height
width0 = border.width
NewImage = CreateImage(width0, height0)
Print "width0 " + width0 + " height0 " + height0
Created_Image = LoadImage("Vertical.png")
scaleH = width0 / Created_Image.width
scaleV = (height0 - (bordesAlto * 2)) / Created_Image.Height
Created_Image.flags = 1 | 0 | 0 | 1
Print "scaleH " + scaleH + " scaleV " + scaleV
'draws the lenght part of the button
Cls
SetImageHandle(Created_Image, 0, 0)
SetImageHandle(NewImage, 0, 0)
SetScale(scaleH, scaleV)
Print "1"
DrawImage(Created_Image, 0, bordesAlto)
'Flip; WaitKey()
Print "2"
'draws the borders
SetScale(1, 1)
SetImageHandle(border, 0, 0)
DrawImage(border, 0, 0)
border = LoadImage("Border_bottom.png")
SetImageHandle(border, 0, 0)
DrawImage(border, 0, (height0 - bordesAlto))
'Flip; WaitKey()
'captures button image
GrabImage(NewImage, 0, 0)
MidHandleImage(NewImage)
Created_Image = NewImage
Print "3"
Cls
'Flip; WaitKey()
EndFunction
' ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' This type allows you to make games that can run at any resolution.
' ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Type ProjectionMatrix
Global _Width% ' The size of the screen, in BlitzMax coordinates.
Global _Height% ' Normally BlitzMax coordinates correspond 1:1 with pixels on the screen, but when you adjust the projection matrix, that relationship changes.
Global _VirtualWidth% ' The size of the visible region in which gameplay takes place. The area inside the letterbox.
Global _VirtualHeight%
' -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' This function sets the scale of the projection matrix.
'
' If you simply wish your game to stretch vertically and horizontally to match the current resolution, and fill the screen, call this function with your desired "virtual" resolution.
' Ie, if you want to build your game around an 800x600 resolution, then set Width and Height to 800,600. If the game is then run at 1920x1200, it will be squashed vertically.
'
' If you want letterboxing however, call InitLetterbox() and then DrawLetterBox() every frame just before you flip.
' -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Function SetScale(Width%, Height%)
_Width = Width
_Height = Height
_VirtualWidth = Width
_VirtualHeight = Height
?Win32
Local D3D7Driver:TD3D7Max2DDriver = TD3D7Max2DDriver(_max2dDriver)
If D3D7Driver
Local Matrix#[] = [2.0/Width, 0.0, 0.0, 0.0,..
0.0, -2.0/Height, 0.0, 0.0,..
0.0, 0.0, 1.0, 0.0,..
-1-(1.0/Width), 1+(1.0/Height), 1.0, 1.0]
D3D7Driver.device.SetTransform(D3DTS_PROJECTION, Matrix)
Else
?
' If on platform other than Win32, or using OpenGL run this code.
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glortho(0, Width, Height, 0, 0, 1)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
?Win32
EndIf
?
End Function
' -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' This function initializes the letterbox.
'
' Call it with the virtual resolution you want to use for your game after you have set the graphics mode, and then DrawLetterBox() every frame just before you flip.
'
' These functions will automatically handle both letterboxing on screens which are too tall, and pillarboxing on screens which are too wide. So if you design your game for 800x600,
' then InitLetterbox() will squash things horizontally to maintain the proper aspect ratio, and DrawLetterbox() will add black bars to the sides of the display for you.
'
'
' -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Function SetLetterbox(Width%, Height%)
Local NewWidth#, NewHeight#
NewWidth# = Width
NewHeight# = Float(GraphicsHeight()) / (Float(GraphicsWidth()) / Float(Width))
' If screen is wider than the desired apsect ratio...
If NewHeight# < Height
' Use pillarboxing instead of letterboxing.
NewHeight# = Height
NewWidth# = Float(GraphicsWidth()) / (Float(GraphicsHeight())/Float(Height))
EndIf
' Adjust the scale of the projection matrix to achieve the desired result.
ProjectionMatrix.SetScale(NewWidth#, NewHeight#)
' Store the size of the visible game region.
_VirtualWidth = Width
_VirtualHeight = Height
End Function
' -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' This function draws black bars over the portions of the screen which are outside the gameplay area.
' -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Function DrawLetterbox()
Local Size%
RenderState.Push()
If _VirtualHeight < _Height
' Draw Letterbox.
Size = (_Height-_VirtualHeight) / 2
SetColor(0,0,0)
DrawRect(0, 0, _Width, Size)
DrawRect(0, _Height-Size, _Width, Size)
Else
' Draw pillarbox.
Size = (_Width-_VirtualWidth) / 2
SetColor(0,0,0)
DrawRect( 0, 0, Size, _Height)
DrawRect(_Width-Size, 0, Size, _Height)
EndIf
RenderState.Pop() ' Render push and pop simply resets the color and other display properties to whatever they were beforehand. These two functions are in the code archives.
End Function
' -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' These functions return the virtual width and height of the usuable region of the screen, inside any letterboxing.
'
' Basically, these functions are equivalent to GraphicsWidth() and GraphicsHeight() when using a projection matrix where coordinates don't match up 1:1 to pixels
' and/or letterboxing is being used.
'
' These functions will not return useful values until either ProjectionMatrix.SetScale() is called, or ProjectonMatrix.SetLetterbox() is called!
' -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Function Width#()
Return _VirtualWidth
End Function
Function Height#()
Return _VirtualHeight
End Function
' -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' These functions tell you where the center of the screen is when using letterboxing.
'
' Note that they do not calculate this using the width and height of the visible area of the screen, but rather, the size of the whole screen including the letterboxed regions.
' This is important, because if you draw objects using the size of the visible region only, they will be higher on the screen than they should be, or more to the left.
'
' In my games, what I do is create a pivot called Origin, and place it in the center of the screen, and attach all my sprites to that, so the only time I need to worry about where
' the center of the screen really is is when I position that pivot initially.
'
' Then when I've done that, the top of the screen is at -ProjectionMatrix.Height#()/2, half the height I passed to SetLetterbox(), and so on.
' -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Function CenterX#()
Return _Width/2
End Function
Function CenterY#()
Return _Height/2
End Function
End Type
Type RenderState
Global RenderStateList:TList = CreateList()
Field Alpha#
Field Blend
Field ClsColor_R, ClsColor_G, ClsColor_B
Field Color_R, Color_G, Color_B
Field Handle_X#, Handle_Y#
Field ImageFont:TImageFont
Field LineWidth#
Field MaskColor_R, MaskColor_G, MaskColor_B
Field Origin_X#, Origin_Y#
Field Rotation#
Field Scale_X#, Scale_Y#
Field Viewport_X, Viewport_Y, Viewport_Width, Viewport_Height
' -------------------------------------------------------------------------------------------------------------------------------------------------------
' These methods allow you to save and restore the current render settings
'
' Each time you call the push method, the current state is placed on the stack.
' Each time you call the pop method, the last state placed on the stack is restored and removed from the stack.
' -------------------------------------------------------------------------------------------------------------------------------------------------------
Function Push()
Local RS:RenderState = New RenderState
RS.Alpha# = GetAlpha#()
RS.Blend = GetBlend()
GetClsColor(RS.ClsColor_R, RS.ClsColor_G, RS.ClsColor_B)
GetColor(RS.Color_R, RS.Color_G, RS.Color_B)
GetHandle(RS.Handle_X#, RS.Handle_Y#)
RS.ImageFont = GetImageFont()
RS.LineWidth# = GetLineWidth#()
GetMaskColor(RS.MaskColor_R, RS.MaskColor_G, RS.MaskColor_B)
GetOrigin(RS.Origin_X#, RS.Origin_Y#) ; SetOrigin 0,0
RS.Rotation# = GetRotation#()
GetScale(RS.Scale_X#, RS.Scale_Y#)
GetViewport(RS.Viewport_X, RS.Viewport_Y, RS.Viewport_Width, RS.Viewport_Height)
RenderStateList.AddLast(RS)
End Function
Function Pop()
Local RS:RenderState = RenderState(RenderStateList.RemoveLast())
SetAlpha(RS.Alpha#)
SetBlend(RS.Blend)
SetClsColor(RS.ClsColor_R, RS.ClsColor_G, RS.ClsColor_B)
SetColor(RS.Color_R, RS.Color_G, RS.Color_B)
SetHandle(RS.Handle_X#, RS.Handle_Y#)
SetImageFont(RS.ImageFont)
SetLineWidth(RS.LineWidth#)
SetMaskColor(RS.MaskColor_R, RS.MaskColor_G, RS.MaskColor_B)
SetOrigin(RS.Origin_X#, RS.Origin_Y#)
SetRotation(RS.Rotation#)
SetScale(RS.Scale_X#, RS.Scale_Y#)
SetViewport(RS.Viewport_X, RS.Viewport_Y, RS.Viewport_Width, RS.Viewport_Height)
End Function
End Type