Author |
Topic: Change Display Width/Height (Read 271 times) |
|
Rod
Full Member
member is offline


Gender: 
Posts: 110
|
 |
Re: Change Display Width/Height
« Reply #6 on: Jan 22nd, 2018, 1:52pm » |
|
Ok, progress. This code blits well and because I am using LBB's buffer and LBB's screen update it is a lot simpler to code.
However I am finding that I MUST use a timer loop. If I don't I get no screen updates. It isn't a problem running a timer but is there a way to force a screen update from the buffer once I am done drawing?
Code: nomainwin
WindowWidth = 800
WindowHeight = 600
UpperLeftX = (DisplayWidth - WindowWidth)/2
UpperLeftY = (DisplayHeight - WindowHeight)/2
graphicbox #blit.gb 0,0,800,600
open "Blit Test" for window as #blit
#blit "trapclose [quit]"
#blit.gb "down ; fill red ; home"
#blit.gb "backcolor white ; circlefilled 50 ;\2"
#blit.gb "place 0 0 ; color green ; backcolor green ; boxfilled 50 50"
#blit.gb "getbmp bmp 0 0 800 600"
'LBB has a screen DC and a buffer DC, perhaps we only need a resource DC
'get the handle of our graphicbox
hWnd=hwnd(#blit.gb)
'get the handle to its associated DC
'LBB intercepts this call and passes us the buffer DC
bDC=GetDC(hWnd)
'create a copy called rDC (Resource)
'and load image
rDC=CreateCompatibleDC(bDC)
hBitmap=hbmp("bmp")
oldBmp=SelectObject(rDC,hBitmap)
'now lets repeatedly blit to the buffer
'I leave LBB to take care of flipping the buffer in view
'we should see a moving red portion of the resource bmp
'on a green background
timer 56,[blit]
wait
[blit]
'scan
x=x+2
if x=500 then x=0
'fill the background ie cls
call StretchBlt,bDC,0,0,800,600,rDC,0,0,50,50
'draw from the resource
call StretchBlt,bDC,x,0,200,600,rDC,300,0,200,600
'calldll #kernel32, "Sleep",56 as ulong, NULL as void
'goto [blit]
wait
[quit]
timer 0
call ReleaseDC hWnd,bDC
call ReleaseDC hWnd,rDC
call DeleteDC bDC
call DeleteDC rDC
close #blit
end
Function GetDC(hWnd)
CallDLL #user32, "GetDC",_
hWnd As Ulong,_
GetDC As Ulong
End Function
Sub ReleaseDC hWnd, hDC
CallDLL#user32,"ReleaseDC",_
hWnd As Ulong,_
hDC As Ulong,_
result As Long
End Sub
Function CreateCompatibleDC(hDC)
CallDLL #gdi32,"CreateCompatibleDC",_
hDC As Ulong,_
CreateCompatibleDC As Ulong
End Function
Sub DeleteDC hDC
CallDLL #gdi32, "DeleteDC",_
hDC As Ulong,_
result As Ulong
End Sub
Sub StretchBlt hDCdest,x,y,w,h,hDCsrc,x2,y2,w2,h2
CallDLL #gdi32, "StretchBlt",_
hDCdest As Ulong,_
x As Long,_
y As Long,_
w As Long,_
h As Long,_
hDCsrc As Ulong,_
x2 As Long,_
y2 As Long,_
w2 As Long,_
h2 As Long,_
_SRCCOPY As Ulong,_
result As Ulong
End Sub
Function SelectObject(hDC,hObject)
CallDLL #gdi32,"SelectObject",_
hDC As Ulong,_
hObject As Ulong,_
SelectObject As Ulong
End Function
|
|
Logged
|
|
|
|
Richard Russell
Administrator
member is offline


Posts: 1348
|
 |
Re: Change Display Width/Height
« Reply #7 on: Jan 22nd, 2018, 2:30pm » |
|
on Jan 22nd, 2018, 1:52pm, Rod wrote:| However I am finding that I MUST use a timer loop. If I don't I get no screen updates. |
|
The problem is that Windows doesn't know that you've updated the buffer (by blitting into it) and therefore it doesn't 'waste' time updating the screen. The 'official' way of dealing with this it to call the InvalidateRect API, which allows you to specify "the portion of the window's client area that must be redrawn" (or the whole window by default). Try using this in your program to force the update:
Code: calldll #user32, "InvalidateRect", hWnd as ulong, 0 as long, 0 as long, ret as void However I think I might argue that a timer is a better method anyway, at least in the case of an animation such as your program.
Richard.
|
|
Logged
|
|
|
|
Rod
Full Member
member is offline


Gender: 
Posts: 110
|
 |
Re: Change Display Width/Height
« Reply #8 on: Jan 23rd, 2018, 12:30pm » |
|
I am able to use the built in buffer now and I can get smooth blitting. I still don't fully understand how to sync the update. In this code the timer brings back the conflict but left to loop it can run really fast, although a sleep is required.
You will need this bmp, right click and save as wolf.bmp in your project directory.

Code: 'From http://lodev.org/cgtutor/raycasting.html
nomainwin
mapWidth = 24
mapHeight = 24
dim worldMap(mapWidth, mapHeight)
gosub [readMap]
dim wallTexture(5)
wallTexture(1)=128
wallTexture(2)=64
wallTexture(3)=384
wallTexture(4)=512
wallTexture(5)=448
WindowWidth = DisplayWidth
WindowHeight = DisplayHeight
graphicbox #raycaster.gb 0,0,DisplayWidth,DisplayHeight
open "Raycaster " for window_popup as #raycaster
#raycaster "trapclose [quit]"
loadbmp "wolf","wolf.bmp"
'LBB has a screen DC and a buffer DC, we only need a resource DC
'get the handle of our graphicbox
hWnd=hwnd(#raycaster.gb)
'get the handle to its associated DC
'LBB intercepts this call and passes us the buffer DC
bDC=GetDC(hWnd)
'create a copy called rDC (Resource)
'and load image
rDC=CreateCompatibleDC(bDC)
hBitmap=hbmp("wolf")
oldBmp=SelectObject(rDC,hBitmap)
'#raycaster.gb " down ; setfocus"
w=800
h=600
moveSpeed = .2
rotSpeed = .1
posX = 22: posY = 12
dirX = -1: dirY = 0
planeX = 0: planeY = 0.66
'timer 16,[blit]
'wait
[blit]
'blit the buffer full screen from its 800x600 origin
'the graphics are drawn to the buffer 800x600, we expand this to full
'screen once each cycle
call StretchBlt,bDC,0,0,DisplayWidth,DisplayHeight,bDC,0,0,800,600
'tell Windows the full area of the buffer needs flipped onscreen
calldll #user32, "InvalidateRect", hWnd as ulong, 0 as long, 0 as long, ret as void
'pause a little, else it is too fast and buffer conflict/flicker
calldll #kernel32, "Sleep",16 as ulong, NULL as void
'clear the 800x600 area of buffer by blitting the sky and ground images from rDC
call StretchBlt,bDC,0,0,800,600,rDC,0,0,64,128
[drawingloop]
scan
cameraX = 2 * x / w - 1 'x-coordinate in camera space
rayPosX = posX
rayPosY = posY
rayDirX = dirX + planeX * cameraX
rayDirY = dirY + planeY * cameraX
mapX = int(rayPosX)
mapY = int(rayPosY)
select case
case rayDirY=0
deltaDistX = 1: deltaDistY=999999
case rayDirX=0
deltaDistX = 999999: deltaDistY=1
case else
deltaDistX = sqr(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX))
deltaDistY = sqr(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY))
end select
if rayDirX<0 then
stepX=-1
sideDistX=(rayPosX-mapX)*deltaDistX
else
stepX=1
sideDistX=(mapX+1-rayPosX)*deltaDistX
end if
if rayDirY<0 then
stepY=-1
sideDistY=(rayPosY-mapY)*deltaDistY
else
stepY=1
sideDistY=(mapY+1-rayPosY)*deltaDistY
end if
while worldMap(mapX,mapY)=0
if sideDistX<sideDistY then
sideDistX = sideDistX+deltaDistX
mapX=mapX+stepX
side=0
else
sideDistY=sideDistY+deltaDistY
mapY=mapY+stepY
side=1
end if
wend
if (side = 0) then
perpWallDist = abs((mapX - rayPosX + (1 - stepX) / 2) / rayDirX)
else
perpWallDist = abs((mapY - rayPosY + (1 - stepY) / 2) / rayDirY)
end if
lineHeight = abs(int(h / perpWallDist))
drawStart = int(0-lineHeight / 2 + h / 2)
if (side = 1) then
wallX = rayPosX + ((mapY - rayPosY + (1 - stepY) / 2) / rayDirY) * rayDirX
ws=64
else
wallX = rayPosY + ((mapX - rayPosX + (1 - stepX) / 2) / rayDirX) * rayDirY
ws=0
end if
wallX = wallX - int((wallX))
texW=64
texX=int(wallX*texW)
if side=0 and rayDirX>0 then texX=texW-texX-1
if side=1 and rayDirY<0 then texX=texW-texX-1
srcW=int(lineHeight/32+1)
'draw the relevant line segment to the 800x600 area of the buffer from rDC
call StretchBlt,bDC,x,drawStart,srcW,lineHeight,rDC,wallTexture(worldMap(mapX,mapY))+texX,ws,2,64
x=x+srcW
if x<800 then goto [drawingloop]
x=0
if GetAsnycKeyState(_VK_ESCAPE) then goto [quit]
if GetAsnycKeyState(_VK_UP) then
if(worldMap(int(posX + dirX * moveSpeed),int(posY)) = 0) then posX = posX +dirX * moveSpeed
if(worldMap(int(posX),int(posY + dirY * moveSpeed)) = 0) then posY = posY +dirY * moveSpeed
end if
if GetAsnycKeyState(_VK_DOWN) then
if(worldMap(int(posX - dirX * moveSpeed),int(posY)) = 0) then posX = posX -dirX * moveSpeed
if(worldMap(int(posX),int(posY - dirY * moveSpeed)) = 0) then posY = posY -dirY * moveSpeed
end if
if GetAsnycKeyState(_VK_RIGHT) then
oldDirX = dirX
dirX = dirX * cos(0-rotSpeed) - dirY * sin(0-rotSpeed)
dirY = oldDirX * sin(0-rotSpeed) + dirY * cos(0-rotSpeed)
oldPlaneX = planeX
planeX = planeX * cos(0-rotSpeed) - planeY * sin(0-rotSpeed)
planeY = oldPlaneX * sin(0-rotSpeed) + planeY * cos(0-rotSpeed)
end if
if GetAsnycKeyState(_VK_LEFT) then
oldDirX = dirX
dirX = dirX * cos(rotSpeed) - dirY * sin(rotSpeed)
dirY = oldDirX * sin(rotSpeed) + dirY * cos(rotSpeed)
oldPlaneX = planeX
planeX = planeX * cos(rotSpeed) - planeY * sin(rotSpeed)
planeY = oldPlaneX * sin(rotSpeed) + planeY * cos(rotSpeed)
end if
goto [blit]
wait
[quit]
timer 0
call ReleaseDC hwnd,bDC
call ReleaseDC hWnd,rDC
call DeleteDC rDC
close #raycaster
end
[readMap]
data "{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},"
data "{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},"
data "{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},"
data "{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},"
data "{1,0,0,0,0,0,1,1,2,1,1,0,0,0,0,3,0,3,0,3,0,0,0,1},"
data "{1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1},"
data "{1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,3,0,0,0,3,0,0,0,1},"
data "{1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1},"
data "{1,0,0,0,0,0,1,1,0,1,1,0,0,0,0,3,0,3,0,3,0,0,0,1},"
data "{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},"
data "{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},"
data "{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},"
data "{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},"
data "{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,1},"
data "{1,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,5,0,0,0,0,0,0,1},"
data "{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},"
data "{1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},"
data "{1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},"
data "{1,4,0,0,0,0,5,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},"
data "{1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},"
data "{1,4,0,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},"
data "{1,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},"
data "{1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},"
data "{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}"
for j= 1 to mapHeight
read a$
a$=mid$(a$,2)
for i = 1 to mapWidth
worldMap(i,j)=val(word$(a$,i,","))
'print worldMap(i,j);
next
'print
next
return
Function GetDC(hWnd)
CallDLL #user32, "GetDC",_
hWnd As Ulong,_
GetDC As Ulong
End Function
Sub ReleaseDC hWnd, hDC
CallDLL#user32,"ReleaseDC",_
hWnd As Ulong,_
hDC As Ulong,_
result As Long
End Sub
Function CreateCompatibleDC(hDC)
CallDLL #gdi32,"CreateCompatibleDC",_
hDC As Ulong,_
CreateCompatibleDC As Ulong
End Function
Sub DeleteDC hDC
CallDLL #gdi32, "DeleteDC",_
hDC As Ulong,_
result As Ulong
End Sub
Sub StretchBlt hDCdest,x,y,w,h,hDCsrc,x2,y2,w2,h2
CallDLL #gdi32, "StretchBlt",_
hDCdest As Ulong,_
x As Long,_
y As Long,_
w As Long,_
h As Long,_
hDCsrc As Ulong,_
x2 As Long,_
y2 As Long,_
w2 As Long,_
h2 As Long,_
_SRCCOPY As Ulong,_
result As Ulong
End Sub
Function SelectObject(hDC,hObject)
CallDLL #gdi32,"SelectObject",_
hDC As Ulong,_
hObject As Ulong,_
SelectObject As Ulong
End Function
function GetAsnycKeyState(key)
calldll #user32, "GetAsyncKeyState",_
key as long,ret as long
if ret <> 0 then GetAsnycKeyState = 1
end function
|
| « Last Edit: Jan 23rd, 2018, 12:33pm by Rod » |
Logged
|
|
|
|
Richard Russell
Administrator
member is offline


