Blitz Plus Intro by Mark Sibly
BlitzPlus Forums/BlitzPlus Tutorials/Blitz Plus Intro by Mark Sibly
| ||
Here is an old Blitz Plus tutorial that Mark wrote long ago for newbies to Blitz Plus, that "disappeared" during one of the many forum revamps. I hope Mark does not mind me posting this. Introduction to event driven coding for games --------------------------------------------- Part 1: Blitz2D, Blitz3D and polling ------------------------------------ The design of both Blitz2D and Blitz3D is based around a concept known as 'polling'. The idea behind polling is that, in order for a program to find stuff out about devices like keyboards, mice, joyticks and so on, it must continually check to see what the user is up to. For example, a program such as... Graphics 640,480,16,1 ; While Not KeyHit(1) mx=MouseX() my=MouseY() Cls Text 0,0,mx+","+my Flip Wend ; End ...is continually polling the keyboard to see if the "esc' key has been hit. It is also polling the mouse for its current x,y coordinates, and writing those coordinates to the screen. This is a very simple and easy to understand technique, but suffers from a few drawbacks. * The most serious drawback is that this is NOT how the underlying OS actually works, so it limits how your program can interact with the OS. * Polling is not very 'system friendly'. Since your program is constantly polling for user activity - and therefore running - it isn't allowing other programs much 'CPU time'. * It is not very efficient - why continually check the mouse when the user isn't moving it? The above loop is executing 3 commands (KeyHit, MouseX and MouseY) that, 99% of the time, aren't really necessary. Of course, that other 1%, when the user actually hits a key or moves the mouse, are VERY important! Part 2: Event driven coding --------------------------- An alternative to polling is 'event driven' coding. Although a little more complex, the idea is really pretty simple. Instead of your program constantly checking devices, it is instead 'told' about changes that occur to the devices - eg: user hitting a key, moving the mouse and so on. When such changes occur, an 'event' is generated and send to your program. The basic idea when writing event driven code is for your program to sit there waiting for events to occur, and then to study each event and take some kind of action based on that event. For example, the example above rewritten to use events might look like... Graphics 640,480,16,1 ; While WaitEvent() Select EventID() case $101 ;A 'Key Down' event If EventData()=1 ;EventData() is the rawcode of the key End Endif case $203 ;A 'Mouse Move' event mx=EventX() ;EventX() is the new x coordinate of the mouse my=EventY() ;EventY() is the new y coordinate of the mouse Cls Text 0,0,mx+","+my Flip End Select Wend Why is this any better than the first version? It certainly looks more complex! Well... * The event driven version is completely 'system friendly'. The WaitEvent command will cause the program to come to a complete halt until an event occurs. While your program is halted, other programs the user may be running can run freely without be interupted by your program. * Its also more efficient; the screen is only redrawn when the mouse actually moves, while the first version was constantly redrawing the screen. While its true that the first version could be rewritten to achieve this, event driven code makes this kind of efficiency much easier, while polled code has a tendancy to settle into a 'naturally' inefficient state! * While the above only makes use of 'Key Down' and 'Mouse Move' events, there are a ton of other events for your program to play with! This allows a much greater degree of communication between your program and the OS. A few other things to note: * The meaning of EventData(), EventX() and EventY() depend upon the kind of event. Not all events make use of all of these. Part 3: Game timing using timers -------------------------------- Ok, here's an example of using timers to control game timing: Graphics 640,480,16,1 ; timer=CreateTimer( 30 ) ticks=0 ; While WaitEvent() Select EventID() Case $101 If EventData()=1 End ;Quit if 'Esc' hit case $4001 ;Event ID for a timer tick event... elapsed=EventData()-ticks ;EventData() contains the TOTAL number of timer ticks. For n=1 To elapsed UpdateEverything() Next ticks=ticks+elapsed RenderEverything() Flip False End Select Wend Probably the only tricky bit to understand here is the 'elapsed' stuff, but all this is really doing is calculating how many 'ticks' have elapsed since the previous timer event. 'elapsed' will usually be equal to '1', but may be greater on some slower machines. Note that this is perhaps the nicest and easiest way to handle game timing. While your program is waiting for an event to occur, it is completely halted and other programs can run freely. Part 4: Game timing using VWait/Flip ------------------------------------ This is a little more complex, but not much... Graphics 640,480,16,1 ; Repeat While WaitEvent() Select EventID() Case $101 If EventData()=1 End End Select Wend UpdateEverything() RenderEverything() Flip True Forever Note how the WaitEvent loop has moved. This is necessary because Flip could potentially take quite a while to execute, since it waits for vertical blank. During this time, a bunch of events may have occured, so its therefore a good idea to 'greedily' examine all these events. Note that, although VWait/Flip based timing gives the nicest results due to frame-syncing, its not very system friendly. This is mainly because 'Vwait' itself actually uses polling! There's not much Blitz can do about this, as Vwait is performed the graphics driver. |
| ||
Thanks Brice. Some useful info there, and I don't remember seeing it before. |