Position of child of instance variable not updating - objective-c

Hopefully this is a fairly simple question. I create an instance variable named tutorialBox1 from my main game scene Grid.m. Inside my class TutorialBox.m, I create a sprite named textBox1, and as I tap on the main game scene, I want the position of that sprite, textBox1 to be updated. I've been trying to figure out for hours why the position of the sprite will not update after adding the child once. Here is my attempt, and all the necessary code.
Grid.m
# implementation Grid {
TutorialBox *tutorialBox1;
}
-(void)checkTutorials {
//This method is called upon loading of the scene
tutorialBox1 = (TutorialBox*)[CCBReader load:#"TutorialBox"] //creates instance of variable using Spritebuilder (don't worry if you don't use SB, this part works)
[tutorialBox1 updateBoxDisplay:1] //used to add text box child to textBox1
[self addChild:tutorialBox1];
}
-(void)gridTapped {
//When game scene is tapped, this is called to update position of textBox1 in tutorialBox1
[tutorialBox1 updateBoxDisplay:2]; //updates position of textBox1 in tutorialBox1
}
TutorialBox.m
# implementation Grid {
CCSprite9Slice *textBox1;
}
-(void)didLoadFromCCB {
//Called upon initialization of tutorialBox1
textBox1 = [CCSprite9Slice spriteWithImageNamed:#"RetroSprites/tutorialtextBox1.png"];
}
-(void)updateBoxDisplay:(int)newTutorialLevelNumber {
if (newTutorialLevelNumber == 1) {
textBox1.position = ccp(0,0);
[self addChild:textBox1];
}
else if (newTutorialLevelNumber == 2) {
textBox1.position = ccp(100,100)
}
}
TutorialBox.h
#interface TutorialBox : CCNode
- (void)updateBoxDisplay:(int)newTutorialLevelNumber
#end
I have checked to make sure everything is running properly with print statements, so it isn't an issue with anything else. It is simply being called, but the position in my main game scene, Grid.m is not being updated.
Thanks for the help!

I am not sure about this, but I guess its issue with the threading. Give a try with this code:
-(void)updateBoxDisplay:(int)newTutorialLevelNumber {
dispatch_async(dispatch_get_main_queue(), ^{
if (newTutorialLevelNumber == 1) {
textBox1.position = ccp(0,0);
[self addChild:textBox1];
}
else if (newTutorialLevelNumber == 2) {
textBox1.position = ccp(100,100)
}
});
}

Related

Optimise Kotlin code for button clicked state

I want to change the button background when the button clicked, the function is work by using this code
bank1.setOnClickListener {
bank1.setBackgroundResource(R.drawable.selected_btn_border_blue_bg);
bank2.setBackgroundResource(R.drawable.default_option_border_bg);
bank3.setBackgroundResource(R.drawable.default_option_border_bg);
bank4.setBackgroundResource(R.drawable.default_option_border_bg);
}
bank2.setOnClickListener {
bank2.setBackgroundResource(R.drawable.selected_btn_border_blue_bg);
bank1.setBackgroundResource(R.drawable.default_option_border_bg);
bank3.setBackgroundResource(R.drawable.default_option_border_bg);
bank4.setBackgroundResource(R.drawable.default_option_border_bg);
}
bank3.setOnClickListener {
bank3.setBackgroundResource(R.drawable.selected_btn_border_blue_bg);
bank2.setBackgroundResource(R.drawable.default_option_border_bg);
bank1.setBackgroundResource(R.drawable.default_option_border_bg);
bank4.setBackgroundResource(R.drawable.default_option_border_bg);
}
bank4.setOnClickListener {
bank4.setBackgroundResource(R.drawable.selected_btn_border_blue_bg);
bank2.setBackgroundResource(R.drawable.default_option_border_bg);
bank3.setBackgroundResource(R.drawable.default_option_border_bg);
bank1.setBackgroundResource(R.drawable.default_option_border_bg);
}
But it kinda hardcoded, and make it to so many lines, any way to make the code shorter?
I would keep a variable that keeps track of the selected one like
private var selectedBank: View? = null
And then do
arrayOf(bank1, bank2, bank3, bank4).forEach {
it.setOnClickListener {
selectedBank?.setBackgroundResource(R.drawable.default_option_border_bg)
selectedBank = it
it.setBackgroundResource(R.drawable.selected_btn_border_blue_bg)
}
}
you only need to deselected the previous selected one

UIDragInteraction / UIDropItem get frame of preview

Currently I’m trying to get the frame of my drag/drop interaction object preview view. I can get the position of my finger thanks to:
- (CGPoint)locationInView:(UIView *)view;
I’ve searched through everything and can’t find a way to access the preview view object, or a frame reference. Has anyone figured this out?
Figured this one out - I found out there's a method called after the actual drop function that provides a UITargetedDragPreview object. So my logic is to store the drop session and interaction, then call my "update" function when this preview function has been called.
First, I create some variables for future use:
CGRect destinationFrame; // destination frame.
UIDropInteraction *storedInteraction; // stored interaction.
id <UIDropSession> storedSession; // stored session.
- (UITargetedDragPreview *)dropInteraction:(UIDropInteraction *)interaction previewForDroppingItem:(UIDragItem *)item withDefault:(UITargetedDragPreview *)defaultPreview {
if (!item.localObject) { return nil; }
CGPoint center = defaultPreview.target.center;
CGPoint converted = [defaultPreview.target.container convertPoint:center toView:<TARGETVIEW>];
CGPoint origin = CGPointMake(converted.x - (defaultPreview.view.frame.size.width / 2), converted.y - (defaultPreview.view.frame.size.height / 2));
self->destinationFrame = CGRectMake(origin.x, origin.y, defaultPreview.view.frame.size.width, defaultPreview.view.frame.size.height);
if (self->storedSession && self->storedInteraction) {
[self performDropWithInteraction:self->storedInteraction session:self->storedSession];
}
return nil;
}
- (void)dropInteraction:(UIDropInteraction *)interaction performDrop:(id<UIDropSession>)session {
self->storedInteraction = interaction;
self->storedSession = session;
}
- (void)performDropWithInteraction:(UIDropInteraction *)interaction session:(id<UIDropSession>)session {
// this where I will perform my actual drop, I get the frame with:
// self->destinationFrame.
}

loosing fps after nodes leave screen

I am currently working on a simple game in Sprite Kit. In the game, you are a square that moves around and can shoot at enemies. You shoot "Projectiles" which are just a custom class that inherits from SKSpriteNode. The game works great at first but slowly as you continue shooting the FPS rate slowly deteriorates to extremely low. As the projectiles leave the screen however the Node count goes back down to what it was originally before the projectile was fired.
The first thing I tried to fix it was somehow release the projectiles from the scene when they hit the edge. Here is the code where I attempt to do so but it has not worked at all.
-(void)didBeginContact:(SKPhysicsContact *)contact {
if (contact.bodyA.categoryBitMask == projectileCategory) {
if (contact.bodyB.categoryBitMask == edgeCategory) {
[contact.bodyA.node removeFromParent];
}
} else if (contact.bodyA.categoryBitMask == edgeCategory) {
if (contact.bodyB.categoryBitMask == projectileCategory) {
[contact.bodyB.node removeFromParent];
}
}
}
To improve performance, you can remove the projectiles when they are out of the screen inside the update function.
override func update(currentTime: CFTimeInterval) {
for node in self.children as [SKNode] {
if node.name == "projectile" {
if !CGRectContainsPoint(self.frame, node.position)
{
println("removed")
node.removeFromParent()
}
}
}
}

NSSearchField with menu not being updated

I haev a Document Based Application, and In the document view, I have a NSSearchField. In the search field, I have enabled the menu, which I get to show up, and I have associated actions with the menu item. One of the menu items is called "Match Case". I want to be able to put (and remove) a check next this menu item. When I attempt to do so, the menu does not show the check.
-(IBAction)searchMenuMatchCase:(id)sender {
NSMenuItem *smi = [searchMenu itemWithTitle:#"Match Case"];
if (searchCaseSensitive) {
searchCaseSensitive = false;
[[searchMenu itemWithTitle:#"Match Case"] setState:NSOffState];
} else {
searchCaseSensitive = true;
[[searchMenu itemWithTitle:#"Match Case"] setState:NSOnState];
}
[searchMenu update];
NSLog(#"SM State %ld",[smi state]);
}
The code gets executed, and I get a log message showing the state going from 0 to 1 to 0 to 1. But there is never a check next to the menu item. When I look at the menu item object while debugging, I do see the "state" value set to 0 and 1 before I toggle it.
Any suggestions as to what I am missing?
To get around this issue, I had to use the NSMenuDelegate and use the method validateMenuItem. This way the validateMenuItem method was called before the menu was drawn, and I could make sure the state was set correctly before the menu was drawn. I believe what was happening was that the menu item I was getting in the original code was not the actual menu that was being drawn, but just a template.
/**
This is called when the user selectes the "Match Case" menu item found in the Search field
*/
-(IBAction)searchMenuMatchCase:(id)sender {
if (searchCaseSensitive) {
searchCaseSensitive = false;
} else {
searchCaseSensitive = true;
}
}
/**
This is called Each time a menu is shown.
*/
-(BOOL) validateMenuItem:(NSMenuItem *)menuItem {
if ([[menuItem title] compare:#"Match Case"] == 0) {
if (searchCaseSensitive) {
[menuItem setState:NSOnState];
} else {
[menuItem setState:NSOffState];
}
}
return YES;
}

Cocos2D - CCLabelTTF - waiting for end of running actions

simply, before I start new level of my game, I show countdown (using CCLabelTTF, Cocos2D).
I have this code:
centerLevelLabel.string=#"New level";
centerLevelLabel.visible=true;
[centerLevelLabel runAction:[CCFadeOut actionWithDuration:1]];
while (centerLevelLabel.numberOfRunningActions>0) {
}
centerLevelLabel.string=#"3";
while (centerLevelLabel.numberOfRunningActions>0) {
}
centerLevelLabel.string=#"2";
while (centerLevelLabel.numberOfRunningActions>0) {
}
centerLevelLabel.string=#"1";
while (centerLevelLabel.numberOfRunningActions>0) {
}
//some code bellow
I want to show thist label and then I need continue with code bellow. Problem is, that UI is freezed and in first while block is running infinite loop. But i don`t kwon why, because when running actions is finished, numberOfRunningActions is zero.
Is there any other way, how could I wait for end of running actions and then continue?
Thank you
You could serialize the action by using a CCSequence and add the CCCallFuncN to execute some code after the original action completes.
id action1 = [CCFadeOut actionWithDuration:1];
id action2 = [CCCallFuncN actionWithTarget:self selector:#selector(finishedRunning)];
id sequenceActions = [CCSequence actions:action1, action2, nil]];
[centerLevelLabel runAction:sequenceActions];
....
-(void) finishedRunning {
// Do stuff after action finishes
}
This will always be an infinite loop:
while (centerLevelLabel.numberOfRunningActions > 0)
{
}
It's similar to writing:
while (value > 0)
{
}
For the time the while loop is running, the thread is blocked. Therefore no other code will run that updates the number of actions, or that might change the value of value.