Optymalizacja wyświetlania
This commit is contained in:
		@@ -1,18 +1,43 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"flag"
 | 
			
		||||
	"gol/gol"
 | 
			
		||||
	"gol/term"
 | 
			
		||||
	"log"
 | 
			
		||||
	"os"
 | 
			
		||||
	"os/signal"
 | 
			
		||||
	"runtime/pprof"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
	back := gol.New(20, 40)
 | 
			
		||||
 | 
			
		||||
	// draw initial objects
 | 
			
		||||
	// glider
 | 
			
		||||
	front[0][3] = true
 | 
			
		||||
	front[1][4] = true
 | 
			
		||||
@@ -21,35 +46,40 @@ func main() {
 | 
			
		||||
	front[2][4] = true
 | 
			
		||||
 | 
			
		||||
	// cross
 | 
			
		||||
 | 
			
		||||
	front[16][21] = true
 | 
			
		||||
	front[17][21] = true
 | 
			
		||||
	front[18][21] = true
 | 
			
		||||
 | 
			
		||||
	// catch interrupt signals
 | 
			
		||||
	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.TurnCursor(term.CursorOff)
 | 
			
		||||
 | 
			
		||||
	loop := func() {
 | 
			
		||||
		ticker := time.NewTicker(250 * time.Millisecond)
 | 
			
		||||
		defer ticker.Stop()
 | 
			
		||||
		for {
 | 
			
		||||
			term.GoHome()
 | 
			
		||||
			front.PrintMe()
 | 
			
		||||
			front.NextGen(back)
 | 
			
		||||
			front, back = back, front
 | 
			
		||||
			select {
 | 
			
		||||
			case <-sigs: // przerwanie
 | 
			
		||||
				return
 | 
			
		||||
			case <-ticker.C: // upłynął czas do kolejnej generacji
 | 
			
		||||
			}
 | 
			
		||||
	defer restoreScreen()
 | 
			
		||||
 | 
			
		||||
	// setup timer
 | 
			
		||||
	ticker := time.NewTicker(250 * time.Millisecond)
 | 
			
		||||
	defer ticker.Stop()
 | 
			
		||||
 | 
			
		||||
mainLoop:
 | 
			
		||||
	for {
 | 
			
		||||
		term.GoHome()
 | 
			
		||||
		front.PrintMe()
 | 
			
		||||
		front.NextGen(back)
 | 
			
		||||
		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)
 | 
			
		||||
	}()
 | 
			
		||||
	loop()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// restoreScreen switch back terminal to normal mode.
 | 
			
		||||
func restoreScreen() {
 | 
			
		||||
	term.FinishFullscreen()
 | 
			
		||||
	term.TurnCursor(term.CursorOn)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										27
									
								
								gol/types.go
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								gol/types.go
									
									
									
									
									
								
							@@ -1,6 +1,10 @@
 | 
			
		||||
package gol
 | 
			
		||||
 | 
			
		||||
import "fmt"
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"os"
 | 
			
		||||
	"sync"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Arena [][]bool
 | 
			
		||||
 | 
			
		||||
@@ -12,18 +16,31 @@ func New(ysize, xsize int) Arena {
 | 
			
		||||
	return arena
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// bufPool
 | 
			
		||||
var bufPool = sync.Pool{
 | 
			
		||||
	New: func() any {
 | 
			
		||||
		return new(bytes.Buffer)
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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 j := 0; j < len(a[0]); j++ {
 | 
			
		||||
			if a[i][j] {
 | 
			
		||||
				fmt.Print("\ue0b6\ue0b4")
 | 
			
		||||
				b.Write(spriteOn)
 | 
			
		||||
			} else {
 | 
			
		||||
				//fmt.Print("\ue0b7\ue0b5")
 | 
			
		||||
				fmt.Print("\u2022\u2022")
 | 
			
		||||
				b.Write(spriteOff)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		fmt.Println()
 | 
			
		||||
		b.WriteRune('\n')
 | 
			
		||||
	}
 | 
			
		||||
	os.Stdout.Write(b.Bytes())
 | 
			
		||||
	bufPool.Put(b)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
func TurnCursor(onOff CursorFlag) {
 | 
			
		||||
	if onOff == CursorOn {
 | 
			
		||||
		fmt.Printf("\033[?25h")
 | 
			
		||||
	} else {
 | 
			
		||||
		fmt.Printf("\033[?25l")
 | 
			
		||||
	switch onOff {
 | 
			
		||||
	case CursorOn:
 | 
			
		||||
		fmt.Print("\033[?25h")
 | 
			
		||||
	case CursorOff:
 | 
			
		||||
		fmt.Print("\033[?25l")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ClearScreen clears current screen.
 | 
			
		||||
func ClearScreen() {
 | 
			
		||||
	fmt.Printf("\033[2J")
 | 
			
		||||
	fmt.Print("\033[2J")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ResetTerminal resets terminal (ESC c)
 | 
			
		||||
func ResetTerminal() {
 | 
			
		||||
	fmt.Printf("\033c")
 | 
			
		||||
	fmt.Print("\033c")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GoHome moves cursor to the home position (upper left corner)
 | 
			
		||||
func GoHome() {
 | 
			
		||||
	fmt.Printf("\033[H")
 | 
			
		||||
	fmt.Print("\033[H")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SaveCursor saves curent position of the SaveCursor
 | 
			
		||||
func SaveCursor() {
 | 
			
		||||
	fmt.Printf("\033[s")
 | 
			
		||||
	fmt.Print("\033[s")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RestoreCursor restore cursor to the position saved previously with SaveCursor().
 | 
			
		||||
func RestoreCursor() {
 | 
			
		||||
	fmt.Printf("\033[u")
 | 
			
		||||
	fmt.Print("\033[u")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EnableAlternateScreen switches the terminal to the alternative screen.
 | 
			
		||||
// The alternative screen doesn't have the scroll buffer.
 | 
			
		||||
func EnableAlternateScreen() {
 | 
			
		||||
	fmt.Printf("\033[?1049h")
 | 
			
		||||
	fmt.Print("\033[?1049h")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DiableAlternateScreen switches the terminal to the primary screen.
 | 
			
		||||
func DisableAlternateScreen() {
 | 
			
		||||
	fmt.Printf("\033[?1049l")
 | 
			
		||||
	fmt.Print("\033[?1049l")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StartFullscreen saves the cursor, enables alternate screen and clears it.
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user