I'm creating a Fire Emblem-like system in XP and having trouble displaying attack ranges as FE does. I've got the range showing up right:
http://img.photobucket.com/albums/v194/ ... _Thing.png[/img]
(First image is range displayed, second is base map for reference)
However, for characters with very long range attacks (Bolting, Purge, Eclipse) the method I created that checks for locations in range simply takes too long; at 3-10 range, it makes some 9000 extraneous checks for the 200 valid locations, taking about a second when it shouldn't drop the framerate. (At least somehow it doesn't in FE itself D: ) I'm hoping someone has a way to do this that's more efficient.
Also, for the reason it makes so many checks, look at the first image; it displays the attack range compared to every square the character can move to. So for a character that can move to some 40-70 squares, it has to check every square in range of all those locations.
http://img.photobucket.com/albums/v194/ ... _Thing.png[/img]
(First image is range displayed, second is base map for reference)
However, for characters with very long range attacks (Bolting, Purge, Eclipse) the method I created that checks for locations in range simply takes too long; at 3-10 range, it makes some 9000 extraneous checks for the 200 valid locations, taking about a second when it shouldn't drop the framerate. (At least somehow it doesn't in FE itself D: ) I'm hoping someone has a way to do this that's more efficient.
Also, for the reason it makes so many checks, look at the first image; it displays the attack range compared to every square the character can move to. So for a character that can move to some 40-70 squares, it has to check every square in range of all those locations.
Code:
move_range = []
#move_range is an array holding a list of locations in range of the character in [x,y] form
for i in @move_range
x = i[0]
y = i[1]
# Checks the current location to see if another event (will always be allied or neutral) is there already
blocked = false
for j in @events.values
if j.x == x and j.y == y and j.is_a_unit
blocked = true unless j.id == id
end
end
unless blocked
move_range.push(i)
end
end
for i in move_range
x = i[0]
y = i[1]
# Create the outer range
temp_range = []
# I had some reason for making this 1..max range and delete the ones too close later instead of
# min range.. max range, but I can't remember it right now. Either way that part doesn't slow it down
# much, but feel free to redo it in a rewrite if you feel it would be better
for range in 1..5#10 # reduced to 5 here since 10 covers 95% of the map
for i in (-1 * range)..range
xx = x + i
k = i.abs
for j in [(-1 * (range - k)),(range - k)]
yy = y + j
unless temp_range.include?([xx,yy])
temp_range.push([xx,yy])
#@l += 1 # recorded how many extra checks were being made
end
end
end
end
# Create an array of locations under the minimum
temp_range2 = []
for range in 1..2
for i in (-1 * range)..range
xx = x + i
k = i.abs
for j in [(-1 * (range - k)),(range - k)]
yy = y + j
unless temp_range2.include?([xx,yy])
temp_range2.push([xx,yy])
end
end
end
end
# Delete locations under minimum
for i in temp_range2
temp_range.delete(i)
end
# Add found locations to attack/staff range
# This is separate instead of writing to @attack/staff_range directly because they can have locations
# recorded into them separately for other ranges (1, 2, etc)
for i in temp_range
if staff
@staff_range.push(i) unless @staff_range.include?(i)
else
@attack_range.push(i) unless @attack_range.include?(i)
end
end
end