设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 1741|回复: 2
打印 上一主题 下一主题

[原创发布] 用RGD绘制Bézier曲线

[复制链接]

Lv3.寻梦者

梦石
0
星屑
1934
在线时间
403 小时
注册时间
2015-8-30
帖子
395
跳转到指定楼层
1
发表于 2018-11-18 21:30:07 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
本帖最后由 有丘直方 于 2018-12-2 20:29 编辑

RUBY 代码复制
  1. class Vector
  2.  
  3.   include(Enumerable)
  4.  
  5.   attr_accessor :x
  6.   attr_accessor :y
  7.  
  8.   def initialize(*args)
  9.     case args.size
  10.     when 0
  11.       @x = 0
  12.       @y = 0
  13.     when 1
  14.       @x = args[0]
  15.       @y = args[0]
  16.     when 2
  17.       @x = args[0]
  18.       @y = args[1]
  19.     end
  20.   end
  21.  
  22.   def +@
  23.     self
  24.   end
  25.  
  26.   def -@
  27.     Vector.new(-@x, -@y)
  28.   end
  29.  
  30.   def +(other)
  31.     Vector.new(@x + other.x, @y + other.y)
  32.   end
  33.  
  34.   def -(other)
  35.     self + -other
  36.   end
  37.  
  38.   def *(other)
  39.     case other
  40.     when Numeric
  41.       Vector.new(@x * other, @y * other)
  42.     when Vector
  43.       @x * other.x + @y * other.y
  44.     end
  45.   end
  46.  
  47.   def dot(other)
  48.     self * other
  49.   end
  50.  
  51.   def cross(other)
  52.     self.x * other.y - other.x * self.y
  53.   end
  54.  
  55.   def slope
  56.     y / x
  57.   end
  58.  
  59.   def square_length
  60.     self * self
  61.   end
  62.  
  63.   def length
  64.     Math.sqrt(square_length)
  65.   end
  66.  
  67.   def is_out_of?(other)
  68.     @x.abs > other.x.abs || @y.abs > other.y.abs
  69.   end
  70.  
  71.   def abs
  72.     Vector.new(@x.abs, @y.abs)
  73.   end
  74.  
  75.   def each
  76.     yield @x
  77.     yield @y
  78.   end
  79. end
  80.  
  81. module Math
  82.  
  83.   def self.definite_proportion(point1, point2, proportion)
  84.     point1 * (1 - proportion) + point2 * proportion
  85.   end
  86. end
  87.  
  88. class Rect
  89.  
  90.   alias ulysses201811181949_initialize initialize
  91.   def initialize(*args)
  92.     args = case args.size
  93.     when 0, 4
  94.       args
  95.     when 2
  96.       [args[0].x, args[0].y, args[1].x, args[1].y]
  97.     end
  98.     ulysses201811181949_initialize(*args)
  99.   end
  100.  
  101.   def position
  102.     Vector.new(x, y)
  103.   end
  104.  
  105.   def position=(position)
  106.     self.x = position.x
  107.     self.y = position.y
  108.   end
  109.  
  110.   def size
  111.     Vector.new(width, height)
  112.   end
  113.  
  114.   def size=(size)
  115.     self.width = size.x
  116.     self.height = size.y
  117.   end
  118. end
  119.  
  120. module Kernel
  121.  
  122.   def do_by_step(from, to, step)
  123.     if block_given?
  124.       i = from
  125.       until i >= to
  126.         yield i
  127.         i += step
  128.       end
  129.     else
  130.       to_enum(__method__, from, to, step)
  131.     end
  132.   end
  133. end
  134.  
  135. class Bitmap
  136.  
  137.   alias ulysses201811181708_initialize initialize
  138.   def initialize(*args)
  139.     args = if args.size == 2 || args[0].is_a?(String)
  140.       args
  141.     elsif args.size == 1
  142.       [args[0].x, args[0].y]
  143.     else
  144.       [0, 0]
  145.     end
  146.     ulysses201811181708_initialize(*args)
  147.   end
  148.  
  149.   def fill_circle(center, radius, color)
  150.     i_max = (radius * 707) / 1000 + 1
  151.     square_distance_max = radius * radius + radius / 2
  152.     x = radius
  153.     fill_rect(center.x - radius, center.y, 2 * radius, 1, color)
  154.     for i in 1..i_max
  155.       if Vector.new(center.x, i).square_length > square_distance_max
  156.         if x > i_max
  157.           fill_rect(center.x - i + 1, center.y + x, 2 * (i - 1), 1, color)
  158.           fill_rect(center.x - i + 1, center.y - x, 2 * (i - 1), 1, color)
  159.         end
  160.         x -= 1
  161.       end
  162.       fill_rect(center.x - x, center.y + i, 2 * x, 1, color)
  163.       fill_rect(center.x - x, center.y - i, 2 * x, 1, color)
  164.     end
  165.   end
  166.  
  167.   def draw_line(point1, point2, color)
  168.     difference = point2 - point1
  169.     abs_difference = difference.abs
  170.     total_step = abs_difference.max
  171.     delta = difference * (1.0 / total_step)
  172.     vector = point1
  173.     (total_step - 1).to_i.times do
  174.       set_pixel(vector, color)
  175.       vector += delta
  176.     end
  177.   end
  178.  
  179.   alias ulysses201811182036_set_pixel set_pixel
  180.   def set_pixel(*args)
  181.     args = case args.size
  182.     when 3
  183.       args
  184.     when 2
  185.       [args[0].x, args[0].y, args[1]]
  186.     end
  187.     ulysses201811182036_set_pixel(*args)
  188.   end
  189.  
  190.   def text_vector(text)
  191.     text_size(text).size
  192.   end
  193.  
  194.   def size
  195.     Vector.new(width, height)
  196.   end
  197.  
  198.   def size=(size)
  199.     self.rect.size = size
  200.   end
  201.  
  202.   alias ulysses201811181952_draw_text draw_text
  203.   def draw_text(*args)
  204.     args = case args[0]
  205.     when Numeric, Rect
  206.       args
  207.     when Vector
  208.       a = [args[0].x, args[0].y, args[1].x, args[1].y, args[2]]
  209.       a.push(args[3]) if args.size >= 4
  210.       a
  211.     end
  212.     ulysses201811181952_draw_text(*args)
  213.   end
  214. end
  215.  
  216. class Sprite
  217.  
  218.   alias ulysses201811181903_initialize initialize
  219.   def initialize(viewport = nil)
  220.     ulysses201811181903_initialize(viewport)
  221.     self.bitmap = Bitmap.new
  222.   end
  223.  
  224.   def position=(position)
  225.     self.x = position.x
  226.     self.y = position.y
  227.   end
  228. end
  229.  
  230. module Graphics
  231.  
  232.   def self.size
  233.     Vector.new(width, height)
  234.   end
  235. end
  236.  
  237. module Mouse
  238.  
  239.   def self.position
  240.     Vector.new(x, y)
  241.   end
  242. end
  243.  
  244. module Scene
  245.  
  246.   POINT_RADIUS = 3
  247.   POINT_COLOR = Color.new(255, 255, 255, 255)
  248.   POINT_Z = 10
  249.   CURVE_RADIUS = 2
  250.   CURVE_COLOR = Color.new(255, 255, 255, 255)
  251.   LINE_COLOR = Color.new(255, 255, 255, 255)
  252.   T_BEGINNING = 0.0
  253.   T_END = 1.0
  254.   T_STEP = 0.001
  255.   UPDATE_STEPS = 20
  256.  
  257.   def self.init
  258.     Graphics.resize_screen(1024, 768)
  259.     @graph_sprite = Sprite.new
  260.     @graph_sprite.bitmap = Bitmap.new(Graphics.size)
  261.     @line_sprite = Sprite.new
  262.     @line_sprite.bitmap = Bitmap.new(Graphics.size)
  263.     @points = []
  264.     @point_sprites = []
  265.     @temp_bitmap = Bitmap.new(32, 32)
  266.     @line_visible = true
  267.     @point_visible = true
  268.     @fast_mode = false
  269.     @covering_drawing = 0
  270.   end
  271.  
  272.   def self.create_point(point)
  273.     sprite = Sprite.new
  274.     sprite.visible = @point_visible
  275.     radius_vector = Vector.new(POINT_RADIUS)
  276.     text_vector = @temp_bitmap.text_vector(@points.size)
  277.     radius_text_vector = radius_vector + text_vector
  278.     sprite.bitmap = Bitmap.new(radius_text_vector + radius_vector)
  279.     flip = (point + radius_text_vector).is_out_of?(Graphics.size)
  280.     excursion = flip ? radius_text_vector : radius_vector
  281.     sprite.position = point - excursion
  282.     sprite.bitmap.fill_circle(excursion, POINT_RADIUS, POINT_COLOR)
  283.     text_position = flip ? Vector.new : radius_vector * 2
  284.     sprite.bitmap.draw_text(text_position, text_vector, @points.size)
  285.     sprite.z = POINT_Z
  286.     @points.push(point)
  287.     @point_sprites.push(sprite)
  288.     refresh_graph
  289.   end
  290.  
  291.   def self.delete_point
  292.     @points.pop
  293.     @point_sprites.pop.dispose
  294.     refresh_graph
  295.   end
  296.  
  297.   def self.refresh_graph
  298.     @covering_drawing += 1
  299.     @graph_sprite.bitmap.clear
  300.     return if @points.empty?
  301.     step_count = 0
  302.     will_update = false
  303.     do_by_step(T_BEGINNING, T_END, T_STEP) do |t|
  304.       will_update = true if !@fast_mode && (step_count += 1) >= UPDATE_STEPS
  305.       @line_sprite.bitmap.clear
  306.       sequences = [@points]
  307.       (@points.size - 1).times do |i|
  308.         last_sequence = sequences.last
  309.         sequences.push([])
  310.         (last_sequence.size - 1).times do |j|
  311.           if @line_visible && will_update
  312.             @line_sprite.bitmap.draw_line(*last_sequence[j, 2], LINE_COLOR)
  313.           end
  314.           sequences.last.push(Math.definite_proportion(*last_sequence[j, 2], t))
  315.         end
  316.       end
  317.       @graph_sprite.bitmap.fill_circle(*sequences.last, CURVE_RADIUS, CURVE_COLOR)
  318.       if will_update
  319.         step_count = 0
  320.         will_update = false
  321.         last_covering_drawing = @covering_drawing
  322.         update
  323.         return if @covering_drawing > last_covering_drawing
  324.       end
  325.     end
  326.     (@points.size - 1).times do |i|
  327.       @line_sprite.bitmap.draw_line(*@points[i, 2], LINE_COLOR)
  328.     end
  329.   end
  330.  
  331.   def self.toggle_line_visible
  332.     @line_visible = !@line_visible
  333.     @line_sprite.visible = @line_visible
  334.   end
  335.  
  336.   def self.toggle_point_visible
  337.     @point_visible = !@point_visible
  338.     @point_sprites.each {|sprite| sprite.visible = @point_visible }
  339.   end
  340.  
  341.   def self.toggle_fast_mode
  342.     @fast_mode = !@fast_mode
  343.   end
  344.  
  345.   def self.update_basic
  346.     Graphics.update
  347.     Input.update
  348.     Mouse.update
  349.   end
  350.  
  351.   def self.update
  352.     update_basic
  353.     if Mouse.click?(:L)
  354.       create_point(Mouse.position)
  355.     elsif Mouse.click?(:R)
  356.       delete_point
  357.     elsif Input.trigger?(:A)
  358.       toggle_fast_mode
  359.     elsif Input.trigger?(:B)
  360.       toggle_line_visible
  361.     elsif Input.trigger?(:C)
  362.       toggle_point_visible
  363.     end
  364.   end
  365.   def self.main
  366.     init
  367.     loop { update }
  368.   end
  369. end
  370.  
  371. Scene.main
