Implement next and hold

This commit is contained in:
Pavle Portic 2024-01-28 02:16:03 +01:00
parent d22fa6e189
commit 545a76109e
Signed by: TheEdgeOfRage
GPG Key ID: 66AD4BA646FBC0D2
4 changed files with 116 additions and 48 deletions

View File

@ -8,7 +8,7 @@ type Piece struct {
Blocks []*Block
}
var Pieces = []*Piece{
var Pieces = []Piece{
{
Blocks: []*Block{
{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 {
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
}

View File

@ -7,35 +7,30 @@ import (
"github.com/gen2brain/raylib-go/raylib"
)
type Board interface {
DescendActivePiece() bool
DropActivePiece() bool
MoveActivePiece(direction int)
RotateActivePiece(clockwise bool)
ClearLines()
Draw(offset, scale rl.Vector2)
}
type board struct {
type Board struct {
Board [10][20]*elements.Block
ActivePiece *elements.Piece
ActivePiecePos rl.Vector2
NextPiece *elements.Piece
HeldPiece *elements.Piece
AlreadyHeld bool
}
var _ Board = (*board)(nil)
func InitBoard() *board {
board := &board{}
board.newActivePiece()
func InitBoard() *Board {
board := &Board{
NextPiece: elements.GetRandomPiece(),
}
board.getNextPiece()
return board
}
func (b *board) newActivePiece() bool {
func (b *Board) getNextPiece() bool {
b.AlreadyHeld = false
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 {
newX, newY := b.ActivePiecePos.X+block.Position.X, b.ActivePiecePos.Y+block.Position.Y
if newY >= 0 && b.Board[int(newX)][int(newY)] != nil {
@ -45,7 +40,7 @@ func (b *board) newActivePiece() bool {
return false
}
func (b *board) setBlocksFromActivePiece() {
func (b *Board) setBlocksFromActivePiece() {
for _, block := range b.ActivePiece.Blocks {
newX, newY := b.ActivePiecePos.X+block.Position.X, b.ActivePiecePos.Y+block.Position.Y
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 {
xPos := int(b.ActivePiecePos.X + activeBlock.Position.X)
yPos := int(b.ActivePiecePos.Y + activeBlock.Position.Y)
@ -78,7 +73,7 @@ func (b *board) checkHorizontalCollision(left bool) bool {
return false
}
func (b *board) descendActivePiece() bool {
func (b *Board) descendActivePiece() bool {
b.ActivePiecePos.Y += 1
for _, activeBlock := range b.ActivePiece.Blocks {
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.
// 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() {
return b.newActivePiece()
return b.getNextPiece()
}
return false
}
// 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.
func (b *board) DropActivePiece() bool {
func (b *Board) DropActivePiece() bool {
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.
func (b *board) MoveActivePiece(direction int) {
func (b *Board) MoveActivePiece(direction int) {
if !b.checkHorizontalCollision(direction == -1) {
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
// direction, nothing happens.
func (b *board) RotateActivePiece(clockwise bool) {
func (b *Board) RotateActivePiece(clockwise bool) {
if b.ActivePiece.Blocks[0].Color == elements.Yellow {
return
}
@ -195,8 +190,22 @@ func (b *board) RotateActivePiece(clockwise bool) {
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.
func (g *board) ClearLines() {
func (g *Board) ClearLines() {
for y := 19; y >= 0; {
skip := false
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++ {
rl.DrawLine(
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) Draw(offset rl.Vector2, scale rl.Vector2) {
b.drawGrid(offset, scale)
func (b *Board) drawUIPiece(piece *elements.Piece, position, scale rl.Vector2) {
centerOffset := rl.NewVector2(0, 0)
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 j := 0; j < 10; j++ {
if b.Board[j][i] == nil {

View File

@ -16,7 +16,7 @@ type Game struct {
Scale rl.Vector2
Board Board
Board *Board
UI *UI
}
@ -49,6 +49,9 @@ func (g *Game) Update() {
return
}
if rl.IsKeyPressed(rl.KeyC) {
g.Board.HoldPiece()
}
if rl.IsKeyPressed(rl.KeyI) {
g.Board.MoveActivePiece(1)
}
@ -77,7 +80,9 @@ func (g *Game) Draw() {
g.UI.Draw(g)
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 {
rl.DrawText(
"PRESS [ENTER] TO PLAY AGAIN",

View File

@ -1,19 +1,21 @@
package game
import (
// "fmt"
"fmt"
"gitea.theedgeofrage.com/theedgeofrage/yeetris/elements"
"github.com/gen2brain/raylib-go/raylib"
)
type UI struct {
ScreenWidth int32
ScreenHeight int32
BoardWidth int32
BoardHeight int32
BoardOffset rl.Vector2
UIOffsetWidth int32
ScreenWidth int32
ScreenHeight int32
BoardWidth int32
BoardHeight int32
BoardOffset rl.Vector2
UIOffsetWidth int32
NextPiecePosition rl.Vector2
HeldPiecePosition rl.Vector2
Score int
}
@ -26,12 +28,14 @@ func InitUI(scale rl.Vector2) *UI {
rl.InitWindow(screenWidth, screenHeight, "Yeetris")
return &UI{
ScreenWidth: screenWidth,
ScreenHeight: screenHeight,
BoardWidth: boardWidth,
BoardHeight: boardHeight,
BoardOffset: rl.NewVector2(20, 20),
UIOffsetWidth: boardWidth + 40 + 20,
ScreenWidth: screenWidth,
ScreenHeight: screenHeight,
BoardWidth: boardWidth,
BoardHeight: boardHeight,
BoardOffset: rl.NewVector2(20, 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) {
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(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 {
rl.DrawText(