starfield.go 1.9 KB

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