package game import ( "slices" "tetris/engine/graphics" ) const ( GRID_WIDTH = 10 GRID_HEIGHT = 16 ) type Grid [GRID_WIDTH * GRID_HEIGHT]Block func (Grid) Width() int32 { return GRID_WIDTH } func (Grid) Height() int32 { return GRID_HEIGHT } func (g Grid) At(x, y byte) Block { return g[uint16(x)+(uint16(y)*GRID_WIDTH)] } func (g Grid) Tile(x, y byte) graphics.Tile { return g.At(x, y).Tile() } func (g *Grid) Set(x, y byte, c Block) { (*g)[uint16(x)+(uint16(y)*GRID_WIDTH)] = c } func (g *Grid) ClearFullLines() byte { completed := byte(0) for y := int(g.Height() - 1); y >= 0; y-- { if g.IsLineFull(byte(y)) { completed++ g.ClearLine(byte(y)) } else if completed > 0 { g.MoveLineDown(byte(y), completed) } } return completed } func (g *Grid) FullLines() []byte { lines := []byte{} for y := byte(0); y < byte(g.Height()); y++ { if g.IsLineFull(y) { lines = append(lines, y) } } return lines } func (g *Grid) IsLineFull(y byte) bool { for x := range byte(g.Width()) { if g.At(x, y) == BLOCK_EMPTY { return false } } return true } func (g *Grid) MoveLinesDown(rows ...byte) { completed := byte(0) for y := int(g.Height() - 1); y >= 0; y-- { if slices.Contains(rows, byte(y)) { completed++ } else if completed > 0 { g.MoveLineDown(byte(y), completed) } } } func (g *Grid) MoveLineDown(y, num_lines byte) { w := uint16(g.Width()) src := uint16(y) * w dst := uint16(y+num_lines) * w copy(g[dst:dst+w], g[src:src+w]) clear(g[src : src+w]) } func (g *Grid) ClearLine(y byte) { w := uint16(g.Width()) n := uint16(y) * w clear(g[n : n+w]) }