From 1ca5399a2e51c15628a7342295559519038215e9 Mon Sep 17 00:00:00 2001 From: 127-Z3R0 <81heti1bif@hft-stuttgart.de> Date: Wed, 13 May 2020 14:59:26 +0200 Subject: [PATCH] add LabelEntity, LabelNode and Labelcomponent - ability to customize and add a Label with animation --- GoldWars/GoldWars.xcodeproj/project.pbxproj | 12 ++ GoldWars/GoldWars/Label.swift | 21 +++ GoldWars/GoldWars/LabelComponent.swift | 32 +++++ GoldWars/GoldWars/LabelNode.swift | 152 ++++++++++++++++++++ 4 files changed, 217 insertions(+) create mode 100644 GoldWars/GoldWars/Label.swift create mode 100644 GoldWars/GoldWars/LabelComponent.swift create mode 100644 GoldWars/GoldWars/LabelNode.swift diff --git a/GoldWars/GoldWars.xcodeproj/project.pbxproj b/GoldWars/GoldWars.xcodeproj/project.pbxproj index 89e886a..ba4f9b5 100644 --- a/GoldWars/GoldWars.xcodeproj/project.pbxproj +++ b/GoldWars/GoldWars.xcodeproj/project.pbxproj @@ -49,6 +49,9 @@ C04783EE2468583F004961FB /* intro-music.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = C04783ED2468583F004961FB /* intro-music.mp3 */; }; C04783F024685995004961FB /* SettingsScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = C04783EF24685995004961FB /* SettingsScene.swift */; }; C05FAED62468559D0006AF2E /* SoundManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C05FAED52468559D0006AF2E /* SoundManager.swift */; }; + C064E9A8246C0EA50022B228 /* LabelNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = C064E9A7246C0EA50022B228 /* LabelNode.swift */; }; + C064E9AA246C114C0022B228 /* LabelComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = C064E9A9246C114C0022B228 /* LabelComponent.swift */; }; + C064E9AC246C151F0022B228 /* Label.swift in Sources */ = {isa = PBXBuildFile; fileRef = C064E9AB246C151F0022B228 /* Label.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -109,6 +112,9 @@ C04783ED2468583F004961FB /* intro-music.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = "intro-music.mp3"; sourceTree = ""; }; C04783EF24685995004961FB /* SettingsScene.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScene.swift; sourceTree = ""; }; C05FAED52468559D0006AF2E /* SoundManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoundManager.swift; sourceTree = ""; }; + C064E9A7246C0EA50022B228 /* LabelNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelNode.swift; sourceTree = ""; }; + C064E9A9246C114C0022B228 /* LabelComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelComponent.swift; sourceTree = ""; }; + C064E9AB246C151F0022B228 /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -169,6 +175,9 @@ AE151588245F18EF001D363E /* MatchmakingHelper.swift */, 3EBD242B245D8044003CECE7 /* GameCenterHelper.swift */, C04783EF24685995004961FB /* SettingsScene.swift */, + C064E9A7246C0EA50022B228 /* LabelNode.swift */, + C064E9A9246C114C0022B228 /* LabelComponent.swift */, + C064E9AB246C151F0022B228 /* Label.swift */, ); path = GoldWars; sourceTree = ""; @@ -384,6 +393,7 @@ 110360D9244B101A008610AF /* GameScene.swift in Sources */, C04783F024685995004961FB /* SettingsScene.swift in Sources */, 116060F7245C57D2004E5A36 /* EntityManager.swift in Sources */, + C064E9AA246C114C0022B228 /* LabelComponent.swift in Sources */, 3EBD242E245D9332003CECE7 /* Team.swift in Sources */, 9E174C88245DF1FF00209FF0 /* BackgroundComponent.swift in Sources */, 9E78ACBA245CBDAF00526FF7 /* HUD.swift in Sources */, @@ -394,12 +404,14 @@ 9EA3ABE9245C6DAA006BC61D /* DefaultBaseComponent.swift in Sources */, 9E174C8A245E1A0A00209FF0 /* Background.swift in Sources */, 9EA3ABED245C8143006BC61D /* ModalBackgroundComponent.swift in Sources */, + C064E9A8246C0EA50022B228 /* LabelNode.swift in Sources */, 3EBD242C245D8044003CECE7 /* GameCenterHelper.swift in Sources */, AB1D759C245DD18100671525 /* MapProtocol.swift in Sources */, AB1D75A0245DEC0500671525 /* MapFactory.swift in Sources */, AB1D759D245DD18100671525 /* TwoPlayerDefaultTestMap.swift in Sources */, 9EBFD7552462CF5A00E1E219 /* SliderComponent.swift in Sources */, ABA03DA0244BD54F00A66916 /* Base.swift in Sources */, + C064E9AC246C151F0022B228 /* Label.swift in Sources */, 9E174C82245DD81D00209FF0 /* ButtonNode.swift in Sources */, 9EC7E48B2461FBF700396BCD /* SliderNode.swift in Sources */, 9E174C84245DD8CE00209FF0 /* Button.swift in Sources */, diff --git a/GoldWars/GoldWars/Label.swift b/GoldWars/GoldWars/Label.swift new file mode 100644 index 0000000..2cac987 --- /dev/null +++ b/GoldWars/GoldWars/Label.swift @@ -0,0 +1,21 @@ +// +// Label.swift +// GoldWars +// +// Created by Tim Herbst on 13.05.20. +// Copyright © 2020 SP2. All rights reserved. +// + +import GameplayKit + +class Label: GKEntity { + + init(fontnamed: String, name: String, text: String, fontSize: CGFloat, fontColor: UIColor, position: CGPoint, horizontalAlignmentMode: SKLabelHorizontalAlignmentMode, vertikalAligmentMode: SKLabelVerticalAlignmentMode, isAnimationEnabled: Bool, isAnimationInfinite: Bool) { + super.init() + self.addComponent(LabelComponent(fontnamed: fontnamed, name: name, text: text, fontSize: fontSize, fontColor: fontColor, position: position, horizontalAlignmentMode: horizontalAlignmentMode, vertikalAligmentMode: vertikalAligmentMode, isAnimationEnabled: isAnimationEnabled, isAnimationInfinite: isAnimationInfinite)) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/GoldWars/GoldWars/LabelComponent.swift b/GoldWars/GoldWars/LabelComponent.swift new file mode 100644 index 0000000..aa57816 --- /dev/null +++ b/GoldWars/GoldWars/LabelComponent.swift @@ -0,0 +1,32 @@ +// +// LabelComponent.swift +// GoldWars +// +// Created by Tim Herbst on 13.05.20. +// Copyright © 2020 SP2. All rights reserved. +// + +import GameplayKit + +class LabelComponent: GKComponent { + var labelNode: LabelNode + + init(fontnamed: String?, name: String, text: String, fontSize: CGFloat, fontColor: UIColor, position: CGPoint, horizontalAlignmentMode: SKLabelHorizontalAlignmentMode, vertikalAligmentMode: SKLabelVerticalAlignmentMode, isAnimationEnabled: Bool, isAnimationInfinite: Bool) { + labelNode = LabelNode(fontNamed: fontnamed) + labelNode.name = name + labelNode.text = text + labelNode.fontSize = fontSize + labelNode.fontColor = fontColor + labelNode.horizontalAlignmentMode = horizontalAlignmentMode + labelNode.verticalAlignmentMode = vertikalAligmentMode + labelNode.position = position + if isAnimationEnabled { + labelNode.sequentiallyBouncingZoom(delay: 0.3, infinite: isAnimationInfinite) + } + super.init() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/GoldWars/GoldWars/LabelNode.swift b/GoldWars/GoldWars/LabelNode.swift new file mode 100644 index 0000000..669a0b5 --- /dev/null +++ b/GoldWars/GoldWars/LabelNode.swift @@ -0,0 +1,152 @@ +// +// LabelNode.swift +// GoldWars +// +// Created by Tim Herbst on 13.05.20. +// Copyright © 2020 SP2. All rights reserved. +// + +import SpriteKit + +class LabelNode: SKNode { + let colt = SKLabelNode() + var labels = [SKLabelNode]() + var text = "" { + didSet { + refreshLabels() + } + } + var fontName = "HelveticaNeue-UltraLight" { + didSet { + _ = labels.compactMap({ $0.fontName = fontName }) + refreshLabels() + } + } + var fontSize = CGFloat(30.0) { + didSet { + _ = labels.compactMap({ $0.fontSize = fontSize }) + refreshLabels() + } + } + var fontColor = UIColor.init(white: 1.0, alpha: 1.0) { + didSet { + _ = labels.compactMap({ $0.fontColor = fontColor }) + refreshLabels() + } + } + var horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.init(rawValue: 0) { // left + didSet { + _ = labels.compactMap({ $0.horizontalAlignmentMode = horizontalAlignmentMode! }) + refreshLabels() + } + } + var verticalAlignmentMode = SKLabelVerticalAlignmentMode.init(rawValue: 0) { // center + didSet { + _ = labels.compactMap({ $0.verticalAlignmentMode = verticalAlignmentMode! }) + refreshLabels() + } + } + var lineSpacingFactor: CGFloat = -1.3 { + didSet { + refreshLabels() + } + } + override init() { + super.init() + } + convenience init(text: String) { + self.init() + self.text = text + } + convenience init(fontNamed fontName: String?) { + self.init(text: "") + if let f = fontName { + self.fontName = f + } + } + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func refreshLabels() { + _ = labels.compactMap({ $0.removeFromParent() }) + labels.removeAll() + if text.count > 0 { + var newX: CGFloat = 0.0 + var gapX: CGFloat = 0.0 + let ghostSpace = SKLabelNode(text: ".") + ghostSpace.fontName = fontName + ghostSpace.fontSize = fontSize + let ghostSpaceWidth = ghostSpace.frame.size.width + var fullNodeWidth:CGFloat = 0.0 + for char in text { + if String(char) != " " { + let charLabelNode = SKLabelNode(text: String(char)) + charLabelNode.fontName = fontName + charLabelNode.fontSize = fontSize + fullNodeWidth += charLabelNode.frame.size.width + lineSpacingFactor + } else { + fullNodeWidth += ghostSpaceWidth + lineSpacingFactor + } + } + switch horizontalAlignmentMode { + case .left? : gapX = 0.0 + case .center? : gapX = fullNodeWidth/2 + case .right? : gapX = fullNodeWidth + default: break + } + var index: Int = 0 + for char in text { + if String(char) != " " { + let charLabelNode = SKLabelNode(text: String(char)) + charLabelNode.fontName = fontName + charLabelNode.fontSize = fontSize + charLabelNode.fontColor = fontColor + charLabelNode.horizontalAlignmentMode = .left + charLabelNode.verticalAlignmentMode = verticalAlignmentMode! + charLabelNode.position.x = newX - gapX + charLabelNode.alpha = 1 + self.addChild(charLabelNode) + labels.append(charLabelNode) + newX += charLabelNode.frame.size.width + lineSpacingFactor + } else { + ghostSpace.horizontalAlignmentMode = .left + ghostSpace.verticalAlignmentMode = verticalAlignmentMode! + ghostSpace.position.x = newX - gapX + labels.append(ghostSpace) + newX += ghostSpaceWidth + lineSpacingFactor + } + index += 1 + } + } + } + + func sequentiallyBouncingZoom(delay:TimeInterval, infinite:Bool = false) { + if labels.count > 0 && self.action(forKey: "sequentiallyBouncingZoom") == nil { + let main = SKAction.run { [weak self] in + guard let strongSelf = self else { return } + for i in 0.. SKAction { + return SKAction.sequence([SKAction.wait(forDuration: delay), action]) + } + class func afterDelay(_ delay: TimeInterval, runBlock block: @escaping () -> Void) -> SKAction { + return SKAction.afterDelay(delay, performAction: SKAction.run(block)) + } +}