File: term_plasma

package info (click to toggle)
ruby-term-ansicolor 1.11.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 332 kB
  • sloc: ruby: 2,138; makefile: 10
file content (97 lines) | stat: -rwxr-xr-x 2,661 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#!/usr/bin/env ruby

require 'tins/go'
include Tins::GO
require 'term/ansicolor'
include Term::ANSIColor
Term::ANSIColor.true_coloring = ENV['COLORTERM'] =~ /\A(truecolor|24bit)\z/
include Math

# Generates a palette of 256 colors based on sine waves
#
# @return [Array<Array<Integer>>] An array of arrays, each containing
#    three integers representing the RGB values of a color.
def generate_palette
  (0..255).map { |i|
    [
      128 + 128 * sin(PI * i / 32.0),
      128 + 128 * sin(PI * i / 64.0),
      128 + 128 * sin(PI * i / 128.0),
    ].map { _1.clamp(0, 255).round }
  }
end

# Resets the terminal to its original state, and assigns width $w and height
# $h.
def full_reset
  $w, $h = Tins::Terminal.cols, Tins::Terminal.lines
  $h *= 2
  print reset, clear_screen, move_home, hide_cursor
end

# Generates a screen based on a plasma.
#
# @param plasma [Array<Array<Integer>>] An array of arrays, each containing
#    three integers representing the RGB values of a color.
# @return [String] The string representation of the screen, each character
#    representing a pixel on the screen with the corresponding color.
def generate_screen(plasma)
  screen = ''
  0.step($h - 1, 2) do |y|
    0.upto($w - 1) do |x|
      screen << color(plasma[y][x]) + on_color(plasma[y + 1][x]) + ?▀
    end
  end
  screen
end

# Generates a plasma generated based on sine waves
#
# @param now [Float] A value based on the current time in seconds
# @return [Array<Array<Integer>>] An array of arrays, each containing
#    three integers representing the RGB values of a color.
def generate_plasma(now)
  plasma = Array.new($h) { [ nil ] * $w }
  0.upto($h - 1) do |y|
    0.upto($w - 1) do |x|
      x, y = x.to_f, y.to_f
      color = (
        128.0 + (128.0 * sin((x / 7.0) - 3.0 * cos(now / 2.0))) +
        128.0 + (128.0 * sin((y / 13.0) - 2.0 * sin(now))) +
        128.0 + (128.0 * sin(hypot((x - $w / 3.0), (y - $h / 2.0)) / 5.0)) +
        128.0 + (128.0 * sin((hypot(x, y) / 5.0) - sin(now / 3.0)))
      ) / 4.0
      plasma[y][x] = $palette[(color + now).round % $palette.size]
    end
  end
  plasma
end

$opts = go('n:')

$palette = generate_palette

begin
  $full_reset = true
  trap(:SIGWINCH) { $full_reset = true }

  loop do
    if $full_reset
      $full_reset = false
      full_reset
    end

    now    = Time.now.to_f / ($opts[?n]&.to_f || 1)
    plasma = generate_plasma(now)
    print move_home, generate_screen(plasma), reset

    if n = $opts[?n]&.to_f
      sleep n
    else
      print move_to_column(1), erase_in_line, show_cursor
      exit
    end
  end
rescue Interrupt
  print reset, clear_screen, move_home, show_cursor
end