diff --git a/Examples/SwiftIOPlayground/12MoreProjects/Snake/.gitignore b/Examples/SwiftIOPlayground/12MoreProjects/Snake/.gitignore new file mode 100644 index 0000000..0023a53 --- /dev/null +++ b/Examples/SwiftIOPlayground/12MoreProjects/Snake/.gitignore @@ -0,0 +1,8 @@ +.DS_Store +/.build +/Packages +xcuserdata/ +DerivedData/ +.swiftpm/configuration/registries.json +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +.netrc diff --git a/Examples/SwiftIOPlayground/12MoreProjects/Snake/Package.mmp b/Examples/SwiftIOPlayground/12MoreProjects/Snake/Package.mmp new file mode 100644 index 0000000..102d0e2 --- /dev/null +++ b/Examples/SwiftIOPlayground/12MoreProjects/Snake/Package.mmp @@ -0,0 +1,17 @@ +# This is a MadMachine project file in TOML format +# This file holds those parameters that could not be managed by SwiftPM +# Edit this file would change the behavior of the building/downloading procedure +# Those project files in the dependent libraries would be IGNORED + +# Specify the board name below +# There are "SwiftIOBoard" and "SwiftIOMicro" now +board = "SwiftIOMicro" + +# Specifiy the target triple below +# There are "thumbv7em-unknown-none-eabi" and "thumbv7em-unknown-none-eabihf" now +# If your code use significant floating-point calculation, +# plz set it to "thumbv7em-unknown-none-eabihf" +triple = "thumbv7em-unknown-none-eabi" + +# Reserved for future use +version = 1 diff --git a/Examples/SwiftIOPlayground/12MoreProjects/Snake/Package.swift b/Examples/SwiftIOPlayground/12MoreProjects/Snake/Package.swift new file mode 100644 index 0000000..abc18f2 --- /dev/null +++ b/Examples/SwiftIOPlayground/12MoreProjects/Snake/Package.swift @@ -0,0 +1,26 @@ +// swift-tools-version: 5.9 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "Snake", + dependencies: [ + // Dependencies declare other packages that this package depends on. + .package(url: "https://github.com/madmachineio/SwiftIO.git", branch: "main"), + .package(url: "https://github.com/madmachineio/MadBoards.git", branch: "main"), + .package(url: "https://github.com/madmachineio/MadDrivers.git", branch: "main"), + ], + targets: [ + // Targets are the basic building blocks of a package, defining a module or a test suite. + // Targets can depend on other targets in this package and products from dependencies. + .executableTarget( + name: "Snake", + dependencies: [ + "SwiftIO", + "MadBoards", + // Use specific library name rather than "MadDrivers" would speed up the build procedure. + .product(name: "ST7789", package: "MadDrivers") + ]), + ] +) diff --git a/Examples/SwiftIOPlayground/12MoreProjects/Snake/Sources/Snake.swift b/Examples/SwiftIOPlayground/12MoreProjects/Snake/Sources/Snake.swift new file mode 100644 index 0000000..c9bdc97 --- /dev/null +++ b/Examples/SwiftIOPlayground/12MoreProjects/Snake/Sources/Snake.swift @@ -0,0 +1,166 @@ +import ST7789 +import SwiftIO + +typealias Point = (x: Int, y: Int) + +struct Food { + var pos: Point + let size = 10 + let color = UInt16(0xF81F).byteSwapped + let strokeColor = UInt16(0xC618) + + // Generate food at a random position, ensuring it does not overlap with the snake. + init(screen: ST7789, snakeBody: [Point]) { + pos = (0, 0) + createNew(snakeBody: snakeBody) + } + + // Check if the snake eats the food. + mutating func isEaten(at pos: Point) -> Bool { + return pos.x == self.pos.x && pos.y == self.pos.y + } + + mutating func createNew(snakeBody: [Point]) { + repeat { + pos.x = Array(1.. Bool { + // Check if the snake's head collides with its own body. + for i in 1.. screen.width - size || body[0].x < 0 || body[0].y > screen.height - size || body[0].y < 0 + } + + // Move the snake in the specified direction. + mutating func update() { + for i in (1..= 300 { + let lastBody = body + + // Update snake's position. + update() + + if gameOver() { + end = true + screen.clearScreen(UInt16(0xF800).byteSwapped) + } else { + screen.drawSquare(at: lastBody.last!, width: size, color: 0) + screen.drawSquare(at: body[0], width: size, color: color, strokeColor: strokeColor) + + if food.isEaten(at: body[0]) { + food.createNew(snakeBody: body) + + if let last = lastBody.last { + body.append(last) + screen.drawSquare(at: last, width: size, color: color, strokeColor: strokeColor) + } + } + } + + lastUpdateTime = current + } + } +} + +extension ST7789 { + func drawSquare(at point: Point, width: Int, color: UInt16, strokeColor: UInt16) { + for py in (point.y + 1)..<(point.y + width - 1) { + for px in (point.x + 1)..<(point.x + width - 1) { + writePixel(x: px, y: py, color: color) + } + } + + for w in 0.. 25 && !clockwiseButton.read() { + snake.setSpeed(clockwise: true) + clockwisePressCount = 0 + } + + if clockwiseButton.read() { + clockwisePressCount += 1 + } else { + clockwisePressCount = 0 + } + + if anticlockwisePressCount > 25 && !anticlockwiseButton.read() { + snake.setSpeed(clockwise: false) + anticlockwisePressCount = 0 + } + + if anticlockwiseButton.read() { + anticlockwisePressCount += 1 + } else { + anticlockwisePressCount = 0 + } + + snake.play() + } + + sleep(ms: 2) +} \ No newline at end of file