onTouchBegan not being called sometimes on iphoneX

in my game you have to press the screen and hold it down to move the ball object, and some beta testers have been reporting that the ball does not move sometimes which means onTouchBegan is not being called in some cases, and all of them have the iPhoneX , has anybody else had this issue of onTouchBegan not being called on iphoneX sometimes ? its kind of a serious issue because then it causes them to get GameOver since the ball crashes into the object

Well my iPhone X is going in for repair because the screen stops responding.

Also is the event being triggered? Any edge cases?

1 Like

may just be an iphoneX issue then, I don’t think the event is being triggered because if it got triggered then it would call onTouchBegan? and in onTouchBegan I change the value of a variable which causes the ball to move, so my only conclusion was that onTouchBegan is not being called. Im going to try to borrow a friends iphoneX and put a log(); in onTouchBegan to see if it is in fact not being called. im not sure what you mean by “edge cases” ?

Show me the code you have for any touch events. Let’s take a look.

1 Like

i’ve testen on my iPhone XS and iphone 6 and low end android phones and it works fine

 bool levelOne::init() {
auto listener = EventListenerTouchOneByOne::create();
    listener->setSwallowTouches(true);
    listener->onTouchBegan = CC_CALLBACK_2(LevelOne::onTouchBegan, this);
    listener->onTouchMoved = CC_CALLBACK_2(LevelOne::onTouchMoved, this);
    listener->onTouchEnded = CC_CALLBACK_2(LevelOne::onTouchEnded, this);
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
}

bool LevelOne::onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *event)
{
    auto visibleSize = Director::getInstance()->getVisibleSize();
    
    if(start == 0){
        start = 1;
        ball->setVisible(true);
        scoreLabel->setVisible(true);
        startL->setVisible(false);
        SimpleAudioEngine::getInstance()->playBackgroundMusic("levelOneS.mp3", true);
    }
    
    if(touch->getLocation().x < visibleSize.width / 2){
        
        moveLeft = true;
        
    } else if(touch->getLocation().x > visibleSize.width / 2)
    {
        moveRight = true;
        
    }
    
    return true;
}

void LevelOne::onTouchMoved(cocos2d::Touch *touch, cocos2d::Event *event)
{
  
}

void LevelOne::onTouchEnded(cocos2d::Touch *touch, cocos2d::Event *event)
{
    moveLeft = false;
    moveRight = false;
}

void LevelOne::update(float dt)
{
    auto visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();
    
    auto ballPosition = ball->getPosition();
    
    if(start == 1) {
    
    if(moveLeft == true){
        
        ball->setPositionX(ball->getPositionX() - 9);
        
        if(ballPosition.x <= origin.x + 15){
            ball->setPositionX(origin.x + 15);
        }
        
    } else if(moveRight == true)
    {
        ball->setPositionX(ball->getPositionX() + 9);
        
        if(ballPosition.x >= visibleSize.width - 15){
            ball->setPositionX(visibleSize.width - 15);
        }
        
     }   
    }

what are these events attached to a ball?

I do my events a bit different than you do. I do some containsPoint() checking and also return false if needed. You always return true regardless.

I can share my code later once I can open my laptop.

1 Like

I have a sprite that is a ball, and I have blocks(also sprites) moving up the screen from the bottom continuously, and the ball sprite stays on the same Y-axis the whole time, I only want it to move left and right , so I have if the touch is on the left side of the screen move to the left, and if its on the right side of the screen move the ball to the right. and when they remove their touch from the screen it sets the moveLeft and moveRight variabled to false so it stops moving in the update loop. Is there a better way of doing it ? im not exactly sure about what “return true;” does and if I did something wrong by always having it return true ? that would be great if you could share your code.

Ok so what object are these attached to? What priority is the event?

the moveLeft and moveRight are just 2 boolean values, or which are you referreing to that are attached ? the ball and blocks are all individual sprites, or are you asking what object the listener for onTouchBegan, onTouchEnded attached to ? auto listener = EventListenerTouchOneByOne::create();

i have it set to sceneGraphPriority
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);

I will have an iphoneX tomorrow so ill be able to tell if its being triggered

May 3d touch cause this issue?

not sure what 3d touch is ?? it works fine on my iphone XS, but iphoneX it randomly does not work

Try off 3d touch.

I’m not entirely sure if this would be the cause of your issue, but it may be possible with the way you’ve designed your code.

You’re setting moveLeft and moveRight to true in the onTouchBegan, yet you’re setting them to false in onTouchEnded. Where you actually use them in the update() call, so is there any chance that the onTouchBegan and onTouchEnded are called within the same cycle, before the next update() is called?

In this case, what may happen is moveLeft and moveRight are still false, since the transition from false->true->false happened before that update() was called. The issue would be intermittent, and not easily reproducible.

Add CCLOG("") calls in onTouchBegan, onTouchEnded, and in update(), within the if (moveLeft == true) block, so your console does not get spammed with messages. This way, you will see the exact order they’re being called in.

2 Likes

Interesting idea…

I will try it out its just weird that it works fine on all other devices except iphoneX but let me see what happens right now when I try, i couldn’t come up with a better way to move the ball if anyone has any ideas ? also its not a quick tap in my game they hold down the screen so wouldn’t it be updated by the next time the update method was called ?

If you want the movement to occur as soon as the player touches the screen, then use onTouchBegan, but if you want it to occur after their finger is lifted off the screen, then use onTouchEnded, but not both (at least not the way you’ve implemented it).

For instance, if you want it as soon as they touch the screen (just pseudocode):

onTouchBegan() 
{
    moveLeft = true;
}

onTouchEnded() 
{
    stopMovement = true;
}

update()
{
    if (moveLeft) 
    {
        // ... code to move left goes here ...
        
        // then set moveLeft to false in here instead of onTouchEnded
        if (stopMovement)
        {
            moveLeft = false;
            stopMovement = false;
        }
    }
}

What happens here is that it still allows the update() method to process the movement at least once after you tap the screen, since you’re no longer setting the same variable back to false in onTouchEnded().

I really don’t know if this will fix your issue, or that it’s even the cause of it, but the only way to really know is to add some kind of logging to your code so you can see the call order of the methods.

1 Like

ok that makes alot of sense I never thought about using 2 different variables for it, ill see if it works tomorrow when I get the iphoneX to test on

I will be getting the iphoneX on friday, hopefully it fixes it, but I forgot to mention i kind of use the variables to make it like a touch holding down method, because they hold down the screen for how ever long they want the ball to move, I think this will work as a touch holding down method since there is not one so im trying to think wouldn’t the cycle catch it the next time it was called and then begin to move the ball. I’ll have to see friday

IzzyJM, guessing where the problem is and what it may be can only get you so far. You really need to use the tools available to you in order to track down the true source of the problem, and the only real way to do that is to give yourself as much information as possible. I cannot stress enough how important it is that you do this, and one of the methods, as I mentioned previously, is to use logging to console (CCLOG etc.).

You can also use a debugger, but in this case it may not help since pausing with a debugger causes unintended code paths to be taken, or button events to not happen as you would expect because of the breakpoints.

1 Like

yes I know im just waiting on the iphoneX so i can reproduce and see exactly whats happening and using CCLOGs to see if the method is being called