Detecting touch on a specific node

I've got a CCSprite on a CCLayer and scrolling is handled by a CCFollow action.

I'm trying to detect a touch on the CCSprite, but I cant find the magic incantation to detect it reliably when the screen has scrolled. I'm not sure if I should be adding the CCEventListenerTouchOneByOne to the sprite, to the layer, what the 2nd optional parameter is when I create the CCEventListenerTouchOneByOne. Touch location seems to be in relation to the screen. The sprite will always be topmost, so I'm not worried about it being behind other nodes.

I must be missing something obvious, but Ive been Console.Writelining out positions and bounding rects of every conversion I can think of, and I'm losiong the will to live now!

Anyone any handy pointers?

Posts

  • kjpou1kjpou1 LUMember, Xamarin Team Xamurai

    Neil

    Can you put together a small project for us to take a look at. That will help with tracking where the problem is.

  • NeilDansonNeilDanson USMember
    edited October 2015

    Using CocosSharp 1.6, this relies on a file called Sprite.png (mine is 100x100Px). You should be able to just copy/paste this into a new project.

    `using CocosSharp;

    namespace CocosTouchIssue
    {
    class AppDelegate : CCApplicationDelegate
    {
    public override void ApplicationDidFinishLaunching(CCApplication application, CCWindow mainWindow)
    {
    base.ApplicationDidFinishLaunching(application, mainWindow);
    var scene = new CCScene(mainWindow);
    var layer = new CCLayerColor(CCColor4B.AliceBlue);
    scene.AddChild(layer);
    var sprite = new CCSprite(new CCTexture2D("Sprite.png"));
    layer.AddChild(sprite);
    var follow = new CCFollow(sprite, new CCRect(0, 0, 3000, 600));
    layer.RunAction(follow);

            sprite.PositionX = 1000;
            sprite.PositionY = 300;
    
            var touchEvent = new CCEventListenerTouchOneByOne();
            touchEvent.OnTouchBegan = (touch, _event) =>
            {
                var attempt1 = sprite.BoundingBox.ContainsPoint(touch.Location);
                var attempt2 = sprite.BoundingBoxTransformedToWorld.ContainsPoint(layer.ScreenToWorldspace(touch.Location));
                var attempt3 = sprite.BoundingBoxTransformedToWorld.ContainsPoint(sprite.ScreenToWorldspace(touch.Location));
                var attempt4 = sprite.BoundingBox.ContainsPoint(layer.ScreenToWorldspace(touch.Location));
                var attempt5 = sprite.BoundingBox.ContainsPoint(sprite.ScreenToWorldspace(touch.Location));
                //var attempt6 = sprite.BoundingBox.ContainsPoint(scene.ScreenToWorldspace(touch.Location)); Null Reference Exception
                var pt = layer.WorldToScreenspace(sprite.Position);
                var attempt6 = new CCRect(pt.X, pt.Y, sprite.ContentSize.Width, sprite.ContentSize.Height).ContainsPoint(touch.LocationOnScreen);
                return attempt1 || attempt2 || attempt3 || attempt4 || attempt5 || attempt6;
            };
            sprite.AddEventListener(touchEvent, sprite);
            mainWindow.DefaultDirector.PushScene(scene);
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            var app = new CCApplication(false, new CCSize(1024, 600));
            app.ApplicationDelegate = new AppDelegate();
            app.StartGame();
        }
    }
    

    }
    `

  • NeilDansonNeilDanson USMember
    edited October 2015

    In fact - here's the file so you can just add it to a new project....(I'd missed the attach file option!)

    (Edit: File wouldnt upload)

  • kjpou1kjpou1 LUMember, Xamarin Team Xamurai

    Neil

    Try something like this your touchEvent.OnTouchBegan = (touch, _event) => delegate:

                var layerOffset = Layer.PositionWorldspace;
                var target = (CCSprite)touchEvent.CurrentTarget;
                var locationInNode = touch.Location;
    
                CCRect rect = target.BoundingBoxTransformedToWorld;
                rect.Origin += layerOffset;
    
                if (rect.ContainsPoint(locationInNode))
                {
                    CCLog.Log("sprite began... x = {0}, y = {1}", locationInNode.X, locationInNode.Y);
                    target.Opacity = 180;
                    return true;
                }
    
  • NeilDansonNeilDanson USMember

    Thanks Kenneth - that worked perfectly. Was there a reference point for creating that or was it just through experience?

    Many thanks!

  • DJPDJP USMember ✭✭

    @NeilDanson : you can use this by using BoundingBoxTransformedToParent.ContainsPoint(). ballSprite.BoundingBoxTransformedToParent.ContainsPoint(arg1.Location) in this manner in the HandleTouchBegan Method or in case you face any problem try to create separate listeners on the layer.

Sign In or Register to comment.