Implement next and hold
This commit is contained in:
parent
d22fa6e189
commit
545a76109e
|
@ -8,7 +8,7 @@ type Piece struct {
|
||||||
Blocks []*Block
|
Blocks []*Block
|
||||||
}
|
}
|
||||||
|
|
||||||
var Pieces = []*Piece{
|
var Pieces = []Piece{
|
||||||
{
|
{
|
||||||
Blocks: []*Block{
|
Blocks: []*Block{
|
||||||
{rl.NewVector2(-1, 0), Cyan, false},
|
{rl.NewVector2(-1, 0), Cyan, false},
|
||||||
|
@ -67,8 +67,24 @@ var Pieces = []*Piece{
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Piece) Draw(pos rl.Vector2, scale rl.Vector2, offset rl.Vector2) {
|
func (p Piece) Draw(pos rl.Vector2, scale rl.Vector2, offset rl.Vector2) {
|
||||||
for _, block := range p.Blocks {
|
for _, block := range p.Blocks {
|
||||||
block.Draw(pos, scale, offset)
|
block.Draw(pos, scale, offset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetRandomPiece() *Piece {
|
||||||
|
base := Pieces[rl.GetRandomValue(0, int32(len(Pieces)-1))]
|
||||||
|
newPiece := &Piece{
|
||||||
|
Blocks: make([]*Block, 4),
|
||||||
|
}
|
||||||
|
for i, block := range base.Blocks {
|
||||||
|
newPiece.Blocks[i] = &Block{
|
||||||
|
Position: block.Position,
|
||||||
|
Color: block.Color,
|
||||||
|
LongBoi: block.LongBoi,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newPiece
|
||||||
|
}
|
||||||
|
|
100
game/board.go
100
game/board.go
|
@ -7,35 +7,30 @@ import (
|
||||||
"github.com/gen2brain/raylib-go/raylib"
|
"github.com/gen2brain/raylib-go/raylib"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Board interface {
|
type Board struct {
|
||||||
DescendActivePiece() bool
|
|
||||||
DropActivePiece() bool
|
|
||||||
MoveActivePiece(direction int)
|
|
||||||
RotateActivePiece(clockwise bool)
|
|
||||||
ClearLines()
|
|
||||||
Draw(offset, scale rl.Vector2)
|
|
||||||
}
|
|
||||||
|
|
||||||
type board struct {
|
|
||||||
Board [10][20]*elements.Block
|
Board [10][20]*elements.Block
|
||||||
|
|
||||||
ActivePiece *elements.Piece
|
ActivePiece *elements.Piece
|
||||||
ActivePiecePos rl.Vector2
|
ActivePiecePos rl.Vector2
|
||||||
NextPiece *elements.Piece
|
NextPiece *elements.Piece
|
||||||
|
HeldPiece *elements.Piece
|
||||||
|
AlreadyHeld bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ Board = (*board)(nil)
|
func InitBoard() *Board {
|
||||||
|
board := &Board{
|
||||||
func InitBoard() *board {
|
NextPiece: elements.GetRandomPiece(),
|
||||||
board := &board{}
|
}
|
||||||
board.newActivePiece()
|
board.getNextPiece()
|
||||||
|
|
||||||
return board
|
return board
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *board) newActivePiece() bool {
|
func (b *Board) getNextPiece() bool {
|
||||||
|
b.AlreadyHeld = false
|
||||||
b.ActivePiecePos = rl.NewVector2(5, 0)
|
b.ActivePiecePos = rl.NewVector2(5, 0)
|
||||||
b.ActivePiece = elements.Pieces[rl.GetRandomValue(0, int32(len(elements.Pieces)-1))]
|
b.ActivePiece = b.NextPiece
|
||||||
|
b.NextPiece = elements.GetRandomPiece()
|
||||||
for _, block := range b.ActivePiece.Blocks {
|
for _, block := range b.ActivePiece.Blocks {
|
||||||
newX, newY := b.ActivePiecePos.X+block.Position.X, b.ActivePiecePos.Y+block.Position.Y
|
newX, newY := b.ActivePiecePos.X+block.Position.X, b.ActivePiecePos.Y+block.Position.Y
|
||||||
if newY >= 0 && b.Board[int(newX)][int(newY)] != nil {
|
if newY >= 0 && b.Board[int(newX)][int(newY)] != nil {
|
||||||
|
@ -45,7 +40,7 @@ func (b *board) newActivePiece() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *board) setBlocksFromActivePiece() {
|
func (b *Board) setBlocksFromActivePiece() {
|
||||||
for _, block := range b.ActivePiece.Blocks {
|
for _, block := range b.ActivePiece.Blocks {
|
||||||
newX, newY := b.ActivePiecePos.X+block.Position.X, b.ActivePiecePos.Y+block.Position.Y
|
newX, newY := b.ActivePiecePos.X+block.Position.X, b.ActivePiecePos.Y+block.Position.Y
|
||||||
b.Board[int(newX)][int(newY)] = &elements.Block{
|
b.Board[int(newX)][int(newY)] = &elements.Block{
|
||||||
|
@ -55,7 +50,7 @@ func (b *board) setBlocksFromActivePiece() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *board) checkHorizontalCollision(left bool) bool {
|
func (b *Board) checkHorizontalCollision(left bool) bool {
|
||||||
for _, activeBlock := range b.ActivePiece.Blocks {
|
for _, activeBlock := range b.ActivePiece.Blocks {
|
||||||
xPos := int(b.ActivePiecePos.X + activeBlock.Position.X)
|
xPos := int(b.ActivePiecePos.X + activeBlock.Position.X)
|
||||||
yPos := int(b.ActivePiecePos.Y + activeBlock.Position.Y)
|
yPos := int(b.ActivePiecePos.Y + activeBlock.Position.Y)
|
||||||
|
@ -78,7 +73,7 @@ func (b *board) checkHorizontalCollision(left bool) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *board) descendActivePiece() bool {
|
func (b *Board) descendActivePiece() bool {
|
||||||
b.ActivePiecePos.Y += 1
|
b.ActivePiecePos.Y += 1
|
||||||
for _, activeBlock := range b.ActivePiece.Blocks {
|
for _, activeBlock := range b.ActivePiece.Blocks {
|
||||||
if b.ActivePiecePos.Y+activeBlock.Position.Y == 20 {
|
if b.ActivePiecePos.Y+activeBlock.Position.Y == 20 {
|
||||||
|
@ -98,23 +93,23 @@ func (b *board) descendActivePiece() bool {
|
||||||
|
|
||||||
// DescendActivePiece moves the piece down by one block. If the piece cannot move down, it will be placed on the board.
|
// DescendActivePiece moves the piece down by one block. If the piece cannot move down, it will be placed on the board.
|
||||||
// After that, a new piece will be generated. If the new piece cannot be placed, true is returned.
|
// After that, a new piece will be generated. If the new piece cannot be placed, true is returned.
|
||||||
func (b *board) DescendActivePiece() bool {
|
func (b *Board) DescendActivePiece() bool {
|
||||||
if b.descendActivePiece() {
|
if b.descendActivePiece() {
|
||||||
return b.newActivePiece()
|
return b.getNextPiece()
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// DropActivePiece moves the piece down until it cannot move down anymore. After that, a new piece will be generated.
|
// DropActivePiece moves the piece down until it cannot move down anymore. After that, a new piece will be generated.
|
||||||
// If the new piece cannot be placed, true is returned.
|
// If the new piece cannot be placed, true is returned.
|
||||||
func (b *board) DropActivePiece() bool {
|
func (b *Board) DropActivePiece() bool {
|
||||||
for !b.descendActivePiece() {
|
for !b.descendActivePiece() {
|
||||||
}
|
}
|
||||||
return b.newActivePiece()
|
return b.getNextPiece()
|
||||||
}
|
}
|
||||||
|
|
||||||
// MoveActivePiece moves the piece left or right. If the piece cannot move in the specified direction, nothing happens.
|
// MoveActivePiece moves the piece left or right. If the piece cannot move in the specified direction, nothing happens.
|
||||||
func (b *board) MoveActivePiece(direction int) {
|
func (b *Board) MoveActivePiece(direction int) {
|
||||||
if !b.checkHorizontalCollision(direction == -1) {
|
if !b.checkHorizontalCollision(direction == -1) {
|
||||||
b.ActivePiecePos.X += float32(direction)
|
b.ActivePiecePos.X += float32(direction)
|
||||||
}
|
}
|
||||||
|
@ -130,7 +125,7 @@ func getCollisionDepth(collisionDepth int, longBoi bool) int {
|
||||||
|
|
||||||
// RotateActivePiece rotates the piece clockwise or counter-clockwise. If the piece cannot rotate in the specified
|
// RotateActivePiece rotates the piece clockwise or counter-clockwise. If the piece cannot rotate in the specified
|
||||||
// direction, nothing happens.
|
// direction, nothing happens.
|
||||||
func (b *board) RotateActivePiece(clockwise bool) {
|
func (b *Board) RotateActivePiece(clockwise bool) {
|
||||||
if b.ActivePiece.Blocks[0].Color == elements.Yellow {
|
if b.ActivePiece.Blocks[0].Color == elements.Yellow {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -195,8 +190,22 @@ func (b *board) RotateActivePiece(clockwise bool) {
|
||||||
b.ActivePiece = tmpPiece
|
b.ActivePiece = tmpPiece
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Board) HoldPiece() {
|
||||||
|
if b.AlreadyHeld {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
b.AlreadyHeld = true
|
||||||
|
if b.HeldPiece == nil {
|
||||||
|
b.HeldPiece = b.ActivePiece
|
||||||
|
b.getNextPiece()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
b.HeldPiece, b.ActivePiece = b.ActivePiece, b.HeldPiece
|
||||||
|
b.ActivePiecePos = rl.NewVector2(5, 0)
|
||||||
|
}
|
||||||
|
|
||||||
// ClearLines clears all lines that are completely filled.
|
// ClearLines clears all lines that are completely filled.
|
||||||
func (g *board) ClearLines() {
|
func (g *Board) ClearLines() {
|
||||||
for y := 19; y >= 0; {
|
for y := 19; y >= 0; {
|
||||||
skip := false
|
skip := false
|
||||||
for x := 0; x < 10; x++ {
|
for x := 0; x < 10; x++ {
|
||||||
|
@ -225,7 +234,7 @@ func (g *board) ClearLines() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *board) drawGrid(offset, scale rl.Vector2) {
|
func (b *Board) DrawGrid(offset, scale rl.Vector2) {
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
rl.DrawLine(
|
rl.DrawLine(
|
||||||
int32(scale.X*float32(i)+offset.X),
|
int32(scale.X*float32(i)+offset.X),
|
||||||
|
@ -246,9 +255,38 @@ func (b *board) drawGrid(offset, scale rl.Vector2) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw draws the board with placed blocks and the active piece.
|
func (b *Board) drawUIPiece(piece *elements.Piece, position, scale rl.Vector2) {
|
||||||
func (b *board) Draw(offset rl.Vector2, scale rl.Vector2) {
|
centerOffset := rl.NewVector2(0, 0)
|
||||||
b.drawGrid(offset, scale)
|
for _, block := range piece.Blocks {
|
||||||
|
centerOffset = rl.Vector2Add(
|
||||||
|
centerOffset,
|
||||||
|
rl.Vector2Add(block.Position, rl.NewVector2(0.5, 0.5)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
centerOffset = rl.Vector2Divide(centerOffset, rl.NewVector2(4, 4))
|
||||||
|
centerOffset = rl.Vector2Add(centerOffset, rl.NewVector2(0, 1))
|
||||||
|
centerOffset = rl.Vector2Multiply(centerOffset, scale)
|
||||||
|
for _, block := range piece.Blocks {
|
||||||
|
block.Draw(rl.NewVector2(0, 1), scale, rl.Vector2Subtract(position, centerOffset))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DrawNextPiece draws the next piece in the UI at the specified position.
|
||||||
|
func (b *Board) DrawNextPiece(position, scale rl.Vector2) {
|
||||||
|
b.drawUIPiece(b.NextPiece, position, scale)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DrawHeldPiece draws the held piece in the UI at the specified position.
|
||||||
|
func (b *Board) DrawHeldPiece(position, scale rl.Vector2) {
|
||||||
|
if b.HeldPiece == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
b.drawUIPiece(b.HeldPiece, position, scale)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DrawBoard draws the board with placed blocks and the active piece.
|
||||||
|
func (b *Board) DrawBoard(offset rl.Vector2, scale rl.Vector2) {
|
||||||
|
// b.DrawGrid(offset, scale)
|
||||||
for i := 0; i < 20; i++ {
|
for i := 0; i < 20; i++ {
|
||||||
for j := 0; j < 10; j++ {
|
for j := 0; j < 10; j++ {
|
||||||
if b.Board[j][i] == nil {
|
if b.Board[j][i] == nil {
|
||||||
|
|
|
@ -16,7 +16,7 @@ type Game struct {
|
||||||
|
|
||||||
Scale rl.Vector2
|
Scale rl.Vector2
|
||||||
|
|
||||||
Board Board
|
Board *Board
|
||||||
UI *UI
|
UI *UI
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,6 +49,9 @@ func (g *Game) Update() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if rl.IsKeyPressed(rl.KeyC) {
|
||||||
|
g.Board.HoldPiece()
|
||||||
|
}
|
||||||
if rl.IsKeyPressed(rl.KeyI) {
|
if rl.IsKeyPressed(rl.KeyI) {
|
||||||
g.Board.MoveActivePiece(1)
|
g.Board.MoveActivePiece(1)
|
||||||
}
|
}
|
||||||
|
@ -77,7 +80,9 @@ func (g *Game) Draw() {
|
||||||
g.UI.Draw(g)
|
g.UI.Draw(g)
|
||||||
|
|
||||||
if !g.GameOver {
|
if !g.GameOver {
|
||||||
g.Board.Draw(g.UI.BoardOffset, g.Scale)
|
g.Board.DrawBoard(g.UI.BoardOffset, g.Scale)
|
||||||
|
g.Board.DrawNextPiece(g.UI.NextPiecePosition, g.Scale)
|
||||||
|
g.Board.DrawHeldPiece(g.UI.HeldPiecePosition, g.Scale)
|
||||||
} else {
|
} else {
|
||||||
rl.DrawText(
|
rl.DrawText(
|
||||||
"PRESS [ENTER] TO PLAY AGAIN",
|
"PRESS [ENTER] TO PLAY AGAIN",
|
||||||
|
|
35
game/ui.go
35
game/ui.go
|
@ -1,19 +1,21 @@
|
||||||
package game
|
package game
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// "fmt"
|
"fmt"
|
||||||
|
|
||||||
"gitea.theedgeofrage.com/theedgeofrage/yeetris/elements"
|
"gitea.theedgeofrage.com/theedgeofrage/yeetris/elements"
|
||||||
"github.com/gen2brain/raylib-go/raylib"
|
"github.com/gen2brain/raylib-go/raylib"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UI struct {
|
type UI struct {
|
||||||
ScreenWidth int32
|
ScreenWidth int32
|
||||||
ScreenHeight int32
|
ScreenHeight int32
|
||||||
BoardWidth int32
|
BoardWidth int32
|
||||||
BoardHeight int32
|
BoardHeight int32
|
||||||
BoardOffset rl.Vector2
|
BoardOffset rl.Vector2
|
||||||
UIOffsetWidth int32
|
UIOffsetWidth int32
|
||||||
|
NextPiecePosition rl.Vector2
|
||||||
|
HeldPiecePosition rl.Vector2
|
||||||
|
|
||||||
Score int
|
Score int
|
||||||
}
|
}
|
||||||
|
@ -26,12 +28,14 @@ func InitUI(scale rl.Vector2) *UI {
|
||||||
rl.InitWindow(screenWidth, screenHeight, "Yeetris")
|
rl.InitWindow(screenWidth, screenHeight, "Yeetris")
|
||||||
|
|
||||||
return &UI{
|
return &UI{
|
||||||
ScreenWidth: screenWidth,
|
ScreenWidth: screenWidth,
|
||||||
ScreenHeight: screenHeight,
|
ScreenHeight: screenHeight,
|
||||||
BoardWidth: boardWidth,
|
BoardWidth: boardWidth,
|
||||||
BoardHeight: boardHeight,
|
BoardHeight: boardHeight,
|
||||||
BoardOffset: rl.NewVector2(20, 20),
|
BoardOffset: rl.NewVector2(20, 20),
|
||||||
UIOffsetWidth: boardWidth + 40 + 20,
|
UIOffsetWidth: boardWidth + 40 + 20,
|
||||||
|
NextPiecePosition: rl.NewVector2(float32(boardWidth+40+20+110), 250),
|
||||||
|
HeldPiecePosition: rl.NewVector2(float32(boardWidth+40+20+110), 510),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +47,11 @@ func drawRectangleBorder(x, y, width, height, border int32, color rl.Color) {
|
||||||
func (u *UI) Draw(g *Game) {
|
func (u *UI) Draw(g *Game) {
|
||||||
drawRectangleBorder(int32(u.BoardOffset.X), int32(u.BoardOffset.Y), u.BoardWidth, u.BoardHeight, 20, elements.Gray)
|
drawRectangleBorder(int32(u.BoardOffset.X), int32(u.BoardOffset.Y), u.BoardWidth, u.BoardHeight, 20, elements.Gray)
|
||||||
rl.DrawText("Yeetris", u.UIOffsetWidth, 20, 40, rl.White)
|
rl.DrawText("Yeetris", u.UIOffsetWidth, 20, 40, rl.White)
|
||||||
|
rl.DrawText(fmt.Sprintf("Score: %d", u.Score), u.UIOffsetWidth, 70, 20, rl.White)
|
||||||
|
rl.DrawText("Next Piece:", u.UIOffsetWidth, 110, 20, rl.White)
|
||||||
|
drawRectangleBorder(u.UIOffsetWidth+10, 150, 200, 200, 10, elements.Gray)
|
||||||
|
rl.DrawText("Hold:", u.UIOffsetWidth, 370, 20, rl.White)
|
||||||
|
drawRectangleBorder(u.UIOffsetWidth+10, 410, 200, 200, 10, elements.Gray)
|
||||||
|
|
||||||
if g.Pause {
|
if g.Pause {
|
||||||
rl.DrawText(
|
rl.DrawText(
|
||||||
|
|
Loading…
Reference in New Issue