starfield.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. package main
  2. import (
  3. "fmt"
  4. "math/rand"
  5. "red-green/door"
  6. "strings"
  7. "time"
  8. "github.com/seehuhn/mt19937"
  9. )
  10. type StarPos struct {
  11. Y int
  12. X int
  13. }
  14. type StarInfo struct {
  15. Symbol int
  16. Color bool
  17. }
  18. type StarField struct {
  19. RNG *rand.Rand
  20. MX int
  21. MY int
  22. Sky map[StarPos]StarInfo
  23. }
  24. func (s *StarField) make_pos() StarPos {
  25. for {
  26. pos := StarPos{X: s.RNG.Intn(s.MX), Y: s.RNG.Intn(s.MY)}
  27. _, found := (*s).Sky[pos]
  28. if !found {
  29. return pos
  30. }
  31. }
  32. }
  33. func (s *StarField) Regenerate() {
  34. s.MX = door.Width
  35. s.MY = door.Height
  36. s.RNG = rand.New(mt19937.New())
  37. s.RNG.Seed(time.Now().UnixNano())
  38. max_stars := ((s.MX * s.MY) / 40)
  39. s.Sky = make(map[StarPos]StarInfo, max_stars)
  40. for i := 0; i < max_stars; i++ {
  41. pos := s.make_pos()
  42. info := StarInfo{Symbol: i % 2, Color: i%5 < 2}
  43. s.Sky[pos] = info
  44. }
  45. }
  46. func (s *StarField) Display(d *door.Door) {
  47. white := door.ColorText("WHITE")
  48. dark := door.ColorText("BOLD BLACK")
  49. d.Write(door.Reset + door.Clrscr)
  50. var stars [2]string
  51. stars[0] = "."
  52. if door.Unicode {
  53. stars[1] = "\u2219"
  54. } else {
  55. stars[1] = "\xf9"
  56. }
  57. var i int = 0
  58. var last_pos StarPos
  59. // maps in go are not sorted
  60. for pos, info := range s.Sky {
  61. use_goto := true
  62. if i != 0 {
  63. if pos.Y == last_pos.Y {
  64. dx := pos.X - last_pos.X
  65. // Sometimes pos.X < last_pos.X
  66. if dx == 0 {
  67. use_goto = false
  68. } else {
  69. if dx < 0 {
  70. // handle negative
  71. // fmt.Printf("from %#v to %#v\n", last_pos, pos)
  72. dx = -dx
  73. if dx < 5 {
  74. d.Write(strings.Repeat("\x08", dx))
  75. } else {
  76. d.Write(fmt.Sprintf("\x1b[%dD", dx))
  77. }
  78. use_goto = false
  79. } else {
  80. if dx < 5 {
  81. d.Write(strings.Repeat(" ", dx))
  82. } else {
  83. d.Write(fmt.Sprintf("\x1b[%dC", dx))
  84. }
  85. use_goto = false
  86. }
  87. }
  88. }
  89. }
  90. if use_goto {
  91. d.Write(door.Goto(pos.X, pos.Y))
  92. }
  93. if info.Color {
  94. d.Write(dark)
  95. } else {
  96. d.Write(white)
  97. }
  98. d.Write(stars[info.Symbol])
  99. last_pos = pos
  100. last_pos.X++
  101. i++
  102. }
  103. }