Hi. The game I'm working on at the moment seems to have a problem with the way it renders on screen. Whenever I run it, a few lines of pixels appear to be missing. The strange thing about this is that it always seems to be the same lines. I've attached a screenshot of the problem. The mistakes are quite subtle so I've highlighted them in red. It's mostly on my auto-generated text which I create by printing the text to a bitmap, grabbing it as an image and putting it into a sprite. However the problem is not with the text created algorithm as when the text moves, the errors no longer display. Rather, the problems appear to be linked to locations on the screen. For example, in the screenshot provided, The word wave appears to be standing alone but in fact, the text is "---Wave 1---". When the notifications all move up one line, using the same images, the --- appear as they should as they are no longer lined up with the 'missing pixel line'. I've tried to demonstrate this clearly by typing CAT in three times into the command box near the bottom. The middle one has the horizontal line on the A missing. The others don't but they do when they are moved to that location.
I'm not at all sure what is causing this error. I wondered if it might be some form of screen tearing but I'm not all that clear on it's causes and effects. Any thoughts on what mistake I may have made would be greatly appreciated.
Here is the source code for the main loop of the game. I update the screen myself having set sync on. I've also turned on vsync in the set display mode command.
` Main loop
do
` Reset variables
bTextUpdated = 0
` Check we have the focus
if not has focus()
nLastStepDiff = timer() - nLastStep
nUpdatedTimeDiff = timer() - gnUpdatedTime
while not has focus()
nice wait 1000
endwhile
nLastStep = timer() - nLastStepDiff
gnUpdatedTime = timer() - nUpdatedTimeDiff
endif
` Play animation
play sprite PORT1,1,2,500
play sprite PORT2,1,2,500
play sprite PORT3,1,2,500
play sprite RADARBASE,1,2,500
for c = 1 to array count(Objects(0))
if Objects(c).nType = WATERMINE or Objects(c).nType = RAMMINGSUB or Objects(c).nType = TORPEDOSUB or Objects(c).nType = RAMMINGBATTLESHIP or Objects(c).nType = FIRINGBATTLESHIP or Objects(c).nType = AIRCRAFTCARIER or Objects(c).nType = TRANSPORTSHIP
play sprite Objects(c).nSpriteNo,1,2,500
endif
next c
` Rotate radar line
fRadarRotation = RotateRadarLine(fRadarRotation)
` Get user inputs
if len(entry$(1)) > 0
if ValidCharacter(entry$(1))
if len(gsUserInput + entry$(1)) <= 100
gsUserInput = gsUserInput + entry$(1)
bTextUpdated = 1
endif
endif
clear entry buffer
endif
if returnkey()
if len(gsUserInput) > 0
ExecuteCommand()
bTextUpdated = 1
endif
endif
if backspacekey()
select nBackspace
case 0 ` Backspace key just pressed but not acted upon
gsUserInput = left$(gsUserInput,len(gsUserInput) - 1)
nBackspace = 1
nTimeOfBackspace = timer()
bTextUpdated = 1
endcase
case 1 ` Backspace key deleted one character this press
if TimeSince(nTimeOfBackspace) > 500
gsUserInput = left$(gsUserInput,len(gsUserInput) - 1)
nBackspace = 2
nTimeOfBackspace = timer()
bTextUpdated = 1
endif
endcase
case 2 ` Backspace key deleted more than one character this press
if TimeSince(nTimeOfBackspace) > 40
gsUserInput = left$(gsUserInput,len(gsUserInput) - 1)
nTimeOfBackspace = timer()
bTextUpdated = 1
endif
endcase
endselect
else
if nBackspace > 0
nBackspace = 0
endif
endif
if leftkey()
if fMultiplier > 1 and bLeft = 0
dec fMultiplier,0.5
bInfoUpdated = 1
bLeft = 1
endif
else
if bLeft
bLeft = 0
endif
endif
if rightkey()
if fMultiplier < 3 and bRight = 0
inc fMultiplier,0.5
bInfoUpdated = 1
bRight = 1
endif
else
if bRight
bRight = 0
endif
endif
if upkey() ` FOR DEBUG ONLY --- REMOVE BEFORE COMPILE
for c = 1 to array count(Objects(0))
show message sprite width(Objects(c).nSpriteNo)
show message sprite height(Objects(c).nSpriteNo)
next c
endif
if downkey() ` FOR DEBUG ONLY --- REMOVE BEFORE COMPILE
for c = 1 to array count(Objects(0))
show message Objects(c).nX
show message Objects(c).nY
next c
endif
` Move objects
for c = 1 to array count(Objects(0))
if TimeSince(nLastStep) > 39
Objects(c).nX = Objects(c).nX + ((gVectors(Objects(c).nVectorNo).fX * (TimeSince(nLastStep) / 40.0)) * fMultiplier)
Objects(c).nY = Objects(c).nY + ((gVectors(Objects(c).nVectorNo).fY * (TimeSince(nLastStep) / 40.0)) * fMultiplier)
nLastStep = timer()
endif
next c
` Check transport status (on or off screen)
for c = 1 to array count(Objects(0))
if Objects(c).nType = TRANSPORTSHIP and Objects(c).bOn = 0
if Objects(c).nX > 0 and Objects(c).nY > 0 and Objects(c).nX < screen height() and Objects(c).nY < screen height()
Objects(c).bOn = 1
endif
endif
next c
` Collision handling
dim nOldVals(array count(Objects(0)),1) as integer
for c = 1 to array count(Objects(0))
nOldVals(c,0) = sprite x(Objects(c).nSpriteNo)
nOldVals(c,1) = sprite y(Objects(c).nSpriteNo)
sprite Objects(c).nSpriteNo,Objects(c).nX,Objects(c).nY,Objects(c).nSpriteNo
spr prepare collision Objects(c).nSpriteNo
next c
for c = 1 to array count(Objects(0))
` Check for ships sinking
if spr get collision(Objects(c).nSpriteNo,ISLAND,1) > 10 or spr get collision(Objects(c).nSpriteNo,ROCK1,1) > 10 or spr get collision(Objects(c).nSpriteNo,ROCK2,1) > 10 or spr get collision(Objects(c).nSpriteNo,ROCK3,1) > 10
if Objects(c).nType = WATERMINE or Objects(c).nType = RAMMINGSUB or Objects(c).nType = TORPEDOSUB or Objects(c).nType = RAMMINGBATTLESHIP or Objects(c).nType = FIRINGBATTLESHIP or Objects(c).nType = AIRCRAFTCARIER or Objects(c).nType = TRANSPORTSHIP
RemoveObject(c,REASONSUNK)
if c > array count(Objects(0))
exit
endif
endif
endif
` Check for transport events
if Objects(c).nType = TRANSPORTSHIP
` Check for transport reaching port
if spr get distance(Objects(c).nSpriteNo,PORT1) < 20 or spr get distance(Objects(c).nSpriteNo,PORT2) < 20 or spr get distance(Objects(c).nSpriteNo,PORT3) < 20
gnResources = gnResources + Objects(c).nAmount
bInfoUpdated = 1
RemoveObject(c,REASONHOME)
if c > array count(Objects(0))
exit
endif
endif
` Check for transport going out of/coming into range
if Objects(c).bOn = 0
if Objects(c).nX > 0 and Objects(c).nY > 0 and Objects(c).nX < screen height() and Objects(c).nY < screen height()
Objects(c).bOn = 1
endif
else
if Objects(c).nX < 0 or Objects(c).nY < 0 or Objects(c).nX > screen height() or Objects(c).nY > screen height()
RemoveObject(c,REASONOUTOFRANGE)
if c > array count(Objects(0))
exit
endif
endif
endif
endif
next c
` Restore sprites to screen positions
for c = 1 to array count(Objects(0))
sprite Objects(c).nSpriteNo,nOldVals(c,0),nOldVals(c,1),Objects(c).nSpriteNo
next c
` Update the screen
if bTextUpdated
gsUserInput = upper$(gsUserInput)
sText$ = "> " + gsUserInput + "_"
if text width(sText$) >= (screen width() - screen height()) - GetPxFromPercent(screen width() - screen height(),16)
nNoOfChars = len(sText$)
while text width(right$(sText$,nNoOfChars)) >= (screen width() - screen height()) - GetPxFromPercent(screen width() - screen height(),16)
nNoOfChars = nNoOfChars - 1
endwhile
sText$ = right$(sText$,nNoOfChars)
endif
CommandTextOverSprite(0,sprite x(gnCommands(0,SPRITENO)),sprite y(gnCommands(0,SPRITENO)),sText$)
endif
if bInfoUpdated
DrawTitleInfo(nLevel)
bInfoUpdated = 0
endif
if fRadarRotation >= 360.0
fRadarRotation = 360.0 - fRadarRotation
for c = 1 to array count(Objects(0))
sprite Objects(c).nSpriteNo,CentredX(Objects(c).nSpriteNo,Objects(c).nX),CentredY(Objects(c).nSpriteNo,Objects(c).nY),Objects(c).nSpriteNo
PlaceCaption(Objects(c).nSpriteNo,Objects(c).nCaptionSpriteNo)
if Objects(c).bOn = 1
show sprite Objects(c).nCaptionSpriteNo
else
hide sprite Objects(c).nCaptionSpriteNo
endif
next c
endif
sync
` Check if the game ends
if gbExit = 1
exit
endif
loop
Thanks in advance for your help.