Overlapping UIImageViews on screen: select the right view - ios

I am creating an iPhone app in which the user taps structures on an image of an MRI scan to select regions of interest and calculate a score. Each screen contains a UIView with multiple UIImage views. Each UIImageView that is touched by the user is "highlighted". However, on one of the screens the structures of interest are so close together that the frame rectangles of the UIImageView overlap (3 of them). Now, tapping in some areas highlights the wrong image. Rearranging views does not help (moving to front or back) doesn't help, there is a large area of overlap. I included a screen shot of the Storyboard and corresponding code of the view controller. Can anybody think of a solution??
override func touchesBegan(_ touches: Set, with event: UIEvent?)
{
let touch = touches.first!
switch touch.view {
case PO_PV_R:
if PO_PV_R.isHighlighted == false
{
PO_PV_R.isHighlighted = true
loesScore.parieto_occipital_R_perivent = 0.5
}
else
{
PO_PV_R.isHighlighted = false
loesScore.parieto_occipital_R_perivent = 0.0
}
case PO_C_R:
if PO_C_R.isHighlighted == false
{
PO_C_R.isHighlighted = true
loesScore.parieto_occipital_R_central = 0.5
}
else
{
PO_C_R.isHighlighted = false
loesScore.parieto_occipital_R_central = 0.0
}
case PO_SC_R:
if PO_SC_R.isHighlighted == false
{
PO_SC_R.isHighlighted = true
loesScore.parieto_occipital_R_subcortical = 0.5
}
else
{
PO_SC_R.isHighlighted = false
loesScore.parieto_occipital_R_subcortical = 0.0
}
default:
print("default")
}
let score = loesData.shared.totalLoesScore()
scoreLabel.text = String(format:"%.1f", score)
}

Related

Swift change the position of a button

In the following piece of code I try to move a button and update the score label.
When I move the button the button moves exactly as I intended, but when I update the label as well the button just stays on the same coordinates.
In the piece of code below everything works great.
#IBAction func clickButtonTapped(_ sender: Any) {
if inGame == false {
segmentedControl.isHidden = true
inGame = true
score = 0
} else {
clickButton.isHidden = true
let height = arc4random_uniform(UInt32(screenHeight))
let width = arc4random_uniform(UInt32(screenWidth))
clickButton.center.x = CGFloat(width)
clickButton.center.y = CGFloat(height)
score += 1
clickButton.isHidden = false
}
}
But when I add this below score += 1 the button does not move anymore.
scoreDisplay.text = String(score)
How can I get the button to move and get to scoreDisplay updated?

Get touch location of screen in a spritekit game

i have a sprite kit game and im trying to know if the user has touch the left, right or middle of the screen (25/50/25)
At the moment when i touch the very left side of the screen, it says im touching -450 on the x axis when it should be 0. I assume its getting my touch position relative to the scene and as the achor point starts 450 pixels to the right, gives me -450 when i touch 0.
As this is a side scroller, moving the achor wont work and i need the touch location of the screen:
override func touchesBegan(_ touches: Set<UITouch>,with event: UIEvent?){
var touchLeft : Bool = false
var touchRight : Bool = false
var touchMiddle : Bool = false
for touch in (touches) {
let location = touch.location(in: self)
if(location.x < self.size.width/4){
touchLeft = true
print("Left")
} else if(location.x > ((self.size.width/4) * 3)){
touchRight = true
print("Right")
} else {
touchMiddle = true
print("Middle")
}
}
}
You almost had it, just factor in negative numbers.
In case you were not aware, 0 is the center by default for SKScene. This is because the default anchor point is 0.5,0.5.
Since you are using the camera to handle your scrolling, you want to use
touch.location(in: self.camera) so that you are always touching relative to where the camera is and not where the scene is.
So just change your code to as follows:
override func touchesBegan(_ touches: Set<UITouch>,with event: UIEvent?){
var touchLeft : Bool = false
var touchRight : Bool = false
var touchMiddle : Bool = false
for touch in (touches) {
let location = touch.location(in: self.camera)
if(location.x < -self.size.width/4){
touchLeft = true
print("Left")
} else if(location.x > ((self.size.width/4))){
touchRight = true
print("Right")
} else { //x is between -width / 4 and width / 4
touchMiddle = true
print("Middle")
}
}
}

How can i detect if the user touched the screen in Swift

i want to know detect if the user touched the screen until rect is in a specific x or y position. If not stop the game here's my code:
func didTouchedIntime() -> Bool{
let screenRect = UIScreen.mainScreen().bounds
let viewHeight = screenRect.size.height
let viewWidth = screenRect.size.width
if rect.center.x == 0 {
return false
} else if rect.center.x == viewWidth {
return false
} else if rect.center.y == viewHeight {
return false
} else if rect.center.y == 0 {
return false
}
return true
}
This can be most easily done with a GestureRecognizer. There are, I believe, 3 or 4 different types of GestureRecognizers. You would drag this item onto your storyboard just as you would a label or a TextField. Once this is done, you can configure the GestureRecognizer to do exactly what you want to. Finally you should connect it to an IBAction method and write all the code of pausing the game and resuming the game in there.
Try this link for more information!
Also let me know if you have any other questions.

