Sprites in a Layer show on web but not on phone

  • efares
    Likes 0

    Problem Description

    I have a PlayScene with an obstacleLayer in it like this:

    onEnter: function () {
            this._super();
            this.initPhysics();
            this.gameLayer = new cc.Layer();
    
            // Add the playScene layers
            this.gameLayer.addChild(new BackgroundLayer(), 0, tagOfLayer.background);
            this.gameLayer.addChild(new TopLayer(), 0, tagOfLayer.topLayer);
            this.gameLayer.addChild(new ObstacleLayer(this.space), 0, tagOfLayer.obstacleLayer);
            this.gameLayer.addChild(new AnimationLayer(this.space), 0, tagOfLayer.animation);
            this.addChild(this.gameLayer);
            this.addChild(new StatusLayer(), 0, tagOfLayer.status);
    
            this.scheduleUpdate();
        }

    And my obstacleLayer is very close to Parkour Tutorial Chapter 8

    The obstacles (rocks and bomb) are displaying perfectly fine when I run my game on web like this:

    but the rocks and bombs are not displaying when I run it on my android device or iOS simulator. I know the obstacles ARE being loaded on the scene but I'm guessing they are being rendered behind the background layer? I tried playing around with it but no luck :(

    Has anyone come across this issue before? Any idea why this happens?
    Let me know if you need more source code to help me debug this issue.

    Thanks in advance!


  • Sonar Systems admin
    Likes 0

    First try only displaying one object at a time to make sure everything is appearing and once you confirm that works we can move on.


    This reply has been verified.
  • efares
    Likes 0

    Ok so after extensive debugging (this was helpfull: http://www.learn-cocos2d.com/2012/09/reasons-node-show/#TheManyReasonsWhyANodeWontShow-DebuggingTip)
    I found that the obstacles ARE being loaded/displayed correctly but I have positioned them off screen. So my intention is to do this:

    1. Load a sprite on the right side of the screen
    2. Run a MoveTo action on the sprite

    The MoveTo action is what is not working/running on the phone.

    Here is my code for the obstacleLayer (Look at the LoadAnObstacle function):

    /* 
     * This file is to setup the obstacles in the race (PlayScene)
     */
    
    var ObstacleLayer = cc.Layer.extend({
        // Declare variables
        space: null,
        topWallHeight: 0,
        bottomWallHeight: 0,
        obstaclesSpritesheet: null,
        screenSize: 0,
        screenOrigin: 0,
        obstacles: [],
    
        ctor: function (space, topWallHeight, bottomWallHeight) {
            this._super();
            this.topWallHeight = topWallHeight;
            this.bottomWallHeight = bottomWallHeight;
            this.space = space;
            this.init(); // init needs to be called right after assignment of space
        },
    
        init: function () {
            this._super();
    
            // Initialize
            this.screenSize = cc.director.getVisibleSize();
            this.screenOrigin = cc.director.getVisibleOrigin();
    
            // Initialize obstaclesSpritesheet
            cc.spriteFrameCache.addSpriteFrames(res.obstacles_plist);
            this.obstaclesSpritesheet = new cc.SpriteBatchNode(res.obstacles_png);
            this.addChild(this.obstaclesSpritesheet);
    
            // Start timer for when the next obstacle should load
            this.nextObstacleTimer();
    
            // Start scheduleUpdate
            this.scheduleUpdate();
        },
    
        // Timer for when the next obstacle should load
        nextObstacleTimer: function () {
            this.unschedule(this.loadAnObstacle);
            this.schedule(this.loadAnObstacle, Math.floor((Math.random() * 2) + 0.5)); // Generate a random number between 0.5-2.5 (seconds)
        },
    
        // Load a random obstacle at a random height on the road
        loadAnObstacle: function () {
            // Re-call timer so countdown starts for next obstacle to load
            this.nextObstacleTimer();
    
            var sprite = new cc.PhysicsSprite.create("#obstacle1.png");
            // Get obstacle size
            var obstacleSize = sprite.getContentSize();
    
            // Select a random height on the road
            var totalWallHeight = this.topWallHeight - this.bottomWallHeight - obstacleSize.height;
            var obstacleHeight = (Math.random() * totalWallHeight) + this.bottomWallHeight + (obstacleSize.height / 2);
    
            // Initialize the physics
            var obstacleBody = new cp.Body(1, cp.momentForBox(1, obstacleSize.width, obstacleSize.height));
            obstacleBody.p = cc.p(this.screenOrigin.x + this.screenSize.width, obstacleHeight);
            sprite.setBody(obstacleBody);
    
            var shape = new cp.BoxShape(obstacleBody, obstacleSize.width, obstacleSize.height);
            shape.setElasticity(elasticity); // These are set in globals.js
            shape.setFriction(friction);
            shape.setCollisionType(2);
            shape.setSensor(true);
            this.space.addShape(shape);
    
            // Start moving the obstacle
            var obstacleAction = cc.MoveTo.create(1, cc.p(this.screenOrigin.x, obstacleHeight)); //MoveTo(time/seconds, position)
            sprite.runAction(obstacleAction);
    
            // Add this obstacle sprite to spritesheet
            this.obstaclesSpritesheet.addChild(sprite);
        },
    
        // Update each frame
        update: function (dt) {
            //Function to check if obstacle reached the end of the screen
        }
    });

    So the obstacleAction is not working as it’s supposed to on my android device. Am I setting it up wrong? Should it be in the scheduler update?

    This is what is happening:


  • Sonar Systems admin
    Likes 0

    But it’s working on other devices?

  • efares
    Likes 0

    No, it's not working on other devices.  I tried it on 3 different phones and the ios simulator.

    It's the same logic that moves the road background (striped lines are moving left) but that is just an image sprite, not a physics sprite. Does that make a difference? 

  • Sonar Systems admin
    Likes 0

    Is the road working?

  • efares
    Likes 0

    yes, the road (only an image, no physics) is working when MoveTo action is run on it.

  • Sonar Systems admin
    Likes 0

    So the object with physics isn’t working.

  • efares
    Likes 0

    Correct.

    MoveTo seems to have no effect on the physics sprite. Maybe I’m doing something wrong? Can you replicate the issue?

  • Sonar Systems admin
    Likes 0

    Try disabling/commenting out the physics just to see if the sprite is set up properly.


    This reply has been verified.
  • efares
    Likes 0

    Ya that’s it!

    I don’t think I can use MoveTo on a physics sprite. I should apply force to it by either using velocity or impulse or force? I’ll watch these tutorials: http://www.sonarlearning.co.uk/coursepage.php?topic=game&course=cocos2d-x-v3-cplusplus-physics

    But any suggestion of which one I should use just to move the physics sprite horizontally from right to left, no change in the y-axis.

    UPDATE:
    setVelocity doesn't seem to work in JS and for my game I feel applyImpulse works better than applyForce. When Force is applied, it takes some time for the physics sprite to get up to speed, using impulse moves the sprite instantly.
    Also, this only works if the physics sprite body is added to the space, if it's not then force and impulse do not work.


  • Sonar Systems admin
    Likes 0

    Try applying more impulse


    This reply has been verified.
  • efares
    Likes 0

    Ya, using impulse got what I needed. This can be marked as solved :)

    Thanks for all your help and replies!

Login to reply