|
|
发表于 2026-1-20 10:46:43
|
显示全部楼层
现在可以直接问 deepseek 来撰写 RMVA 使用的脚本了,当然,还是可能会有冲突或者数据结构错误,需要自己改正,不过简单的优化应该都没问题了,你可以去试试看。
比如询问我想将RPG Maker VX Ace中默认菜单里的状态界面的展示八维属性值,修改为展示八边型雷达图,中心点的属性值为0,且不同属性可以设置不同的最大值
它给出了
[fold=DS回复]
[pre lang="ruby"]#==============================================================================
# ** 雷达图状态窗口
#==============================================================================
class Window_Status < Window_Selectable
# 属性索引映射
STATS = [
:maxhp, # 0 - 最大HP
:maxmp, # 1 - 最大MP
:atk, # 2 - 攻击力
:def, # 3 - 防御力
:mat, # 4 - 魔法攻击
:mdf, # 5 - 魔法防御
:agi, # 6 - 敏捷
:luk, # 7 - 幸运
]
# 各属性最大值配置
STAT_MAX = {
maxhp: 999, # HP最大值
maxmp: 999, # MP最大值
atk: 999, # 攻击力最大值
def: 999, # 防御力最大值
mat: 999, # 魔法攻击最大值
mdf: 999, # 魔法防御最大值
agi: 999, # 敏捷最大值
luk: 999, # 幸运最大值
}
# 颜色配置(对应8种属性)
STAT_COLORS = [
Color.new(255, 50, 50), # HP - 红色
Color.new(50, 100, 255), # MP - 蓝色
Color.new(255, 150, 50), # 攻击 - 橙色
Color.new(100, 200, 100), # 防御 - 绿色
Color.new(200, 50, 200), # 魔攻 - 紫色
Color.new(50, 200, 200), # 魔防 - 青色
Color.new(255, 200, 50), # 敏捷 - 黄色
Color.new(200, 100, 200), # 幸运 - 粉色
]
# 雷达图中心位置和半径
RADAR_CENTER_X = 180
RADAR_CENTER_Y = 180
RADAR_RADIUS = 80
#--------------------------------------------------------------------------
# * 绘制内容
#--------------------------------------------------------------------------
def draw_all_items
draw_radar_chart
draw_stat_values
draw_actor_info
end
#--------------------------------------------------------------------------
# * 绘制雷达图
#--------------------------------------------------------------------------
def draw_radar_chart
contents.clear
# 绘制雷达图背景
draw_radar_background
# 绘制雷达图数据区域
draw_radar_data_area
# 绘制属性标签
draw_stat_labels
end
#--------------------------------------------------------------------------
# * 绘制雷达图背景
#--------------------------------------------------------------------------
def draw_radar_background
# 绘制同心圆
[0.25, 0.5, 0.75, 1.0].each do |ratio|
radius = RADAR_RADIUS * ratio
contents.draw_circle(RADAR_CENTER_X, RADAR_CENTER_Y, radius.to_i, Color.new(100, 100, 100, 100))
end
# 绘制8条轴线
8.times do |i|
angle = i * Math::PI / 4
x = RADAR_CENTER_X + RADAR_RADIUS * Math.cos(angle)
y = RADAR_CENTER_Y + RADAR_RADIUS * Math.sin(angle)
contents.draw_line(RADAR_CENTER_X, RADAR_CENTER_Y, x.to_i, y.to_i, Color.new(150, 150, 150))
end
end
#--------------------------------------------------------------------------
# * 绘制雷达图数据区域
#--------------------------------------------------------------------------
def draw_radar_data_area
return unless @actor
points = []
# 计算每个属性在雷达图上的点
8.times do |i|
stat = STATS
value = @actor.send(stat)
max_value = STAT_MAX[stat]
# 计算归一化值(0-1范围)
normalized_value = [[value.to_f / max_value, 1.0].min, 0.0].max
# 计算点在雷达图上的位置
angle = i * Math::PI / 4 - Math::PI / 2 # 调整起始角度,使顶部为第一个属性
radius = RADAR_RADIUS * normalized_value
x = RADAR_CENTER_X + radius * Math.cos(angle)
y = RADAR_CENTER_Y + radius * Math.sin(angle)
points << [x.to_i, y.to_i]
end
# 绘制填充区域
fill_color = Color.new(100, 150, 255, 100)
contents.fill_polygon(points, fill_color)
# 绘制边界线
points.each_with_index do |point, i|
next_point = points[(i + 1) % 8]
contents.draw_line(point[0], point[1], next_point[0], next_point[1], Color.new(50, 100, 255))
end
# 绘制顶点
points.each_with_index do |point, i|
contents.fill_circle(point[0], point[1], 4, STAT_COLORS)
end
end
#--------------------------------------------------------------------------
# * 绘制属性标签
#--------------------------------------------------------------------------
def draw_stat_labels
stat_names = [
"HP", "MP", "攻击", "防御",
"魔攻", "魔防", "敏捷", "幸运"
]
8.times do |i|
angle = i * Math::PI / 4 - Math::PI / 2
# 标签位置在雷达图外侧
label_radius = RADAR_RADIUS + 40
x = RADAR_CENTER_X + label_radius * Math.cos(angle)
y = RADAR_CENTER_Y + label_radius * Math.sin(angle)
# 根据位置调整文本对齐方式
align = 1 # 默认居中
if x < RADAR_CENTER_X - 10
align = 2 # 右对齐(左侧)
elsif x > RADAR_CENTER_X + 10
align = 0 # 左对齐(右侧)
end
change_color(system_color)
contents.draw_text(x.to_i - 40, y.to_i - 12, 80, 24, stat_names, align)
end
end
#--------------------------------------------------------------------------
# * 绘制属性数值
#--------------------------------------------------------------------------
def draw_stat_values
return unless @actor
# 在雷达图下方显示具体数值
y = RADAR_CENTER_Y + RADAR_RADIUS + 60
x = RADAR_CENTER_X - RADAR_RADIUS - 20
STATS.each_with_index do |stat, i|
row = i / 4
col = i % 4
draw_x = x + col * 100
draw_y = y + row * 30
# 属性名
change_color(system_color)
contents.draw_text(draw_x, draw_y, 48, 24, STATS_NAMES[stat] || stat.to_s)
# 属性值
change_color(normal_color)
value = @actor.send(stat)
max_value = STAT_MAX[stat]
contents.draw_text(draw_x + 48, draw_y, 52, 24, "#{value}/#{max_value}", 2)
end
end
#--------------------------------------------------------------------------
# * 绘制角色信息
#--------------------------------------------------------------------------
def draw_actor_info
return unless @actor
# 角色名字
change_color(normal_color)
contents.font.size = 20
contents.draw_text(0, 0, contents.width, 24, @actor.name, 1)
contents.font.size = Font.default_size
# 角色职业和等级
draw_x = RADAR_CENTER_X - RADAR_RADIUS - 20
draw_y = RADAR_CENTER_Y - RADAR_RADIUS - 60
change_color(system_color)
contents.draw_text(draw_x, draw_y, 120, 24, "职业:")
change_color(normal_color)
contents.draw_text(draw_x + 40, draw_y, 80, 24, @actor.class.name)
change_color(system_color)
contents.draw_text(draw_x, draw_y + 24, 120, 24, "等级:")
change_color(normal_color)
contents.draw_text(draw_x + 40, draw_y + 24, 80, 24, @actor.level.to_s)
end
#--------------------------------------------------------------------------
# * 属性显示名称
#--------------------------------------------------------------------------
STATS_NAMES = {
maxhp: "HP",
maxmp: "MP",
atk: "攻击",
def: "防御",
mat: "魔攻",
mdf: "魔防",
agi: "敏捷",
luk: "幸运"
}
end
#==============================================================================
# ** 图形绘制扩展
#==============================================================================
class Bitmap
#--------------------------------------------------------------------------
# * 绘制圆形
#--------------------------------------------------------------------------
def draw_circle(cx, cy, radius, color)
# 简化的圆形绘制
(0...360).step(5) do |angle|
rad = angle * Math::PI / 180
x1 = cx + radius * Math.cos(rad)
y1 = cy + radius * Math.sin(rad)
x2 = cx + radius * Math.cos(rad + 0.1)
y2 = cy + radius * Math.sin(rad + 0.1)
draw_line(x1.to_i, y1.to_i, x2.to_i, y2.to_i, color)
end
end
#--------------------------------------------------------------------------
# * 填充圆形
#--------------------------------------------------------------------------
def fill_circle(cx, cy, radius, color)
# 简单的实心圆绘制
(cx - radius..cx + radius).each do |x|
(cy - radius..cy + radius).each do |y|
if (x - cx) ** 2 + (y - cy) ** 2 <= radius ** 2
set_pixel(x, y, color)
end
end
end
end
#--------------------------------------------------------------------------
# * 绘制多边形
#--------------------------------------------------------------------------
def fill_polygon(points, color)
return if points.size < 3
# 找到多边形的边界
min_x = points.map { |p| p[0] }.min
max_x = points.map { |p| p[0] }.max
min_y = points.map { |p| p[1] }.min
max_y = points.map { |p| p[1] }.max
# 简单的多边形填充(扫描线算法简化版)
(min_y..max_y).each do |y|
intersections = []
# 计算与每条边的交点
points.each_with_index do |point, i|
next_point = points[(i + 1) % points.size]
x1, y1 = point
x2, y2 = next_point
# 确保y1 <= y2
if y1 > y2
x1, x2 = x2, x1
y1, y2 = y2, y1
end
# 如果y在边的高度范围内
if y >= y1 && y <= y2 && y1 != y2
# 计算交点x坐标
x = x1 + (x2 - x1) * (y - y1) / (y2 - y1)
intersections << x
end
end
# 按x坐标排序并成对填充
intersections.sort!
(0...intersections.size).step(2) do |i|
break if i + 1 >= intersections.size
x1 = intersections.ceil
x2 = intersections[i + 1].floor
fill_rect(x1, y, x2 - x1 + 1, 1, color) if x2 >= x1
end
end
end
end[/pre]
[/fold]
但实际运行时就发现,bitmap类没有 draw_line 方法,那继续问
补充 draw_line(x1.to_i, y1.to_i, x2.to_i, y2.to_i, color) 的具体实现
它再回复
[fold=DS回复]
[pre lang="ruby"]#==============================================================================
# ** Bitmap图形绘制扩展
#==============================================================================
class Bitmap
#--------------------------------------------------------------------------
# * 绘制直线(Bresenham算法)
#--------------------------------------------------------------------------
def draw_line(x1, y1, x2, y2, color)
# 确保起点和终点的整数坐标
x1, y1 = x1.to_i, y1.to_i
x2, y2 = x2.to_i, y2.to_i
# 使用Bresenham直线算法
dx = (x2 - x1).abs
dy = (y2 - y1).abs
# 确定步进方向
sx = x1 < x2 ? 1 : -1
sy = y1 < y2 ? 1 : -1
err = dx - dy
loop do
# 绘制当前像素(确保在边界内)
set_pixel(x1, y1, color) if in_bounds?(x1, y1)
# 到达终点
break if x1 == x2 && y1 == y2
e2 = 2 * err
if e2 > -dy
err -= dy
x1 += sx
end
if e2 < dx
err += dx
y1 += sy
end
end
end
#--------------------------------------------------------------------------
# * 绘制圆形轮廓(中点圆算法)
#--------------------------------------------------------------------------
def draw_circle(cx, cy, radius, color)
cx, cy, radius = cx.to_i, cy.to_i, radius.to_i
x = radius
y = 0
err = 0
while x >= y
# 绘制8个对称点
draw_circle_points(cx, cy, x, y, color)
y += 1
err += 1 + 2 * y
if 2 * (err - x) + 1 > 0
x -= 1
err += 1 - 2 * x
end
end
end
#--------------------------------------------------------------------------
# * 绘制圆形的8个对称点
#--------------------------------------------------------------------------
def draw_circle_points(cx, cy, x, y, color)
# 八个对称点
points = [
[cx + x, cy + y], [cx - x, cy + y],
[cx + x, cy - y], [cx - x, cy - y],
[cx + y, cy + x], [cx - y, cy + x],
[cx + y, cy - x], [cx - y, cy - x]
]
points.each do |px, py|
set_pixel(px, py, color) if in_bounds?(px, py)
end
end
#--------------------------------------------------------------------------
# * 填充圆形(扫描线填充)
#--------------------------------------------------------------------------
def fill_circle(cx, cy, radius, color)
cx, cy, radius = cx.to_i, cy.to_i, radius.to_i
# 确保半径为正
return if radius <= 0
# 扫描线填充
(-radius..radius).each do |y|
# 计算当前扫描线的x范围
x_span = Math.sqrt(radius * radius - y * y).to_i
next if x_span <= 0
# 绘制水平线
x1 = cx - x_span
x2 = cx + x_span
# 确保在边界内
x1 = 0 if x1 < 0
x2 = width - 1 if x2 >= width
y_pos = cy + y
# 绘制扫描线
if y_pos >= 0 && y_pos < height
fill_rect(x1, y_pos, x2 - x1 + 1, 1, color)
end
end
end
#--------------------------------------------------------------------------
# * 绘制矩形轮廓
#--------------------------------------------------------------------------
def draw_rect(x, y, width, height, color)
x, y = x.to_i, y.to_i
width, height = width.to_i, height.to_i
# 上边
fill_rect(x, y, width, 1, color) if height > 0
# 下边
fill_rect(x, y + height - 1, width, 1, color) if height > 0
# 左边
fill_rect(x, y, 1, height, color) if width > 0
# 右边
fill_rect(x + width - 1, y, 1, height, color) if width > 0
end
#--------------------------------------------------------------------------
# * 绘制多边形轮廓
#--------------------------------------------------------------------------
def draw_polygon(points, color)
return if points.size < 2
# 绘制多边形的每条边
points.each_with_index do |point, i|
next_point = points[(i + 1) % points.size]
draw_line(point[0], point[1], next_point[0], next_point[1], color)
end
end
#--------------------------------------------------------------------------
# * 填充多边形(扫描线算法)
#--------------------------------------------------------------------------
def fill_polygon(points, color)
return if points.size < 3
# 找到多边形的边界
min_y = points.map { |p| p[1].to_i }.min
max_y = points.map { |p| p[1].to_i }.max
# 对每条扫描线处理
min_y.upto(max_y) do |scan_y|
intersections = []
# 检查每条边与扫描线的交点
points.each_with_index do |point, i|
next_point = points[(i + 1) % points.size]
x1, y1 = point[0].to_i, point[1].to_i
x2, y2 = next_point[0].to_i, next_point[1].to_i
# 确保y1 <= y2
if y1 > y2
x1, x2 = x2, x1
y1, y2 = y2, y1
end
# 检查扫描线是否与边相交
if scan_y >= y1 && scan_y <= y2
# 排除水平线
if y1 != y2
# 计算交点x坐标
x_intersect = x1 + (scan_y - y1) * (x2 - x1).to_f / (y2 - y1)
intersections << x_intersect
end
end
end
# 排序交点
intersections.sort!
# 成对填充
(0...intersections.size).step(2) do |i|
break if i + 1 >= intersections.size
x_start = intersections.ceil
x_end = intersections[i + 1].floor
# 确保在边界内
x_start = 0 if x_start < 0
x_end = self.width - 1 if x_end >= self.width
# 绘制扫描线段
if scan_y >= 0 && scan_y < self.height && x_end >= x_start
fill_rect(x_start, scan_y, x_end - x_start + 1, 1, color)
end
end
end
end
#--------------------------------------------------------------------------
# * 绘制带圆角的矩形
#--------------------------------------------------------------------------
def draw_rounded_rect(x, y, width, height, radius, color)
x, y = x.to_i, y.to_i
width, height = width.to_i, height.to_i
radius = radius.to_i
# 限制圆角半径不超过矩形尺寸的一半
radius = [radius, width / 2, height / 2].min
# 绘制四个圆角
draw_circle_arc(x + radius, y + radius, radius, 180, 270, color) # 左上
draw_circle_arc(x + width - radius, y + radius, radius, 270, 360, color) # 右上
draw_circle_arc(x + width - radius, y + height - radius, radius, 0, 90, color) # 右下
draw_circle_arc(x + radius, y + height - radius, radius, 90, 180, color) # 左下
# 绘制四条直线
# 上边
fill_rect(x + radius, y, width - 2 * radius, 1, color) if width > 2 * radius
# 下边
fill_rect(x + radius, y + height - 1, width - 2 * radius, 1, color) if width > 2 * radius
# 左边
fill_rect(x, y + radius, 1, height - 2 * radius, color) if height > 2 * radius
# 右边
fill_rect(x + width - 1, y + radius, 1, height - 2 * radius, color) if height > 2 * radius
end
#--------------------------------------------------------------------------
# * 绘制圆弧
#--------------------------------------------------------------------------
def draw_circle_arc(cx, cy, radius, start_angle, end_angle, color)
cx, cy, radius = cx.to_i, cy.to_i, radius.to_i
# 角度转弧度
start_rad = start_angle * Math::PI / 180
end_rad = end_angle * Math::PI / 180
# 确保结束角度大于起始角度
if end_rad < start_rad
end_rad += 2 * Math::PI
end
# 步长根据半径调整
step = 1.0 / radius
# 绘制圆弧
theta = start_rad
while theta <= end_rad
x = (cx + radius * Math.cos(theta)).to_i
y = (cy + radius * Math.sin(theta)).to_i
set_pixel(x, y, color) if in_bounds?(x, y)
theta += step
end
end
#--------------------------------------------------------------------------
# * 绘制三角形
#--------------------------------------------------------------------------
def draw_triangle(x1, y1, x2, y2, x3, y3, color)
points = [[x1, y1], [x2, y2], [x3, y3]]
draw_polygon(points, color)
end
#--------------------------------------------------------------------------
# * 填充三角形
#--------------------------------------------------------------------------
def fill_triangle(x1, y1, x2, y2, x3, y3, color)
points = [[x1, y1], [x2, y2], [x3, y3]]
fill_polygon(points, color)
end
#--------------------------------------------------------------------------
# * 绘制贝塞尔曲线(二次)
#--------------------------------------------------------------------------
def draw_bezier_curve(x1, y1, x2, y2, cx, cy, color, segments = 20)
# 二次贝塞尔曲线公式: B(t) = (1-t)²P₀ + 2(1-t)tP₁ + t²P₂
segments.times do |i|
t1 = i.to_f / segments
t2 = (i + 1).to_f / segments
# 计算点
px1 = (1 - t1) * (1 - t1) * x1 + 2 * (1 - t1) * t1 * cx + t1 * t1 * x2
py1 = (1 - t1) * (1 - t1) * y1 + 2 * (1 - t1) * t1 * cy + t1 * t1 * y2
px2 = (1 - t2) * (1 - t2) * x1 + 2 * (1 - t2) * t2 * cx + t2 * t2 * x2
py2 = (1 - t2) * (1 - t2) * y1 + 2 * (1 - t2) * t2 * cy + t2 * t2 * y2
# 绘制线段
draw_line(px1.to_i, py1.to_i, px2.to_i, py2.to_i, color)
end
end
#--------------------------------------------------------------------------
# * 绘制虚线
#--------------------------------------------------------------------------
def draw_dashed_line(x1, y1, x2, y2, color, dash_length = 4, gap_length = 4)
# 计算线段总长度和方向
dx = x2 - x1
dy = y2 - y1
length = Math.sqrt(dx * dx + dy * dy)
# 单位向量
ux = dx / length
uy = dy / length
# 绘制虚线
current_length = 0
while current_length < length
# 线段的起始和结束
seg_start = current_length
seg_end = [current_length + dash_length, length].min
# 计算实际坐标
sx1 = x1 + ux * seg_start
sy1 = y1 + uy * seg_start
sx2 = x1 + ux * seg_end
sy2 = y1 + uy * seg_end
# 绘制实线段
draw_line(sx1.to_i, sy1.to_i, sx2.to_i, sy2.to_i, color)
# 移动到下一段
current_length = seg_end + gap_length
end
end
#--------------------------------------------------------------------------
# * 检查坐标是否在边界内
#--------------------------------------------------------------------------
def in_bounds?(x, y)
x >= 0 && x < self.width && y >= 0 && y < self.height
end
#--------------------------------------------------------------------------
# * 绘制带箭头的线
#--------------------------------------------------------------------------
def draw_arrow_line(x1, y1, x2, y2, color, arrow_size = 6)
# 绘制主线段
draw_line(x1, y1, x2, y2, color)
# 计算箭头方向
dx = x2 - x1
dy = y2 - y1
angle = Math.atan2(dy, dx)
# 箭头角度
arrow_angle1 = angle + Math::PI - Math::PI / 6
arrow_angle2 = angle + Math::PI + Math::PI / 6
# 计算箭头顶点
ax1 = x2 + arrow_size * Math.cos(arrow_angle1)
ay1 = y2 + arrow_size * Math.sin(arrow_angle1)
ax2 = x2 + arrow_size * Math.cos(arrow_angle2)
ay2 = y2 + arrow_size * Math.sin(arrow_angle2)
# 绘制箭头
draw_line(x2, y2, ax1.to_i, ay1.to_i, color)
draw_line(x2, y2, ax2.to_i, ay2.to_i, color)
end
end[/pre][/fold]
基于以上,我修改后就获得了一个可以通用的雷达图绘制方法,一是形状绘制,二是雷达图绘制,比以前效率高出不少。
也因此,挺推荐新人尝试在编写独立功能插件时,先问问AI。 |
|