How to leftAnchor multiplier? - swift3

I would like to use the for statement to give it left multiplier as many times as 'i'.
How do I write code?
I would definitely like to solve this problem.
Please help me
This is my code
for i in 0 ..< exchangeCategories.count {
let menuBtn: customButton = {
let menu = customButton(type: .system)
menu.item = i
menu.addTarget(self, action: #selector(scrollToPage(_:)), for: .touchUpInside)
menu.translatesAutoresizingMaskIntoConstraints = false
let name = exchangeCategories[i]
let label = UILabel()
label.text = name
label.font = UIFont(name: "SpoqaHanSans-Regular", size: 15)
label.textAlignment = .center
label.textColor = black_textColor
label.backgroundColor = white_backgroundColor
label.translatesAutoresizingMaskIntoConstraints = false
menu.addSubview(label)
label.topAnchor.constraint(equalTo: menu.topAnchor).isActive = true
label.leftAnchor.constraint(equalTo: menu.leftAnchor).isActive = true
label.rightAnchor.constraint(equalTo: menu.rightAnchor).isActive = true
label.bottomAnchor.constraint(equalTo: menu.bottomAnchor, constant: -2).isActive = true
let underLine = UIView()
if i == 0 {
underLine.backgroundColor = selectedPinkColor
label.font = UIFont(name: "SpoqaHanSans-Bold", size: 15)
label.textColor = pink_textColor
}
underLine.tag = i + 1 + 100
underLine.translatesAutoresizingMaskIntoConstraints = false
menu.addSubview(underLine)
underLine.leftAnchor.constraint(equalTo: menu.leftAnchor).isActive = true
underLine.rightAnchor.constraint(equalTo: menu.rightAnchor).isActive = true
underLine.heightAnchor.constraint(equalToConstant: 2).isActive = true
underLine.bottomAnchor.constraint(equalTo: menu.bottomAnchor, constant: 0).isActive = true
return menu
}()
wrap.addSubview(menuBtn)
menuBtn.topAnchor.constraint(equalTo: wrap.topAnchor).isActive = true
menuBtn.leftAnchor.constraint(equalToSystemSpacingAfter: <#T##NSLayoutXAxisAnchor#>, multiplier: <#T##CGFloat#>)
menuBtn.widthAnchor.constraint(equalTo: wrap.widthAnchor, multiplier: 0.25).isActive = true
menuBtn.bottomAnchor.constraint(equalTo: gap.topAnchor).isActive = true
}

Related

.removeAll() no longer working on devices running iOS 16+

I have the removeAll function in my app. It works on iOS 15.7, but not on iOS 16+.
I've looked at the official developer documentation, and it doesn't mention any changes that could've happened in iOS 16+.
Further searching hasn't brought up any mention of this.
What has changed in iOS16+, that has caused this?
UPDATED QUESTION BELOW:
This method is called when user submits an answer to a question. The user's answer is stored as a string literal variable. The user's answer must be cleared from the screen whether the answer is correct or wrong.
I used another part of the app in iOS16+, which uses removeAll to empty an array. It emptied the array. I now suspect that removeAll should only be used on arrays. The user's answer in the code listing below should be assigned empty double quotes, instead of calling the removeAll method.
func checkAnswer() {
cancelDisabled = true
switchLanguageDisabled = true
attemptFinished = true
answered = true
if replaceApostrophesWithBackSlashes(userAnswer: userAnswer.allowedCharacters(string: userAnswer.trimmingCharacters(in: .whitespacesAndNewlines).lowercased())) == foreignNativeAnswer.allowedCharacters(string: foreignNativeAnswer.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()) {
aurotorial.speak(native: dataOps.removeEverythingInBrackets(nativeWord: nativeWordWithoutBrackets), foreign: dataOps.removeDashes(foreignWord: foreignWordWithoutDashes), language: (testSectionThings?[questionCounter].languageSection?.language)!, changeVoiceSpeed: changeVoiceSpeed ?? 0.25, maxLoops: numberSpeechLoops ?? 1)
updateWordCounters(correct: true)
userAnswer.removeAll()
languageColour = .green
showTapSkip = false
showNextTimeDisabled = true
let englishAnswerFont = UIFont.boldSystemFont(ofSize: 16)
let promptAttributes: [NSAttributedString.Key: Any] = [
.font: englishAnswerFont,
.foregroundColor: UIColor(red: 0, green: 0.7, blue: 0, alpha: 1)
]
languageText = NSAttributedString(string: foreignNativeAnswer, attributes: promptAttributes)
nativeForeignPlaceholder = NSMutableAttributedString(string: NSLocalizedString("Correct answer, well done!", comment: "Correct answer"))
DispatchQueue.main.asyncAfter(deadline: .now() + dataOps.determineTextToSpeechDelay(changeVoiceSpeed: changeVoiceSpeed ?? 0.25, numberForeignCharacters: foreignWordWithoutDashes.count)) {
self.prepareForNextQuestion()
}
} else {
updateWordCounters(correct: false)
yourAnswerPrompt = "Your answer: "
wrongAnswer = "\(userAnswer)"
userAnswer.removeAll()
foreignNativeAnswer.removeAll()
languageColour = .blue
showTapSkip = false
iKnowThisDisabled = false
let wrongAnswerFont = UIFont.boldSystemFont(ofSize: 16)
let wrongAnswerAttributes: [NSAttributedString.Key: Any] = [
.font: wrongAnswerFont,
.foregroundColor: UIColor(red: 0, green: 0, blue: 0.7, alpha: 1)
]
languageText = NSAttributedString(string: foreignNativeAnswer, attributes: wrongAnswerAttributes)
answerDisabled = true
let separator = NSMutableAttributedString(string: " ", attributes: noTestSectionThingsAttributes)
let tapAttributedString = NSMutableAttributedString(string: NSLocalizedString("Tap a blue button, then ", comment: "Answer field tap skip 1"), attributes: noTestSectionThingsAttributes)
let skipImageAttachment = NSTextAttachment()
skipImageAttachment.image = UIImage(named: "skip.png")?.withTintColor(.systemBlue)
let skipImageAttributedString = NSMutableAttributedString(attachment: skipImageAttachment)
let nextQuestionAttributedString = NSMutableAttributedString(string: NSLocalizedString(".", comment: "Answer field tap skip 2"), attributes: noTestSectionThingsAttributes)
let NSMutableAttributedStringArray = [tapAttributedString, skipImageAttributedString, nextQuestionAttributedString]
nativeForeignPlaceholder = NSMutableAttributedStringArray.join(withSeparator: separator)
}
enableHint()
enableSkip()
}

Detecting collision and removing child with spritekit in swift 3

At the end, I'm trying to detect collision, and delete the marble as it touches the rectangle. How do I do that?
import CoreMotion
import SpriteKit
import GameplayKit
class GameScene: SKScene, SKPhysicsContactDelegate{
let marbleSprite = SKSpriteNode(imageNamed: "marble")
let marbleSprite1 = SKSpriteNode(imageNamed: "marble")
let marbleSprite2 = SKSpriteNode(imageNamed: "marble")
let marbleSprite3 = SKSpriteNode(imageNamed: "marble")
let marbleSprite4 = SKSpriteNode(imageNamed: "marble")
let marbleSprite5 = SKSpriteNode(imageNamed: "marble")
let marbleSprite6 = SKSpriteNode(imageNamed: "marble")
let marbleSprite7 = SKSpriteNode(imageNamed: "marble")
let marbleSprite8 = SKSpriteNode(imageNamed: "marble")
let marbleSprite9 = SKSpriteNode(imageNamed: "marble")
let rectSprite = SKSpriteNode(imageNamed: "rect")
let rectSprite1 = SKSpriteNode(imageNamed: "rect")
let motionManager = CMMotionManager()
let marbleCategory: UInt32 = 1 << 0
let wallCategory: UInt32 = 2 << 0
let rectCategory: UInt32 = 3 << 0
var teal = SKColor(red: 0, green: 128, blue: 128, alpha: 1)
override func didMove(to view: SKView) {
backgroundColor = teal
marbleSprite.position = CGPoint(x: self.frame.width / 15, y: self.frame.height / 15)
marbleSprite.setScale(0.5)
marbleSprite.physicsBody = SKPhysicsBody(circleOfRadius: marbleSprite.size.width / 2)
marbleSprite.physicsBody?.allowsRotation = true
marbleSprite.physicsBody?.categoryBitMask = marbleCategory
marbleSprite.physicsBody?.collisionBitMask = wallCategory | marbleCategory
self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)
self.physicsBody?.isDynamic = false
self.physicsBody?.categoryBitMask = wallCategory
marbleSprite1.name = "Marble"
marbleSprite1.position = CGPoint(x: self.frame.width / 15, y: self.frame.height / 15)
marbleSprite1.setScale(0.5)
marbleSprite1.physicsBody = SKPhysicsBody(circleOfRadius: marbleSprite1.size.width / 2)
marbleSprite1.physicsBody?.allowsRotation = true
marbleSprite1.physicsBody?.categoryBitMask = marbleCategory
marbleSprite1.physicsBody?.collisionBitMask = wallCategory | marbleCategory
self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)
self.physicsBody?.isDynamic = false
self.physicsBody?.categoryBitMask = wallCategory
marbleSprite1.name = "Marble"
marbleSprite2.position = CGPoint(x: self.frame.width / 15, y: self.frame.height / 15)
marbleSprite2.setScale(0.5)
marbleSprite2.physicsBody = SKPhysicsBody(circleOfRadius: marbleSprite2.size.width / 2)
marbleSprite2.physicsBody?.allowsRotation = true
marbleSprite2.physicsBody?.categoryBitMask = marbleCategory
marbleSprite2.physicsBody?.collisionBitMask = wallCategory | marbleCategory
self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)
self.physicsBody?.isDynamic = false
self.physicsBody?.categoryBitMask = wallCategory
marbleSprite2.name = "Marble"
marbleSprite3.position = CGPoint(x: self.frame.width / 15, y: self.frame.height / 15)
marbleSprite3.setScale(0.5)
marbleSprite3.physicsBody = SKPhysicsBody(circleOfRadius: marbleSprite3.size.width / 2)
marbleSprite3.physicsBody?.allowsRotation = true
marbleSprite3.physicsBody?.categoryBitMask = marbleCategory
marbleSprite3.physicsBody?.collisionBitMask = wallCategory | marbleCategory
self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)
self.physicsBody?.isDynamic = false
self.physicsBody?.categoryBitMask = wallCategory
marbleSprite3.name = "Marble"
marbleSprite4.position = CGPoint(x: self.frame.width / 15, y: self.frame.height / 15)
marbleSprite4.setScale(0.5)
marbleSprite4.physicsBody = SKPhysicsBody(circleOfRadius: marbleSprite4.size.width / 2)
marbleSprite4.physicsBody?.allowsRotation = true
marbleSprite4.physicsBody?.categoryBitMask = marbleCategory
marbleSprite4.physicsBody?.collisionBitMask = wallCategory | marbleCategory
self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)
self.physicsBody?.isDynamic = false
self.physicsBody?.categoryBitMask = wallCategory
marbleSprite4.name = "Marble"
marbleSprite5.position = CGPoint(x: self.frame.width / 15, y: self.frame.height / 15)
marbleSprite5.setScale(0.5)
marbleSprite5.physicsBody = SKPhysicsBody(circleOfRadius: marbleSprite5.size.width / 2)
marbleSprite5.physicsBody?.allowsRotation = true
marbleSprite5.physicsBody?.categoryBitMask = marbleCategory
marbleSprite5.physicsBody?.collisionBitMask = wallCategory | marbleCategory
self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)
self.physicsBody?.isDynamic = false
self.physicsBody?.categoryBitMask = wallCategory
marbleSprite5.name = "Marble"
marbleSprite6.position = CGPoint(x: self.frame.width / 15, y: self.frame.height / 15)
marbleSprite6.setScale(0.5)
marbleSprite6.physicsBody = SKPhysicsBody(circleOfRadius: marbleSprite6.size.width / 2)
marbleSprite6.physicsBody?.allowsRotation = true
marbleSprite6.physicsBody?.categoryBitMask = marbleCategory
marbleSprite6.physicsBody?.collisionBitMask = wallCategory | marbleCategory
self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)
self.physicsBody?.isDynamic = false
self.physicsBody?.categoryBitMask = wallCategory
marbleSprite6.name = "Marble"
marbleSprite7.position = CGPoint(x: self.frame.width / 15, y: self.frame.height / 15)
marbleSprite7.setScale(0.5)
marbleSprite7.physicsBody = SKPhysicsBody(circleOfRadius: marbleSprite7.size.width / 2)
marbleSprite7.physicsBody?.allowsRotation = true
marbleSprite7.physicsBody?.categoryBitMask = marbleCategory
marbleSprite7.physicsBody?.collisionBitMask = wallCategory | marbleCategory
self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)
self.physicsBody?.isDynamic = false
self.physicsBody?.categoryBitMask = wallCategory
marbleSprite7.name = "Marble"
marbleSprite8.position = CGPoint(x: self.frame.width / 15, y: self.frame.height / 15)
marbleSprite8.setScale(0.5)
marbleSprite8.physicsBody = SKPhysicsBody(circleOfRadius: marbleSprite8.size.width / 2)
marbleSprite8.physicsBody?.allowsRotation = true
marbleSprite8.physicsBody?.categoryBitMask = marbleCategory
marbleSprite8.physicsBody?.collisionBitMask = wallCategory | marbleCategory
self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)
self.physicsBody?.isDynamic = false
self.physicsBody?.categoryBitMask = wallCategory
marbleSprite8.name = "Marble"
marbleSprite9.position = CGPoint(x: self.frame.width / 15, y: self.frame.height / 15)
marbleSprite9.setScale(0.5)
marbleSprite9.physicsBody = SKPhysicsBody(circleOfRadius: marbleSprite9.size.width / 2)
marbleSprite9.physicsBody?.allowsRotation = true
marbleSprite9.physicsBody?.categoryBitMask = marbleCategory
marbleSprite9.physicsBody?.collisionBitMask = wallCategory | marbleCategory
self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)
self.physicsBody?.isDynamic = false
self.physicsBody?.categoryBitMask = wallCategory
marbleSprite9.name = "Marble"
rectSprite.position = CGPoint(x: 0, y: self.frame.height / 2)
rectSprite.setScale(3.0)
rectSprite.physicsBody = SKPhysicsBody(rectangleOf: rectSprite.size)
rectSprite.physicsBody?.allowsRotation = false
rectSprite.physicsBody?.categoryBitMask = rectCategory
rectSprite.physicsBody?.collisionBitMask = marbleCategory
rectSprite.physicsBody?.affectedByGravity = false
rectSprite.physicsBody?.isDynamic = false
rectSprite.name = "Rect"
rectSprite1.position = CGPoint(x: 410, y: self.frame.height / 2)
rectSprite1.setScale(3.0)
rectSprite1.physicsBody = SKPhysicsBody(rectangleOf: rectSprite1.size)
rectSprite1.physicsBody?.allowsRotation = false
rectSprite1.physicsBody?.categoryBitMask = rectCategory
rectSprite1.physicsBody?.collisionBitMask = marbleCategory
rectSprite1.physicsBody?.affectedByGravity = false
rectSprite1.physicsBody?.isDynamic = false
rectSprite1.name = "Rect"
physicsWorld.gravity = CGVector(dx: 0, dy: 0)
addChild(marbleSprite)
addChild(marbleSprite1)
addChild(marbleSprite2)
addChild(marbleSprite3)
addChild(marbleSprite4)
addChild(marbleSprite5)
addChild(marbleSprite6)
addChild(marbleSprite7)
addChild(marbleSprite8)
addChild(marbleSprite9)
addChild(rectSprite)
addChild(rectSprite1)
motionManager.startAccelerometerUpdates()
}
override func update(_ currentTime: TimeInterval) {
if let accelerometerData = motionManager.accelerometerData {
print(accelerometerData)
physicsWorld.gravity = CGVector(dx: accelerometerData.acceleration.x * 10, dy: accelerometerData.acceleration.y * 10)
}
}
func didBegin(_ contact: SKPhysicsContact) {
var firstBody = SKPhysicsBody()
var secondBody = SKPhysicsBody()
if contact.bodyA.node?.name == "Marble" {
firstBody = contact.bodyA
secondBody = contact.bodyB
} else {
firstBody = contact.bodyB
secondBody = contact.bodyA
}
if firstBody.node?.name == "Marble" && secondBody.node?.name == "Rect" {
secondBody.node?.removeFromParent()
}
}
}
What I thought that would happen was that once the marble touches the rectangle, the marble would disappear, and be gone. What actually happens is when the marble hits the rectangle, nothing happens. Am I doing something wrong?
Try making these changes and set the contact delegate.
let marbleCategory: UInt32 = 0x1 << 0
let wallCategory: UInt32 = 0x1 << 1
let rectCategory: UInt32 = 0x1 << 2
override func didMove(to view: SKView) {
physicsWorld.contactDelegate = self
}
func didBegin(_ contact: SKPhysicsContact) {
let collision: UInt32 = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
if collision == marbleCategory | rectCatagory {
rectSprite.removeFromParent()
}
}

