diff --git a/c/raylib/_demo/tetris/tetris.go b/c/raylib/_demo/tetris/tetris.go new file mode 100644 index 00000000..ce93e5b2 --- /dev/null +++ b/c/raylib/_demo/tetris/tetris.go @@ -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() + } +} diff --git a/c/raylib/raylib.go b/c/raylib/raylib.go index 4f7a0eab..f3c3d9bc 100644 --- a/c/raylib/raylib.go +++ b/c/raylib/raylib.go @@ -52,6 +52,173 @@ type Vector4 struct { // Quaternion, 4 components (Vector4 alias) type Quaternion = Vector4 +//---------------------------------------------------------------------------------- +// Enumerators Definition + +// System/Window config flags +// By default all flags are set to 0 + +// Trace log level + +// Keyboard keys (US keyboard layout) +// required keys for alternative layouts +const ( + KEY_NULL = 0 // Key: NULL, used for no key pressed + + // Alphanumeric keys + KEY_APOSTROPHE = 39 // Key: ' + KEY_COMMA = 44 // Key: , + KEY_MINUS = 45 // Key: - + KEY_PERIOD = 46 // Key: . + KEY_SLASH = 47 // Key: / + KEY_ZERO = 48 // Key: 0 + KEY_ONE = 49 // Key: 1 + KEY_TWO = 50 // Key: 2 + KEY_THREE = 51 // Key: 3 + KEY_FOUR = 52 // Key: 4 + KEY_FIVE = 53 // Key: 5 + KEY_SIX = 54 // Key: 6 + KEY_SEVEN = 55 // Key: 7 + KEY_EIGHT = 56 // Key: 8 + KEY_NINE = 57 // Key: 9 + KEY_SEMICOLON = 59 // Key: ; + KEY_EQUAL = 61 // Key: = + KEY_A = 65 // Key: A | a + KEY_B = 66 // Key: B | b + KEY_C = 67 // Key: C | c + KEY_D = 68 // Key: D | d + KEY_E = 69 // Key: E | e + KEY_F = 70 // Key: F | f + KEY_G = 71 // Key: G | g + KEY_H = 72 // Key: H | h + KEY_I = 73 // Key: I | i + KEY_J = 74 // Key: J | j + KEY_K = 75 // Key: K | k + KEY_L = 76 // Key: L | l + KEY_M = 77 // Key: M | m + KEY_N = 78 // Key: N | n + KEY_O = 79 // Key: O | o + KEY_P = 80 // Key: P | p + KEY_Q = 81 // Key: Q | q + KEY_R = 82 // Key: R | r + KEY_S = 83 // Key: S | s + KEY_T = 84 // Key: T | t + KEY_U = 85 // Key: U | u + KEY_V = 86 // Key: V | v + KEY_W = 87 // Key: W | w + KEY_X = 88 // Key: X | x + KEY_Y = 89 // Key: Y | y + KEY_Z = 90 // Key: Z | z + KEY_LEFT_BRACKET = 91 // Key: [ + KEY_BACKSLASH = 92 // Key: '\' + KEY_RIGHT_BRACKET = 93 // Key: ] + KEY_GRAVE = 96 // Key: ` + + // Function keys + KEY_SPACE = 32 // Key: Space + KEY_ESCAPE = 256 // Key: Esc + KEY_ENTER = 257 // Key: Enter + KEY_TAB = 258 // Key: Tab + KEY_BACKSPACE = 259 // Key: Backspace + KEY_INSERT = 260 // Key: Ins + KEY_DELETE = 261 // Key: Del + KEY_RIGHT = 262 // Key: Cursor right + KEY_LEFT = 263 // Key: Cursor left + KEY_DOWN = 264 // Key: Cursor down + KEY_UP = 265 // Key: Cursor up + KEY_PAGE_UP = 266 // Key: Page up + KEY_PAGE_DOWN = 267 // Key: Page down + KEY_HOME = 268 // Key: Home + KEY_END = 269 // Key: End + KEY_CAPS_LOCK = 280 // Key: Caps lock + KEY_SCROLL_LOCK = 281 // Key: Scroll down + KEY_NUM_LOCK = 282 // Key: Num lock + KEY_PRINT_SCREEN = 283 // Key: Print screen + KEY_PAUSE = 284 // Key: Pause + KEY_F1 = 290 // Key: F1 + KEY_F2 = 291 // Key: F2 + KEY_F3 = 292 // Key: F3 + KEY_F4 = 293 // Key: F4 + KEY_F5 = 294 // Key: F5 + KEY_F6 = 295 // Key: F6 + KEY_F7 = 296 // Key: F7 + KEY_F8 = 297 // Key: F8 + KEY_F9 = 298 // Key: F9 + KEY_F10 = 299 // Key: F10 + KEY_F11 = 300 // Key: F11 + KEY_F12 = 301 // Key: F12 + KEY_LEFT_SHIFT = 340 // Key: Shift left + KEY_LEFT_CONTROL = 341 // Key: Control left + KEY_LEFT_ALT = 342 // Key: Alt left + KEY_LEFT_SUPER = 343 // Key: Super left + KEY_RIGHT_SHIFT = 344 // Key: Shift right + KEY_RIGHT_CONTROL = 345 // Key: Control right + KEY_RIGHT_ALT = 346 // Key: Alt right + KEY_RIGHT_SUPER = 347 // Key: Super right + KEY_KB_MENU = 348 // Key: KB menu + + // Keypad keys + KEY_KP_0 = 320 // Key: Keypad 0 + KEY_KP_1 = 321 // Key: Keypad 1 + KEY_KP_2 = 322 // Key: Keypad 2 + KEY_KP_3 = 323 // Key: Keypad 3 + KEY_KP_4 = 324 // Key: Keypad 4 + KEY_KP_5 = 325 // Key: Keypad 5 + KEY_KP_6 = 326 // Key: Keypad 6 + KEY_KP_7 = 327 // Key: Keypad 7 + KEY_KP_8 = 328 // Key: Keypad 8 + KEY_KP_9 = 329 // Key: Keypad 9 + KEY_KP_DECIMAL = 330 // Key: Keypad . + KEY_KP_DIVIDE = 331 // Key: Keypad / + KEY_KP_MULTIPLY = 332 // Key: Keypad * + KEY_KP_SUBTRACT = 333 // Key: Keypad - + KEY_KP_ADD = 334 // Key: Keypad + + KEY_KP_ENTER = 335 // Key: Keypad Enter + KEY_KP_EQUAL = 336 // Key: Keypad = + + // Android key buttons + KEY_BACK = 4 // Key: Android back button + KEY_MENU = 82 // Key: Android menu button + KEY_VOLUME_UP = 24 // Key: Android volume up button + KEY_VOLUME_DOWN = 25 // Key: Android volume down button +) + +// Mouse buttons + +// Mouse cursor + +// Gamepad buttons + +// Gamepad axis + +// Material map index + +// Shader location index + +// Shader uniform data type + +// Shader attribute data types + +// Pixel formats + +// Texture parameters: filter mode + +// Texture parameters: wrap mode + +// Cubemap layouts + +// Font type, defines generation method + +// Color blending modes (pre-defined) + +// Gesture + +// Camera system modes + +// Camera projection + +// N-patch layout + // ----------------------------------------------------------------------------- // Window-related functions @@ -267,12 +434,42 @@ func GetTime() c.Double // ----------------------------------------------------------------------------- // Random values generation functions +//go:linkname SetRandomSeed C.SetRandomSeed +func SetRandomSeed(seed c.Uint) + +//go:linkname GetRandomValue C.GetRandomValue +func GetRandomValue(min c.Int, max c.Int) c.Int + // ----------------------------------------------------------------------------- // Misc. functions // ----------------------------------------------------------------------------- // Input-related functions: keyboard +//go:linkname IsKeyPressed C.IsKeyPressed +func IsKeyPressed(key c.Int) bool + +//go:linkname IsKeyPressedRepeat C.IsKeyPressedRepeat +func IsKeyPressedRepeat(key c.Int) bool + +//go:linkname IsKeyDown C.IsKeyDown +func IsKeyDown(key c.Int) bool + +//go:linkname IsKeyReleased C.IsKeyReleased +func IsKeyReleased(key c.Int) bool + +//go:linkname IsKeyUp C.IsKeyUp +func IsKeyUp(key c.Int) bool + +//go:linkname GetKeyPressed C.GetKeyPressed +func GetKeyPressed() c.Int + +//go:linkname GetCharPressed C.GetCharPressed +func GetCharPressed() c.Int + +//go:linkname SetExitKey C.SetExitKey +func SetExitKey(key c.Int) + // ----------------------------------------------------------------------------- // Input-related functions: gamepads diff --git a/c/raylib/shape.go b/c/raylib/shape.go index d8c0514d..4e78b4c2 100644 --- a/c/raylib/shape.go +++ b/c/raylib/shape.go @@ -207,4 +207,9 @@ func UpdateCameraPro(camera *Camera, movement, rotation Vector3, zoom float32) //go:linkname DrawRectangle C.DrawRectangle func DrawRectangle(posX, posY, width, height c.Int, color Color) +// Draw text (using default font) +// +//go:linkname DrawText C.DrawText +func DrawText(text *c.Char, posX, posY, fontSize c.Int, color Color) + // -----------------------------------------------------------------------------