123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- package main
- import (
- "fmt"
- "math/rand"
- "red-green/door"
- "strings"
- )
- type StarPos struct {
- Y int
- X int
- }
- type StarInfo struct {
- Symbol int
- Color bool
- }
- /*
- StarField holds the information needed to render a starfield.
- */
- type StarField struct {
- MX int
- MY int
- Sky map[StarPos]StarInfo
- }
- // Make a new StarPos in the StarField Sky.
- func (s *StarField) make_pos(RNG *rand.Rand) StarPos {
- for {
- pos := StarPos{X: RNG.Intn(s.MX), Y: RNG.Intn(s.MY)}
- _, found := (*s).Sky[pos]
- if !found {
- return pos
- }
- }
- }
- // Regenerate a StarField structure.
- // This uses make_pos to find a new unused position.
- // This needs a seeded rand.Rand.
- func (s *StarField) Regenerate(RNG *rand.Rand) {
- s.MX = door.Width
- s.MY = door.Height
- max_stars := ((s.MX * s.MY) / 40)
- s.Sky = make(map[StarPos]StarInfo, max_stars)
- for i := 0; i < max_stars; i++ {
- pos := s.make_pos(RNG)
- info := StarInfo{Symbol: i % 2, Color: i%5 < 2}
- s.Sky[pos] = info
- }
- }
- // Display StarField.
- // This optimizes the output. Uses CURSOR LEFT/RIGHT
- // \x1b[C or \x1b[D to optimize output.
- func (s *StarField) Display(d *door.Door) {
- white := door.ColorText("WHITE")
- dark := door.ColorText("BOLD BLACK")
- d.Write(door.Reset + door.Clrscr)
- var stars [2]string
- stars[0] = "."
- if door.Unicode {
- stars[1] = "\u2219"
- } else {
- stars[1] = "\xf9"
- }
- var i int = 0
- var last_pos StarPos
- // maps in go are not sorted
- for pos, info := range s.Sky {
- use_goto := true
- if i != 0 {
- if pos.Y == last_pos.Y {
- dx := pos.X - last_pos.X
- // Sometimes pos.X < last_pos.X
- if dx == 0 {
- use_goto = false
- } else {
- if dx < 0 {
- // handle negative
- // fmt.Printf("from %#v to %#v\n", last_pos, pos)
- dx = -dx
- if dx < 5 {
- d.Write(strings.Repeat("\x08", dx))
- } else {
- d.Write(fmt.Sprintf("\x1b[%dD", dx))
- }
- use_goto = false
- } else {
- if dx < 5 {
- d.Write(strings.Repeat(" ", dx))
- } else {
- d.Write(fmt.Sprintf("\x1b[%dC", dx))
- }
- use_goto = false
- }
- }
- }
- }
- if use_goto {
- d.Write(door.Goto(pos.X, pos.Y))
- }
- if info.Color {
- d.Write(dark)
- } else {
- d.Write(white)
- }
- d.Write(stars[info.Symbol])
- last_pos = pos
- last_pos.X++
- i++
- }
- }
|