News:

PlayBASIC2DLL V0.99 Revision I Commercial Edition released! - Convert PlayBASIC programs to super fast Machine Code. 

Main Menu

Cellular-Based Worlds

Started by ScottB, February 04, 2025, 10:57:54 AM

Previous topic - Next topic

ScottB

How would I chase the player down say tank to tanks shoot at player and move around.
Is there an easy way? My Question is this how do I add bad guys to hunt down player and shoot at each other.
Thanks Scottie B an example within the game would be great. I'd like to learn some A.I. to do this different ways.
But first I would like to see enemy tank hunt player down.

kevin

   
  That's not really a lot to go on. ie Some tanks roaming a maze.  Do the tanks roam like PacMan ghosts?, or like   tanks-a-lot  . Do they avoid each other?   
 

 

 
QuoteI'd like to learn some A.I. to do this different way

  Ok, but what's your current approach  ? What have you tried ?  Your asking a lot of somebody to build a complete solution from nothing.

  Having characters find roaming is generally the domain the of path finding..   The trouble with that is then the ai will locate the player exactly, Making it unbalanced.  So some type of hybrid set of rules might work better.  With various behavior modes..


 
  links:

   --> Line Of Sight - (Clever Coders Challenge #10)

   --> Flood Fill Path Finder

ScottB

Here is pathfinding.
Can you move the enemy player according to these rules?
*A star pathfinding is the shortest way.
 

ScottB

Is this correct. Or is there there a better way to traverse the nodes?
ScottB

kevin


  I can't run anything at the moment.

  But looking at the code..   my first question is what is this ?? why are you making lots of individual variables for things that would be better served in a type?   


PlayBASIC Code: [Select]
   X1_Enemy_Old# = X1_Enemy#
Y1_Enemy_Old# = Y1_Enemy#

X1_Enemy_Cell_Old = X1_Enemy_Cell
Y1_Enemy_Cell_Old = Y1_Enemy_Cell

X1_Enemy_Cell = Int(X1_Enemy#) / X_Cell_Size
Y1_Enemy_Cell = Int(Y1_Enemy#) / Y_Cell_Size

X1_Enemy_Cell_Old_2 = X1_Enemy_Cell_2
Y1_Enemy_Cell_Old_2 = Y1_Enemy_Cell_2

X1_Enemy_Cell_2 = (Int(X1_Enemy#) + X_Cell_Size - 1) / X_Cell_Size
Y1_Enemy_Cell_2 = (Int(Y1_Enemy#) + Y_Cell_Size - 1) / Y_Cell_Size

Up = Array_2(X1_Enemy# / X_Cell_Size,Y1_Enemy# / Y_Cell_Size - 1)
Down = Array_2(X1_Enemy# / X_Cell_Size,Y1_Enemy# / Y_Cell_Size + 1)
Left = Array_2(X1_Enemy# / X_Cell_Size - 1,Y1_Enemy# / Y_Cell_Size)
Right = Array_2(X1_Enemy# / X_Cell_Size + 1,Y1_Enemy# / Y_Cell_Size)

Middle = Array_2(X1_Enemy# / X_Cell_Size,Y1_Enemy# / Y_Cell_Size)

If Dir_5 = 0 And Dir_6 = 0 And Dir_7 = 0 And Dir_8 = 0 And Array_1(X1_Enemy_Cell + 1,Y1_Enemy_Cell) = 0

If Right = Middle - 1 Then Dir_5 = 1

EndIf

If Dir_5 = 0 And Dir_6 = 0 And Dir_7 = 0 And Dir_8 = 0 And Array_1(X1_Enemy_Cell_2 - 1,Y1_Enemy_Cell) = 0

If Left = Middle - 1 Then Dir_6 = 1

EndIf

If Dir_5 = 0 And Dir_6 = 0 And Dir_7 = 0 And Dir_8 = 0 And Array_1(X1_Enemy_Cell,Y1_Enemy_Cell + 1) = 0

If Down = Middle - 1 Then Dir_7 = 1

EndIf

If Dir_5 = 0 And Dir_6 = 0 And Dir_7 = 0 And Dir_8 = 0 And Array_1(X1_Enemy_Cell,Y1_Enemy_Cell_2 - 1) = 0

If Up = Middle - 1 Then Dir_8 = 1

EndIf

If Dir_5 = 0 And Dir_6 = 0 And Dir_7 = 0 And Dir_8 = 0 And Array_1(X1_Enemy_Cell + 1,Y1_Enemy_Cell) = 0

If Right = Middle - 1 Then Dir_5 = 1

EndIf

If Dir_5 = 1 And Array_1(X1_Enemy_Cell + 1,Y1_Enemy_Cell) = 0 And X1_Enemy_Cell = X1_Enemy_Cell_Old

X1_Enemy# += X1_Enemy_Speed * Elapsed_Time#

Else

If Dir_5 = 1

X1_Enemy# = X1_Enemy_Cell * X_Cell_Size

Dir_5 = 0

EndIf

EndIf

If Dir_6 = 1 And Array_1(X1_Enemy_Cell_2 - 1,Y1_Enemy_Cell) = 0 And X1_Enemy_Cell_2 = X1_Enemy_Cell_Old_2

X1_Enemy# -= X1_Enemy_Speed * Elapsed_Time#

Else

If Dir_6 = 1

X1_Enemy# = X1_Enemy_Cell_2 * X_Cell_Size

Dir_6 = 0

EndIf

EndIf

If Dir_7 = 1 And Array_1(X1_Enemy_Cell,Y1_Enemy_Cell + 1) = 0 And Y1_Enemy_Cell = Y1_Enemy_Cell_Old

Y1_Enemy# += X1_Enemy_Speed * Elapsed_Time#

Else

If Dir_7 = 1

Y1_Enemy# = Y1_Enemy_Cell * Y_Cell_Size

Dir_7 = 0

EndIf

EndIf

If Dir_8 = 1 And Array_1(X1_Enemy_Cell,Y1_Enemy_Cell_2 - 1) = 0 And Y1_Enemy_Cell_2 = Y1_Enemy_Cell_Old_2

Y1_Enemy# -= Y1_Enemy_Speed * Elapsed_Time#

Else

If Dir_8 = 1

Y1_Enemy# = Y1_Enemy_Cell_2 * Y_Cell_Size

Dir_8 = 0

EndIf
EndIf




    if Array_1 is the Map then not just call it MAP() 

    Moreover what do variables like these mean to anyone else ? 

    Dir_5 = 0 And Dir_6 = 0 And Dir_7 = 0 And Dir_8 = 0   ? 


   you can pack all those into a single expression and get rid of the repetition. 

   Something like,

    Direction_Selected =  Dir_5 = 0 And Dir_6 = 0 And Dir_7 = 0 And Dir_8 = 0 

   Effectively packs the those four comparisons into a single 0 or 1 answer 


   The problem with such approaches is then apparently every time a new character is added you need to 'cut'n'paste'  the basic code to a new enemy class and customize the variables so they don't clash.   Way too much work and unnecessary.   

   

   My advice would be to learn types... just think of them as an array with named data fields..   


PlayBASIC Code: [Select]
    setfps 60


type tAnimatedObject
X#,Y#
Angle#
Speed#
Colour
endtype

Dim object as tAnimatedobject list

do
cls

mx=mousex()
my=mousey()
mb=mousebutton()

if mb=1
Object = new tAnimatedobject

Object.Angle = 0
Object.Speed = 4.45
Object.Colour = rndrgb()
flushmouse
endif


print "press mouse to create dynamic object"

// draw a circle at mouse position
circle mx,my,50,true


for each object()

angle#=Object.Angle
// Animate object
object.X#=mx+cos(angle#)*100
object.Y#=my+sin(angle#)*100
circlec object.x#,object.y#,50,true,object.colour
angle#+=object.speed#
Object.Angle=angle#
print angle#
if (angle#>180) then Object = null
next
Sync
loop





  --> See Types

  --> See Linked Lists





kevin


 Did you get this going or not ?? 

 With the flood fill path finding stuff,

 --> if you get the logic to start from the target (the player) then fill out until it can't continue.    This should give the characters a way to track the direction back to the target.  So each step of the fill is the link to the previous step..  So chaining these steps together creates the paths.     

 --> Characters then look at the tile they're currently standing  on and try and traverse backwards down the links. 
 
 -->  So a bad guy looks at what link of the tile they're standing upon, then looks for any neighboring  links around it, looking for the current link minus one.   This works as those tiles would have been drawn in a previous pass during the flood fill and the fill radiated out from the target (the player) those links will lead back to the target. 

  I wrote something like this for the Lode Runner years ago, but can't find the example today..

  I'll write something using this type approach tomorrow