Optymalizacja wyświetlania
This commit is contained in:
		@@ -1,18 +1,43 @@
 | 
				
			|||||||
package main
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"flag"
 | 
				
			||||||
	"gol/gol"
 | 
						"gol/gol"
 | 
				
			||||||
	"gol/term"
 | 
						"gol/term"
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"os/signal"
 | 
						"os/signal"
 | 
				
			||||||
 | 
						"runtime/pprof"
 | 
				
			||||||
	"syscall"
 | 
						"syscall"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func main() {
 | 
					func main() {
 | 
				
			||||||
 | 
						cpuprofile := flag.String("cpuprofile", "", "write cpu profile to file")
 | 
				
			||||||
 | 
						flag.Parse()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Jeśli podano flagę cpuprofile, rozpocznij profilowanie
 | 
				
			||||||
 | 
						if *cpuprofile != "" {
 | 
				
			||||||
 | 
							f, err := os.Create(*cpuprofile)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.Fatal("could not create CPU profile: ", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							defer f.Close()
 | 
				
			||||||
 | 
							if err := pprof.StartCPUProfile(f); err != nil {
 | 
				
			||||||
 | 
								log.Fatal("could not start CPU profile: ", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							defer pprof.StopCPUProfile()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						game()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func game() {
 | 
				
			||||||
 | 
						// arenas - front one is printent, then new state is calculated into back one
 | 
				
			||||||
 | 
						// next front and back are switched
 | 
				
			||||||
	front := gol.New(20, 40)
 | 
						front := gol.New(20, 40)
 | 
				
			||||||
	back := gol.New(20, 40)
 | 
						back := gol.New(20, 40)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// draw initial objects
 | 
				
			||||||
	// glider
 | 
						// glider
 | 
				
			||||||
	front[0][3] = true
 | 
						front[0][3] = true
 | 
				
			||||||
	front[1][4] = true
 | 
						front[1][4] = true
 | 
				
			||||||
@@ -21,35 +46,40 @@ func main() {
 | 
				
			|||||||
	front[2][4] = true
 | 
						front[2][4] = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// cross
 | 
						// cross
 | 
				
			||||||
 | 
					 | 
				
			||||||
	front[16][21] = true
 | 
						front[16][21] = true
 | 
				
			||||||
	front[17][21] = true
 | 
						front[17][21] = true
 | 
				
			||||||
	front[18][21] = true
 | 
						front[18][21] = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// catch interrupt signals
 | 
				
			||||||
	sigs := make(chan os.Signal, 1)
 | 
						sigs := make(chan os.Signal, 1)
 | 
				
			||||||
	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
 | 
						signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// initialize screen
 | 
				
			||||||
	term.StartFullscreen()
 | 
						term.StartFullscreen()
 | 
				
			||||||
	term.TurnCursor(term.CursorOff)
 | 
						term.TurnCursor(term.CursorOff)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	loop := func() {
 | 
						defer restoreScreen()
 | 
				
			||||||
		ticker := time.NewTicker(250 * time.Millisecond)
 | 
					
 | 
				
			||||||
		defer ticker.Stop()
 | 
						// setup timer
 | 
				
			||||||
		for {
 | 
						ticker := time.NewTicker(250 * time.Millisecond)
 | 
				
			||||||
			term.GoHome()
 | 
						defer ticker.Stop()
 | 
				
			||||||
			front.PrintMe()
 | 
					
 | 
				
			||||||
			front.NextGen(back)
 | 
					mainLoop:
 | 
				
			||||||
			front, back = back, front
 | 
						for {
 | 
				
			||||||
			select {
 | 
							term.GoHome()
 | 
				
			||||||
			case <-sigs: // przerwanie
 | 
							front.PrintMe()
 | 
				
			||||||
				return
 | 
							front.NextGen(back)
 | 
				
			||||||
			case <-ticker.C: // upłynął czas do kolejnej generacji
 | 
							front, back = back, front // switch arenas
 | 
				
			||||||
			}
 | 
							select {
 | 
				
			||||||
 | 
							case <-sigs: // interrupt (Ctrl-C etc)
 | 
				
			||||||
 | 
								break mainLoop
 | 
				
			||||||
 | 
							case <-ticker.C: // wait for next tick
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	defer func() {
 | 
					}
 | 
				
			||||||
		term.FinishFullscreen()
 | 
					
 | 
				
			||||||
		term.TurnCursor(term.CursorOn)
 | 
					// restoreScreen switch back terminal to normal mode.
 | 
				
			||||||
	}()
 | 
					func restoreScreen() {
 | 
				
			||||||
	loop()
 | 
						term.FinishFullscreen()
 | 
				
			||||||
 | 
						term.TurnCursor(term.CursorOn)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										27
									
								
								gol/types.go
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								gol/types.go
									
									
									
									
									
								
							@@ -1,6 +1,10 @@
 | 
				
			|||||||
package gol
 | 
					package gol
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import "fmt"
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Arena [][]bool
 | 
					type Arena [][]bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -12,18 +16,31 @@ func New(ysize, xsize int) Arena {
 | 
				
			|||||||
	return arena
 | 
						return arena
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// bufPool
 | 
				
			||||||
 | 
					var bufPool = sync.Pool{
 | 
				
			||||||
 | 
						New: func() any {
 | 
				
			||||||
 | 
							return new(bytes.Buffer)
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (a Arena) PrintMe() {
 | 
					func (a Arena) PrintMe() {
 | 
				
			||||||
 | 
						b := bufPool.Get().(*bytes.Buffer)
 | 
				
			||||||
 | 
						b.Reset()
 | 
				
			||||||
 | 
						spriteOn := ([]byte)("\ue0b6\ue0b4")
 | 
				
			||||||
 | 
						spriteOff := ([]byte)("\u2022\u2022")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for i := 0; i < len(a); i++ {
 | 
						for i := 0; i < len(a); i++ {
 | 
				
			||||||
		for j := 0; j < len(a[0]); j++ {
 | 
							for j := 0; j < len(a[0]); j++ {
 | 
				
			||||||
			if a[i][j] {
 | 
								if a[i][j] {
 | 
				
			||||||
				fmt.Print("\ue0b6\ue0b4")
 | 
									b.Write(spriteOn)
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				//fmt.Print("\ue0b7\ue0b5")
 | 
									b.Write(spriteOff)
 | 
				
			||||||
				fmt.Print("\u2022\u2022")
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		fmt.Println()
 | 
							b.WriteRune('\n')
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						os.Stdout.Write(b.Bytes())
 | 
				
			||||||
 | 
						bufPool.Put(b)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (a Arena) NextGen(to Arena) {
 | 
					func (a Arena) NextGen(to Arena) {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										23
									
								
								term/term.go
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								term/term.go
									
									
									
									
									
								
							@@ -13,47 +13,48 @@ const (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// TurnCursor turns the cursor on and off according to the parameter.
 | 
					// TurnCursor turns the cursor on and off according to the parameter.
 | 
				
			||||||
func TurnCursor(onOff CursorFlag) {
 | 
					func TurnCursor(onOff CursorFlag) {
 | 
				
			||||||
	if onOff == CursorOn {
 | 
						switch onOff {
 | 
				
			||||||
		fmt.Printf("\033[?25h")
 | 
						case CursorOn:
 | 
				
			||||||
	} else {
 | 
							fmt.Print("\033[?25h")
 | 
				
			||||||
		fmt.Printf("\033[?25l")
 | 
						case CursorOff:
 | 
				
			||||||
 | 
							fmt.Print("\033[?25l")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ClearScreen clears current screen.
 | 
					// ClearScreen clears current screen.
 | 
				
			||||||
func ClearScreen() {
 | 
					func ClearScreen() {
 | 
				
			||||||
	fmt.Printf("\033[2J")
 | 
						fmt.Print("\033[2J")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ResetTerminal resets terminal (ESC c)
 | 
					// ResetTerminal resets terminal (ESC c)
 | 
				
			||||||
func ResetTerminal() {
 | 
					func ResetTerminal() {
 | 
				
			||||||
	fmt.Printf("\033c")
 | 
						fmt.Print("\033c")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GoHome moves cursor to the home position (upper left corner)
 | 
					// GoHome moves cursor to the home position (upper left corner)
 | 
				
			||||||
func GoHome() {
 | 
					func GoHome() {
 | 
				
			||||||
	fmt.Printf("\033[H")
 | 
						fmt.Print("\033[H")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SaveCursor saves curent position of the SaveCursor
 | 
					// SaveCursor saves curent position of the SaveCursor
 | 
				
			||||||
func SaveCursor() {
 | 
					func SaveCursor() {
 | 
				
			||||||
	fmt.Printf("\033[s")
 | 
						fmt.Print("\033[s")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RestoreCursor restore cursor to the position saved previously with SaveCursor().
 | 
					// RestoreCursor restore cursor to the position saved previously with SaveCursor().
 | 
				
			||||||
func RestoreCursor() {
 | 
					func RestoreCursor() {
 | 
				
			||||||
	fmt.Printf("\033[u")
 | 
						fmt.Print("\033[u")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// EnableAlternateScreen switches the terminal to the alternative screen.
 | 
					// EnableAlternateScreen switches the terminal to the alternative screen.
 | 
				
			||||||
// The alternative screen doesn't have the scroll buffer.
 | 
					// The alternative screen doesn't have the scroll buffer.
 | 
				
			||||||
func EnableAlternateScreen() {
 | 
					func EnableAlternateScreen() {
 | 
				
			||||||
	fmt.Printf("\033[?1049h")
 | 
						fmt.Print("\033[?1049h")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DiableAlternateScreen switches the terminal to the primary screen.
 | 
					// DiableAlternateScreen switches the terminal to the primary screen.
 | 
				
			||||||
func DisableAlternateScreen() {
 | 
					func DisableAlternateScreen() {
 | 
				
			||||||
	fmt.Printf("\033[?1049l")
 | 
						fmt.Print("\033[?1049l")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// StartFullscreen saves the cursor, enables alternate screen and clears it.
 | 
					// StartFullscreen saves the cursor, enables alternate screen and clears it.
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user