Skip to content

Commit

Permalink
rotation
Browse files Browse the repository at this point in the history
  • Loading branch information
Kuechlin committed Mar 13, 2024
1 parent 6e5c4a7 commit 8d774a8
Show file tree
Hide file tree
Showing 4 changed files with 310 additions and 52 deletions.
154 changes: 130 additions & 24 deletions field.go
Original file line number Diff line number Diff line change
@@ -1,63 +1,169 @@
package main

import (
"math/rand"
"strings"
)

const W = 10
const H = 20

var COLORS = map[int]int{
0: 0,
1: 10,
2: 20,
3: 40,
4: 50,
1: 1,
2: 2,
3: 4,
4: 5,
5: 6,
6: 7,
7: 8,
}

type Field struct {
Curr Piece
Curr Current
Cells [W * H]int
}

type Piece struct {
// r 0 ^
// r 1 >
// r 2 v
// r 3 <
type Current struct {
Id int
R int
X int
Y int
}
type Point struct {
X int
Y int
}

func idx(x int, y int) int {
return x + W*y
return idxw(x, y, W)
}
func idxw(x int, y int, w int) int {
return x + w*y
}

func contains(arr []Point, x int, y int) bool {
for _, p := range arr {
if p.X == x && p.Y == y {
return true
}
}
return false
}

func nextRotation(r int, offset int) int {
next := r + offset
if next > 3 {
return 0
}
return next
}

func (c *Current) getPoints(offsetX int, offsetY int, offsetR int) []Point {
p := pieces[c.Id]
m := p.ToMatrix(nextRotation(c.R, offsetR))

points := []Point{}

anchor := (p.Size + p.Size%2) / 2

for y := 0; y < p.Size; y++ {
for x := 0; x < p.Size; x++ {
if !m[y][x] {
continue
}
x1 := c.X - anchor + x + offsetX
y1 := c.Y - anchor + y + offsetY
points = append(points, Point{
X: x1,
Y: y1,
})
}
}

return points
}

func (f *Field) Place() {
for _, p := range f.Curr.getPoints(0, 0, 0) {
i := idx(p.X, p.Y)
f.Cells[i] = f.Curr.Id
}
}

func (f *Field) CollisionDown() bool {
y := f.Curr.Y + 1
next := idx(f.Curr.X, y)
return y >= H || f.Cells[next] != 0
func (f *Field) DropLines() int {
var lines []int
// find lines to drop
for y := 0; y < H; y++ {
full := true
for x := 0; x < W; x++ {
if f.Cells[idx(x, y)] == 0 {
full = false
}
}
if full {
lines = append(lines, idx(0, y))
}
}

if len(lines) == 0 {
return 0
}
// build new cells array
cells := make([]int, len(lines)*W)
last := 0
for _, i := range lines {
cells = append(cells, f.Cells[last:i]...)
last = i + W
}
cells = append(cells, f.Cells[last:]...)
// apply update
for i, val := range cells {
f.Cells[i] = val
}

return len(lines)
}
func (f *Field) CollisionLeft() bool {
x := f.Curr.X - 1
next := idx(x, f.Curr.Y)
return x < 0 || f.Cells[next] != 0

func (f *Field) Spawn() {
id := 1 + rand.Intn(7)
f.Curr = Current{
Id: id,
X: W / 2,
Y: 0,
}
}
func (f *Field) CollisionRight() bool {
x := f.Curr.X + 1
next := idx(x, f.Curr.Y)
return x >= W || f.Cells[next] != 0

func (f *Field) Collision(offsetX int, offsetY int, offsetR int) bool {
for _, p := range f.Curr.getPoints(offsetX, offsetY, offsetR) {
if p.X < 0 || p.X >= W || p.Y >= H {
return true
} else if p.Y < 0 {
continue
}
i := idx(p.X, p.Y)
if f.Cells[i] != 0 {
return true
}
}
return false
}

func (f *Field) String() []string {
lines := []string{}
lines = append(lines, "┌"+strings.Repeat("─", W*2)+"┐")
piece := idx(f.Curr.X, f.Curr.Y)
points := f.Curr.getPoints(0, 0, 0)
for y := 0; y < H; y++ {
value := "│"
for x := 0; x < W; x++ {
i := idx(x, y)
if i == piece {
if contains(points, x, y) {
value += block(COLORS[f.Curr.Id])
} else {
val := f.Cells[idx(x, y)]
i := idx(x, y)
val := f.Cells[i]
if val == 0 {
value += empty()
} else {
Expand Down
57 changes: 29 additions & 28 deletions game.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import (
"fmt"
"math/rand"
"os"
"time"
)
Expand All @@ -19,9 +18,9 @@ func NewGame(done *chan bool) *Game {
done: done,
ticker: time.NewTicker(time.Second),
field: Field{
Curr: Piece{
Curr: Current{
Id: 1,
X: 0,
X: W / 2,
Y: 0,
},
},
Expand Down Expand Up @@ -79,7 +78,7 @@ func (g *Game) inputs() {
if b[0] == 27 && b[1] == 91 {
switch b[2] {
case 65:
fmt.Println("up")
g.rotate()
case 66:
g.moveDown()
case 67:
Expand All @@ -91,13 +90,29 @@ func (g *Game) inputs() {
}
}

func (g *Game) rotate() {
if g.field.Collision(0, 0, 1) {
return
}
g.field.Curr.R = nextRotation(g.field.Curr.R, 1)
g.Redraw()
}

func (g *Game) moveDown() {
if g.field.CollisionDown() {
if g.field.Collision(0, 1, 0) {
// place block
i := idx(g.field.Curr.X, g.field.Curr.Y)
g.field.Cells[i] = g.field.Curr.Id
g.log("place block")
g.field.Place()
lines := g.field.DropLines()
if lines > 0 {
g.log(fmt.Sprintf("%d lines dropped", lines))
}
// Spawn next block
g.Spawn()
g.field.Spawn()
g.Redraw()
if g.field.Collision(0, 1, 0) {
g.End()
}
} else {
// move
g.log("move down")
Expand All @@ -107,7 +122,7 @@ func (g *Game) moveDown() {
}

func (g *Game) moveLeft() {
if g.field.CollisionLeft() {
if g.field.Collision(-1, 0, 0) {
return
}
g.log("move left")
Expand All @@ -116,30 +131,16 @@ func (g *Game) moveLeft() {
}

func (g *Game) moveRight() {
if g.field.CollisionRight() {
if g.field.Collision(1, 0, 0) {
return
}
g.log("move right")
g.field.Curr.X += 1
g.Redraw()
}

func (g *Game) Spawn() {
p := Piece{
X: W / 2,
Y: 0,
Id: 1 + rand.Intn(4),
}
i := idx(p.X, p.Y)

if g.field.Cells[i] != 0 {
// end game
fmt.Println("gg")
*g.done <- true
return
}

g.log(fmt.Sprintf("span %d at %d, %d", p.Id, p.X, p.Y))
g.field.Curr = p
g.Redraw()
func (g *Game) End() {
// end game
fmt.Println("gg")
*g.done <- true
}
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

var ticker *time.Ticker

// vsp +term
func main() {
exec.Command("stty", "-F", "/dev/tty", "cbreak", "min", "1").Run()
exec.Command("stty", "-F", "/dev/tty", "-echo").Run()
Expand Down
Loading

0 comments on commit 8d774a8

Please sign in to comment.