Project1
标题:
求一个SLG,大十字,米字,直线 等范围的算法,有知道么
[打印本页]
作者:
66rpg学习
时间:
2009-4-26 06:17
提示:
作者被禁止或删除 内容自动屏蔽
作者:
sjzzjl
时间:
2009-4-26 06:30
详细点哦
作者:
66rpg学习
时间:
2009-4-27 21:38
提示:
作者被禁止或删除 内容自动屏蔽
作者:
叶子
时间:
2009-4-27 21:47
#==============================================================================
# ■ Grids
#------------------------------------------------------------------------------
# 获得各种范围的模块。
#==============================================================================
module Grids
#==========================================================================
# ■ 目标范围算法
#==========================================================================
# 图例解析
# ■ 范围格子
# ● 范围格子&确定格子
# ○ 确定格子
# ◎ 战斗者位置
#--------------------------------------------------------------------------
# ● 获得菱形范围
# range为2的范围
# □□□□□
# □□■□□
# □■●■□
# □□■□□
# □□□□□
#--------------------------------------------------------------------------
def self.get_diamond_grids(grid, range)
# 射程小于等于0的话,返回空数组
if range <= 0
return []
end
# 初始化范围格集合
available_grids = get_squar_grids(grid, range)
for each_grid in available_grids.clone
if each_grid.distance(grid) >= range
available_grids.delete(each_grid)
end
end
# 添加菱形上半部分及平行部分
#for line in 1..(range)
# width = line * 2 - 1
# grid_y = grid.y + range - line + 1
# for grid_x in (grid.x - line + 1)..(grid.x + line - 1)
# # 防止生成地图外格子
# next if !$game_map.valid?(grid_x, grid_y)
# distance = (grid.x - grid_x).abs + (grid.y - grid_y).abs
# available_grids.push Grid.new(grid_x, grid_y, distance)
# end
#end
# 添加菱形下半部分
#for line in 1..(range - 1)
# width = line * 2 - 1
# grid_y = grid.y - (range - line + 1)
# for grid_x in (grid.x - line + 1)..(grid.x + line - 1)
# # 防止生成地图外格子
# next if !$game_map.valid?(grid_x, grid_y)
# distance = (grid.x - grid_x).abs + (grid.y - grid_y).abs
# available_grids.push Grid.new(grid_x, grid_y, distance)
# end
#end
return available_grids
end
#--------------------------------------------------------------------------
# ● 获得正方形范围
# range为2的范围
# □□□□□
# □■■■□
# □■●■□
# □■■■□
# □□□□□
#--------------------------------------------------------------------------
def self.get_squar_grids(grid, range, valid = true)
# 射程小于等于0的话,返回空数组
if range <= 0
return []
end
available_grids = []
for x in (grid.x - range)..(grid.x + range)
for y in (grid.y - range)..(grid.y + range)
# 防止生成地图外格子
if !$game_map.valid?(grid.x, grid.y) and valid
next
end
distance = (grid.x - x).abs + (grid.y - y).abs
available_grids.push Grid.new(x, y, distance)
end
end
return available_grids
end
#--------------------------------------------------------------------------
# ● 获得直线范围
# range为2的范围
# □□□□
# ■●◎□
# □□□□
#--------------------------------------------------------------------------
def self.get_linear_grids(battler_grid, target_grid, range)
# 射程小于等于0的话,返回空数组
if range <= 0 or target_grid.distance(battler_grid) == 0
return []
end
# 初始化范围格集合
available_grids = []
# 获得战斗者格子与目标格子的直线函数
funtion = Math.get_2_grids_function(battler_grid, target_grid)
a = funtion[0]
b = funtion[1]
c = funtion[2]
# 取得正方形范围
squar_grids = self.get_squar_grids(target_grid, range, false)
# 排序
squar_grids = self.sort_grids(squar_grids)
# 循环正方形范围,如果直线过格子,并且格子不和战斗者格子在同一方向的话,添加
number = 0
for grid in squar_grids
# 只添加range个格子
if number >= range
break
end
if Math.overlap?(a, b, c, grid) and !Math.grids_same_side?(target_grid, battler_grid, grid)
number += 1
if $game_map.valid?(grid.x, grid.y)
available_grids.push(grid)
end
end
end
return available_grids
end
#--------------------------------------------------------------------------
# ● 获得横线范围
# range为2的范围
# □□□□□
# □■●■□
# □□◎□□
# □□□□□
#--------------------------------------------------------------------------
def self.get_transverse_grids(battler_grid, target_grid, range)
# 射程小于等于0的话,返回空数组
if range <= 0 or target_grid.distance(battler_grid) == 0
return []
end
# 初始化范围格集合
available_grids = []
# 获得战斗者格子与目标格子的直线函数
funtion = Math.get_2_grids_function(battler_grid, target_grid)
a = funtion[0]
b = funtion[1]
c = funtion[2]
# 取得直线过目标格子的垂线
funtion_90 = Math.get_90_linear(a, b, c, target_grid.center_x, target_grid.center_y)
a = funtion_90[0]
b = funtion_90[1]
c = funtion_90[2]
# 取得正方形范围
squar_grids = self.get_squar_grids(target_grid, range, false)
# 排序
squar_grids = self.sort_grids(squar_grids)
# 循环正方形范围,如果直线过格子的话,添加
number = 0
true_range = range * 2 - 1
for grid in squar_grids
# 只添加range个格子
if number >= true_range
break
end
if Math.overlap?(a, b, c, grid)
number += 1
if $game_map.valid?(grid.x, grid.y)
available_grids.push(grid)
end
end
end
return available_grids
end
#--------------------------------------------------------------------------
# ● 获得十字范围
# range为3的范围
# □□□□□□□
# □□□■□□□
# □□□■□□□
# □■■●■■□
# □□□■□□□
# □□□■□□□
# □□□□□□□
#--------------------------------------------------------------------------
def self.get_cross_grids(target_grid, range)
# 射程小于等于0的话,返回空数组
if range <= 0
return []
end
# 初始化范围格集合
available_grids = []
# 添加平行部分
for x in (target_grid.x - range + 1)..(target_grid.x + range - 1)
# 防止生成地图外格子
next if !$game_map.valid?(x, target_grid.y)
distance = (x - target_grid.x).abs
available_grids.push Grid.new(x, target_grid.y, distance)
end
# 添加垂直部分
for y in (target_grid.y - range + 1)..(target_grid.y + range - 1)
# 防止生成地图外格子
next if !$game_map.valid?(target_grid.x, y)
distance = (y - target_grid.y).abs
# 防止重复生成
next if distance == 0
available_grids.push Grid.new(target_grid.x, y, distance)
end
return available_grids
end
#--------------------------------------------------------------------------
# ● 获得扇形范围(范围需要比较大才看得出是扇形..)
# range为2,正切为1的范围
# □□□□□
# □■■■□
# □□●□□
# □□◎□□
# □□□□□
#--------------------------------------------------------------------------
def self.get_fan_grids(battler_grid, target_grid, tan, range)
# 射程小于等于0的话,返回空数组
if range <= 0 or target_grid.distance(battler_grid) == 0
return []
end
# 取得半径
radius = range * Math.cos(Math.atan(tan))
# 初始化范围格集合
available_grids = []
# 获得战斗者格子与目标格子的直线函数
funtion = Math.get_2_grids_function(battler_grid, target_grid)
a = funtion[0]
b = funtion[1]
c = funtion[2]
# 获得直线与X轴夹角
if b == 0
slope_radian = Math::PI / 2
else
slope_radian = Math.atan(-a / b.to_f)
end
# 获得扇形夹角的二分之一
deflective_radian = Math.atan(tan)
# 获得扇形靠近Y轴的边
radian = slope_radian + deflective_radian
slope = Math.tan(radian)
side1 = Math.get_linear_function(target_grid.center_x, target_grid.center_y, target_grid.center_x + 1, slope + target_grid.center_y)
side1_grids = []
# 获得扇形靠近X轴的边
radian = slope_radian - deflective_radian
slope = Math.tan(radian)
side2 = Math.get_linear_function(target_grid.center_x, target_grid.center_y, target_grid.center_x + 1, slope + target_grid.center_y)
side2_grids = []
# 取得正方形范围
squar_grids = self.get_squar_grids(target_grid, radius.ceil)
# 排序
squar_grids = self.sort_grids(squar_grids)
a1 = side1[0]
b1 = side1[1]
c1 = side1[2]
a2 = side2[0]
b2 = side2[1]
c2 = side2[2]
# 循环正方形范围
for grid in squar_grids
# 超出范围的不添加
distance = (grid.center_x - target_grid.center_x) ** 2 + (grid.center_y - target_grid.center_y) ** 2
if distance > radius ** 2
next
end
# 只添加同方向格子
if Math.grids_same_side?(target_grid, battler_grid, grid)
next
end
# 添加边上的格子
if Math.overlap?(a1, b1, c1, grid)
side1_grids.push(grid)
available_grids.push(grid)
elsif Math.overlap?(a2, b2, c2, grid)
side2_grids.push(grid)
available_grids.push(grid)
end
end
if side1_grids == [] or side2_grids == []
return available_grids
end
# 循环正方形范围
for grid in squar_grids
# 超出范围的不添加
distance = (grid.center_x - target_grid.center_x) ** 2 + (grid.center_y - target_grid.center_y) ** 2
if distance > radius ** 2
next
end
# 只添加同方向格子
if Math.grids_same_side?(target_grid, battler_grid, grid)
next
end
# 添加中间的格子
if Math.same_side?(a1, b1, c1, grid, side2_grids[side2_grids.size-1]) and
Math.same_side?(a2, b2, c2, grid, side1_grids[side1_grids.size-1])
available_grids.push(grid)
end
end
return available_grids
end
#--------------------------------------------------------------------------
# ● 以grid的point由小到大进行排序
#--------------------------------------------------------------------------
def self.sort_grids(grids)
grids.sort! do |a, b|
a.point <=> b.point
end
return grids
end
#--------------------------------------------------------------------------
# ● 通过通行列表对格子进行遮挡处理
#--------------------------------------------------------------------------
def self.block_grids(target_grid, grids, map_cost_list)
fixed_grids = grids.clone
# 循环所有格子
for grid in grids
# 获得战斗者格子与格子的直线函数
funtion = Math.get_2_grids_function(target_grid, grid)
a = funtion[0]
b = funtion[1]
c = funtion[2]
delete_flag = false
for x in 0...map_cost_list.xsize
break if delete_flag == true
for y in 0...map_cost_list.ysize
break if delete_flag == true
if (x - target_grid.x).abs + (y - target_grid.y).abs >
(grid.x - target_grid.x).abs + (grid.y - target_grid.y).abs
next
end
if map_cost_list[x, y] == 30000
block = Grid.new(x, y)
if Math.overlap?(a, b, c, block)
if Math.grids_same_side?(target_grid, block, grid)
fixed_grids.delete(grid)
delete_flag = true
end
end
end
end
end
end
return fixed_grids
end
end
复制代码
#==============================================================================
# ■ Grid
#------------------------------------------------------------------------------
# SLG地图格子的类。
#==============================================================================
class Grid
attr_accessor :x # x坐标
attr_accessor :y # y坐标
attr_accessor :point # 移动用
def initialize(x, y, point = 0)
@x = x
@y = y
@point = point
end
#--------------------------------------------------------------------------
# ◎中心坐标,应用到解析计算中
#--------------------------------------------------------------------------
def center_x
return @x + 0.5
end
def center_y
return @y + 0.5
end
#--------------------------------------------------------------------------
# ◎比较坐标集
#--------------------------------------------------------------------------
def compare_grids(grids)
for grid in grids
if @x == grid.x and @y == grid.y
return grid
end
end
return false
end
#--------------------------------------------------------------------------
# ◎取得距离
#--------------------------------------------------------------------------
def distance(other_grid_or_x, or_y = 0)
if other_grid_or_x.is_a?(Grid)
return ((@x - other_grid_or_x.x).abs + (@y - other_grid_or_x.y).abs)
else
return ((@x - other_grid_or_x).abs + (@y - or_y).abs)
end
end
end
复制代码
#==============================================================================
# ■ Math
#------------------------------------------------------------------------------
# 支持浮点运算的模块。
#==============================================================================
module Math
#--------------------------------------------------------------------------
# ● 获得积点(0~1)
# number : 目标数字
# array : 对比的数组
#--------------------------------------------------------------------------
def self.rate_number(number, array)
return 0.5 if array == [] or number.nil?
max = array.max
min = array.min
return 0.5 if max - min == 0
return (number - min)/(max - min)
end
#--------------------------------------------------------------------------
# ● 返回弧度对应的角度
#--------------------------------------------------------------------------
def self.radian_to_angle(radian)
return radian * 180 / PI
end
#--------------------------------------------------------------------------
# ● 返回角度对应的弧度
#--------------------------------------------------------------------------
def self.angle_to_radian(angle)
return angle * PI / 180
end
#--------------------------------------------------------------------------
# ● 返回一次函数(ax+by+c=0)的[a,b,c]
# x1, y1, x2, y2 : 直线上两点的坐标
#--------------------------------------------------------------------------
def self.get_linear_function(x1, y1, x2, y2)
a = y2 - y1
b = -(x2 - x1)
c = y1 * (x2 - x1) - x1 * (y2 - y1)
return [a, b, c]
end
#--------------------------------------------------------------------------
# ● 返回过两个格子中心的一次函数(ax+by+c=0)的[a,b,c]
# grid1,grid2 : 两个格子
#--------------------------------------------------------------------------
def self.get_2_grids_function(grid1, grid2)
return self.get_linear_function(grid1.center_x, grid1.center_y,
grid2.center_x, grid2.center_y)
end
#--------------------------------------------------------------------------
# ● 已知x与一次函数(ax+by+c=0),返回y
#--------------------------------------------------------------------------
def self.get_y(a, b, c, x)
return -(c + a * x) / b.to_f
end
#--------------------------------------------------------------------------
# ● 返回与一次函数(ax+by+c=0)成直角,并且交于x,y的一次函数的[a,b,c]
# y不可等于0
#--------------------------------------------------------------------------
def self.get_90_linear(a, b, c, x, y)
if b == 0
return self.get_linear_function(x, y, 0, y)
elsif a == 0
return self.get_linear_function(x, y, x, 0)
else
a2 = 1
b2 = -a / b.to_f
c2 = -(a2 * x + b2 * y)
return [a2, b2, c2]
end
end
#--------------------------------------------------------------------------
# ● 判断一次函数(ax+by+c=0)是否通过grid
#--------------------------------------------------------------------------
def self.overlap?(a, b, c, grid)
if b == 0
if -c / a > grid.x and -c / a < grid.x + 1
return true
end
elsif -a / b >= 0
y1 = self.get_y(a, b, c, grid.x)
y2 = self.get_y(a, b, c, grid.x + 1)
if y1 < (grid.y + 1) and y2 > grid.y
return true
end
elsif -a / b < 0
y1 = self.get_y(a, b, c, grid.x)
y2 = self.get_y(a, b, c, grid.x + 1)
if y1 > grid.y and y2 < (grid.y + 1)
return true
end
end
return false
end
#--------------------------------------------------------------------------
# ● 判断grid是否与target_grid在一次函数(ax+by+c=0)的同一方向
#--------------------------------------------------------------------------
def self.same_side?(a, b, c, target_grid, grid)
if b < 0.1 and b > -0.1
x_intercept = -c / a
if target_grid.center_x > x_intercept and grid.center_x > x_intercept
return true
elsif target_grid.center_x < x_intercept and grid.center_x < x_intercept
return true
end
else
if target_grid.center_y > self.get_y(a, b, c, target_grid.center_x) and
grid.center_y > self.get_y(a, b, c, grid.center_x)
return true
elsif target_grid.center_y < self.get_y(a, b, c, target_grid.center_x) and
grid.center_y < self.get_y(a, b, c, grid.center_x)
return true
end
end
return false
end
#--------------------------------------------------------------------------
# ● 判断grid是否与target_grid在同一方向
# 分割线为target_grid与ori_grid的连线的垂线,垂线过ori_grid中心
#--------------------------------------------------------------------------
def self.grids_same_side?(ori_grid, target_grid, grid)
connecting_line = self.get_2_grids_function(ori_grid, target_grid)
a = connecting_line[0]
b = connecting_line[1]
c = connecting_line[2]
parting_line = self.get_90_linear(a, b, c, ori_grid.center_x, ori_grid.center_y)
a = parting_line[0]
b = parting_line[1]
c = parting_line[2]
return self.same_side?(a, b, c, target_grid, grid)
end
#--------------------------------------------------------------------------
# ● SLG用的数字增加
#--------------------------------------------------------------------------
def self.plus_number(number1, number2)
if number2.is_a?(Float)
number1 *= number2
else
number1 += number2
end
return number1.round
end
#--------------------------------------------------------------------------
# ● 以(0,0)为中心,逆时针方向旋转angle度,返回旋转后的[x, y]
#--------------------------------------------------------------------------
def self.rotate(x, y, angle)
r1 = angle * PI / 180
r2 = r1 - self.atan((x/y.to_f).abs)
radius = self.sqrt(x**2 + y**2)
x = (radius * self.sin(r2)).round
y = (radius * self.cos(r2)).round
return [x, y]
end
#--------------------------------------------------------------------------
# ● 获得直线(ax+by+c=0)与半径为r,中心为(0,0)的圆的交点
# 返回两个交点的坐标的数组,无解时返回nil
#--------------------------------------------------------------------------
def self.solve_linear_circle(a, b, c, r)
boo = 4*(b*c)**2 + 4*(c**2-a**2*r**2)*(a**2+b**2)
if boo < 0
return
end
y1 = (-2*b*c + self.sqrt(boo)) / (2.0 * (a**2 + b**2))
if a == 0
x1 = 0
else
x1 = - (b * y1 + c) / a
end
y2 = (-2*b*c - self.sqrt(boo)) / (2.0 * (a**2 + b**2))
if a == 0
x2 = 0
else
x2 = - (b * y2 + c) / a
end
return [x1, y1, x2, y2]
end
end
复制代码
[LINE]1,#dddddd[/LINE]
系统信息:本贴由楼主认可为正确答案,66RPG感谢您的热情解答~
作者:
qqp987987
时间:
2009-4-27 22:13
提示:
作者被禁止或删除 内容自动屏蔽
作者:
66rpg学习
时间:
2009-4-27 22:40
提示:
作者被禁止或删除 内容自动屏蔽
作者:
叶子
时间:
2009-4-27 22:41
http://rpg.blue/viewthread.php?tid=12035
欢迎光临 Project1 (https://rpg.blue/)
Powered by Discuz! X3.1