问题描述
我是 swift/spritekit 的新手,我 8 岁的孩子要求我为他制作一款基本游戏,所以我答应了(现在几乎后悔了,哈哈)
我想要实现的目标:能够根据获得的经验值“升级”的角色 - 我使用 JSON 文件来描述级别
JSON 文件:
[
{
"id": 1,"spriteTexture": "playerL1","weapon": "playerL1Weapon","expToLvlUp": 50,"health": 2,"attack": 1,"defense": 1,},{
"id": 2,"spriteTexture": "playerL2","weapon": "playerL2Weapon","expToLvlUp": 60,"health": 7,"attack": 2,"defense": 2,{
"id": 3,"spriteTexture": "playerL3","weapon": "playerL3Weapon","expToLvlUp": 100,"health": 10,"attack": 5,"defense": 5,}
]
可解码文件:
import Foundation
extension Bundle{
func decode<T: Decodable>(_ Type: T.Type,from file: String) -> T {
guard let url = self.url(forResource: file,withExtension: nil) else {
fatalError("Failed to locate \(file) in bundle")
}
guard let data = try? Data(contentsOf: url) else{
fatalError("Failed to load \(file) from bundle")
}
let decoder = JSONDecoder()
guard let loaded = try? decoder.decode(T.self,from: data) else {
fatalError("Failed to decode /(file) from bundle")
}
return loaded
}
}
import SpriteKit
struct PlayerLevel: Codable {
let id: Int
let spriteTexture: String
let weapon: String
let expToLvlUp: Int
let health: Int
let attack: Int
let defense: Int
}
这是我的课:
import Foundation
import SpriteKit
class Player: SKSpriteNode {
var type: PlayerLevel
{
didSet{
levelUp()
}
}
init(type: PlayerLevel){
self.type = type
let texture = SKTexture(imageNamed: type.spriteTexture)
super.init(texture: texture,color: .clear,size: texture.size())
position.x = -900
physicsBody = SKPhysicsBody(texture: texture,size: texture.size())
physicsBody?.categoryBitMask = CollisionType.player.rawValue
physicsBody?.collisionBitMask = CollisionType.enemy.rawValue | CollisionType.enemyWeapon.rawValue
physicsBody?.contactTestBitMask = CollisionType.enemy.rawValue | CollisionType.enemyWeapon.rawValue
zPosition = 5
name = "player"
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func shoot(){
let shot = SKSpriteNode(imageNamed: type.weapon)
shot.name = self.type.weapon
shot.size = CGSize(width: 50,height: 50)
shot.physicsBody = SKPhysicsBody(rectangleOf: shot.size)
shot.physicsBody?.categoryBitMask = CollisionType.playerWeapon.rawValue
shot.physicsBody?.collisionBitMask = CollisionType.enemy.rawValue | CollisionType.enemyWeapon.rawValue
shot.physicsBody?.contactTestBitMask = CollisionType.enemy.rawValue | CollisionType.enemyWeapon.rawValue
addChild(shot)
shot.zPosition = 3
shot.physicsBody?.affectedByGravity = false
let movement = SKAction.move(to: CGPoint(x: 4000,y: shot.position.y),duration: 1)
let sequence = SKAction.sequence([movement,.removeFromParent()])
shot.run(sequence)
}
func levelUp(){
self.texture = SKTexture(imageNamed: type.spriteTexture)
let texture = SKTexture(imageNamed: type.spriteTexture)
self.physicsBody = SKPhysicsBody(texture: texture,size: texture.size())
}
}
首先,我想知道我的设置是否正确。 在我的游戏场景中:
import SpriteKit
import GameplayKit
enum CollisionType: UInt32 {
case player = 1
case playerWeapon = 2
case enemy = 4
case enemyWeapon = 8
case ground = 16
}
class GameScene: SKScene,SKPhysicsContactDelegate {
// Properties
var isPlayerAlive = true
var playerLevels = Bundle.main.decode([PlayerLevel].self,from: "player-levels.json")
let enemyTypes = Bundle.main.decode([EnemyType].self,from: "enemies.json")
var currentEnemy = 0
var currentLevel = 0 {
didSet {
player.type = playerLevels[currentLevel]
}
}
var player: Player!
var enemy: Enemy!
var levelUp: SKSpriteNode!
var healthLabel: SKLabelNode!
var scoreLabel: SKLabelNode!
let playerLevelLabel = SKLabelNode(fontNamed: "Chalkduster")
var score = 0 {
didSet{
scoreLabel.text = "score: \(score)"
}
}
let ground = SKSpriteNode(imageNamed: "groundBottom")
let groundT = SKSpriteNode(imageNamed: "gameGroundTop")
var expLabel: SKLabelNode!
var exp = 0 {
didSet{
expLabel.text = "Experience Points: \(exp) / \(playerLevels[currentLevel].expToLvlUp)"
}
}
var health = 0 {
didSet{
healthLabel.text = "Health: \(playerLevels[currentLevel].health)"
}
}
override func didMove(to view: SKView) {
physicsWorld.contactDelegate = self
makeGround()
initializePlayer()
spawnEnemy()
makescoreLabel()
makeExpLabel()
makeHealthLabel()
}
func initializePlayer(){
player = Player(type: playerLevels[currentLevel])
addChild(player)
playerLevelLabel.text = "Details: \(player.type)"
playerLevelLabel.fontSize = 40
playerLevelLabel.position = CGPoint(x: 0,y: self.frame.minY + 200)
}
func makescoreLabel(){
scoreLabel = SKLabelNode(fontNamed: "Chalkduster")
scoreLabel.position = CGPoint(x:self.frame.maxX - 250,y:self.frame.maxY - 100)
scoreLabel.horizontalAlignmentMode = .right
scoreLabel.fontSize = 40
scoreLabel.zPosition = 5
scoreLabel.text = "score: 0"
scoreLabel.name = "score"
addChild(scoreLabel)
}
func makeExpLabel(){
expLabel = SKLabelNode(fontNamed: "Chalkduster")
expLabel.position = CGPoint(x:self.frame.minX + 500,y:self.frame.maxY - 110)
scoreLabel.fontSize = 40
expLabel.zPosition = 5
expLabel.text = "Expereience Points: 0 / \(playerLevels[currentLevel].expToLvlUp)"
expLabel.name = "exp"
addChild(expLabel)
}
func makeHealthLabel(){
healthLabel = SKLabelNode(fontNamed: "Chalkduster")
healthLabel.position = CGPoint(x:self.frame.minX + 1200,y:self.frame.maxY - 110)
healthLabel.fontSize = 40
healthLabel.zPosition = 5
healthLabel.text = "Health: \(playerLevels[currentLevel].health)"
healthLabel.name = "health"
addChild(healthLabel)
}
func makeGround(){
ground.name = "ground"
ground.position.x = frame.midX
ground.position.y = frame.minY
ground.zPosition = 1
addChild(ground)
ground.physicsBody = SKPhysicsBody(texture: ground.texture!,size: ground.texture!.size())
ground.physicsBody?.affectedByGravity = false
ground.physicsBody?.isDynamic = false
groundT.position.x = frame.midX
groundT.position.y = ground.position.y + 50
groundT.physicsBody?.isDynamic = false
addChild(groundT)
}
override func touchesBegan(_ touches: Set<UITouch>,with event: UIEvent?) {
let touch = touches.first
let location = touch?.location(in: self)
let nodesAtLocation = nodes(at: location!)
for node in nodesAtLocation {
if node.name == "score"{
score += 10
exp += 5
upgrade()
}
if node.name == "attack"{
attack()
}
}
}
func upgrade() {
if exp < playerLevels[currentLevel].expToLvlUp { return }
if currentLevel + 1 > playerLevels.count - 1 {
gameOver()
return
}
if let explosion = SKEmitterNode(fileNamed: "Explosion") {
explosion.position = player.position
addChild(explosion)
}
//charLevelUp()
currentLevel += 1
playerLevelLabel.text = "Details: \(player.type)"
}
func didBegin(_ contact: SKPhysicsContact) {
guard let nodeA = contact.bodyA.node else { return }
guard let nodeB = contact.bodyB.node else { return }
let sortednodes = [nodeA,nodeB].sorted { $0.name ?? "" < $1.name ?? ""}
let firstNode = sortednodes[0]
let secondNode = sortednodes[1]
if firstNode.name == "ground" { return }
if secondNode.name == "ground" { return }
if secondNode.name == "player" {
guard isPlayerAlive else { return }
if let explosion = SKEmitterNode(fileNamed: "explosion"){
explosion.position = firstNode.position
addChild(explosion)
}
//health -= 1
if playerLevels[currentLevel].health == 0{
gameOver()
secondNode.removeFromParent()
}
firstNode.removeFromParent()
} else if let enemy = firstNode as? Enemy {
enemy.health -= 1
if enemy.health == 0 {
if let explosion = SKEmitterNode(fileNamed: "Explosion") {
expLabel.position = enemy.position
addChild(explosion)
}
enemy.removeFromParent()
score += 50
exp = enemy.expGive
}
if let explosion = SKEmitterNode(fileNamed: "Explosion") {
explosion.position = enemy.position
addChild(explosion)
}
secondNode.removeFromParent()
} else {
if let explosion = SKEmitterNode(fileNamed: "Explosion") {
explosion.position = secondNode.position
addChild(explosion)
}
firstNode.removeFromParent()
secondNode.removeFromParent()
}
}
我已经设法让精灵改变纹理和物理身体,expReq 指向根据玩家级别改变,但是,我似乎无法更新健康属性或任何其他属性。任何帮助将不胜感激 - 我不确定我是否正确设置 - 请告知:)
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)