-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
272 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
.DS_Store | ||
/.build | ||
/Packages | ||
xcuserdata/ | ||
DerivedData/ | ||
.swiftpm/configuration/registries.json | ||
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata | ||
.netrc |
17 changes: 17 additions & 0 deletions
17
Examples/SwiftIOPlayground/12MoreProjects/Snake/Package.mmp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
26 changes: 26 additions & 0 deletions
26
Examples/SwiftIOPlayground/12MoreProjects/Snake/Package.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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") | ||
]), | ||
] | ||
) |
166 changes: 166 additions & 0 deletions
166
Examples/SwiftIOPlayground/12MoreProjects/Snake/Sources/Snake.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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..<screen.width / size).shuffled().randomElement()! * size | ||
pos.y = Array(1..<screen.height / size).shuffled().randomElement()! * size | ||
} while snakeBody.contains (where: { $0.x == pos.x && $0.y == pos.y }) | ||
|
||
screen.drawSquare(at: pos, width: size, color: color, strokeColor: strokeColor) | ||
} | ||
} | ||
|
||
struct Snake { | ||
let size = 10 | ||
let color = UInt16(0x07FF).byteSwapped | ||
let strokeColor = UInt16(0xC618) | ||
var xSpeed: Int | ||
var ySpeed: Int | ||
|
||
var food: Food | ||
var body: [Point] = [] | ||
|
||
let screen: ST7789 | ||
var lastUpdateTime: Int64 | ||
var end = false | ||
|
||
// Initialize the snake in the middle of the screen. | ||
init(screen: ST7789) { | ||
xSpeed = 1 | ||
ySpeed = 0 | ||
self.screen = screen | ||
|
||
let pos = (screen.width / 2, screen.height / 2) | ||
body.append(pos) | ||
|
||
food = Food(screen: screen, snakeBody: body) | ||
|
||
screen.drawSquare(at: pos, width: size, color: color, strokeColor: strokeColor) | ||
lastUpdateTime = getSystemUptimeInMilliseconds() | ||
} | ||
|
||
// Update direction. | ||
mutating func setSpeed(clockwise: Bool) { | ||
let direction = clockwise ? 1 : -1 | ||
|
||
switch (xSpeed, ySpeed) { | ||
case (-1, 0): | ||
xSpeed = 0 | ||
ySpeed = -direction | ||
case (0, -1): | ||
xSpeed = direction | ||
ySpeed = 0 | ||
case (1, 0): | ||
xSpeed = 0 | ||
ySpeed = direction | ||
case (0, 1): | ||
xSpeed = -direction | ||
ySpeed = 0 | ||
default: break | ||
} | ||
} | ||
|
||
// Check if the snake collides with the wall or itself. | ||
mutating func gameOver() -> Bool { | ||
// Check if the snake's head collides with its own body. | ||
for i in 1..<body.count { | ||
if body[i].x == body[0].x && body[i].y == body[0].y { | ||
return true | ||
} | ||
} | ||
|
||
// Check if the snake's head collides with the boundaries. | ||
return body[0].x > 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..<body.count).reversed() { | ||
body[i] = body[i-1] | ||
} | ||
|
||
body[0].x += xSpeed * size | ||
body[0].y += ySpeed * size | ||
} | ||
|
||
mutating func play() { | ||
let current = getSystemUptimeInMilliseconds() | ||
if current - lastUpdateTime >= 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..<width { | ||
for line in 0..<1 { | ||
writePixel(x: point.x + w, y: point.y + line, color: strokeColor) | ||
writePixel(x: point.x + w, y: point.y + width - 1 + line, color: strokeColor) | ||
} | ||
} | ||
|
||
for h in 1..<(width - 1) { | ||
for line in 0..<1 { | ||
writePixel(x: point.x + line, y: point.y + h, color: 0) | ||
writePixel(x: point.x + width - 1 + line, y: point.y + h, color: strokeColor) | ||
} | ||
} | ||
} | ||
|
||
func drawSquare(at point: Point, width: Int, color: UInt16) { | ||
for py in point.y..<(point.y + width) { | ||
for px in point.x..<(point.x + width) { | ||
writePixel(x: px, y: py, color: color) | ||
} | ||
} | ||
} | ||
} |
55 changes: 55 additions & 0 deletions
55
Examples/SwiftIOPlayground/12MoreProjects/Snake/Sources/main.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
// Import SwiftIO to set the communication and MadBoard to use pin id. | ||
import SwiftIO | ||
import MadBoard | ||
// Import the library to configure the LCD and write pixels on it. | ||
import ST7789 | ||
|
||
// Initialize the SPI pin and the digital pins for the LCD. | ||
let bl = DigitalOut(Id.D2) | ||
let rst = DigitalOut(Id.D12) | ||
let dc = DigitalOut(Id.D13) | ||
let cs = DigitalOut(Id.D5) | ||
let spi = SPI(Id.SPI0, speed: 30_000_000) | ||
|
||
// Initialize the LCD using the pins above. Rotate the screen to keep the original at the upper left. | ||
let screen = ST7789(spi: spi, cs: cs, dc: dc, rst: rst, bl: bl, rotation: .angle90) | ||
|
||
// Initialize the two buttons for changing the snake's direction. | ||
let clockwiseButton = DigitalIn(Id.D1) | ||
let anticlockwiseButton = DigitalIn(Id.D19) | ||
|
||
var clockwisePressCount = 0 | ||
var anticlockwisePressCount = 0 | ||
|
||
var snake = Snake(screen: screen) | ||
|
||
while true { | ||
if !snake.end { | ||
// If a button is pressed, the snake's direction will change accordingly, | ||
if clockwisePressCount > 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) | ||
} |