How to add dictionary values to images using SpriteKit?

(( EDIT 4: Successful in making cards flip. Using .contains on the node and running a SKAction sequence. How would I create three states for the card? Tuple sounds like a fun idea. Unflipped, Flipped, Flipped-Highlighted. It loads with all cards down (done), I want to unflip the card (done), then tap it again to highlight it. In doing so the second time, it highlights itself and the top guess word. The two strings are then concatenated in a label at the bottom, and a Next button activated (not built yet). Upon successful match of the key[value] == A[B] then Score += 1. Getting closer! ))
(( EDIT 3: Update of didMove with split keys and values. Can get the title to be the first key now and I can put the first value on the top left card okay as a test. Progress. Now I just need to either blank out the card on touch down or find a way to flip it. How would the touch down code be done? touch Began? ))
(( EDIT 2: Now thinking of it from the perspective of dictionary key value pairs rather than values alone. Gets rid of the problem of finding the key when the value is assigned to the card. Now to play with labelling the card with SKLabelNode. Need to flip card, add value, compare key. ))
(( EDIT: I made the elements all code in GameScene.swift . That file is now included in this post. Also updated question text and removed some other text. ))
I'm new to SpriteKit and Swift 3. With a few million speakers there's not a lot of Esperanto software so I want to make a game for myself to learn 1000 Esperanto words. (not shown!)
I want to have each card flip to reveal a word value from the dictionary key/values.
Then see if that word matches the wordGuess label key for the value selected.
Also JSON might be better for breaking up 1000 words into modular sections but I'll cross that bridge at another time.
// Code updated to EDIT 4
//
//
import SpriteKit
class GameScene: SKScene {
let guessLabel = SKLabelNode(fontNamed: "HelveticaNeue-UltraLight")
let anotherLabel = SKLabelNode(fontNamed: "HelveticaNeue-UltraLight")
var cardTopLeftLabel = SKLabelNode(fontNamed: "Arial-BoldMT")
let cardTopLeft = SKSpriteNode(imageNamed: "Redcard")
var cardTopRightLabel = SKLabelNode(fontNamed: "Arial-BoldMT")
let cardTopRight = SKSpriteNode(imageNamed: "Redcard")
var cardBottomLeftLabel = SKLabelNode(fontNamed: "Arial-BoldMT")
let cardBottomLeft = SKSpriteNode(imageNamed: "Redcard")
var cardBottomRightLabel = SKLabelNode(fontNamed: "Arial-BoldMT")
let cardBottomRight = SKSpriteNode(imageNamed: "Redcard")
var cardsDictionary: [String:String] = [
"tree": "arbo",
"forest": "arbaro",
"spider": "araneo",
"water": "akvo",
"watermelon": "akvomelono",
"school": "lerno",
"year": "jaro",
"grasshopper": "akrido",
"lawn": "gazono",
"friend": "amiko",
"people": "homoj",
"city": "urbo",
"mayor": "urbestro",
"movie": "filmo",
"Monday": "lundo",
"dog": "hundo"
]
// not used yet
func randomSequenceGenerator(min: Int, max: Int) -> () -> Int {
var numbers: [Int] = []
return {
if numbers.count == 0 {
numbers = Array(min ... max)
}
let index = Int(arc4random_uniform(UInt32(numbers.count)))
return numbers.remove(at: index)
}
}
func addLabel(spriteNode:SKSpriteNode, labelNode: SKLabelNode, cardValue: String, cardName: String) {
labelNode.zPosition = 1
labelNode.text = cardValue
labelNode.name = cardName //"cardTopRightLabel"
labelNode.fontSize = 40
labelNode.fontColor = .black
labelNode.position = CGPoint.init(x: cardTopLeft.size.width/4, y: 0.5)
labelNode.isHidden = true
spriteNode.addChild(labelNode)
}
override func didMove(to view: SKView) {
if let words = self.userData?.value(forKey: "words")
{
print("word information contains \(words)")
}
// get all the card keys
var cardKeys:[String] = []
for (k,_) in cardsDictionary {
cardKeys.append(k)
}
print("all keys are \(cardKeys)")
// slice for four card keys
var fourCardKeys = cardKeys[0...3]
print("four keys are \(fourCardKeys)")
// get keys for display
var firstCardKey = fourCardKeys[0]
var secondCardKey = fourCardKeys[1]
var thirdCardKey = fourCardKeys[2]
var fourthCardKey = fourCardKeys[3]
// print("Card Keys are \(firstCardKey), \(secondCardKey), \(thirdCardKey), \(fourthCardKey)")
// get the card values
var cardsValue:[String] = []
for (_,v) in cardsDictionary {
cardsValue.append(v)
}
print(cardsValue)
// slice for card values
let fourCardValues = cardsValue[0...3]
print(fourCardValues)
// get values for display
let firstCardValue = fourCardValues[0]
let secondCardValue = fourCardValues[1]
let thirdCardValue = fourCardValues[2]
let fourthCardValue = fourCardValues[3]
print("Card Values are \(firstCardValue), \(secondCardValue), \(thirdCardValue), \(fourthCardValue)")
// put first card key into label
guessLabel.zPosition = 1
guessLabel.text = firstCardKey //cardKeys[0]
guessLabel.name = "guessLabel"
guessLabel.fontSize = 144;
guessLabel.fontColor = .black
//anotherLabel.position = CGPoint(x:frame.midX, y:frame.midY - 100.0)
guessLabel.position = CGPoint(x:-2, y:233)
addChild(guessLabel)
anotherLabel.zPosition = 0
anotherLabel.text = "Guess key here, values in cards"
anotherLabel.name = "anotherLabel"
anotherLabel.fontSize = 45;
anotherLabel.fontColor = .blue
//anotherLabel.position = CGPoint(x:frame.midX, y:frame.midY - 100.0)
anotherLabel.position = CGPoint(x:-2, y:203)
addChild(anotherLabel)
////////////////
// top left card
cardTopLeft.zPosition = 0
cardTopLeft.size = CGSize(width: 300.0, height: 300.0)
cardTopLeft.anchorPoint = CGPoint(x: 0.5, y: 0.5)
cardTopLeft.position = CGPoint(x:-229, y:-57)
addChild(cardTopLeft)
addLabel(spriteNode: cardTopLeft,
labelNode: cardTopLeftLabel,
cardValue: firstCardValue,
cardName: "cardTopLeftLabel")
/////////////////
// top right card
cardTopRight.zPosition = 1
cardTopRight.size = CGSize(width: 300.0, height: 300.0)
cardTopRight.anchorPoint = CGPoint(x: 0.5, y: 0.5)
cardTopRight.position = CGPoint(x:132, y:-57)
addChild(cardTopRight)
addLabel(spriteNode: cardTopRight,
labelNode: cardTopRightLabel,
cardValue: secondCardValue,
cardName: "cardTopRightLabel")
///////////////////
// bottom left card
cardBottomLeft.zPosition = 1
cardBottomLeft.size = CGSize(width: 300.0, height: 300.0)
cardBottomLeft.anchorPoint = CGPoint(x: 0.5, y: 0.5)
cardBottomLeft.position = CGPoint(x:-225, y:-365)
addChild(cardBottomLeft)
addLabel(spriteNode: cardBottomLeft,
labelNode: cardBottomLeftLabel,
cardValue: thirdCardValue,
cardName: "cardBottomLeftLabel")
////////////////////
// bottom right card
cardBottomRight.zPosition = 1
cardBottomRight.size = CGSize(width: 300.0, height: 300.0)
cardBottomRight.anchorPoint = CGPoint(x: 0.5, y: 0.5)
cardBottomRight.position = CGPoint(x:132, y:-365)
addChild(cardBottomRight)
addLabel(spriteNode: cardBottomRight,
labelNode: cardBottomRightLabel,
cardValue: fourthCardValue,
cardName: "cardBottomRightLabel")
}
func touchDown(atPoint pos : CGPoint)
{
}
func touchMoved(toPoint pos : CGPoint) {
}
func touchUp(atPoint pos : CGPoint) {
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else {
return
}
let touchLocation = touch.location(in: self)
let touchedNode = self.atPoint(touchLocation)
func flipCard (node: SKNode, label: SKLabelNode)
{
label.isHidden = true
node.run(SKAction.sequence(
[SKAction.scaleX(to: 0, duration: 0.2),
SKAction.scale(to: 1, duration: 0.0),
SKAction.setTexture(SKTexture(imageNamed: "Redcard-blank"))
]
))
label.isHidden = false
}
func flipCardPause (node: SKNode, interval: Double)
{
node.run(SKAction.wait(forDuration: interval))
print("paused for \(interval) seconds")
}
func flipCardBack (node: SKNode, label: SKLabelNode)
{
label.isHidden = true
node.run(SKAction.sequence(
[SKAction.scaleX(to: 1, duration: 0.2),
SKAction.setTexture(SKTexture(imageNamed: "Redcard"))
// SKAction.scale(to: 1, duration: 0.2)
]
))
}
if cardTopLeft.contains(touchLocation)
{
flipCard(node: cardTopLeft, label: cardTopLeftLabel)
//flipCardPause(node: cardTopLeft, interval: 3)
//flipCardBack(node: cardTopLeft, label: cardTopLeftLabel)
}
if cardTopRight.contains(touchLocation)
{
flipCard(node: cardTopRight, label: cardTopRightLabel)
}
if cardBottomLeft.contains(touchLocation)
{
flipCard(node: cardBottomLeft, label: cardBottomLeftLabel)
}
if cardBottomRight.contains(touchLocation)
{
flipCard(node: cardBottomRight, label: cardBottomRightLabel)
}
for t in touches { self.touchDown(atPoint: t.location(in: self)) }
}
How to assign dictionary values to the cards?. EDIT 2: By not using values! I'm going to do from the perspective of dictionary keys, that way each card has a key value pair, then just display the value.
// get all the card keys
var cardKeys:[String] = []
for (k,_) in cardsDictionary {
cardKeys.append(k)
}
// slice for only four cards
var fourCardKeys = cardKeys[0...3]
// get 1st value for display
cardsDictionary[fourCardKeys[0]]
So SKLabelNode on touchDown? I'll try it. Also need to flip card so word is not on the image. Lastly compare the pressed card's key to the wordGuess key text. Getting closer
EDIT 3: Update of didMove with split keys and values. Can get the title to be the first key now and I can put the first value on the top left card okay as a test. Progress. Now I just need to either blank out the card on touchDown or find a way to flip it.
cardTopLeft.zPosition = 0
cardTopLeft.size = CGSize(width: 300.0, height: 300.0)
cardTopLeft.anchorPoint = CGPoint(x: 0.5, y: 0.5)
cardTopLeft.position = CGPoint(x:-229, y:-57)
addChild(cardTopLeft)
cardTopLeftLabel.zPosition = 1
cardTopLeftLabel.text = fourCardValues[0]
cardTopLeftLabel.name = "cardTopLeftLabel"
cardTopLeftLabel.fontSize = 40
cardTopLeftLabel.fontColor = .black
cardTopLeftLabel.position = CGPoint.init(x: cardTopLeft.size.width/4, y: 0.5)
cardTopLeft.addChild(cardTopLeftLabel)
EDIT 4: Successful in making cards flip. Using .contains on the node and running a SKAction sequence. How would I create three states for the card? Tuple sounds like a fun idea. Unflipped, Flipped, Flipped-Highlighted. It loads with all cards down (done), I want to unflip the card (done), then tap it again to highlight it (help?). In doing so the second time, it highlights itself and the top guess word. The two strings are then concatenated in a label at the bottom, and a Next button activated (not built yet). Upon successful match of the key[value] == A[B] then Score += 1. Getting closer! It's really similar to just a matching game but I'm adding an extra layer of card flipping.
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else {
return
}
let touchLocation = touch.location(in: self)
let touchedNode = self.atPoint(touchLocation)
func flipCard (node: SKNode, label: SKLabelNode)
{
label.isHidden = true
node.run(SKAction.sequence(
[SKAction.scaleX(to: 0, duration: 0.2),
SKAction.scale(to: 1, duration: 0.0),
SKAction.setTexture(SKTexture(imageNamed: "Redcard-blank"))
]
))
label.isHidden = false
}
Personally, I don't like to use userData, my opinion is that isn't a readable code.
I'd some like to create a custom SKNode like:
class Card: SKSpriteNode {
var value....
var dictionary
etc
}
Another solution, you can create a tuples:
var cardsDictionary: [String:String] = [
"vegetable":"legomo",
"plant":"vegetalo",
"actually":"efektive",
"currently":"aktuale"
]
let cardTopLeft = (node:SKNode, value:Int, type:[String:String])
cardTopLeft.node = SKSpriteNode(imageNamed: "Redcard")
cardTopLeft.value = 1
cardTopLeft.type = cardsDictionary[0]
All SKNodes have a dictionary you can write to called userData. It is an optional NSMutableDictionary, so you are going to have to create it:
cardTopLeft.zPosition = 1
cardTopLeft.size = CGSize(width: 300.0, height: 300.0)
cardTopLeft.anchorPoint = CGPoint(x: 0.5, y: 0.5)
cardTopLeft.position = CGPoint(x:-229, y:-57)
cardTopLeft.userData = ["word":"tree","value","arbo"]
addChild(cardTopLeft)
To use:
let word = cardTopLeft.userData["word"]
let value = cardTopLeft.userData["value"]
Getting a better understanding of your question, I would use SKLabelNode as an alternative.
What you can do is create SKLabelNodes to the cards with the word you want to attach, and mark it as isHidden = true. When you are ready to reveal the word, you just mark isHidden = false
let value = SKLabelNode("arbo")
value.isHidden = false
cardTopLeft.zPosition = 1
cardTopLeft.size = CGSize(width: 300.0, height: 300.0)
cardTopLeft.anchorPoint = CGPoint(x: 0.5, y: 0.5)
cardTopLeft.position = CGPoint(x:-229, y:-57)
cardTopLeft.addChild(value)
addChild(cardTopLeft)
//to reveal it
if let label = cardTopLeft.children[0] as? SKLabelNode
{
label.isHidden = false
}
//to use it
if let label = cardTopLeft.children[0] as? SKLabelNode
{
let value = label.text
//compare value to dictionary of answers
}
You may want to give your labels a name so that you do not have to use children[0], but I will leave how you want to find a node up to you.

iOS-Charts xAxis Labels cut off

I am using iOS-Charts to show a horizontal bar chart.
The x-Axis labels on the left are cut-off.
Only when I double tap on the chart, the correct sizing appears to happen and the labels are not cut off anymore.
Here's the code I'm using
func setChart(_ dataPoints: [(String,Int)], chart: HorizontalBarChartView) {
chart.noDataText = "No data available."
var dataEntries: [BarChartDataEntry] = []
let maxNumberEntries = dataPoints.count
var xAxisLabel: [String] = []
var counter:Int = maxNumberEntries-1
for _ in 0..<maxNumberEntries {
let dataEntry = BarChartDataEntry(x: Double(counter), yValues: [Double(dataPoints[counter].1)], label: dataPoints[counter].0)
dataEntries.append(dataEntry)
xAxisLabel.append(dataPoints[counter].0)
counter -= 1
}
xAxisLabel = xAxisLabel.reversed()
let chartDataSet = BarChartDataSet(values: dataEntries, label: "")
let chartData = BarChartData(dataSet: chartDataSet)
chart.data = chartData
chart.animate(xAxisDuration: 2.0, yAxisDuration: 2.0)
// disable zoom of chart
chart.pinchZoomEnabled = false
chart.scaleXEnabled = false
chart.scaleYEnabled = false
chart.chartDescription?.text = ""
chart.legend.enabled = false
// disable selection of bars
chartDataSet.highlightEnabled = false
chartDataSet.valueFont = NSUIFont.systemFont(ofSize: 10)
let numberFormatter = ValueFormatter()
chartData.setValueFormatter(numberFormatter)
// specify the width each bar should have
let barWidth = 0.8
chartData.barWidth = barWidth
let formato:BarChartFormatter = BarChartFormatter()
formato.strings = xAxisLabel
let xaxis:XAxis = XAxis()
_ = formato.stringForValue(Double(1), axis: xaxis)
xaxis.valueFormatter = formato
chart.xAxis.valueFormatter = xaxis.valueFormatter
let xAxis = chart.xAxis
xAxis.labelPosition = XAxis.LabelPosition.bottom // label at bottom
xAxis.drawGridLinesEnabled = false
xAxis.granularity = 1.0
xAxis.labelCount = maxNumberEntries
xAxis.labelRotationAngle = 0
// Don't show other axis
let leftAxis = chart.leftAxis
leftAxis.enabled = false
let rightAxis = chart.rightAxis
rightAxis.enabled = false
}
Any idea how to fix that?
Screenshots:
cut-off xAxis labels
after double tap the labels are not cut-off anymore
If you values are cut off even after notifyDataSetChanged, try offseting it like this:
mChart.extraTopOffset = 20
I solved this issue by calling
chart.fitScreen()
for every bar chart once all the data is passed.
HorizontalBarChart label cut issue solved you just only put this code in your chart setup:
chart.extraRightOffset = 30
If anyone has been struggling and answer did not help, once you set a chart with a new data, do not forget to call notifyDataSetChanged on chart, otherwise labels will be cut. That was my case.

How can I add buttons to roImagecanvas (customvideoplayer)

I am newbie in ROKU development.I apologise if my question seems stupid because i am just starting with it.I am working on customvideoplayer example that comes with ROKU sdk examples. I want to add buttons on the canvas for play ,stop ,minimise and maximise functionality. I have reseacrhed on it but have not been able to add the buttons. Moreover I also want to capture the click events of those buttons and perform the requireds fuctionality on their click.
How do I write maximise and minimise codes on button click??
Any suggestions about how I can create those buttons and perform required functionality , would be really appreciated.
Here is the code I am using:
Sub RunUserInterface()
o = Setup()
o.setup()
o.paint()
o.eventloop()
End Sub
Sub Setup() As Object
this = {
port: CreateObject("roMessagePort")
progress: 0 'buffering progress
position: 0 'playback position (in seconds)
paused: false 'is the video currently paused?
feedData: invalid
playing: 0
playingPrev: 0
playlistSize: 0
canvas: CreateObject("roImageCanvas") 'user interface
player: CreateObject("roVideoPlayer")
load: LoadFeed
setup: SetupFullscreenCanvas
paint: PaintFullscreenCanvas
create_playlist_text: CreatePlaylistText
drawtext: false
eventloop: EventLoop
}
this.targetRect ={x: 100, y: 100, w: 600, h:500}
' this.targetRect = this.canvas.GetCanvasRect()
'this.textRect = {x: 520, y: 480, w: 300, h:200}
this.textRect = {x: 150, y: 470, w: 300, h:200}
this.load()
'Setup image canvas:
this.canvas.SetMessagePort(this.port)
this.canvas.SetLayer(0, { Color: "#000000" })
this.canvas.Show()
this.player.SetMessagePort(this.port)
this.player.SetLoop(true)
this.player.SetPositionNotificationPeriod(1)
this.player.SetDestinationRect(this.targetRect)
this.player.Play()
this.playingPrev = this.playing
return this
End Sub
Sub EventLoop()
while true
msg = wait(0, m.port)
if msg <> invalid
if msg.isStatusMessage() and msg.GetMessage() = "startup progress"
m.paused = false
print "Raw progress: " + stri(msg.GetIndex())
progress% = msg.GetIndex() / 10
if m.progress <> progress%
m.progress = progress%
m.paint()
end if
'Playback progress (in seconds):
else if msg.isPlaybackPosition()
m.position = msg.GetIndex()
print "Playback position: " + stri(m.position)
else if msg.isRemoteKeyPressed()
index = msg.GetIndex()
print "Remote button pressed: " + index.tostr()
if index = 4 '<LEFT>
m.playing = m.playing - 1
if (m.playing < 0)
m.playing = 2
endif
m.player.SetNext(m.playing)
m.player.Play()
m.playingPrev = m.playing
else if index = 8 '<REV>
m.position = m.position - 60
m.player.Seek(m.position * 1000)
else if index = 5 '<RIGHT>
m.playing = m.playing + 1
if (m.playing > 2)
m.playing = 0
endif
m.player.SetNext(m.playing)
m.player.Play()
m.playingPrev = m.playing
else if index = 9 '<REV>
m.position = m.position + 60
m.player.Seek(m.position * 1000)
else if index = 2 '<Up>
if m.drawtext
m.playing = m.playing - 1
if (m.playing < 0)
m.playing = m.playlistSize-1
endif
m.paint()
endif
else if index = 3 '<Down>
if m.drawtext
m.playing = m.playing + 1
if (m.playing > m.playlistSize-1)
m.playing = 0
endif
m.paint()
endif
else if index = 13 '<PAUSE/PLAY>
if m.paused m.player.Resume() else m.player.Pause()
else if index = 6 'OK
if m.drawtext
m.drawtext = false
if m.playing <> m.playingPrev
m.player.SetNext(m.playing)
m.player.Play()
m.playingPrev = m.playing
endif
else
m.drawtext = true
endif
m.paint()
end if
else if msg.isPaused()
m.paused = true
m.paint()
else if msg.isResumed()
m.paused = false
m.paint()
end if
endif
end while
End Sub
Sub SetupFullscreenCanvas()
m.canvas.AllowUpdates(false)
m.paint()
m.canvas.AllowUpdates(true)
End Sub
Sub PaintFullscreenCanvas()
splash = []
list = []
if m.progress < 100
progress_bar = {TargetRect: {x: 100, y: 500, w: 598, h: 37}, url: "pkg:/images/progress_bar.png"}
color = "#00a0a0a0"
splash.Push({
url: "pkg:/images/splash.png"
TargetRect: m.targetRect
})
list.Push({
Text: "Loading..."
TextAttrs: { font: "large", color: "#707070" }
TargetRect: m.textRect
})
if m.progress >= 0 AND m.progress < 20
progress_bar.url = "pkg:/images/progress_bar_1.png"
print progress_bar.url
else if m.progress >= 20 AND m.progress < 40
progress_bar.url = "pkg:/images/progress_bar_2.png"
print progress_bar.url
else if m.progress >= 40 AND m.progress < 75
progress_bar.url = "pkg:/images/progress_bar_3.png"
print progress_bar.url
else
progress_bar.url = "pkg:/images/progress_bar_4.png"
print progress_bar.url
endif
list.Push(progress_bar)
end if
if m.drawtext
textArr = m.create_playlist_text()
yTxt = 100
color = "#00000000"
index = 0
for each str in textArr
if index = m.playing
textColor = "#00ff00"
else
textColor = "#dddddd"
endif
list.Push({
Text: str
TextAttrs: {color: textColor, font: "medium"}
TargetRect: {x:700, y:yTxt, w: 500, h: 100}
})
yTxt = yTxt + 100
index = index + 1
end for
else
color = "#00000000"
list.Push({
Text: ""
TextAttrs: {font: "medium"}
TargetRect: {x:100, y:600, w: 300, h: 100}
})
endif
'Clear previous contents
m.canvas.ClearLayer(0)
m.canvas.ClearLayer(1)
m.canvas.ClearLayer(2)
m.canvas.SetLayer(0, { Color: color, CompositionMode: "Source" })
if (splash.Count() > 0)
m.canvas.SetLayer(1, splash)
m.canvas.SetLayer(2, list)
else
m.canvas.SetLayer(1, list)
endif
list.Clear()
splash.Clear()
End Sub
Function LoadFeed() as void
jsonAsString = ReadAsciiFile("pkg:/json/feed.json")
m.feedData = ParseJSON(jsonAsString)
m.playlistSize = m.feedData.Videos.Count()
contentList = []
for each video in m.feedData.Videos
contentList.Push({
Stream: { url: video.url }
StreamFormat: "mp4"
})
end for
m.player.SetContentList(contentList)
End Function
Function CreatePlaylistText() as object
textArr = []
for each video in m.feedData.Videos
textArr.Push(video.title)
end for
return textArr
End Function