Problem with monster AI
BlitzMax Forums/BlitzMax Programming/Problem with monster AI
| ||
Hello my friends, I am creating the monster artificial intelligence functions and I have a little problem. I have my monsters moving in the dungeons and I try to make them collide with each other. What I mean , when some monster crawls in the dungeon , collides with the environment (Walls , doors , etc..) but when it arrives in square with other monster I want to change direction and never one square occupies 2 or monsters. (Monster overlapping). The type of the monster is: Type My_Monster Field X:Byte 'position X on the map Field Y:Byte 'position Y on the map Field Direction:Byte 'The direction the monster goes Field Graphic:String 'the graphic of the monster "01"=Skeleton Field State:Byte '1=Walk 2=Attack 3=Guard 4=Patrol Field Square_Transition_frame:Int Field Walking:Byte 'If the monster is walking Field Attacking:Byte Field Attack_animation:Byte Field Frame:Byte 'Animation frame . . . End Type Global Monster:My_Monster[max_levels + 1, Max_Monsters + 1] For LVL = 1 To Max_Levels For All_Monsters = 0 To Max_Monsters Monster[LVL, All_Monsters] = New My_Monster Next Next The monster when it moves change squares smoothly. There is a variable with name Square_Transition_frame. This square_Transition_frame variable takes values from -2 to 2 The monster when it enters in the square have an animation sequence and move its sprite: When it goes NORTH it moves from square_Transition_frame -2 then -1 and then finally 0. At the square_Transition_frame 0 the monster is at the absolute center position of the square. If the monster continue go to the NORTH then the monster will go from the square_Transition_frame 0 to 1 until arrives at the square_Transition_frame 2 after then the square_Transition_frame becomes -2 again and the monster changes its position y on the map. The opposite happens when the monster goes SOUTH the square_Transition_frame increases its value from -2 to -1 to 0. At the 0 the monster is at the center of the square. If it continue going SOUTH the square_Transition_frame becomes -1 to -2 and finally becomes 2 again and the monster increases ins y position on the map. The same happens when the monster goes WEST or EAST. In few words the 0 is the center position of the square and -2 -1 0 1 2 are 5 smooth animation transitions for the monster. The monster always before decide which direction will go , must arrive in square_Transition_frame =0 and then checks the AI if there are obstacles around like doors , statues or even other monsters. Everything are ok when I check non movable things , but when I am checking if there is another monster I have problem. I tried to check if the monster+1 and monster-1 is at the same position but it doesn't seems to work. I use this For All_Monsters = 1 To Max_Monsters If Monster[Party.Level, All_Monsters].X > 0 And Monster[Party.Level, All_Monsters].Y > 0 Then 'Check the previous monster If Monster[Party.Level, All_Monsters].X = Monster[Party.Level, All_Monsters - 1].X And Monster[Party.Level, All_Monsters].Y - 1 = Monster[Party.Level, All_Monsters - 1].Y Then 'Stop this monster Monster[Party.Level, All_Monsters].Walking = 0 'Stop and the previous monster Monster[Party.Level, All_Monsters - 1].Walking = 0 Monster[Party.Level, All_Monsters].Deadline_time = Current_time + Monster[Party.Level, All_Monsters].Time_Delay Monster[Party.Level, All_Monsters].Go_Direction = Rnd(1, 3) If Monster[Party.Level, All_Monsters].Go_Direction = 1 Then Monster[Party.Level, All_Monsters].Direction = 2 Continue If Monster[Party.Level, All_Monsters].Go_Direction = 2 Then Monster[Party.Level, All_Monsters].Direction = 3 Continue If Monster[Party.Level, All_Monsters].Go_Direction = 3 Then Monster[Party.Level, All_Monsters].Direction = 4 Continue 'Check the next monster If Monster[Party.Level, All_Monsters].X = Monster[Party.Level, All_Monsters + 1].X And Monster[Party.Level, All_Monsters].Y - 1 = Monster[Party.Level, All_Monsters + 1].Y Then 'Stop this monster Monster[Party.Level, All_Monsters].Walking = 0 'Stop and the previous monster Monster[Party.Level, All_Monsters + 1].Walking = 0 Monster[Party.Level, All_Monsters].Deadline_time = Current_time + Monster[Party.Level, All_Monsters].Time_Delay Monster[Party.Level, All_Monsters].Go_Direction = Rnd(1, 3) If Monster[Party.Level, All_Monsters].Go_Direction = 1 Then Monster[Party.Level, All_Monsters].Direction = 2 Continue If Monster[Party.Level, All_Monsters].Go_Direction = 2 Then Monster[Party.Level, All_Monsters].Direction = 3 Continue If Monster[Party.Level, All_Monsters].Go_Direction = 3 Then Monster[Party.Level, All_Monsters].Direction = 4 Continue EndIf Next The quick code above tells to check if the all_monsters-1 and all_monsters+1 will going to have equal positions with all_monsters It doesn't seems to work. The only thing I try to do , when the monster see if there is other monster in front (Depends which direction the monster travels) will change direction and the other monster will change direction to. If monster goes NORTH check Y-1 and goes other random direction except NORTH If monster goes SOUTH check Y+1 and goes other random direction except SOUTH If monster goes WEST check X-1 and goes other random direction except WEST If monster goes EAST check X+1 and goes other random direction except EAST |
| ||
Theres a lot of (poorly) formatted text to read there but I think I know what the problem is. The underlying method you are using should be fine - and probably is working under the hood but just looks wrong visually. The common problem with a method like this is that even though the monsters are in different cells their visual representation may overlap because the collision check is between two points while visually the monster takes up an area. The solution is to provide a radial checking distance for each monster which it uses when checking the grid cells instead. It gets complex when you introduce monsters that are larger than a grid cell however. I hope that adds some light. |
| ||
Theres a lot of (poorly) formatted text to read there but I think I know what the problem is. It seems the code tag wasn't activated and the text code wasn't appear well :) Better now? The common problem with a method like this is that even though the monsters are in different cells their visual representation may overlap because the collision check is between two points while visually the monster takes up an area. Yes my monsters moves in squares and each monster see what it have in front of it. But when both monsters look at the counter direction , then both monsters will look or land in square which don't have monster so my collision believes there is no monster and then the monsters will overlap each other. (checking a monster -1 and monster +1 doesn't help much). The collision works with monster and static object. Click here! to downlaod game demo to see how the monsters overlapping The solution is to provide a radial checking distance for each monster which it uses when checking the grid cells instead. My game moves in squares so I don't know if radial checking will help because if I check in a radius of distance between squares , I have and other obstacles , like the walls or the environment , which need the monster to check too , not the other monster , but if there is any closed door or any them moving or static object. (Spells , decoration). I use a similarity of distance checking (Look the square in front) Example: if Monsters[Party.level,All_monsters].y-1 = Monsters[Party.level,All_monsters-1].y If the current monster in all_monsters loop position Y - 1 is equal with the Y of the all_monsters - 1 loop count.(The previous one) and loop +1 for the next one. This method is buggy when I want to turn my monster and if the space is small , for example narrow corridors or a lots of monsters coalition. in small rooms , if for example one small room with for squares have 3 monsters , the monsters when they try to turn or check all of those other monsters they will loose their collision and will continue to walk and then overlap. If you can translate your idea with code? It gets complex when you introduce monsters that are larger than a grid cell however. There is no problem here , none of my monsters are larger than a grid cell , all monsters occupies only one cell (Square) everything fits in one square no larger. So present your idea you are welcome. |
| ||
Im not at a pc at the moment (on holidays by the beach) - but im sure there is something similar in the code archives....I seem to remember an entry with keywords "shifted grid collisions". Re radial distance - I was implying use it in conjunction with the grid. |
| ||
I found one nice code which calculate the distance between to points.Function Monster_Distance:Int(x0:Int, y0:Int, x1:Int, y1:Int) Local dx:Int = x0 - x1 Local dy:Int = y0 - y1 Return Sqr(dx * dx + dy * dy) End Function Global m_dist_previous:Byte[101] Global m_dist_next:Byte[101] for all_monsters=1 to 100 m_dist_previous[All_Monsters]= Monster_Distance(Monster[Party.Level, All_Monsters].X, Monster[Party.Level, All_Monsters].Y, Monster[Party.Level, All_Monsters - 1].X, Monster[Party.Level, All_Monsters - 1].Y) m_dist_next[All_Monsters]= Monster_Distance(Monster[Party.Level, All_Monsters].X, Monster[Party.Level, All_Monsters].Y, Monster[Party.Level, All_Monsters + 1].X, Monster[Party.Level, All_Monsters + 1].Y) next This code calculates the distance in squares between my next and previous but I don't know exactly how to calculate the next and previous. This is an illustration. I am near to the solution |
| ||
I am very near. The monsters stops when the distance between monsters is 1 But the problem is they remain stopped because when 2 monsters are near to each other they have always the distance 1 and the monster remains stopped. So it needs to check if there is another monster in front of the monster regardless the collision. My previous function. |
| ||
After I made a lots of test and I recreated my whole AI code more than 7 times , then it still doesn't work. When 2 monsters simultaneously try to take advance in the same square , the monster overlaps each other again. The distance code doesn't help much. If you have some idea how to avoid each monster arrive in the same X and Y position. Before each monster arrive in the next square , there is a smooth transition , I described it in the first post. But when 2 or more monsters are in transition progress from 4 different directions they are going to occupy the same square again. I thought ,not use smooth transition between monster moves , but then the monster will move convulsive or skip frames between squares , like to move a piece on chess. In worst case if I will not achieve it , I will use the convulsive monster movement like chess. If you have some idea , I will describe you what I want to do exactly. |
| ||
If you have tried several different ways and still no joy, then I would suggest putting the code you are working on 'to bed' - and do a brand new simple project just to get this issue sorted. So, taking that approach you can throw away all complex code and focus on the problem: * square tile based map * tiles (an int)are either free (floor)(0) or not free (wall, door)(1) * monsters that man move on the map (this is a list or array?) draw it to screen Assuming the monster are an array of 10 and are at unique map positions that are free - their starting positions draw them (in a different colour) to the map * get a primitive ai working that treat anything above 0 at a wall and get them to move **** avoidance **** * in the monster update (the move routine) a monster will either be on a tile, or on 2 tiles - so reflect this in your map. make the tile(or tiles) 2 * as we now have the map updated, when you move the monster it will leave a trail where other monster can go (because the map is above 0 - it will also block the source monster too) * so when you update each monster - remove the previous 2 (or 2 2s) from the map Not sure if i'm clear here? But give it a go |
| ||
I made one prototype and it seems worked. Whole code of the prototype all monsters are moving and none of them overlap. AdamStrange you gave me a good idea and I changed whole monster AI functions and it worked. The code: SuperStrict 'Eye of the Beholder IV - monster AI prototype Import brl.bank Import pub.zlib Import brl.filesystem Import brl.standardio Import brl.bankstream Import brl.filesystem Import BRL.Retro Import klepto.klpacker Import maxgui.drivers Import brl.Audio Import brl.Map Import brl.FreeTypeFont Import brl.PNGLoader Import brl.timer Import brl.eventqueue Import brl.textstream Import brl.oggloader Import brl.wavloader Import brl.jpgloader Import brl.bmploader Import brl.stream Global map_grid:TImage Global spider_icon_n:TImage Global spider_icon_s:TImage Global spider_icon_w:TImage Global spider_icon_e:TImage Global ghost_icon_n:TImage Global ghost_icon_s:TImage Global ghost_icon_w:TImage Global ghost_icon_e:TImage Global locked_square:TImage Global Current_time:Int Global Game_Loaded:Byte Const Max_Monsters:Byte = 100 Const Max_Levels:Byte = 51 '(+1 for developer mechanics) Global All_Monsters:Byte Global LVL:Byte 'Global Monster_Table:Byte[52, 39, 38] Global Monster_Table:Int[52, 21, 21] Global MTable_x:Int Global MTable_y:Int Type My_Monster Field X:Byte 'position X on the map Field Y:Byte 'position Y on the map Field Direction:Byte 'The direction the monster goes Field Graphic:String 'the graphic of the monster "01"=Skeleton Field State:Byte '1=Walk 2=Attack 3=Guard 4=Patrol Field Walking:Byte Field Square_transition_frame:Int Field Deadline_time:Int 'Timer Delay Field Time_delay:Int 'animation speed Field Not_Allow_to_move:Byte Field square_locked:Byte Field Choose_Direction:Byte Field Steps:Byte End Type Global Monster:My_Monster[max_levels + 1, Max_Monsters + 1] For LVL = 1 To Max_Levels For All_Monsters = 0 To Max_Monsters Monster[LVL, All_Monsters] = New My_Monster Next Next Type My_Party Field x:Byte Field y:Byte Field Level:Byte Field Level_temp:Byte Field Direction:Byte Field Mana_Points:Float Field Max_Mana_Points:Float Field Mana_Percentage:Float Field Collision:Byte Field Immobilized:Byte Field Dest_Level:Byte EndType Global Party:My_Party = New My_Party 'Windowed ====================== 'Global graph:TGraphics = Graphics(640, 480, 0, 120) 'Full Global graph:TGraphics = Graphics(640, 480, 32, 120, 0) SetMaskColor(255, 0, 255) 'SetBlend(MASKBLEND) SetBlend(ALPHABLEND | MASKBLEND) Load_Data() While Not AppTerminate() Current_time = MilliSecs() If Game_Loaded = 0 Then Load_Data() Draw_Interface() If KeyHit(KEY_ESCAPE) Then Ending() Flip -1 'Windows 8 - Flip 1 Wend Function Ending() End End Function Function Draw_Interface() Monster_Mechanics() Draw_Game() Keyboard_commands() DrawText "Current Time:" + String(Current_time), 350, 10 DrawText "M1 Deadline time:" + String(Monster[1, 1].Deadline_time), 350, 20 DrawText "M1 X:" + String(Monster[1, 1].X), 350, 40 DrawText "M1 Y:" + String(Monster[1, 1].Y), 350, 50 DrawText "M1 STF:" + String(Monster[1, 1].Square_transition_frame), 350, 60 DrawText "M1 Walking:" + String(Monster[1, 1].Walking), 350, 70 End Function Function Load_Data() 'skel_icon = LoadImage("skel_icon.png", MASKEDIMAGE) ghost_icon_n = LoadImage("ghost_icon_n.png", MASKEDIMAGE) ghost_icon_s = LoadImage("ghost_icon_s.png", MASKEDIMAGE) ghost_icon_w = LoadImage("ghost_icon_w.png", MASKEDIMAGE) ghost_icon_e = LoadImage("ghost_icon_e.png", MASKEDIMAGE) spider_icon_n = LoadImage("spider_icon_n.png", MASKEDIMAGE) spider_icon_s = LoadImage("spider_icon_s.png", MASKEDIMAGE) spider_icon_w = LoadImage("spider_icon_w.png", MASKEDIMAGE) spider_icon_e = LoadImage("spider_icon_e.png", MASKEDIMAGE) locked_square = LoadImage("locked_square.png", MASKEDIMAGE) map_grid = LoadImage("Map_grid.png", MASKEDIMAGE) Inits() 'Delay(2000) Game_Loaded = 1 End Function Function Monster_Mechanics() For All_Monsters = 1 To Max_Monsters If Monster[Party.Level, All_Monsters].Direction = 1 Then If Monster[Party.Level, All_Monsters].Square_transition_frame = 0 Then Monster_Table[Party.Level, Monster[Party.Level, All_Monsters].X, Monster[Party.Level, All_Monsters].Y + 1] = 0 Monster_Table[Party.Level, Monster[Party.Level, All_Monsters].X, Monster[Party.Level, All_Monsters].Y] = 1 Monster[Party.Level, All_Monsters].Not_Allow_to_move = 1 'Monster[Party.Level, All_Monsters].square_locked = 0 End If If Monster[Party.Level, All_Monsters].Square_transition_frame > 0 Then Monster_Table[Party.Level, Monster[Party.Level, All_Monsters].X, Monster[Party.Level, All_Monsters].Y] = 2 Monster_Table[Party.Level, Monster[Party.Level, All_Monsters].X, Monster[Party.Level, All_Monsters].Y - 1] = 2 Monster[Party.Level, All_Monsters].Not_Allow_to_move = 0 End If EndIf If Monster[Party.Level, All_Monsters].Direction = 2 Then If Monster[Party.Level, All_Monsters].Square_transition_frame = 0 Then Monster_Table[Party.Level, Monster[Party.Level, All_Monsters].X, Monster[Party.Level, All_Monsters].Y - 1] = 0 Monster_Table[Party.Level, Monster[Party.Level, All_Monsters].X, Monster[Party.Level, All_Monsters].Y] = 1 Monster[Party.Level, All_Monsters].Not_Allow_to_move = 1 'Monster[Party.Level, All_Monsters].square_locked = 0 End If If Monster[Party.Level, All_Monsters].Square_transition_frame > 0 Then Monster_Table[Party.Level, Monster[Party.Level, All_Monsters].X, Monster[Party.Level, All_Monsters].Y] = 2 Monster_Table[Party.Level, Monster[Party.Level, All_Monsters].X, Monster[Party.Level, All_Monsters].Y + 1] = 2 Monster[Party.Level, All_Monsters].Not_Allow_to_move = 0 End If EndIf If Monster[Party.Level, All_Monsters].Direction = 3 Then If Monster[Party.Level, All_Monsters].Square_transition_frame = 0 Then Monster_Table[Party.Level, Monster[Party.Level, All_Monsters].X + 1, Monster[Party.Level, All_Monsters].Y] = 0 Monster_Table[Party.Level, Monster[Party.Level, All_Monsters].X, Monster[Party.Level, All_Monsters].Y] = 1 Monster[Party.Level, All_Monsters].Not_Allow_to_move = 1 'Monster[Party.Level, All_Monsters].square_locked = 0 End If If Monster[Party.Level, All_Monsters].Square_transition_frame > 0 Then Monster_Table[Party.Level, Monster[Party.Level, All_Monsters].X, Monster[Party.Level, All_Monsters].Y] = 2 Monster_Table[Party.Level, Monster[Party.Level, All_Monsters].X - 1, Monster[Party.Level, All_Monsters].Y] = 2 Monster[Party.Level, All_Monsters].Not_Allow_to_move = 0 End If EndIf If Monster[Party.Level, All_Monsters].Direction = 4 Then If Monster[Party.Level, All_Monsters].Square_transition_frame = 0 Then Monster_Table[Party.Level, Monster[Party.Level, All_Monsters].X - 1, Monster[Party.Level, All_Monsters].Y] = 0 Monster_Table[Party.Level, Monster[Party.Level, All_Monsters].X, Monster[Party.Level, All_Monsters].Y] = 1 Monster[Party.Level, All_Monsters].Not_Allow_to_move = 1 'Monster[Party.Level, All_Monsters].square_locked = 0 End If If Monster[Party.Level, All_Monsters].Square_transition_frame > 0 Then Monster_Table[Party.Level, Monster[Party.Level, All_Monsters].X, Monster[Party.Level, All_Monsters].Y] = 2 Monster_Table[Party.Level, Monster[Party.Level, All_Monsters].X + 1, Monster[Party.Level, All_Monsters].Y] = 2 Monster[Party.Level, All_Monsters].Not_Allow_to_move = 0 End If EndIf If Current_time >= Monster[Party.Level, All_Monsters].Deadline_time Then Monster[Party.Level, All_Monsters].Time_Delay = 500 Monster[Party.Level, All_Monsters].Deadline_time = Current_time + Monster[Party.Level, All_Monsters].Time_Delay If Monster[Party.Level, All_Monsters].X = 0 And Monster[Party.Level, All_Monsters].Y = 0 Then Continue If Monster[Party.Level, All_Monsters].X > 0 And Monster[Party.Level, All_Monsters].Y > 0 Then If Monster[Party.Level, All_Monsters].Square_transition_frame = 0 Then Monster[Party.Level, All_Monsters].Steps:+1 If Monster[Party.Level, All_Monsters].Steps > Rand(5, 9) Then Monster[Party.Level, All_Monsters].Steps = 0 If Monster[Party.Level, All_Monsters].Walking = 0 Then Monster[Party.Level, All_Monsters].Walking = 1 If Monster[Party.Level, All_Monsters].Direction = 1 Monster[Party.Level, All_Monsters].choose_direction = Rand(1, 2) If Monster[Party.Level, All_Monsters].choose_direction = 1 Then Monster[Party.Level, All_Monsters].Direction = 3 Return If Monster[Party.Level, All_Monsters].choose_direction = 2 Then Monster[Party.Level, All_Monsters].Direction = 4 Return EndIf If Monster[Party.Level, All_Monsters].Direction = 2 Monster[Party.Level, All_Monsters].choose_direction = Rand(1, 2) If Monster[Party.Level, All_Monsters].choose_direction = 1 Then Monster[Party.Level, All_Monsters].Direction = 4 Return If Monster[Party.Level, All_Monsters].choose_direction = 2 Then Monster[Party.Level, All_Monsters].Direction = 3 Return EndIf If Monster[Party.Level, All_Monsters].Direction = 3 Monster[Party.Level, All_Monsters].choose_direction = Rand(1, 2) If Monster[Party.Level, All_Monsters].choose_direction = 1 Then Monster[Party.Level, All_Monsters].Direction = 1 Return If Monster[Party.Level, All_Monsters].choose_direction = 2 Then Monster[Party.Level, All_Monsters].Direction = 2 Return EndIf If Monster[Party.Level, All_Monsters].Direction = 4 Monster[Party.Level, All_Monsters].choose_direction = Rand(1, 2) If Monster[Party.Level, All_Monsters].choose_direction = 1 Then Monster[Party.Level, All_Monsters].Direction = 2 Return If Monster[Party.Level, All_Monsters].choose_direction = 2 Then Monster[Party.Level, All_Monsters].Direction = 1 Return EndIf EndIf EndIf If Monster[Party.Level, All_Monsters].Walking = 1 Then 'Monster goes NORTH If Monster[Party.Level, All_Monsters].Direction = 1 'The monster is on the first row If Monster[Party.Level, All_Monsters].Y = 1 Then Monster[Party.Level, All_Monsters].choose_direction = Rand(1, 2) If Monster[Party.Level, All_Monsters].choose_direction = 1 Then Monster[Party.Level, All_Monsters].Direction = 3 Return If Monster[Party.Level, All_Monsters].choose_direction = 2 Then Monster[Party.Level, All_Monsters].Direction = 4 Return EndIf 'If the monster found other monster in front If Monster_Table[Party.Level, Monster[Party.Level, All_Monsters].X, Monster[Party.Level, All_Monsters].Y - 1] <> 0 And Monster[Party.Level, All_Monsters].Not_Allow_to_move = 1 Then Monster[Party.Level, All_Monsters].choose_direction = Rand(1, 2) If Monster[Party.Level, All_Monsters].choose_direction = 1 Then Monster[Party.Level, All_Monsters].Direction = 3 Return If Monster[Party.Level, All_Monsters].choose_direction = 2 Then Monster[Party.Level, All_Monsters].Direction = 4 Return EndIf Monster[Party.Level, All_Monsters].Square_transition_frame:+1 If Monster[Party.Level, All_Monsters].Square_transition_frame > 3 Then Monster[Party.Level, All_Monsters].Square_transition_frame = 0 Monster[Party.Level, All_Monsters].Y:-1 EndIf EndIf 'Monster goes SOUTH If Monster[Party.Level, All_Monsters].Direction = 2 'The monster is on the last row If Monster[Party.Level, All_Monsters].Y = 20 Then Monster[Party.Level, All_Monsters].choose_direction = Rand(1, 2) If Monster[Party.Level, All_Monsters].choose_direction = 1 Then Monster[Party.Level, All_Monsters].Direction = 4 Return If Monster[Party.Level, All_Monsters].choose_direction = 2 Then Monster[Party.Level, All_Monsters].Direction = 3 Return EndIf 'If the monster found other monster in front If Monster_Table[Party.Level, Monster[Party.Level, All_Monsters].X, Monster[Party.Level, All_Monsters].Y + 1] <> 0 And Monster[Party.Level, All_Monsters].Not_Allow_to_move = 1 Then Monster[Party.Level, All_Monsters].choose_direction = Rand(1, 2) If Monster[Party.Level, All_Monsters].choose_direction = 1 Then Monster[Party.Level, All_Monsters].Direction = 4 Return If Monster[Party.Level, All_Monsters].choose_direction = 2 Then Monster[Party.Level, All_Monsters].Direction = 3 Return EndIf Monster[Party.Level, All_Monsters].Square_transition_frame:+1 If Monster[Party.Level, All_Monsters].Square_transition_frame > 3 Then Monster[Party.Level, All_Monsters].Square_transition_frame = 0 Monster[Party.Level, All_Monsters].Y:+1 EndIf EndIf 'Monster goes WEST If Monster[Party.Level, All_Monsters].Direction = 3 'The monster is on the first column If Monster[Party.Level, All_Monsters].X = 1 Then Monster[Party.Level, All_Monsters].choose_direction = Rand(1, 2) If Monster[Party.Level, All_Monsters].choose_direction = 1 Then Monster[Party.Level, All_Monsters].Direction = 1 Return If Monster[Party.Level, All_Monsters].choose_direction = 2 Then Monster[Party.Level, All_Monsters].Direction = 2 Return EndIf 'If the monster found other monster in front If Monster_Table[Party.Level, Monster[Party.Level, All_Monsters].X - 1, Monster[Party.Level, All_Monsters].Y] <> 0 And Monster[Party.Level, All_Monsters].Not_Allow_to_move = 1 Then Monster[Party.Level, All_Monsters].choose_direction = Rand(1, 2) If Monster[Party.Level, All_Monsters].choose_direction = 1 Then Monster[Party.Level, All_Monsters].Direction = 1 Return If Monster[Party.Level, All_Monsters].choose_direction = 2 Then Monster[Party.Level, All_Monsters].Direction = 2 Return EndIf Monster[Party.Level, All_Monsters].Square_transition_frame:+1 If Monster[Party.Level, All_Monsters].Square_transition_frame > 3 Then Monster[Party.Level, All_Monsters].Square_transition_frame = 0 Monster[Party.Level, All_Monsters].X:-1 EndIf EndIf 'Monster goes EAST If Monster[Party.Level, All_Monsters].Direction = 4 'The monster is on the last column If Monster[Party.Level, All_Monsters].X = 20 Then Monster[Party.Level, All_Monsters].choose_direction = Rand(1, 2) If Monster[Party.Level, All_Monsters].choose_direction = 1 Then Monster[Party.Level, All_Monsters].Direction = 2 Return If Monster[Party.Level, All_Monsters].choose_direction = 2 Then Monster[Party.Level, All_Monsters].Direction = 1 Return EndIf 'If the monster found other monster in front If Monster_Table[Party.Level, Monster[Party.Level, All_Monsters].X + 1, Monster[Party.Level, All_Monsters].Y] <> 0 And Monster[Party.Level, All_Monsters].Not_Allow_to_move = 1 Then Monster[Party.Level, All_Monsters].choose_direction = Rand(1, 2) If Monster[Party.Level, All_Monsters].choose_direction = 1 Then Monster[Party.Level, All_Monsters].Direction = 2 Return If Monster[Party.Level, All_Monsters].choose_direction = 2 Then Monster[Party.Level, All_Monsters].Direction = 1 Return EndIf Monster[Party.Level, All_Monsters].Square_transition_frame:+1 If Monster[Party.Level, All_Monsters].Square_transition_frame > 3 Then Monster[Party.Level, All_Monsters].Square_transition_frame = 0 Monster[Party.Level, All_Monsters].X:+1 EndIf EndIf EndIf 'If the monster is walking If Monster[Party.Level, All_Monsters].Walking = 0 Then 'Monster[Party.Level, All_Monsters].Walking = 1 EndIf EndIf 'end of monsters XY > 0 EndIf 'End of monster deadline time If Monster[Party.Level, All_Monsters].X <= 1 Then Monster[Party.Level, All_Monsters].X = 1 If Monster[Party.Level, All_Monsters].X >= 20 Then Monster[Party.Level, All_Monsters].X = 20 If Monster[Party.Level, All_Monsters].Y <= 1 Then Monster[Party.Level, All_Monsters].Y = 1 If Monster[Party.Level, All_Monsters].Y >= 20 Then Monster[Party.Level, All_Monsters].Y = 20 Next End Function Function Draw_Game() SetColor(0, 0, 0) DrawRect(0, 0, 640, 480) SetColor(255, 255, 255) For MTable_y = 1 To 20 For MTable_x = 1 To 20 If Monster_Table[Party.Level, MTable_x, MTable_y] = 2 Then DrawImage(locked_square, -16 + (MTable_x * 16), -16 + (MTable_y * 16), 0) Next Next For All_Monsters = 1 To Max_Monsters If Monster[Party.Level, All_Monsters].X <= 0 And Monster[Party.Level, All_Monsters].Y <= 0 Then Continue If Monster[Party.Level, All_Monsters].X > 0 And Monster[Party.Level, All_Monsters].Y > 0 Then If Monster[Party.Level, All_Monsters].Direction = 1 Then If Monster[Party.Level, All_Monsters].Graphic = "01" Then If Monster[Party.Level, All_Monsters].Square_transition_frame = 3 Then DrawImage(spider_icon_n, -16 + (Monster[Party.Level, All_Monsters].X * 16), -16 + (Monster[Party.Level, All_Monsters].Y * 16) - 12, 0) If Monster[Party.Level, All_Monsters].Square_transition_frame = 2 Then DrawImage(spider_icon_n, -16 + (Monster[Party.Level, All_Monsters].X * 16), -16 + (Monster[Party.Level, All_Monsters].Y * 16) - 8, 0) If Monster[Party.Level, All_Monsters].Square_transition_frame = 1 Then DrawImage(spider_icon_n, -16 + (Monster[Party.Level, All_Monsters].X * 16), -16 + (Monster[Party.Level, All_Monsters].Y * 16) - 4, 0) If Monster[Party.Level, All_Monsters].Square_transition_frame = 0 Then DrawImage(spider_icon_n, -16 + (Monster[Party.Level, All_Monsters].X * 16), -16 + (Monster[Party.Level, All_Monsters].Y * 16), 0) EndIf If Monster[Party.Level, All_Monsters].Graphic = "02" Then If Monster[Party.Level, All_Monsters].Square_transition_frame = 3 Then DrawImage(ghost_icon_n, -16 + (Monster[Party.Level, All_Monsters].X * 16), -16 + (Monster[Party.Level, All_Monsters].Y * 16) - 12, 0) If Monster[Party.Level, All_Monsters].Square_transition_frame = 2 Then DrawImage(ghost_icon_n, -16 + (Monster[Party.Level, All_Monsters].X * 16), -16 + (Monster[Party.Level, All_Monsters].Y * 16) - 8, 0) If Monster[Party.Level, All_Monsters].Square_transition_frame = 1 Then DrawImage(ghost_icon_n, -16 + (Monster[Party.Level, All_Monsters].X * 16), -16 + (Monster[Party.Level, All_Monsters].Y * 16) - 4, 0) If Monster[Party.Level, All_Monsters].Square_transition_frame = 0 Then DrawImage(ghost_icon_n, -16 + (Monster[Party.Level, All_Monsters].X * 16), -16 + (Monster[Party.Level, All_Monsters].Y * 16), 0) EndIf End If If Monster[Party.Level, All_Monsters].Direction = 2 Then If Monster[Party.Level, All_Monsters].Graphic = "01" Then If Monster[Party.Level, All_Monsters].Square_transition_frame = 3 Then DrawImage(spider_icon_s, -16 + (Monster[Party.Level, All_Monsters].X * 16), -16 + (Monster[Party.Level, All_Monsters].Y * 16) + 12, 0) If Monster[Party.Level, All_Monsters].Square_transition_frame = 2 Then DrawImage(spider_icon_s, -16 + (Monster[Party.Level, All_Monsters].X * 16), -16 + (Monster[Party.Level, All_Monsters].Y * 16) + 8, 0) If Monster[Party.Level, All_Monsters].Square_transition_frame = 1 Then DrawImage(spider_icon_s, -16 + (Monster[Party.Level, All_Monsters].X * 16), -16 + (Monster[Party.Level, All_Monsters].Y * 16) + 4, 0) If Monster[Party.Level, All_Monsters].Square_transition_frame = 0 Then DrawImage(spider_icon_s, -16 + (Monster[Party.Level, All_Monsters].X * 16), -16 + (Monster[Party.Level, All_Monsters].Y * 16), 0) EndIf If Monster[Party.Level, All_Monsters].Graphic = "02" Then If Monster[Party.Level, All_Monsters].Square_transition_frame = 3 Then DrawImage(ghost_icon_s, -16 + (Monster[Party.Level, All_Monsters].X * 16), -16 + (Monster[Party.Level, All_Monsters].Y * 16) + 12, 0) If Monster[Party.Level, All_Monsters].Square_transition_frame = 2 Then DrawImage(ghost_icon_s, -16 + (Monster[Party.Level, All_Monsters].X * 16), -16 + (Monster[Party.Level, All_Monsters].Y * 16) + 8, 0) If Monster[Party.Level, All_Monsters].Square_transition_frame = 1 Then DrawImage(ghost_icon_s, -16 + (Monster[Party.Level, All_Monsters].X * 16), -16 + (Monster[Party.Level, All_Monsters].Y * 16) + 4, 0) If Monster[Party.Level, All_Monsters].Square_transition_frame = 0 Then DrawImage(ghost_icon_s, -16 + (Monster[Party.Level, All_Monsters].X * 16), -16 + (Monster[Party.Level, All_Monsters].Y * 16), 0) EndIf End If If Monster[Party.Level, All_Monsters].Direction = 3 Then If Monster[Party.Level, All_Monsters].Graphic = "01" Then If Monster[Party.Level, All_Monsters].Square_transition_frame = 3 Then DrawImage(spider_icon_w, -16 + (Monster[Party.Level, All_Monsters].X * 16) - 12, -16 + (Monster[Party.Level, All_Monsters].Y * 16) , 0) If Monster[Party.Level, All_Monsters].Square_transition_frame = 2 Then DrawImage(spider_icon_w, -16 + (Monster[Party.Level, All_Monsters].X * 16) - 8, -16 + (Monster[Party.Level, All_Monsters].Y * 16) , 0) If Monster[Party.Level, All_Monsters].Square_transition_frame = 1 Then DrawImage(spider_icon_w, -16 + (Monster[Party.Level, All_Monsters].X * 16) - 4, -16 + (Monster[Party.Level, All_Monsters].Y * 16) , 0) If Monster[Party.Level, All_Monsters].Square_transition_frame = 0 Then DrawImage(spider_icon_w, -16 + (Monster[Party.Level, All_Monsters].X * 16), -16 + (Monster[Party.Level, All_Monsters].Y * 16), 0) EndIf If Monster[Party.Level, All_Monsters].Graphic = "02" Then If Monster[Party.Level, All_Monsters].Square_transition_frame = 3 Then DrawImage(ghost_icon_w, -16 + (Monster[Party.Level, All_Monsters].X * 16) - 12, -16 + (Monster[Party.Level, All_Monsters].Y * 16) , 0) If Monster[Party.Level, All_Monsters].Square_transition_frame = 2 Then DrawImage(ghost_icon_w, -16 + (Monster[Party.Level, All_Monsters].X * 16) - 8, -16 + (Monster[Party.Level, All_Monsters].Y * 16) , 0) If Monster[Party.Level, All_Monsters].Square_transition_frame = 1 Then DrawImage(ghost_icon_w, -16 + (Monster[Party.Level, All_Monsters].X * 16) - 4, -16 + (Monster[Party.Level, All_Monsters].Y * 16) , 0) If Monster[Party.Level, All_Monsters].Square_transition_frame = 0 Then DrawImage(ghost_icon_w, -16 + (Monster[Party.Level, All_Monsters].X * 16), -16 + (Monster[Party.Level, All_Monsters].Y * 16), 0) EndIf End If If Monster[Party.Level, All_Monsters].Direction = 4 Then If Monster[Party.Level, All_Monsters].Graphic = "01" Then If Monster[Party.Level, All_Monsters].Square_transition_frame = 3 Then DrawImage(spider_icon_e, -16 + (Monster[Party.Level, All_Monsters].X * 16) + 12, -16 + (Monster[Party.Level, All_Monsters].Y * 16) , 0) If Monster[Party.Level, All_Monsters].Square_transition_frame = 2 Then DrawImage(spider_icon_e, -16 + (Monster[Party.Level, All_Monsters].X * 16) + 8, -16 + (Monster[Party.Level, All_Monsters].Y * 16) , 0) If Monster[Party.Level, All_Monsters].Square_transition_frame = 1 Then DrawImage(spider_icon_e, -16 + (Monster[Party.Level, All_Monsters].X * 16) + 4, -16 + (Monster[Party.Level, All_Monsters].Y * 16) , 0) If Monster[Party.Level, All_Monsters].Square_transition_frame = 0 Then DrawImage(spider_icon_e, -16 + (Monster[Party.Level, All_Monsters].X * 16), -16 + (Monster[Party.Level, All_Monsters].Y * 16), 0) EndIf If Monster[Party.Level, All_Monsters].Graphic = "02" Then If Monster[Party.Level, All_Monsters].Square_transition_frame = 3 Then DrawImage(ghost_icon_e, -16 + (Monster[Party.Level, All_Monsters].X * 16) + 12, -16 + (Monster[Party.Level, All_Monsters].Y * 16) , 0) If Monster[Party.Level, All_Monsters].Square_transition_frame = 2 Then DrawImage(ghost_icon_e, -16 + (Monster[Party.Level, All_Monsters].X * 16) + 8, -16 + (Monster[Party.Level, All_Monsters].Y * 16) , 0) If Monster[Party.Level, All_Monsters].Square_transition_frame = 1 Then DrawImage(ghost_icon_e, -16 + (Monster[Party.Level, All_Monsters].X * 16) + 4, -16 + (Monster[Party.Level, All_Monsters].Y * 16) , 0) If Monster[Party.Level, All_Monsters].Square_transition_frame = 0 Then DrawImage(ghost_icon_e, -16 + (Monster[Party.Level, All_Monsters].X * 16), -16 + (Monster[Party.Level, All_Monsters].Y * 16), 0) EndIf End If End If 'End of monster XY>0 Next DrawImage(map_grid, 0, 0, 0) End Function Function Inits() Local all_spiders:Byte For all_spiders = 1 To 30 Monster[1, all_spiders].X = Rand(1, 20) Monster[1, all_spiders].Y = Rand(1, 20) Monster[1, all_spiders].Graphic = "01" Monster[1, all_spiders].Direction = Rand(1, 4) Monster[1, all_spiders].Square_transition_frame = 0 Monster[1, all_spiders].Not_Allow_to_move = 0 Monster[1, all_spiders].Walking = 1 Next Monster[1, 1].X = 3 Monster[1, 1].Y = 7 Monster[1, 1].Graphic = "01" Monster[1, 1].Direction = 1 Monster[1, 1].Square_transition_frame = 0 Monster[1, 1].Not_Allow_to_move = 0 Monster[1, 1].Walking = 1 Monster[1, 2].X = 3 Monster[1, 2].Y = 4 Monster[1, 2].Graphic = "02" Monster[1, 2].Direction = 1 Monster[1, 2].Not_Allow_to_move = 0 Monster[1, 3].Walking = 0 Party.Level = 1 End Function Function Keyboard_commands() If KeyHit(KEY_W) Then If Monster[1, 2].Direction = 1 Then If Monster[1, 2].Y > 1 Then Monster[1, 2].Square_transition_frame:+1 EndIf If Monster[1, 2].Direction = 2 Then If Monster[1, 2].Y < 20 Then Monster[1, 2].Square_transition_frame:+1 EndIf If Monster[1, 2].Direction = 3 Then If Monster[1, 2].X > 1 Then Monster[1, 2].Square_transition_frame:+1 EndIf If Monster[1, 2].Direction = 4 Then If Monster[1, 2].X < 20 Then Monster[1, 2].Square_transition_frame:+1 EndIf If Monster[1, 2].Direction = 1 Then If Monster[1, 2].Square_transition_frame > 3 Then Monster[1, 2].Square_transition_frame = 0 Monster[1, 2].Y:-1 Return EndIf EndIf If Monster[1, 2].Direction = 2 Then If Monster[1, 2].Square_transition_frame > 3 Then Monster[1, 2].Square_transition_frame = 0 Monster[1, 2].Y:+1 Return EndIf EndIf If Monster[1, 2].Direction = 3 Then If Monster[1, 2].Square_transition_frame > 3 Then Monster[1, 2].Square_transition_frame = 0 Monster[1, 2].X:-1 Return EndIf EndIf If Monster[1, 2].Direction = 4 Then If Monster[1, 2].Square_transition_frame > 3 Then Monster[1, 2].Square_transition_frame = 0 Monster[1, 2].X:+1 Return EndIf EndIf EndIf If KeyHit(KEY_Q) Then If Monster[1, 2].Direction = 1 Then If Monster[1, 2].Square_transition_frame <> 0 Then Return Monster[1, 2].Direction = 3 Return EndIf If Monster[1, 2].Direction = 2 Then If Monster[1, 2].Square_transition_frame <> 0 Then Return Monster[1, 2].Direction = 4 Return EndIf If Monster[1, 2].Direction = 3 Then If Monster[1, 2].Square_transition_frame <> 0 Then Return Monster[1, 2].Direction = 2 Return EndIf If Monster[1, 2].Direction = 4 Then If Monster[1, 2].Square_transition_frame <> 0 Then Return Monster[1, 2].Direction = 1 Return EndIf EndIf If KeyHit(KEY_E) Then If Monster[1, 2].Direction = 1 Then If Monster[1, 2].Square_transition_frame <> 0 Then Return Monster[1, 2].Direction = 4 Return EndIf If Monster[1, 2].Direction = 2 Then If Monster[1, 2].Square_transition_frame <> 0 Then Return Monster[1, 2].Direction = 3 Return EndIf If Monster[1, 2].Direction = 3 Then If Monster[1, 2].Square_transition_frame <> 0 Then Return Monster[1, 2].Direction = 1 Return EndIf If Monster[1, 2].Direction = 4 Then If Monster[1, 2].Square_transition_frame <> 0 Then Return Monster[1, 2].Direction = 2 Return EndIf EndIf End Function The files you will need are here: Click for sprites So far so good for now , I will try to adopt this in my game. I will tell you what I managed. |
| ||
Glad youve managed to sort this out. |
| ||
Thank you , now I will adjust this code in the main game engine with new battle system. And when the next version will be finished I will show a demo. |
| ||
Excellent - Sometimes you need to either step away from the code, or come at it from a different view. starting a small project to deal with a single issue is a great way of clearing your mind :) |
| ||
My monsters now are perfect and my new code was updated in my game core engine. No overlaps and smarter Artificial Intelligence , now my monsters can open doors , avoid other obstacles do attacks... Everything goes very nice and now I am programming the battle system. |
| ||
It's great when it starts to come together :) |