You are on page 1of 4

Page # 1 Battle008

Battle008

CREATING A SIMPLE GAME IN 3D


CHAPTER VIII

The Finite State Machine


Brief AI overview The concept of Artificial Intelligence attempts to code programs so that the active entities have a life of their own, interacting with and reacting to situations and events as they occur, simulating reflex actions of real entities. In our example, the enemy pogos should be programmed to react to several events, such as the nearness or absence of the human player, the time they have been wandering about, their health, etc. Brief FSM overview The concept of a Finite State Machine involves the formulation of definite states for the Artificial Intelligence entities, with the proviso that at any given time, an entity can be in only one of those states. There are no intermediate states, and living entities must be in a recognizable state at all times. This would be equivalent to a human being that can be happy, or sad, or angry, but can experience only one emotion at the time, and does not have combinations or mixed emotions. The article/tutorial Finite State Machines: a Little AI Goes a Long Way in the Blitz Coders site (www.Blitzcoders.com) by Morduun contains all the basic concepts, and a 2D implementation of the theory. States for the POGO Let us say that our Pogo can have, from what we have already seen, at least two states: IDLE, and CHASE. As a working hypothesis, we can propose the following states for a pogo: IDLE, CHASE, ATTACK, RECOVER, SPAWN, LOAD and SHOOT. These seven states should then be defined so that they are mutually exclusive, and can only happen one at the time. These are the basic definitions of each state: IDLE : default state; nothing is happening, the pogo is circling around. CHASE: the pogo has seen the human close by and is running after him ATTACK: the pogo has come within attack range and is slapping the human players wrist RECOVER: the pogos health has deteriorated so that it needs to stand still until it recovers. SPAWN: the pogo is giving birth to another pogo. (Different procreation systems, I guess) LOAD : for pogos that carry weapons, the pogo is loading his peashooter SHOOT: for pogos that have peashooters, the pogo is shooting the human being. Constant declarations The first step in coding these states is to declare them as constant states. Add the following under the collision groups:

Page # 2 CODE

Battle008 Remarks
We have assigned a number to each state

;# 1 Constant states Const IDLE = 0,CHAS =1,ATAK=2,RECO=3 Const SPAW = 4,LOAD = 5, SHOT = 6

Converting the pogo to a Blitz Basic Custom type To simplify the code, and to enable us to program efficiently, we need to convert our pogos into a Blitz Custom Type. This will be immensely more convenient when the little grunts begin spawning and we cannot any longer keep track of each blighter separately First Stage: the Type Declaration Below are the first few fields for this type. The field n represents the entity name, as we will see in the following paragraph. CODE REMARKS
;#2 type declaration for POGO Type pogo Field x#,y#,z# Field N,S,H, idTim Field T,I,D, tex End Type ;location ;name. state. health. idle time ;type, inside, distance, texture

Second stage: Starting locations for all pogos: In our existing code, we have given the following locations:
;PositionEntity ;PositionEntity ;PositionEntity ;PositionEntity pogo,10,7,100 pogo2,-125,6,120 pogo3,125,6,120 pogo4,4,7,4

We can comment these lines out, and create the following data statements: CODE REMARKS
;# 4 -- Data statements .places Data 125,7,120,125,7,120,4,7,4 10,7,100,Consolidating the data points locations, under the label .places Data values For x y z for

Now we can assign them to our first four instances. All the pogos appear to be called p now. In reality, Blitz has assigned internal identifiers to each one separately. Code REMARKS
;#3 instance declaration Restore places For j = 1 To 4 p.pogo = New pogo Read k p\x = k Read k p\y = k Read k p\z = k p\T = ENEMY p\n = LoadMD2("tris.md2") ScaleEntity p\n, 0.04,0.04,0.04 go to the start of data Loop 4 times Declare new instance of pogo Read first number Assign to x Read second number Assign to y Read third number Assign to z Collision type Load the mesh Scale the entity

Page # 3

