Re: Timing



"B. Nelsen" <b.nelson@xxxxxxxxx> wrote in message news:ep4hUoosIHA.2064@xxxxxxxxxxxxxxxxxxxxxxx

I'm having a hard time implementing a feature which moves
a graphic over the screen. What I tried was QueryPerformance
Counter, but even that caused problems because it wasn't
exact enough and it was either too fast or too slow. How does
Microsoft do it? If you take for example the ComboBox drop
down procedure you see that it drops down absolutely perfect.

Actually it isn't really perfect at all. It's just that it animates quickly and for a very short period of time. In contrast, watching a continuously moving graphic, especially if that graphic is itself static and is not itself animated in any way, readily shows up any limitations. On a busy "game display" with lots of things happening and with most of the "characters" being themselves animated you do not so easily notice these things, but on a simple static background with just a few moving figures the limitations become obvious.

It is possible on a pc to get the sort of "superbly smooth exact pixel value on each and every frame" kind of motion that was very easily achievable on much older machines such as the Commodore Amiga or the C64, but in order to do so you need to get into using DirectX. Your own problem is definitely nothing whatsoever to do with lack of resolution of your timing device, because on a good day the QueryPerformanceCounter you are using can give you resolutions in the order of 1 microsecond. The problem is simply that you are setting your frame rates using a different clock than the video card is using. To get the sort of super smooth motion that was common on the Amiga and the C64 you need to be timing your drawings using the same clock that the video card is using to draw its frames, which effectively means that you need to be using DirectX. It is possible to use a fairly large subset of DirectX (at least DirectX7 and I think DirectX8) from VB6 (set a reference to DirectX7 For Visual Basic Type Library in Project / References) but I have never done so myself and so I cannot help you with it. Essentially you perform your drawings in a buffer and then wait for the video card's "end of frame vertical blanking period" before sending the buffer to the display, repeating that process on every frame. All this buffering and stuff is also very easy to do in standard VB6 code, but it is the "tying it to the video frame rate" that is difficult. You can use a fairly simple call to DirectX7 WaitForVerticalBlank function, without requiring to actually "get into" DirectX itself, but I've never had any real success with such a simple arrangement in VB6 (although it does work reasonably well in XP, but not in Vista) simply because the two systems are effectively running in "different areas of the machine".

In the meantime, have a look at the following extremely simple example of moving a small shape across the screen (actually a small piece of text) using the standard drawing methods which have nothing whatsoever to do with DirectX. It is possible to achieve reasonably smooth motion if you set the delay to an appropriate value (something which can be calculated in your code but which I have not done in the example). Much depends on exactly what it is you want to do. If you want to write a super smooth operation graphically intensive game in VB6 then you are not going to do it without using DirectX (which has a fairly steep learning curve) but you can get reasonable results fairly easily without using DirectX if your requirements are fairly modest. Anyway, try various different values for the "wait" variable in the following example. You will probably find that the most annoying flicker is produced by values which closely approximate the actual video frame rate on your machine, because you will then "often hit it exactly and often not hit it at all", because they are never going to be exact (without DirectX which is capable of actually determining the frame intervals and of waiting for them). It is usually better to use values that are a fair bit removed from and are either side of the frame rate. Anyway, just play about with it and see what you think. Sorry I couldn't be of more help to you, but I have never actually used DirectX on the pc (come back Amiga!).

There are all sorts of different "sprite drawing routines", many of which I can help you with, that will enable you to draw and animate large numbers of static and animated sprites with transparent backgrounds all over the display using VB6, but of course all of them suffer from the fact that they are not in any way tied to the actual video card frame rate as would be possible in DirectX. Maybe someone else here who has some experience with DirectX in VB6 will come along to help you, but in the meantime here is the very simple "move a piece of text" program I mentioned.

Mike

Option Explicit
Private Declare Function timeBeginPeriod _
Lib "winmm.dll" (ByVal uPeriod As Long) As Long
Private Declare Function timeEndPeriod _
Lib "winmm.dll" (ByVal uPeriod As Long) As Long
Private Declare Function timeGetTime _
Lib "winmm.dll" () As Long

Private Sub Form_Load()
timeBeginPeriod 1
Dim t1 As Long, t2 As Long
t1 = timeGetTime
Do
Loop Until (timeGetTime - t1) > 100
Me.WindowState = vbMaximized
Me.ScaleMode = vbPixels
Me.Show
Me.FontTransparent = False
Me.Font.Name = "Times New Roman"
Me.Font.Bold = True
Me.Font.Size = 28
Dim y As Long, wait As Long
' try various wait values here
wait = 15
'
Do
y = y + 1
Me.CurrentX = y: Me.CurrentY = y
Me.Print "Rum and Coke®"
t1 = timeGetTime
Do
Loop Until (timeGetTime - t1) >= wait
DoEvents
Loop Until y >= Me.ScaleHeight - 100
End Sub

Private Sub Form_Unload(Cancel As Integer)
timeEndPeriod 1
End Sub




.