马上要睡了,不多说了,看图

本来想用shader的,后来还是屈服于Bitmap了……
按左键添加节点,按右键去除节点,按A开启快速模式(不显示绘制过程),按B切换线段的显示,按C切换节点的显示(此处ABC不是键盘上的ABC)
RUBY 代码复制
  1. # 二维向量
  2. class Vector
  3.  
  4.   # 可以进行枚举,参见#each
  5.   include(Enumerable)
  6.  
  7.   attr_accessor :x # x方向上的分量
  8.   attr_accessor :y # y方向上的分量
  9.  
  10.   # 初始化
  11.   # 无参数时:(0, 0)
  12.   # 有一个参数r时:(r, r)
  13.   # 有两个参数x, y时:(x, y)
  14.   def initialize(*args)
  15.     case args.size
  16.     when 0
  17.       @x = 0
  18.       @y = 0
  19.     when 1
  20.       @x = args[0]
  21.       @y = args[0]
  22.     when 2
  23.       @x = args[0]
  24.       @y = args[1]
  25.     end
  26.   end
  27.  
  28.   def +@
  29.     self
  30.   end
  31.  
  32.   # 反向量
  33.   def -@
  34.     Vector.new(-@x, -@y)
  35.   end
  36.  
  37.   # 加法
  38.   def +(other)
  39.     Vector.new(@x + other.x, @y + other.y)
  40.   end
  41.  
  42.   # 减法
  43.   def -(other)
  44.     self + -other
  45.   end
  46.  
  47.   # 点乘或数乘运算
  48.   def *(other)
  49.     case other
  50.     when Numeric
  51.       Vector.new(@x * other, @y * other)
  52.     when Vector
  53.       @x * other.x + @y * other.y
  54.     end
  55.   end
  56.  
  57.   # 点积
  58.   def dot(other)
  59.     @x * other.x + @y * other.y
  60.   end
  61.  
  62.   # 叉积
  63.   def cross(other)
  64.     self.x * other.y - other.x * self.y
  65.   end
  66.  
  67.   # 斜率
  68.   def slope
  69.     x =! 0 ? y / x : Float::Infinity
  70.   end
  71.  
  72.   # 模的平方
  73.   def square_length
  74.     self * self
  75.   end
  76.  
  77.   # 模
  78.   def length
  79.     Math.sqrt(square_length)
  80.   end
  81.  
  82.   # 超出范围
  83.   def is_out_of?(other)
  84.     @x.abs > other.x.abs || @y.abs > other.y.abs
  85.   end
  86.  
  87.   # 对x和y方向的分量分别取绝对值
  88.   def abs
  89.     Vector.new(@x.abs, @y.abs)
  90.   end
  91.  
  92.   # 切向
  93.   def normal
  94.     Vector.new(-@y, @x)
  95.   end
  96.  
  97.   # 枚举,先对x计算,后对y计算
  98.   def each
  99.     yield @x
  100.     yield @y
  101.   end
  102.  
  103.   def inspect
  104.     "(#{@x}, #{@y})"
  105.   end
  106. end
  107.  
  108. module Math
  109.  
  110.   # 获得两点之间由某个比例决定的分点
  111.   def self.definite_proportion(point1, point2, proportion)
  112.     point1 * (1 - proportion) + point2 * proportion
  113.   end
  114. end
  115.  
  116. class Rect
  117.  
  118.   # 初始化
  119.   # 除了原先的参数列表,支持由两个向量来决定其位置大小
  120.   # 如果用向量表示,第一个向量是position,第二个向量是size
  121.   alias ulysses201811181949_initialize initialize
  122.   def initialize(*args)
  123.     args = case args.size
  124.     when 0, 4
  125.       args
  126.     when 2
  127.       [args[0].x, args[0].y, args[1].x, args[1].y]
  128.     end
  129.     ulysses201811181949_initialize(*args)
  130.   end
  131.  
  132.   def position
  133.     Vector.new(x, y)
  134.   end
  135.  
  136.   def position=(position)
  137.     self.x = position.x
  138.     self.y = position.y
  139.   end
  140.  
  141.   def size
  142.     Vector.new(width, height)
  143.   end
  144.  
  145.   def size=(size)
  146.     self.width = size.x
  147.     self.height = size.y
  148.   end
  149. end
  150.  
  151. module Kernel
  152.  
  153.   # 令变量从from到to按照step进行线性变化并传递到块中
  154.   def do_by_step(from, to, step)
  155.     if block_given?
  156.       i = from
  157.       until i >= to
  158.         yield i
  159.         i += step
  160.       end
  161.     else
  162.       to_enum(__method__, from, to, step)
  163.     end
  164.   end
  165.  
  166.   def gets(*args)
  167.     $stdin.gets(*args)
  168.   end
  169.  
  170.   def Vector(*args)
  171.     Vector.new(*args)
  172.   end
  173. end
  174.  
  175. class Bitmap
  176.  
  177.   # 初始化
  178.   # 支持向量表示
  179.   alias ulysses201811181708_initialize initialize
  180.   def initialize(*args)
  181.     args = if args.size == 2 || args[0].is_a?(String)
  182.       args
  183.     elsif args.size == 1
  184.       [args[0].x, args[0].y]
  185.     else
  186.       [0, 0]
  187.     end
  188.     ulysses201811181708_initialize(*args)
  189.   end
  190.  
  191.   # 填充一个圆
  192.   def fill_circle(center, radius, color)
  193.     i_max = (radius * 707) / 1000 + 1
  194.     square_distance_max = radius * radius + radius / 2
  195.     x = radius
  196.     fill_rect(center.x - radius, center.y, 2 * radius, 1, color)
  197.     for i in 1..i_max
  198.       if Vector.new(center.x, i).square_length > square_distance_max
  199.         if x > i_max
  200.           fill_rect(center.x - i + 1, center.y + x, 2 * (i - 1), 1, color)
  201.           fill_rect(center.x - i + 1, center.y - x, 2 * (i - 1), 1, color)
  202.         end
  203.         x -= 1
  204.       end
  205.       fill_rect(center.x - x, center.y + i, 2 * x, 1, color)
  206.       fill_rect(center.x - x, center.y - i, 2 * x, 1, color)
  207.     end
  208.   end
  209.  
  210.   # 用一条1像素宽的线段联结两点
  211.   def draw_line(point1, point2, color)
  212.     difference = point2 - point1
  213.     abs_difference = difference.abs
  214.     total_step = abs_difference.max
  215.     delta = difference * (1.0 / total_step)
  216.     vector = point1
  217.     (total_step.to_i + 1).times do
  218.       set_pixel(vector, color)
  219.       vector += delta
  220.     end
  221.   end
  222.  
  223.   alias ulysses201811182036_set_pixel set_pixel
  224.   def set_pixel(*args)
  225.     args = case args.size
  226.     when 3
  227.       args
  228.     when 2
  229.       [args[0].x, args[0].y, args[1]]
  230.     end
  231.     ulysses201811182036_set_pixel(*args)
  232.   end
  233.  
  234.   def text_vector(text)
  235.     text_size(text).size
  236.   end
  237.  
  238.   def size
  239.     Vector.new(width, height)
  240.   end
  241.  
  242.   def size=(size)
  243.     self.rect.size = size
  244.   end
  245.  
  246.   alias ulysses201811181952_draw_text draw_text
  247.   def draw_text(*args)
  248.     args = case args[0]
  249.     when Numeric, Rect
  250.       args
  251.     when Vector
  252.       a = [args[0].x, args[0].y, args[1].x, args[1].y, args[2]]
  253.       a.push(args[3]) if args.size >= 4
  254.       a
  255.     end
  256.     ulysses201811181952_draw_text(*args)
  257.   end
  258. end
  259.  
  260. class Sprite
  261.  
  262.   def position=(position)
  263.     self.x = position.x
  264.     self.y = position.y
  265.   end
  266. end
  267.  
  268. class Viewport
  269.  
  270.   # 让add_fast_layer接受默认参数blend_type = 0
  271.   alias ulysses201812021851_add_fast_layer add_fast_layer
  272.   def add_fast_layer(z, blend_type = 0)
  273.     ulysses201812021851_add_fast_layer(z, blend_type)
  274.   end
  275. end
  276.  
  277. # 重写了Input模块
  278. # 支持全键盘和鼠标按键
  279. # 如果不需要判断鼠标位置的话,可以不update
  280. module Input
  281.  
  282.   REPEAT_TIME = 4 # 当key被按超过此数时,repeat?(key) == true
  283.   GetKeyState = Win32API.new("user32", "GetAsyncKeyState", ['I'], 'I')
  284.  
  285.   @key_states = {}
  286.   @key_repeat_times = {}
  287.  
  288.   def self.press?(key)
  289.     key < 0x08 ? Mouse.press?(key) : GetKeyState.call(key) != 0
  290.   end
  291.  
  292.   def self.repeat?(key)
  293.     if press?(key)
  294.       unless @key_repeat_times[key]
  295.         @key_repeat_times[key] = 0
  296.         return true
  297.       end
  298.       @key_repeat_times[key] += 1
  299.     else
  300.       @key_repeat_times[key] = nil
  301.       @key_states[key] = 0
  302.     end
  303.     if !@key_repeat_times[key].nil? && @key_repeat_times[key] > REPEAT_TIME
  304.       @key_repeat_times[key] = 0
  305.       return true
  306.     end
  307.     false
  308.   end
  309.  
  310.   def self.trigger?(key)
  311.     if press?(key)
  312.       return false if @key_states[key] == 1
  313.       @key_states[key] = 1
  314.       true
  315.     else
  316.       @key_states[key] = 0
  317.       false
  318.     end
  319.   end
  320.  
  321.   def self.update
  322.     Mouse.update
  323.   end
  324. end
  325.  
  326. class << Graphics
  327.  
  328.   def size
  329.     Vector.new(width, height)
  330.   end
  331.  
  332.   alias ulysses201811251830_resize_screen resize_screen
  333.   def resize_screen(*args)
  334.     case args.size
  335.     when 2
  336.       ulysses201811251830_resize_screen(*args)
  337.     when 1
  338.       ulysses201811251830_resize_screen(args[0].x, args[0].y)
  339.     end
  340.   end
  341. end
  342.  
  343. Graphics.resize_screen(1024, 768) # 更改分辨率
  344.  
  345. module Mouse
  346.  
  347.   def self.position
  348.     Vector.new(x, y)
  349.   end
  350. end
  351.  
  352. # 封装为模块的场景
  353. module Scene
  354.  
  355.   # 绘制控制点的参数
  356.   POINTS_RADIUS = 3
  357.   POINTS_COLOR = Color.new(255, 255, 255, 255)
  358.   POINTS_Z = 10
  359.   # 绘制曲线的参数
  360.   CURVE_COLOR = Color.new(255, 255, 255, 255)
  361.   CURVE_Z = 0
  362.   # 绘制线段的参数
  363.   LINES_COLOR = Color.new(255, 255, 255, 127)
  364.   LINES_Z = -10
  365.   # 用于调整绘制的范围和精度
  366.   T_BEGINNING = 0.0
  367.   T_END = 1.0
  368.   T_STEP = 0.01
  369.   UPDATE_STEPS = 5
  370.   TEMP_BITMAP = Bitmap.new(32, 32) # 临时位图,用于获取文字大小
  371.   # 按键
  372.   CREATE_CONTROL_POINT_KEY = 0x01 # left
  373.   DELETE_CONTROL_POINT_KEY = 0x02 # right
  374.   FAST_MODE_KEY = 0x41 # A
  375.   LINES_VISIBLE_KEY = 0x42 # B
  376.   CONTROL_POINTS_VISIBLE_KEY = 0x43 # C
  377.  
  378.   # 显示端口
  379.   @viewport = Viewport.new
  380.   @viewport.add_fast_layer(POINTS_Z)
  381.   # 曲线
  382.   @curve_sprite = Sprite.new(@viewport)
  383.   @curve_sprite.bitmap = Bitmap.new(Graphics.size)
  384.   @curve_sprite.z = CURVE_Z
  385.   # 线段
  386.   @lines_sprite = Sprite.new(@viewport)
  387.   @lines_sprite.bitmap = Bitmap.new(Graphics.size)
  388.   @lines_sprite.z = LINES_Z
  389.   # 控制点
  390.   @control_points = []
  391.   @control_point_sprites = []
  392.   # 模式控制
  393.   @lines_visible = true
  394.   @control_points_visible = true
  395.   @fast_mode = false
  396.   # 阻断刷新控制
  397.   @covering_drawing = 0
  398.  
  399.   # 创建控制点
  400.   def self.create_control_point(point)
  401.     sprite = Sprite.new(@viewport)
  402.     sprite.visible = @control_points_visible
  403.     radius_vector = Vector.new(POINTS_RADIUS)
  404.     text_vector = TEMP_BITMAP.text_vector(@control_points.size)
  405.     radius_text_vector = radius_vector + text_vector
  406.     sprite.bitmap = Bitmap.new(radius_text_vector + radius_vector)
  407.     sprite.bitmap.font.color = POINTS_COLOR
  408.     x_flip = (point + radius_text_vector).x > Graphics.width
  409.     y_flip = (point + radius_text_vector).y > Graphics.height
  410.     excursion = Vector.new
  411.     excursion.x = x_flip ? radius_text_vector.x : radius_vector.x
  412.     excursion.y = y_flip ? radius_text_vector.y : radius_vector.y
  413.     sprite.position = point - excursion
  414.     sprite.bitmap.fill_circle(excursion, POINTS_RADIUS, POINTS_COLOR)
  415.     text_position = Vector.new
  416.     text_position.x = x_flip ? 0 : radius_vector.x * 2
  417.     text_position.y = y_flip ? 0 : radius_vector.y * 2
  418.     sprite.bitmap.draw_text(text_position, text_vector, @control_points.size)
  419.     sprite.z = POINTS_Z
  420.     @control_point_sprites.push(sprite)
  421.     @control_points.push(point)
  422.     refresh_graph
  423.     point
  424.   end
  425.  
  426.   # 删除上一个控制点
  427.   def self.delete_control_point
  428.     return if @control_points.empty?
  429.     point = @control_points.pop
  430.     sprite = @control_point_sprites.pop
  431.     sprite.bitmap.dispose
  432.     sprite.dispose
  433.     refresh_graph
  434.     point
  435.   end
  436.  
  437.   # 刷新图形
  438.   # 该方法在非快速模式下会阻塞,但update不会停且可以被打断
  439.   def self.refresh_graph
  440.     @covering_drawing += 1
  441.     @curve_sprite.bitmap.clear
  442.     return if @control_points.empty?
  443.     graph_points = []
  444.     steps_count = 0
  445.     do_by_step(T_BEGINNING, T_END, T_STEP) do |t|
  446.       will_update = !@fast_mode && (steps_count += 1) >= UPDATE_STEPS
  447.       graph_points.push(next_graph_point(t, will_update))
  448.       if graph_points.size > 1
  449.         @curve_sprite.bitmap.draw_line(*graph_points.last(2), CURVE_COLOR)
  450.       end
  451.       if will_update
  452.         steps_count = 0
  453.         last_covering_drawing = @covering_drawing
  454.         update
  455.         return if @covering_drawing > last_covering_drawing
  456.       end
  457.     end
  458.     connect_control_points_with_lines
  459.   end
  460.  
  461.   # 根据t返回曲线上的点坐标
  462.   # 若@lines_visible && will_update则会绘制线段
  463.   def self.next_graph_point(t, will_update = false)
  464.     is_drawing = @lines_visible && will_update
  465.     @lines_sprite.bitmap.clear if is_drawing
  466.     sequences = [@control_points]
  467.     (@control_points.size - 1).times do |i|
  468.       last_sequence = sequences.last
  469.       sequences.push([])
  470.       (last_sequence.size - 1).times do |j|
  471.         if is_drawing
  472.           @lines_sprite.bitmap.draw_line(*last_sequence[j, 2], LINES_COLOR)
  473.         end
  474.         sequences.last.push(Math.definite_proportion(*last_sequence[j, 2], t))
  475.       end
  476.     end
  477.     sequences.last.first
  478.   end
  479.  
  480.   # 用线段将控制点联结
  481.   def self.connect_control_points_with_lines
  482.     @lines_sprite.bitmap.clear
  483.     (@control_points.size - 1).times do |i|
  484.       @lines_sprite.bitmap.draw_line(*@control_points[i, 2], LINES_COLOR)
  485.     end
  486.     nil
  487.   end
  488.  
  489.   # 切换线段可见
  490.   def self.toggle_lines_visible
  491.     @lines_visible = !@lines_visible
  492.     @lines_sprite.visible = @lines_visible
  493.   end
  494.  
  495.   # 切换控制点可见
  496.   def self.toggle_points_visible
  497.     @control_points_visible = !@control_points_visible
  498.     @control_point_sprites.each do |sprite|
  499.       sprite.visible = @control_points_visible
  500.     end
  501.   end
  502.  
  503.   # 切换快速模式
  504.   def self.toggle_fast_mode
  505.     @fast_mode = !@fast_mode
  506.   end
  507.  
  508.   # 基础更新,必须每帧调用
  509.   def self.update_basic
  510.     Graphics.update
  511.     Input.update
  512.   end
  513.  
  514.   # 更新,需每帧调用
  515.   def self.update
  516.     update_basic
  517.     if Input.trigger?(CREATE_CONTROL_POINT_KEY)
  518.       create_control_point(Mouse.position)
  519.     elsif Input.trigger?(DELETE_CONTROL_POINT_KEY)
  520.       delete_control_point
  521.     elsif Input.trigger?(FAST_MODE_KEY)
  522.       toggle_fast_mode
  523.     elsif Input.trigger?(LINES_VISIBLE_KEY)
  524.       toggle_lines_visible
  525.     elsif Input.trigger?(CONTROL_POINTS_VISIBLE_KEY)
  526.       toggle_points_visible
  527.     end
  528.   end
  529.  
  530.   # 简单的irb
  531.   def self.simple_irb_start
  532.     Thread.start do
  533.       ans = nil
  534.       loop { puts("=> #{(ans = eval(gets)).inspect}") rescue puts($!.message) }
  535.     end
  536.   end
  537.  
  538.   # 主进程
  539.   def self.main
  540.     simple_irb_start
  541.     loop { update }
  542.   end
  543. end
  544.  
  545. # 入口
  546. Scene.main
更新了很多地方,懒得说了,依赖这玩意https://rpg.blue/thread-400462-1-1.html

评分

参与人数 5+5 收起 理由
kirh_036 + 1 芳芳醋虾
Kim_Shyuen + 1 雖然不是很明白 但是好像很厲害.
百里_飞柳 + 1 有丶东西
KB.Driver + 1 精品文章
张咚咚 + 1 精品文章

查看全部评分

小仙女一枚~

Lv2.观梦者

梦石
0
星屑
735
在线时间
886 小时
注册时间
2012-5-24
帖子
953
2
发表于 2018-11-18 22:18:55 | 只看该作者
厉害啊太强了。。。。。。
回复 支持 反对

使用道具 举报

Lv5.捕梦者

梦石
10
星屑
39440
在线时间
1914 小时
注册时间
2010-11-14
帖子
3315

R考场第七期纪念奖

3
发表于 2018-11-18 23:19:03 | 只看该作者
太强了……
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-4-23 22:09

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表