Good job finding this bug. There is definitely something wrong with the wall algorithm:
#--------------------------------------------------------------------------
# wall?
# char - the character
# x - x-coordinate
# y - y-coordinate
# Checks if between the char and the target is a "wall". Walls prevent
# perception.
#--------------------------------------------------------------------------
def wall?(char, x, y)
# abort instantly if not using this option
return false if Config::WALL_TAGS.size == 0
# get pixel movement rate
pix = $BlizzABS.pixel
# get coordinate difference
dx, dy = (x-char.x)/pix, (y-char.y)/pix
# if x difference is not 0 and x difference is greater
if dx != 0 && dx.abs > dy.abs
# return any wall tile between
return (0..dx.abs).any? {|i| Config::WALL_TAGS.include?($game_map.
terrain_tag(char.x/pix+dx.sgn*i, char.y/pix+(i.to_f*dy/dx).round))}
# if y difference is not 0 and y difference is greater
elsif dy != 0 && dy.abs > dx.abs
# return any wall tile between
return (0..dy.abs).any? {|i| Config::WALL_TAGS.include?($game_map.
terrain_tag(char.x/pix+(i.to_f*dx/dy).round, char.y/pix+dy.sgn*i))}
end
# no wall between
return false
end
For the bottom right corner in your demo, the (dx, dy) is (3, 3). Because dx == dy, the two if-statements are ignored, and the method returns false.
For the bottom left area, we're running through this part of the method:
# return any wall tile between
return (0..dx.abs).any? {|i| Config::WALL_TAGS.include?($game_map.
terrain_tag(char.x/pix+dx.sgn*i, char.y/pix+(i.to_f*dy/dx).round))}
The problem is that, as the loop iterates, it is checking the tile to the left and
UP, starting from the enemy's position.
Your event is at (9, 7). When i = 1, it checks if tile (8, 6) is a wall, which it isn't. It should be checking (8, 8 ) instead.
Not currently in a position to fix it, but letting you know why it's behaving that way.
replacing the method with this one should fix it, but I haven't tested it
#--------------------------------------------------------------------------
# wall?
# char - the character
# x - x-coordinate
# y - y-coordinate
# Checks if between the char and the target is a "wall". Walls prevent
# perception.
#--------------------------------------------------------------------------
def wall?(char, x, y)
# abort instantly if not using this option
return false if Config::WALL_TAGS.size == 0
# get pixel movement rate
pix = $BlizzABS.pixel
# get coordinate difference
dx, dy = (x-char.x)/pix, (y-char.y)/pix
# if x difference is not 0 and x difference is greater
if dx != 0 && dx.abs >= dy.abs
# return any wall tile between
return (0..dx.abs).any? {|i| Config::WALL_TAGS.include?($game_map.
terrain_tag(char.x/pix+dx.sgn*i, char.y/pix+(i.to_f*dy/dx.abs).round))}
# if y difference is not 0 and y difference is greater
elsif dy != 0 && dy.abs > dx.abs
# return any wall tile between
return (0..dy.abs).any? {|i| Config::WALL_TAGS.include?($game_map.
terrain_tag(char.x/pix+(i.to_f*dx/dy.abs).round, char.y/pix+dy.sgn*i))}
end
# no wall between
return false
end
I made the first if block use >= instead of >, and then for the slopes used the absolute value of the denominator so that the signs would match correctly.
Thanks for the response. I replaced the method with the code you posted and it works fine so far- enemies are not detecting the player on the sections of grass any more.
My plan is to implement this new method into my game and test it more thoroughly over the next couple of days before marking this issue as resolved.