spinrite.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. package main
  2. import (
  3. "red-green/door"
  4. )
  5. type SpinRite struct {
  6. Width uint8 // Width of the animation (must be odd)
  7. Length uint8 // Width of the worm (must be odd)
  8. Color string // Color (default CYAN ON BLUE)
  9. OutputB []byte // Output CP437/bytes (Width)
  10. OutputR []rune // Output Unicode (Width)
  11. Buffer []uint8 // Output calculate buffer (Width)
  12. Runes []rune // blank, center, top, bottom, both
  13. Bytes []byte // blank, center, top, bottom, both
  14. CenterPos uint8 // Center Position (Width - 1) / 2
  15. StartPos uint8 // Starting Position (Length -1) / 2
  16. Index uint8 // Index of current iteration
  17. }
  18. func SpinRiteInit(width uint8, length uint8, color string) SpinRite {
  19. if color == "" {
  20. color = door.ColorText("CYAN ON BLUE")
  21. }
  22. var center uint8 = ((width - 1) / 2)
  23. var start uint8 = ((length - 1) / 2)
  24. var result SpinRite = SpinRite{Width: width,
  25. Length: length,
  26. Color: color,
  27. CenterPos: center,
  28. StartPos: start,
  29. Buffer: make([]uint8, width),
  30. Index: 0}
  31. if door.Unicode {
  32. result.OutputR = make([]rune, width)
  33. result.Runes = []rune{' ', '\u221e', '\u2580', '\u2584', '\u2588'}
  34. } else {
  35. result.OutputB = make([]byte, width)
  36. result.Bytes = []byte{' ', 0xec, 0xdf, 0xdc, 0xdb}
  37. }
  38. return result
  39. }
  40. func (sr *SpinRite) PosToIndex(pos int8, top bool) (index uint8, level bool) {
  41. if top {
  42. if pos >= int8(sr.Width) {
  43. // wrap around
  44. level = !top
  45. idx := int8(sr.Width) + (int8(sr.Width) - (pos + 1))
  46. index = uint8(idx)
  47. } else {
  48. level = top
  49. index = uint8(pos)
  50. }
  51. } else {
  52. // bottom
  53. if pos < 0 {
  54. level = !top
  55. pos++
  56. index = uint8(-pos)
  57. } else {
  58. level = top
  59. index = uint8(pos)
  60. }
  61. }
  62. return
  63. }
  64. func (sr *SpinRite) Calculate() {
  65. for i := range sr.Buffer {
  66. sr.Buffer[i] = 0
  67. }
  68. sr.Buffer[sr.CenterPos] = 1
  69. // [ S C s ]
  70. var top int8 = int8(sr.CenterPos) - int8(sr.StartPos) + int8(sr.Index)
  71. var bottom int8 = int8(sr.CenterPos) + int8(sr.StartPos) - int8(sr.Index)
  72. var l int8
  73. for l = 0; l < int8(sr.Length); l++ {
  74. var index uint8
  75. var level bool
  76. index, level = sr.PosToIndex(top+l, true)
  77. // log.Println("TOP", l, top+l, index, level)
  78. if level {
  79. sr.Buffer[index] |= 0x02
  80. } else {
  81. sr.Buffer[index] |= 0x04
  82. }
  83. index, level = sr.PosToIndex(bottom-l, false)
  84. // log.Println("BOT", l, bottom-l, index, level)
  85. if level {
  86. sr.Buffer[index] |= 0x02
  87. } else {
  88. sr.Buffer[index] |= 0x04
  89. }
  90. }
  91. // log.Println("Index", sr.Index, "Buffer", sr.Buffer)
  92. var reset bool = true
  93. // Convert from buffer to output
  94. if door.Unicode {
  95. for l = 0; l < int8(sr.Width); l++ {
  96. switch sr.Buffer[l] {
  97. case 0:
  98. sr.OutputR[l] = sr.Runes[0]
  99. case 1:
  100. sr.OutputR[l] = sr.Runes[1]
  101. reset = false
  102. case 2, 3:
  103. sr.OutputR[l] = sr.Runes[2]
  104. reset = false
  105. case 4, 5:
  106. sr.OutputR[l] = sr.Runes[3]
  107. reset = false
  108. case 6, 7:
  109. sr.OutputR[l] = sr.Runes[4]
  110. }
  111. }
  112. } else {
  113. for l = 0; l < int8(sr.Width); l++ {
  114. switch sr.Buffer[l] {
  115. case 0:
  116. sr.OutputB[l] = sr.Bytes[0]
  117. case 1:
  118. sr.OutputB[l] = sr.Bytes[1]
  119. reset = false
  120. case 2, 3:
  121. sr.OutputB[l] = sr.Bytes[2]
  122. reset = false
  123. case 4, 5:
  124. sr.OutputB[l] = sr.Bytes[3]
  125. reset = false
  126. case 6, 7:
  127. sr.OutputB[l] = sr.Bytes[4]
  128. }
  129. }
  130. }
  131. if reset {
  132. // log.Println("RESET")
  133. sr.Index = 0
  134. }
  135. }
  136. func (sr *SpinRite) Output() string {
  137. var result string
  138. sr.Calculate()
  139. if door.Unicode {
  140. result = string(sr.OutputR)
  141. } else {
  142. result = string(sr.OutputB)
  143. }
  144. sr.Index++
  145. return sr.Color + result
  146. }
  147. /*
  148. Or possibly: · ∞
  149. [ █████ ]
  150. [ ▄▄███▀▀ ]
  151. [ ▄▄▄▄█▀▀▀▀ ]
  152. [ ▄▄▄▄▄•▀▀▀▀▀ ]
  153. [▄▄▄▄▄ • ▀▀▀▀▀]
  154. [█▄▄▄ • ▀▀▀█]
  155. [██▄ • ▀██]
  156. [██▀ • ▄██]
  157. [█▀▀▀ • ▄▄▄█]
  158. [█▀▀▀▀ • ▄▄▄▄█]
  159. [ ▀▀▀▀▀•▄▄▄▄▄ ]
  160. [ ▀▀▀▀█▄▄▄▄ ]
  161. [ ▀▀███▄▄ ]
  162. */