llgo/c/raylib:tetris demo
This commit is contained in:
177
c/raylib/_demo/tetris/tetris.go
Normal file
177
c/raylib/_demo/tetris/tetris.go
Normal file
@@ -0,0 +1,177 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/goplus/llgo/c"
|
||||
"github.com/goplus/llgo/c/raylib"
|
||||
)
|
||||
|
||||
const (
|
||||
BOARD_WIDTH = 10
|
||||
BOARD_HEIGHT = 20
|
||||
BLOCK_SIZE = 30
|
||||
|
||||
SCREENWIDTH = 300
|
||||
SCREENHEIGHT = 600
|
||||
)
|
||||
|
||||
const MAX_BLOCKS = 4
|
||||
|
||||
type Shape struct {
|
||||
Blocks [MAX_BLOCKS]raylib.Vector2
|
||||
Color raylib.Color
|
||||
}
|
||||
|
||||
var SHAPES = []Shape{
|
||||
{Blocks: [MAX_BLOCKS]raylib.Vector2{{X: 0, Y: 0}, {X: 1, Y: 0}, {X: 2, Y: 0}, {X: 3, Y: 0}}, Color: raylib.SKYBLUE},
|
||||
{Blocks: [MAX_BLOCKS]raylib.Vector2{{X: 0, Y: 0}, {X: 1, Y: 0}, {X: 0, Y: 1}, {X: 1, Y: 1}}, Color: raylib.YELLOW},
|
||||
{Blocks: [MAX_BLOCKS]raylib.Vector2{{X: 1, Y: 0}, {X: 0, Y: 1}, {X: 1, Y: 1}, {X: 2, Y: 1}}, Color: raylib.PURPLE},
|
||||
{Blocks: [MAX_BLOCKS]raylib.Vector2{{X: 1, Y: 0}, {X: 2, Y: 0}, {X: 0, Y: 1}, {X: 1, Y: 1}}, Color: raylib.GREEN},
|
||||
{Blocks: [MAX_BLOCKS]raylib.Vector2{{X: 0, Y: 0}, {X: 1, Y: 0}, {X: 1, Y: 1}, {X: 2, Y: 1}}, Color: raylib.RED},
|
||||
{Blocks: [MAX_BLOCKS]raylib.Vector2{{X: 0, Y: 0}, {X: 0, Y: 1}, {X: 1, Y: 1}, {X: 2, Y: 1}}, Color: raylib.BLUE},
|
||||
{Blocks: [MAX_BLOCKS]raylib.Vector2{{X: 2, Y: 0}, {X: 0, Y: 1}, {X: 1, Y: 1}, {X: 2, Y: 1}}, Color: raylib.ORANGE},
|
||||
}
|
||||
|
||||
var board [BOARD_HEIGHT][BOARD_WIDTH]raylib.Color
|
||||
|
||||
var curShape Shape
|
||||
var curPos raylib.Vector2
|
||||
|
||||
var fallTime = c.Float(0)
|
||||
var fallSpeed = c.Float(0.2)
|
||||
var score = 0
|
||||
var scoreText = make([]c.Char, 20)
|
||||
var gameOver = false
|
||||
|
||||
func genShape() {
|
||||
curShape = SHAPES[raylib.GetRandomValue(c.Int(0), c.Int(6))]
|
||||
curPos = raylib.Vector2{BOARD_WIDTH/2 - 1, 0}
|
||||
}
|
||||
|
||||
func checkCollision() bool {
|
||||
for i := 0; i < MAX_BLOCKS; i++ {
|
||||
x := int(curPos.X + curShape.Blocks[i].X)
|
||||
y := int(curPos.Y + curShape.Blocks[i].Y)
|
||||
if x < 0 || x >= BOARD_WIDTH || y >= BOARD_HEIGHT || (y >= 0 && board[y][x] != raylib.BLANK) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func lockShape() {
|
||||
for i := 0; i < MAX_BLOCKS; i++ {
|
||||
x := int(curPos.X + curShape.Blocks[i].X)
|
||||
y := int(curPos.Y + curShape.Blocks[i].Y)
|
||||
if y >= 0 {
|
||||
board[y][x] = curShape.Color
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func rotateShape() {
|
||||
rotated := curShape
|
||||
for i := 0; i < MAX_BLOCKS; i++ {
|
||||
x := rotated.Blocks[i].X
|
||||
rotated.Blocks[i].X = -rotated.Blocks[i].Y
|
||||
rotated.Blocks[i].Y = x
|
||||
}
|
||||
|
||||
temp := curShape
|
||||
curShape = rotated
|
||||
if checkCollision() {
|
||||
curShape = temp
|
||||
}
|
||||
}
|
||||
func clearLines() int {
|
||||
linesCleared := 0
|
||||
for y := BOARD_HEIGHT - 1; y >= 0; y-- {
|
||||
lineFull := true
|
||||
for x := 0; x < BOARD_WIDTH; x++ {
|
||||
if board[y][x] == raylib.BLANK {
|
||||
lineFull = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if lineFull {
|
||||
for yy := y; yy > 0; yy-- {
|
||||
for x := 0; x < BOARD_WIDTH; x++ {
|
||||
board[yy][x] = board[yy-1][x]
|
||||
}
|
||||
}
|
||||
for x := 0; x < BOARD_WIDTH; x++ {
|
||||
board[0][x] = raylib.BLANK
|
||||
}
|
||||
y += 1
|
||||
linesCleared += 1
|
||||
}
|
||||
}
|
||||
return linesCleared
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
raylib.InitWindow(SCREENWIDTH, SCREENHEIGHT, c.Str("Raylib DEMO"))
|
||||
raylib.SetTargetFPS(c.Int(60))
|
||||
genShape()
|
||||
for !raylib.WindowShouldClose() && !gameOver {
|
||||
fallTime += raylib.GetFrameTime()
|
||||
if fallTime >= fallSpeed {
|
||||
fallTime = 0
|
||||
curPos.Y += 1
|
||||
if checkCollision() {
|
||||
curPos.Y -= 1
|
||||
lockShape()
|
||||
linesCleared := clearLines()
|
||||
score += linesCleared * 100
|
||||
genShape()
|
||||
if checkCollision() {
|
||||
gameOver = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if raylib.IsKeyPressed(raylib.KEY_LEFT) {
|
||||
curPos.X -= 1
|
||||
if checkCollision() {
|
||||
curPos.X += 1
|
||||
}
|
||||
}
|
||||
if raylib.IsKeyPressed(raylib.KEY_RIGHT) {
|
||||
curPos.X += 1
|
||||
if checkCollision() {
|
||||
curPos.X -= 1
|
||||
}
|
||||
}
|
||||
if raylib.IsKeyPressed(raylib.KEY_UP) || raylib.IsKeyPressed(raylib.KEY_DOWN) {
|
||||
rotateShape()
|
||||
}
|
||||
|
||||
raylib.BeginDrawing()
|
||||
raylib.ClearBackground(raylib.RAYWHITE)
|
||||
for y := 0; y < BOARD_HEIGHT; y++ {
|
||||
for x := 0; x < BOARD_WIDTH; x++ {
|
||||
raylib.DrawRectangle(c.Int(x*BLOCK_SIZE), c.Int(y*BLOCK_SIZE), c.Int(BLOCK_SIZE-1), c.Int(BLOCK_SIZE-1), board[y][x])
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < MAX_BLOCKS; i++ {
|
||||
raylib.DrawRectangle(c.Int((curPos.X+curShape.Blocks[i].X)*BLOCK_SIZE), c.Int((curPos.Y+curShape.Blocks[i].Y)*BLOCK_SIZE),
|
||||
BLOCK_SIZE-1, BLOCK_SIZE-1, curShape.Color)
|
||||
}
|
||||
|
||||
c.Sprintf(unsafe.SliceData(scoreText), c.Str("Score:%d"), score)
|
||||
raylib.DrawText(unsafe.SliceData(scoreText), 10, 10, 20, raylib.BLACK)
|
||||
|
||||
raylib.EndDrawing()
|
||||
}
|
||||
|
||||
for !raylib.WindowShouldClose() {
|
||||
raylib.BeginDrawing()
|
||||
raylib.ClearBackground(raylib.RAYWHITE)
|
||||
raylib.DrawText(c.Str("Game Over"), SCREENWIDTH/2-50, SCREENHEIGHT/2-10, 20, raylib.RED)
|
||||
raylib.DrawText(unsafe.SliceData(scoreText), SCREENWIDTH/2-50, SCREENHEIGHT/2+10, 20, raylib.BLACK)
|
||||
raylib.EndDrawing()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user