How to skip immediate previous view on back button Ionic2 - ionic2

I am working on Ionic2.
I have few pages e.g.
P1 -> P2 -> P3 -> P4
When I press back button on P4 or use navCtrl.pop(), it goes to P3. But I want to goto P2 if some conditions are met. Is it possible in Ionic2 to skip immediate previous view.
I cant set P2 as root on P4 back button. It should be that P3 is removed from back history.

Try this code within your component class
#ViewChild(Navbar) navBar: Navbar;
ionViewDidLoad() {
this.navBar.backButtonClick = (e: UIEvent) => {
if(condition) //put your condition here
this.navController.remove(2); //if you want to skip P3
this.navController.pop();
}
}

Related

restore the toggle button status in ionic2

On ionChange I am checking some condition, if condtion is set to false I want to restore the toggle buttons previous position. Here is the relevant code
changeStatus(item) {
if(this.mqttservice.response) {
//doing smthg
}
else {
item.status =!item.status;
//bring back the toggle to previous position
}
}
<ion-toggle [(ngModel)]="item.status" (ionChange)="changeStatus(item);" checked="false">
The issue is since I am changing the state changeStatus() is called indefinitely. How do I prevent this and restore toggle button previous position on else condition?
The [()] syntax means you are getting updates and posting updates when the variable changes. Since you are using (ionChange) you can use the [] syntax instead, which means it only gets updates (but won't post them)
<ion-toggle [ngModel]="item.status" (ionChange)="changeStatus($event, item);">
Since the toggle button changes its state, in order for it to "change back" you need to toggle the value back and forth. You can solve this by setting the value and then if it fails, trigger a change "in the future" by adding a setTimeout.
public changeStatus(event: boolean, item: Item) {
item.status = event;
if (allGood) {
// do something
}
else {
// revert to old value
setTimeout(() => { item.status = !event; });
}
}

Swift 3 - how to move sprite node when a bool is true?

Ok, I am working in Swift 3 playgrounds and need to move a sprite node to a certain point ONLY when the user's mouse is down, stopping when it's released. So far I have:
override func mouseDown(with event: NSEvent) {
mouseIsDown = true
}
override func mouseDragged(with event: NSEvent) {
}
override func mouseUp(with event: NSEvent) {
mouseIsDown = false
}
func moveGuy() {
let action = SKAction.move(to: CGPoint(x: size.width / 2,y: 200), duration: 2)
action.timingMode = .easeInEaseOut
guy.run(action)
}
//UPDATE
override func update(_ currentTime: CFTimeInterval) {
if(mouseIsDown)
{
moveGuy()
}
}
This works somewhat, the problem is only after I release the mouse (mouseIsDown is false) does the SKAction actually run (smoothly). I think this is because it is being called again and again.
Normally I would use a moveBy action in little increments, but I need my node to move to a specific point.
How can I make my node move on its way to a point only when the mouse is down?
When you call
guy.run(action)
sprite-kit will run the action on the guy until completion. You're correct, moveGuy() is being called again and again (every time the frame is update, i.e. every ~33ms assuming 30fps).
Try placing moveGuy() in mouseDown(). As soon as you click, the guy will move smoothly to his destination, but he won't stop if you stop clicking. You need to somehow stop the action. What you can do is replace
guy.run(action)
with
guy.run(action, withKey: "moveGuy")
This will associate a key with your action, that you can look up later on in mouseUp():
guy.removeAction(forKey: "moveGuy")
After this, your node will move to a point only when your mouse is down. But as you've pointed out, the node's movement is still irregular if you re-click. Try changing .easeInEaseOut to .linear. The movement will then be consistent, albeit abrupt when starting/stopping.
I highly recommend the reading documentation on SKActions to gain a better understanding of how to use them.

how to do that when i click on the map, the marker disappeared?

I use asmdroid 4.2 and bonuspack 4.5.
my code add marker:
Marker startMarker = new Marker(mapView);
startMarker.setPosition(new GeoPoint(locationA,locationB));
startMarker.setIcon(getResources().getDrawable(drawable));
startMarker.setTitle("jkdfghspdifj");
startMarker.setAnchor(Marker.ANCHOR_CENTER, 1.0f);
MarkerInfoWindow infoWindow = new MyInfoWindow(R.layout.bonuspack_bubble,
mapView,title);
startMarker.setInfoWindow(infoWindow);
mapView.getOverlays().add(startMarker);
mapView.zoomToBoundingBox(boundingBox);
mapView.invalidate();
everything works fine :)
I click on the marker and displayed popup window. and how to do that when you click on the card itself, the marker disappeared? (at the moment it disappears unless again click on it)
To close all open popups when tapping anywhere on the map, follow the Tutorial 5, Chapter 16. Handling Map events
To have an open popup that closes when you are opening the popup on an other marker, a simple solution is to share the same infoWindow object between all your markers.
Or call "InfoWindow.closeAllInfoWindowsOn(map);" in onOpen.
paste in my class MarkerInfoWindow
in the metod onOpen
public void onOpen(Object arg0) {
Marker current = (Marker) arg0;
for(int i=0; i<mMapView.getOverlays().size(); ++i) {
Overlay o = mMapView.getOverlays().get(i);
if (o instanceof Marker) {
Marker m = (Marker) o;
if(m!=current)
m.hideInfoWindow();
}
}
}

