Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/FrezCirno/sprite-snake
https://github.com/FrezCirno/sprite-snake
Last synced: about 1 month ago
JSON representation
- Host: GitHub
- URL: https://github.com/FrezCirno/sprite-snake
- Owner: frezcirno
- Created: 2020-12-29T10:04:55.000Z (almost 4 years ago)
- Default Branch: master
- Last Pushed: 2021-01-04T03:16:37.000Z (almost 4 years ago)
- Last Synced: 2024-08-02T03:02:30.882Z (5 months ago)
- Language: Swift
- Size: 19.7 MB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
- awesome-tjsse-project - FrezCirno/sprite-snake
README
# Snake.io
## 游戏简介
用SpriteKit实现的 Slither.io (中文: 贪吃蛇大作战), 学习工作之余可以用来放松, 单机版无需联网
实现的功能:
- 玩家移动(镜头控制)
- 平滑的转弯
- 双击高速移动
- 吃到食物增长
- 碰撞检测
- 每条蛇与其他蛇的碰撞判断
- 每条蛇与地图边界的碰撞判断
- 每条蛇的蛇头与食物的碰撞判断
- 装饰组件
- 眼睛👀跟踪手指
- 阴影 (高速移动时会闪烁)
- AI bot
- 自动寻找食物
- 自动避障
- 参数为随机生成
- 得分与计分榜与原版的主要区别:
- 原版为多人联机对战, 此处为单机版, 敌人都是AI
## 场景 Scenes
- [] 开始菜单场景 MainMenu
- [x] 游戏中场景 GameScene
## 类设计
* `Snake` - 贪吃蛇基类
* `root: SKNode` - 内含sections, detector, label等, 用于渲染
* `sections: SKNode` - 包含蛇身所有节点, 包括head
* `head: SKSpriteNode` - 蛇头节点
* `label: SKLabelNode` - 名字的标签, 始终位于蛇头上方* `eyes: EyePair` - 贪吃蛇的眼睛
* `shadow: SKNode` - 阴影
* `update()` - 状态更新
* `BotSnake: Snake` - AI控制的蛇
* `careness: CGFloat`
* `distcareness: CGFloat`
* `anglecareness: CGFloat`
* `worldBoundCareness: CGFloat`
* `boundTurnTrend1: CGFloat`
* `boundTurnTrend2: CGFloat`
* `trendRotation: CGFloat`
* `GameScene: SKScene`
* `worldSize: CGSize` - 地图大小
* `camera: CGSize` - 地图大小* `snakes: [Snake]` - 地图上的所有蛇
* `foodNode: SKNode` - 所有食物的容器
* `createSnake()` - 创建一条蛇* 将蛇对象加入snakes中, 将蛇的所有节点(body节点)加到scene中
* 使用空间四叉树`GKQuadtree`来防止新生成的蛇和其他蛇距离过近
* `createFood()` - 创建一个食物* 在地图上随机生成一颗食物
* 同样维护了一棵空间四叉树`GKQuadtree`来记录所有食物的位置, 供AI算法使用
* `(override) update()` - 更新界面, 依次更新所有蛇, 检查是否需要创建新的食物/蛇
## 物理引擎使用
蛇的平滑转弯实现:
```swift
let thisPos = self.head.position
let rot = self.head.zRotationif let touchPos = self.scene.touchPos {
let targetDirect = CGVector(dx: touchPos.x - thisPos.x, dy: touchPos.y - thisPos.y)
var diff = atan2(targetDirect.dy, targetDirect.dx) - rot
if diff > CGFloat.pi {
diff -= 2 * CGFloat.pi
}
else if diff < -CGFloat.pi {
diff += 2 * CGFloat.pi
}
self.head.physicsBody?.angularVelocity = diff * Snake.rotateSpeed // 不断调整角速度以达到平滑转弯的效果
if self.scene.tapCount > 1 {
self.speed = Snake.fastSpeed
} else {
self.speed = Snake.slowSpeed
}
} else {
self.head.physicsBody?.angularVelocity = 0
self.speed = Snake.slowSpeed
}
```* 线速度:velocity
* 角度:zRotation
* 角速度:angularVelocity
## 层次结构- `SKScene`
- `SKNode` - 背景组
- `SKTileMapNode`
- `SKTileMapNode`
- `SKTileMapNode`
- ......
- `SKCameraNode` - 摄像头节点
- `SKNode` - 食物组
- `SKSpriteNode(phy)` - 一个食物
- `SKSpriteNode(phy)` - 一个食物
- `SKSpriteNode(phy)` - 一个食物
- .......
- `SKNode` - 玩家
- `SKLabelNode` - 名字标签
- `SKNode` - 蛇身
- `SKSpriteNode(phy)` - 蛇头
- `SKSpriteNode` - 眼睛1
- `SKSpriteNode` - 眼睛2
- `SKSpriteNode(phy)` - 碰撞探测器
- `SKSpriteNode(phy)` - 蛇身1
- `SKSpriteNode(phy)` - 蛇身2
- ......
- `SKNode` - 蛇1
- `SKLabelNode` - 名字标签
- `SKNode` - 蛇身
- `SKSpriteNode` - 蛇头
- `SKSpriteNode` - 眼睛1
- `SKSpriteNode` - 眼睛2
- `SKSpriteNode` - 碰撞探测器
- `SKSpriteNode` - 蛇身1
- `SKSpriteNode` - 蛇身2
- ......
- `SKNode` - 蛇2
- `SKNode` - 蛇3## 注意
size表示在父坐标系下的尺寸
scale表示对父坐标系的伸缩变化
修改scale的时候会同时修改size
修改size的时候不会修改scale
## AI设计
* 判断一定范围内有没有食物
* 判断最近的敌人的位置
* 判断是否靠近边界
* 随意选择一个感兴趣方向进行探索