Removing sprites/labels slow in swift (removeallchildren)

I am adding sklabelnodes and skspritenodes to the scene with these functions:
var levelnode = SKSpriteNode()
var labelLevel = SKLabelNode(fontNamed: "Courier-Bold")
func addlevels(){
var level = score + 1
if (level > 0){
sprite()
levelnode.position = CGPointMake(frame.size.width / 2.2, -frame.size.height/15.6 - frame.size.height/17.6)
levelnode.name = "1"
addChild(levelnode)
sklabel()
labelLevel.text = ("1")
labelLevel.position.x = levelnode.position.x - (levelnode.size.width/40)
labelLevel.position.y = levelnode.position.y - (levelnode.size.width/6)
labelLevel.name = "1"
addChild(labelLevel)
}
if (level > 1){
sprite()
levelnode.position = CGPointMake(frame.size.width / 1.42 - frame.size.width/100, -frame.size.height/10 - frame.size.height/17.6)
levelnode.name = "2"
addChild(levelnode)
sklabel()
labelLevel.text = ("2")
labelLevel.position.x = levelnode.position.x - (levelnode.size.width/40)
labelLevel.position.y = levelnode.position.y - (levelnode.size.width/6)
labelLevel.name = "2"
addChild(labelLevel)
}
// this goes on and on till level 25
}
func sprite(){
levelnode = SKSpriteNode(imageNamed: "levelnode")
levelnode.size.width = frame.size.width / 8
levelnode.size.height = levelnode.size.width
levelnode.zPosition = 1
}
func sklabel(){
labelLevel = SKLabelNode(fontNamed: "Courier-Bold")
labelLevel.zPosition = 2
labelLevel.fontColor = SKColor.blackColor()
labelLevel.fontSize = frame.size.height / 35
}
When I am changing the scene, the sprites and labels are removed from the willmovefromview function:
override func willMoveFromView(view: SKView) {
removeAllChildren()
}
but this is taking too slow if I compare it with other scenes where even more skspritenodes are added..
I think It has to do with the functions where I add the sprites and labels, but what is wrong about it?
EDIT:
the function that takes me back too the menu:
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
errint = false
for touch: AnyObject in touches {
let location: CGPoint! = touch.locationInNode(self)
let nodeAtPoint = self.nodeAtPoint(location)
if (nodeAtPoint.name != nil) {
if nodeAtPoint.name == "menu" {
removeallAction()
removeAllChildren()
var scene1 = GameMenuScene(size: self.size)
scene1.button = self.button
scene1.button2 = self.button2
scene1.button3 = self.button3
scene1.viewController = self.viewController
let transition = SKTransition.moveInWithDirection(SKTransitionDirection.Left, duration: 0.75)
self.view?.presentScene(scene1, transition: transition)
}
}
}
}
Doesn't transitioning to another scene deallocate the current scene?
And if that scene is deallocated, then there's no need for the nodes and such to be removed...
Could you do me a favor, and transition out without removing the children and actions, then transition back in and see if it matters??
Anyway, speed is trivial if you're testing on the simulator... the simulator really only simulates opengl, the core of SpriteKit.
Please try it on your device.
BTW, I'm not sure of stuff but nobody seemed to have answered you so I tried...
EDIT:
HOLY MOTHER OF GOD WHY DIDN'T I SEE THE TIMESTAMP IT WAS ASKED TWO MONTHS AGO.
Too late now I guess... but to anybody reading this, don't answer questions at 2 am.

Make a Game Over Scene

In my game, I want a game over label to appear when the screen is touched during the red light animation. The red light animation is on when the green light animation is off. I want the game screen to pause and the game over label to appear when the player touches the screen during the red light animation. I have this so far, but the app crashes when I try to run it.
Error Message:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attemped to add a SKNode which already has a parent: name:'(null)' text:'Game Over! Tap to Play Again' fontName:'Helvetica' position:{1024, 768}'
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
/* Called when a touch begins */
if gameOverLabel.parent == nil
{
self.addChild(gameOverLabel)
}
println(score)
scoreLabel.text = "\(score)"
}
Try this. You were setting the gameOverLabel with a font size that was too big and frame that was outside the screen. This was why it was not visible. Also you have to stop the game when it reaches game over.
if (!self.paused)
{
if isGreenLightON
{
score += 50
}
else
{
self.paused = true
if (gameOverLabel.parent != nil)
{
gameOverLabel.removeFromParent()
}
gameOverLabel.fontName = "Helvetica"
gameOverLabel.fontColor = UIColor.blackColor()
gameOverLabel.fontSize = 24
gameOverLabel.text = "Game Over! Tap to Play Again"
gameOverLabel.position = CGPointMake(CGRectGetMidX(self.frame), self.frame.size.height - 50)
self.addChild(gameOverLabel)
}
}
else
{
score = 0
if (gameOverLabel.parent != nil)
{
gameOverLabel.removeFromParent()
}
self.paused = false
}
scoreLabel.text = "\(score)"

Resources