Battle008
Load the texture Assign texture to entity Position the entity Animate the mesh Assign entity radius Assign type

p\tex = LoadTexture("armour.pcx") EntityTexture p\n,p\tex PositionEntity p\n, p\x, p\y, p\z AnimateMD2 p\n, 1,0.1,41,46 EntityRadius p\n, .9 EntityType p\n,p\T Next

With this assignment, we can now delete all the previous entries for pogos, as follows:
; #5 comment out all pogos ;POGO ;pogo = LoadMD2("tris.md2") ;ScaleEntity pogo,0.04,0.04,0.04 ;pogo_tex = LoadTexture("armour.pcx") ;EntityTexture pogo,pogo_tex ;PositionEntity pogo,10,7,100 ;AnimateMD2 pogo,1,0.1,41,46 ;EntityRadius pogo,.9 ;EntityType pogo,ENEMY ; ;pogo2 = LoadMD2("tris.md2") ;ScaleEntity pogo2,0.04,0.04,0.04 ;EntityTexture pogo2,pogo_tex ;PositionEntity pogo2,-125,6,120 ;RotateEntity pogo2,0,180,0 ;AnimateMD2 pogo2,1,0.1,41,46 ;EntityRadius pogo2,.9 ;EntityType pogo2,ENEMY ;POGO 3 ;pogo3 = LoadMD2("tris.md2") ;ScaleEntity pogo3,0.04,0.04,0.04 ;EntityTexture pogo3,pogo_tex ;PositionEntity pogo3,125,6,120 ;RotateEntity pogo3,0,180,0 ;AnimateMD2 pogo3,1,0.1,41,46 ;EntityRadius pogo3,.9 ;EntityType pogo3,ENEMY ;POGO 4 ;pogo4 = LoadMD2("tris.md2") ;ScaleEntity pogo4,0.04,0.04,0.04 ;EntityTexture pogo4,pogo_tex ;PositionEntity pogo4,4,7,4 ;RotateEntity pogo4,0,180,0 ;AnimateMD2 pogo4,1,0.1,41,46 ;EntityRadius pogo4,.9 ;EntityType pogo4,ENEMY

The four individual pogo entries are deleted.

Modifying the main loop and the functions Now we can simplify the main loop and its associated functions, to avoid awkward repetitions:

Add the following lines before checkgravity(pogo)

Page # 4 CODE
;#6 comment out and procedures For p.pogo = Each pogo checkgravity() checkAI(P\N) MoveEntity p\n, 0,0,0.02 Next

Battle008 REMARKS
replace This will look at all active pogos that we may have.

Delete the following lines:


;checkGravity(pogo) ;checkGravity(pogo2) ;checkGravity(pogo3) ;checkGravity(pogo4) ;checkAI ;checkAI(pogo) ;checkAI(pogo2) ;checkAI(pogo3) ;checkAI(pogo4) ;move POGO ;MoveEntity pogo,0,0,0.02 ;TurnEntity pogo,0,-0.04,0--deleted ;MoveEntity pogo2,0,0,0.02 ;TurnEntity pogo2,0,0.04,0--deleted ;MoveEntity pogo3,0,0,0.02 ;TurnEntity pogo3,0,-0.04,0--deleted ;MoveEntity pogo4,0,0,0.02 ;TurnEntity pogo4,0,-0.04,0--deleted

The turn entity lines were deleted before

We should delete the pogo set from the global declarations. We can make the p.pogo type global if we wish. Code Remarks
;#7 declare this Global p.pogo ;#8 delete this ;Global pogo,pogo2,pogo3,pogo4

And we can make check gravity only for pogos (for now, at least) Code Remarks
;#9 make check gravity just for the pogos... Function checkGravity() If Not EntityCollided(P\n,SCENERY) TranslateEntity P\n,0,-0.01,0 End If End Function

Let us try the program. It should work correctly. In the next chapter, we will start defining each state: No new commands Resources : battle008.bb Radius65 Oct 03

You might also like