Posts: 1348
|
 |
Re: Change Display Width/Height
« Reply #9 on: Jan 23rd, 2018, 2:53pm » |
|
on Jan 23rd, 2018, 12:30pm, Rod wrote:| I still don't fully understand how to sync the update. |
|
The InvalidateRect call says that the screen needs to be updated, but still leaves it to Windows to decide when! If you have a time-critical application (such as real-time animation) in which you need to say to Windows "update the screen and do it now!" you need to make an extra call as follows:
Code: calldll #user32, "InvalidateRect", hWnd as ulong, 0 as long, 0 as long, ret as void
calldll #user32, "UpdateWindow", hWnd as ulong, ret as void This may well use more CPU time, but will ensure that the screen is updated when you want it to be rather than when Windows wants it to be.
Unfortunately there's no easy way to synchronise your updates with the display refresh (vertical sync) - that requires the use of DirectDraw which is non-trivial - so there may still be tearing artefacts.
Richard.
|
|
|
|
Rod
Full Member
member is offline


Gender: 
Posts: 110
|
 |
Re: Change Display Width/Height
« Reply #10 on: Jan 23rd, 2018, 5:57pm » |
|
Sigh, vertical sync screen refresh, so simple and so in the past! Will try the code when I get time.
|
|
Logged
|
|
|
|
|