Like the word ”buffer”, I say, you google for the technical word of threading. What I understand about ”threading” is like ”you dance, I dance; you stop when told but I continue until told to do so”. In short, you and me are independent of what we do but obeys a command of stop and go.
In modern game programming (though not necessary 3D games), threading is very important. This gives the illusion that enemies are alive and will come to slay the hero. The hero is then being controlled by a player.
The best way to demonstrate a thread is to make a simple (but not so simple) program.
This tutorial is entitled “Simulating Threads” simply because ”threading” does not exist in KonsolScript. Given that condition, I will try to make a (not-so) simple program in KonsolScript to simulate threading. And honestly, I, surely, can't do any simpler than the code I made – let's just settle for it right now.
Screenshot of the sample program.
function main() { Var:Number imgMan1, imgMan2, imgMan3, imgMan4, imgMan, imgManCTR, imgManX; Var:Number imgBat1, imgBat2, imgBat3, imgBat4, imgBat, imgBatCTR; Var:Boolean bManATK; Image:Load("man1.bmp", imgMan1) Image:Load("man2.bmp", imgMan2) Image:Load("man3.bmp", imgMan3) Image:Load("man4.bmp", imgMan4) Image:Load("bat1.bmp", imgBat1) Image:Load("bat2.bmp", imgBat2) Image:Load("bat3.bmp", imgBat3) Image:Load("bat4.bmp", imgBat4) imgManCTR = 1; imgBatCTR = 1; imgMan = imgMan1; imgManX = 50; Screen:Show() while (B1 == false) { Screen:CLS() if (imgBatCTR == 1) { imgBat = imgBat1; } else if (imgBatCTR == 2) { imgBat = imgBat2; } else if (imgBatCTR == 3) { imgBat = imgBat3; } else if (imgBatCTR == 4) { imgBat = imgBat4; } else if (imgBatCTR == 5) { imgBat = imgBat3; } else if (imgBatCTR == 6) { imgBat = imgBat2; } else if (imgBatCTR == 7) { imgBat = imgBat1; imgBatCTR -= 7; } imgBatCTR++; if (bManATK == true) { if (imgManCTR == 1) { imgMan = imgMan1; } else if (imgManCTR == 2) { imgMan = imgMan2; } else if (imgManCTR == 3) { imgMan = imgMan3; } else if (imgManCTR == 4) { imgMan = imgMan4; } else if (imgManCTR == 5) { imgMan = imgMan1; imgManCTR -= 5; bManATK = false; } imgManX++; imgManCTR++; } Image:TBlit(imgManX, 150, imgMan, screen) Image:TBlit(150, 50, imgBat, screen) Konsol:Delay(100) Screen:Render() if (B3 == true) { if (bManATK == false) { bManATK = true; } } } }
Whew! Pretty intimidating, huh? Did I code that one? Let's see if I can discuss the code.
I decided to make two animating objects in one scene. One will represent the usual enemy (which happens to be called Bat) and one to be controlled by the player (which we will call Man). It so happen that both objects would use 4
-picture each – this means 8
image buffer.
Var:Number imgMan1, imgMan2, imgMan3, imgMan4, imgMan, imgManCTR, imgManX; Var:Number imgBat1, imgBat2, imgBat3, imgBat4, imgBat, imgBatCTR;
The variable names, imgMan1
to imgMan4
and imgBat1
to imgBat4
are the image buffers-to-be.
And since we are going to have one animation for each, this requires us to declare 2
counters, imgManCTR
and imgBatCTR
.
I also added imgManX
which has something to do with the horizontal location – I'll discuss more of this later.
I declared a Boolean
variable which will be utilized for some flagging whether Man should attack or not.
Var:Boolean bManATK;
Let's load those needed pictures into our image buffers. Be sure to download the needed resources if you want to try out the not-so-simple program. (Provide link)
Image:Load("man1.bmp", imgMan1) Image:Load("man2.bmp", imgMan2) Image:Load("man3.bmp", imgMan3) Image:Load("man4.bmp", imgMan4) Image:Load("bat1.bmp", imgBat1) Image:Load("bat2.bmp", imgBat2) Image:Load("bat3.bmp", imgBat3) Image:Load("bat4.bmp", imgBat4)
Now, let's do some initialization.
imgManCTR = 1; imgBatCTR = 1; imgMan = imgMan1; imgManX = 50;
I would also like to skip in explaining what you should already know. For instance, the Screen:Show
to display the ”viewing screen”. The need of game programming to have a “main loop” using “while (B1 == false) { /* scope… */}”. And Screen:CLS
in clearing the ”viewing screen”.
So let us proceed to the animation programming, which by now should be familiar to you already. And since Man and Bat has separate animation, So I will discuss the code separately – I will show the code for the Bat, first.
/* the animation code for the Bat */ if (imgBatCTR == 1) { imgBat = imgBat1; } else if (imgBatCTR == 2) { imgBat = imgBat2; } else if (imgBatCTR == 3) { imgBat = imgBat3; } else if (imgBatCTR == 4) { imgBat = imgBat4; } else if (imgBatCTR == 5) { imgBat = imgBat3; } else if (imgBatCTR == 6) { imgBat = imgBat2; } else if (imgBatCTR == 7) { imgBat = imgBat1; imgBatCTR -= 7; } imgBatCTR++;
You could notice from the code above that no Blit
or TBlit
is present – it will be a little later; I'll get back to that.
One more thing that you should notice, the approach I made is the tip I gave in 3-picture Animation.
/* the animation code for the Man */ if (imgManCTR == 1) { imgMan = imgMan1; } else if (imgManCTR == 2) { imgMan = imgMan2; } else if (imgManCTR == 3) { imgMan = imgMan3; } else if (imgManCTR == 4) { imgMan = imgMan4; } else if (imgManCTR == 5) { imgMan = imgMan1; imgManCTR -= 5; bManATK = false; } imgManX++; imgManCTR++;
Let us focus on the Number
variable imgManX
.
I am adding a value of 1
to imgManX
while it animates (or attacks). This will give the illusion of attacking forward.
If you also notice in the complete sample code above, the animation code for the Man is written inside a scope of another if
command – I am pertaining to the if
written below.
/* code before the part of the animation for the Man */ if (bManATK == true) { /* scope... */ }
What I did to the code is that, I wanted to make the Man animate only when I pressed the ENTER
key.
bManATK
is a Boolean
variable, declared earlier, which will have a value of true
or false
. You could see from the code below that I set the value of bManATK
to false when the whole Man animation has completed a single playing – it is like ”play then stop” and not ”play then loop continuously”;
/* portion of the animation code for the Man */ } else if (imgManCTR == 5) { imgMan = imgMan1; imgManCTR -= 5; bManATK = false; }
Let us skip to where I wrote the code which will set the value of bManATK
to true
.
/* part of the animation code for the Man */ if (B3 == true) { if (bManATK == false) { bManATK = true; } }
What I did is, I first checked if B3
or ENTER
key is pressed. I then check if bManATK
has a value of false
. If both of my questions answered to yes, I then set a value of true
to bManATK
.
Now, let us go back to the other code we skipped.
/* code that TBlit-ed the image buffers */ Image:TBlit(imgManX, 150, imgMan, screen) Image:TBlit(150, 50, imgBat, screen)
imgManX
is Number
variable declared for use of moving the Man horizontally while animating.
And finally, I once again used the Delay
function of Konsol
classs to regulate the animation speed.
/* the delaying tactics ^_^ */ Konsol:Delay(100)
That is all there is to this very (not-so) simple sample program that demonstrates how to fake threading in KonsolScript.
Remember that the code above was constructed to have a logic intended for whatever I intended it to be – to simulate threading in KonsolScript.
Do not get limited to the sample above. There are more better ways to simulate much more complicated program that needs threading.
My best last word for this tutorial would be, if you had a code that looked like the one above, better start crumbling it into small pieces using function
. See the sample code below.
Var:Number imgMan1, imgMan2, imgMan3, imgMan4, imgMan, imgManCTR, imgManX; Var:Number imgBat1, imgBat2, imgBat3, imgBat4, imgBat, imgBatCTR; Var:Boolean bManATK; function main() { LoadImages() Initialize() while (B1 == false) { Screen:CLS() AnimateBat() if (bManATK == true) { AnimateMan() imgManX++; } DisplaySprites() Screen:Render() CheckUserInput() } } function Initialize() { imgManCTR = 1; imgBatCTR = 1; imgMan = imgMan1; imgManX = 50; Screen:Show() } function LoadImages() { Image:Load("man1.bmp", imgMan1) Image:Load("man2.bmp", imgMan2) Image:Load("man3.bmp", imgMan3) Image:Load("man4.bmp", imgMan4) Image:Load("bat1.bmp", imgBat1) Image:Load("bat2.bmp", imgBat2) Image:Load("bat3.bmp", imgBat3) Image:Load("bat4.bmp", imgBat4) } function AnimateBat() { if (imgBatCTR == 1) { imgBat = imgBat1; } else if (imgBatCTR == 2) { imgBat = imgBat2; } else if (imgBatCTR == 3) { imgBat = imgBat3; } else if (imgBatCTR == 4) { imgBat = imgBat4; } else if (imgBatCTR == 5) { imgBat = imgBat3; } else if (imgBatCTR == 6) { imgBat = imgBat2; } else if (imgBatCTR == 7) { imgBat = imgBat1; imgBatCTR -= 7; } imgBatCTR++; } function AnimateMan() { if (imgManCTR == 1) { imgMan = imgMan1; } else if (imgManCTR == 2) { imgMan = imgMan2; } else if (imgManCTR == 3) { imgMan = imgMan3; } else if (imgManCTR == 4) { imgMan = imgMan4; } else if (imgManCTR == 5) { imgMan = imgMan1; imgManCTR -= 5; bManATK = false; } imgManCTR++; } function DisplaySprites() { Image:TBlit(imgManX, 150, imgMan, screen) Image:TBlit(150, 50, imgBat, screen) Konsol:Delay(100) } function CheckUserInput() { if (B3 == true) { if (bManATK == false) { bManATK = true; } } }
That code above will not just make your code look elegant, it will also make your code look neat and more manageable.