Blitz Plus Intro by Mark Sibly

BlitzPlus Forums/BlitzPlus Tutorials/Blitz Plus Intro by Mark Sibly

Kuron(Posted 2005) [#1]
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)
	Text 0,0,mx+","+my
End 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
	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
		Text 0,0,mx+","+my
	End Select

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 )
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


		Flip False

	End Select

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
	While WaitEvent()
		Select EventID()
		Case $101
			If EventData()=1 End
		End Select

	Flip True


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.

Who was John Galt?(Posted 2005) [#2]
Thanks Brice. Some useful info there, and I don't remember seeing it before.