03-16-2002, 12:28 PM
Hi, I'm trying to make a Pong game, and I'm using a BitBlt loop. It looks nice and smooth but the response time is much too slow! I tried using a timer as I did within my demo program, but that makes the paddle and ball's movement too choppy. I'm attaching the code if you care to have a look at it and point out what I'm doing wrong and how to correct it.
Gamer X (http://gamerx-creations.cjb.net)
03-16-2002, 12:41 PM
For some reason there is no attachment. Try again :)
03-16-2002, 01:56 PM
Okay, trying again . . .
03-16-2002, 09:20 PM
Yeah, this is similar to the Tetris game on the other thread here.
The Pong game uses a constant loop instead of a timer so my mouse becomes very sluggish because the doevents don't seem to trigger much. :(
Check out the mods I did to your code, it now uses a timer and runs sweet.
I've deleted most of the stuff from the game as you have written everything lots of times over which ain't necessary.
You don't need to use the doevents like 50 times! :)
With the timer, don't put it under 10 milliseconds, there is no need to go lower then that.
Hope this helps.
03-16-2002, 11:04 PM
Thanks, I'll take a look at the code in a bit. I am new to using BitBlt(only worked with it a few days), and I still don't understand what it does, but thanks once again. ^_^
03-17-2002, 12:11 AM
Uh, thanks anyways, but your code here runs horribly slow on my PC. Thanks for trying. . .
Gamer X (http://gamerx-creations.cjb.net)
03-17-2002, 01:11 AM
To speed it up, you can try several things.
Increase the distance which the paddles moves per frame.
If you are using 32 bit windows resolution then change to 16 bit.
Use DirectDraw if you have a decent video card.
Buy a faster computer. :D j/k
I didn't look at the code much, just deleted half of it and added a timer, and it ran very smooth on mine.
I'll have another look at your code in more detail later if you want to see what the bottleneck in the program is.
03-17-2002, 01:22 AM
I can see a couple of things in your code which is a major problem, especially with older computers.
Is that you are using cls to clear the screen every frame then drawing the objects with merge then paint
Now unless you are going to have a picture in the background, you would get much more speed out of the game if you turn off the form.autoredraw to false then only clear the parts of the screen which need it, as in where the ball was last etc.
So your processor doesn't have to keep clearing the whole form but only a fraction of it.
With the bitblt, if you ain't going to have any picture in the background, then you don't need to merge then paint, you can just use the vbSrcCopy operand by itself.
Then you would have to make the ball have the same back colour as the background.
03-17-2002, 05:24 AM
I looked at it and you're doing an awful lot of things all at onces unnecessarily.
Take out most of the DoEvents, that many will show a marked slow down. Leave them in very tight loops, ie the main loop.
Also, it seems that GameTimer is obsolete, so delete all the code.
Theres a lot of stuff in here I dont get... like this:Show
MainLoopWhats the point of the stuff in bold? Once the main loop is called, it never returns so these bits never get run.
You're clearing the screen in the MainLoop as well as within the DrawStuff sub. You only need to clear the screen once per frame..
Third, you call DrawStuff from within the GameActions sub, which you are again calling in the main loop. Sort out where you're going to call it from, once per frame...
Just spotted this:DoEvents
'If BallAttached = 0 Then bY = bY + Yvel: bX = bX + Xvel
For ii = 1 To 10
' DrawStuff ' I commented this bit
DoEventsAll it does it pause? Thats a *huge* slow down for a game..
[re-edit]I made the changes I suggested above, and it runs at least twice as fast.... Good luck :D[/re-edit]
03-17-2002, 08:07 AM
Thanks! Like I said, I'm new to BitBlt.
Gamer X (http://gamerx-creations.cjb.net)
03-17-2002, 08:20 AM
Originally posted by Lord Pookie
...turn off the form.autoredraw to false then only clear the parts of the screen which need it, as in where the ball was last etc....
How do I only clear the parts where something's been?
And I'm now <i>only</i> using the GameTimer, because if I use any loop at all then it takes too long for it to respond to any input.
Do you know any way around that?
03-17-2002, 08:39 AM
You seem hell bent on not using a timer here.
Considering VB is an event driven program, why not use it to your advantage and use it's timers. After all, the timer will make the program run at the same speed regardless of how fast the user's computer is. (unless of course the computer is so slow it actually takes more time within the timer's loop then the timer is set to)
To clear the bats is easy. You simply redraw the picturebox that they are in so that you give them some lee-way on the top and bottom.
Lets say the bats move up or down at 4 pixels.
Then add 4 pixels of background colour to the top and bottom of the bat in the bat picture box, so when you bitblt the bat, you also bitblt the background above it and below it so when the bat moves up or down 4 pixels, the lee-way will erase the part of the bat which would normally leave a trail...
The ball you can simply erase it, move it then draw it again.
Erasing it can be done by either bitbliting the background to where the ball is or even using .line (x-y)-(x+15,y+15), backgroundcolour, bf to erase the ball.
Hope you can follow what I mean here. :)
03-17-2002, 01:01 PM
Yeah, I kindof understand what you mean about erasing it, thanks. And I would <i>rather</i> use a timer than a loop, if it wasn't for the fact that when I use a timer the movement is choppy, and I would like the game to run smooth.
03-18-2002, 07:35 AM
I'd disagree, always use loops rather than timers.
As for BitBlting parts of the background, thats a lot of unecessary calculations. IMHO it'd be quicker to simply clear the screen.
03-18-2002, 08:56 AM
Okay, but why do you think using loops is better then timers, can you explain why as I always used timers and had no problems with them...
I also don't understand why you think it would be quicker to clear the whole screen compared to just clearing a small ball, which is the only difference as the bat has to be drawn regardless in the scenario... hmm. :-\
03-18-2002, 09:50 AM
Loops will be quicker to respond. This is simply because sometimes, drawing a frame may take less time than the timer interval, and if this is the case, your game engine is sat doing nothing until the timer next fires. You can set the timer interval down to 1 but the timer control is not known for its accuracy..
A loop is constant, and flags can be placed to only do processor and time intensive operations if the screen has changed.
It is easier to control the flow and direction of just pure code without using timers.
Your method above described calculating the number of pixels of backgorund color to BitBlt on top of the paddle, and also by 'erasing' the ball, I assume you mean perform a BitBlt of background color over the top of the existing image.
Calculating the pixels will take time, then may result in two or more BitBlt calls being made per bat, and copying over the ball is another. The Picture.Cls method (I think) performs one single BitBlt to wipe the whole lot. Thus saving several calls as opposed to your method.
03-18-2002, 12:28 PM
No, the bats only need one bitblt call as when you move the bat, it will erase the outer pixels by itself. Sort of hard to describe in writing. :)
Out of curiosity, I'll write two mini routines, one with frm.cls and one with blit clearing to see how they fair using the pong sprites as an example. (Hope you don't mind GamerX) :D As I myself don't know which is going to be faster.
It's just that I've been programming on and off for the last 15 years and most of my programming experience is not with VB or the PC, using the older slower processors, and with them you had to cut corners as best as you knew how to get the most of them. :D
I'll post the results and the code later if anyone is interested. Probably be a loop of like 1000 times of moving the bats up and down and the ball bouncing around....
03-18-2002, 10:38 PM
Okay, I wrote a little test to see how fast screen clearing was compared to just clearing the sprites.
It's not a true indication of speed as with the bats, I didn't need to erase them at all as I put some background pixels above and below them to erase their image when moving up and down. :D (This method of cheating is good for simple games without backgrounds like pong as no game player would know the difference when playing)
So with this example, I got the blit erase routine to run around 10 times faster then clearing the screen.... Which tells me that .cls doesn't use any gpu power (as I have a ultra fast GF card) and indeed is just the same as bitblt, I also removed the .cls and changed it to bitblt the whole page to see if there was any speed increase or decrease and there wasn't.
So the bigger the screen area, the less effective .cls becomes, unless of course you are moving more surface area of the screen per loop cycle then the combined screen size. :)
The only problem is I couldn't get the gettickcount to work properly, so if anyone knows how to fix this, let me know. :)
03-18-2002, 11:19 PM
You go ahead and use my graphics, only took about five minutes to make them. I understand what you mean about the pixel above and below the paddles. That will work great until I put in a BG (which I'm not even sure if I want to).
As for your demo you made Lord Pookie, it runs extremely fast on my PC and flickers the whole time. The whole routine is over in like three seconds. I assume that what you were proving with it is that I can just use PB.cls instead of needing to BitBlt blue onto where the ball had been.
I'll get around to working on Pong again once I have the time. (Busy working with Borax and Glue--it doesn't want to do what I tell it!)
03-20-2002, 02:04 PM
First off, I have to say I prefer loops over timers
a) timers have a minimum resolution of 55ms, even though it *seems* you can set them to 1ms
b) timers are a limited resource (not really true anymore but it was a big concern in VB3)
c) timers are harder to debug, esp. if you have a lot of them.
Second, I will say that DoEvents is a particularily slow instruction. The trick is to only use it if you have to. For instance, the API call GetInputState is really fast. It returns true if the mouse has moved or was clicked or if there was some keyboard activity so you could do something like:
Private Declare Function GetInputState Lib "user32" Alias "GetInputState" () As Long
If GetInputState() Then DoEvents
Thus the loop will only call doevents if something happened.