How to detect touch except the falling bodies from top in cocos2d-x ios game using c++

In my game there are certain zombies coming from top of the screen.I have stored all zombies sprites in an CCArray.Then using foreach loop I am making them falling down.
I just want to perform combo.It means that whenever I kill a zombie on tap, the combo_counter increases.
On killing two consecutive zombies the combo_counter goes to 2 but if I tap at any other location on the screen the combo_counter should go to 0.
So my problem is how to detect whether I have not tapped a zombie and tapped anyother place on the screen.I am attaching my code also of cctouchbegan method
zombies is a CCArray where all zombie sprites are stored
void Level1::ccTouchesBegan(cocos2d::CCSet *pTouch, cocos2d::CCEvent *pEvent)
{
CCTouch* touch = (CCTouch*)(pTouch->anyObject());
CCPoint location = touch->getLocationInView();
location = CCDirector::sharedDirector()->convertToGL(location);
CCObject* touchedzombie;
CCARRAY_FOREACH(zombies, touchedzombie)
{
if(!((CCSprite*) touchedzombie)->isVisible())
continue;
//
if(((CCSprite*)touchedzombie)==zombies->objectAtIndex(0))
{
// if((CCSprite*(touchedzombie)==zombies-))
if(touchedzombie!=NULL&&((CCSprite*)touchedzombie)->boundingBox().containsPoint(location))
{
this->setScoreonGame();
combo_counter++;
CCString *comboString=CCString::createWithFormat("comboX %d",combo_counter);
zombies_left--;
CCLOG("left = %d",zombies_left);
CCSize tt=((CCSprite*)touchedzombie)->getContentSize();
CCPoint pos_of_sprite=((CCSprite*)touchedzombie)->getPosition();
int rand_die1=Level1::random1();
CCString *str = CCString::createWithFormat("z2%d.png", rand_die1);
changedSprite = CCSprite::create(str->getCString());
CCLOG("Inside index 0");
((CCSprite*)touchedzombie)->setVisible(false);
changedSprite->setPositionX(pos_of_sprite.x);
changedSprite->setPositionY(pos_of_sprite.y);
changedSprite->setScaleX(Utils::getScaleX());
changedSprite->setScaleY(Utils::getScaleY());
this->addChild(changedSprite);
combo=CCLabelTTF::create(comboString->getCString(), "HoboStd", 50);
combo->setColor(ccRED);
combo->setPosition((ccp(changedSprite->getContentSize().width*0.50,changedSprite->getContentSize().height*1.05)));
changedSprite->addChild(combo,40);
this->runAction(CCSequence::create(delayAction,
callSelectorAction,
NULL));
this->removeChild( ((CCSprite*)touchedzombie),true);
this->Level1::reloadZombies();
// touchedzombie=NULL;
}
}
if(((CCSprite*)touchedzombie)==zombies->objectAtIndex(3))
{
// if((CCSprite*(touchedzombie)==zombies-))
if(touchedzombie!=NULL&&((CCSprite*)touchedzombie)->boundingBox().containsPoint(location))
{
// iftouched++;
this->setScoreonGame();
combo_counter++;
CCString *comboString=CCString::createWithFormat("comboX %d",combo_counter);
zombies_left--;
CCLOG("left = %d",zombies_left);
CCSize tt=((CCSprite*)touchedzombie)->getContentSize();
CCPoint pos_of_sprite=((CCSprite*)touchedzombie)->getPosition();
int rand_die1=Level1::random1();
CCString *str = CCString::createWithFormat("z2%d.png", rand_die1);
changedSprite3 = CCSprite::create(str->getCString());
// CCLOG("%s",str->getCString());
// CCLOG("Sprite Toucheddd");
CCLOG("Inside index 4");
// CCLog("width= %f height =%f",tt.width,tt.height);
// CCLog("x location =%f y location =%f",location.x,location.y);
// CCLog("Positon of Sprite X=%f Y=%f",pos_of_sprite.x,pos_of_sprite.y);
((CCSprite*)touchedzombie)->setVisible(false);
changedSprite3->setPositionX(pos_of_sprite.x);
changedSprite3->setPositionY(pos_of_sprite.y);
changedSprite3->setScaleX(Utils::getScaleX());
changedSprite3->setScaleY(Utils::getScaleY());
this->addChild(changedSprite3);
combo=CCLabelTTF::create(comboString->getCString(), "HoboStd", 50);
combo->setColor(ccRED);
combo->setPosition((ccp(changedSprite3->getContentSize().width*0.50,changedSprite3->getContentSize().height*1.05)));
changedSprite3->addChild(combo,40);
this->runAction(CCSequence::create(delayAction,
callSelectorAction3,
NULL));
this->removeChild( ((CCSprite*)touchedzombie),true);
this->Level1::reloadZombies();
touchedzombie=NULL;
}
//..upto 9 indexes...
}
}
First of all, it is not neccesary to do this checks : if(((CCSprite*)touchedzombie)==zombies->objectAtIndex(0))
How CCARRAY_FOREACH works, is it takes each object from the provided CCArray and assigns it to your touchedZombie variable - this means that if there are 10 elements in the array, this code will be run 10 times (exactly!). This means that with the first run, you will fall into the first if check (the one with objectAtIndex(0), with the second it will fall into the if check with objectAtIndex(1). Removing this if's not will not only speed up your function, but also tidy it up.
This would save you a lot of space, plus if you wanted to change something you would only have to do it in one place, which is safer.
Ok, to the problem at hand :
I see two solutions to this :
Leaving your code : you should move the combo code from the if blocks, and replace it with a flag. This flag should be set to false at the beginning of ccToucheBegan, and if you you detect a touch on a zombie, set it to true. Then after the CCARRAY_FOREACH block, this flag will tell you if there was a tap on a zombie or not. Change your combo accordingly.
Changing your code : You could also make the zombies CCMenuItemImages - this way they would have a different callback function than the rest of the screen. So whenever the ccTouchBegan method would be fired, you will know that it wasn't a zombie that was touched.
I hope everything is clear, if not - let me know.

How to stop a character from going out of the screen?

i'm making this game where a ninja is supposed to go up and down. I wrote a method for a button to do so but the problem is that when the ninja is at the top of the screen (landscape)
it still goes up when i touch the up button so, i did this
-(void)upPressed:(id)sender
{
if(CGPointEqualToPoint(ninja.position, ccp(0,280)))
{
id standStill = [CCMoveBy actionWithDuration:0 position:ccp(0,0)];
[ninja runAction:standStill];
}else
{
id moveUp = [CCMoveBy actionWithDuration:.1 position:ccp(0,80)];
[ninja runAction:moveUp];
}
}
and the problem still exists. any help?
i.e when the ninja is at (0,280), i want the up button to do nothing
You are testing for equality. This if condition will only be true if the ninja is exactly at {0, 200}.
Try this instead:
if (ninja.position.y < 280)
{
// no need to run an action for this
ninja.position = CGPointZero;
// but you should stop any potentially running (move) action
[ninja stopAllActions];
}
else ...