How do I crop the corners of an image and make the cropped corners transparent?

Not favoritedFavorited Favorited 0 favourites
From the Asset Store
A template for creating sprite editing functionality, including selection, resizing, rotation, duplication and more
  • Ultimately, I want a layer of thumbnail images that the user can drag around. Initially I cropped the corners of the thumbnails using a 9patch with its blend mode set to “destination atop” on a transparent layer with “force own texture” enabled.

    I then made the thumbnails draggable and set the 9patch to be a child, so it follows when the thumbnail is dragged.

    The problem with this is that when a thumbnail is dragged over another, their 9patches cut part of the other thumbnail out and it looks ugly.

    So, I figured the solution would be to crop the corners off BEFORE saving the thumbnails – but when I do that, the cropped corners are black not transparent.

    This sample project shows the issue. I have a sprite with its corners cropped by a 9patch, then paste the sprite into a drawing canvas, then paste the 9patch in, then copy the contents of the canvas to a second sprite and download it too.

    As you’ll notice, the corners are black. I set the background of the project to red to a) show the black corners more easily, and b) to try to see where the black is coming from.

    Any ideas?

    I have considered giving each thumbnail/9patch pair their own layer, but I could have up to 50 and felt this might cause performance issues as they’d all need to have “force own texture” enabled.

    https://drive.google.com/file/d/1JYEnTHC1_JdG9jiOjDpmFZc6gXGYMO_D/view?usp=sharing

  • I would use a drawing canvas. You can paste both the sprite and the 9patch on it, and then drag the canvas object.

    -> DrawingCanvas: Paste object Sprite with effects
    -> DrawingCanvas: Paste object Mask with effects
    

    Or save the canvas image and then load it into another sprite.

    -> System: Wait 0.1 seconds (use time scale: True)
    -> DrawingCanvas: Save image (PNG, quality 75, offset 0, 0 size 0 x 0)
    -> System: Wait for previous actions to complete
    -> AnotherSprite: Load image from DrawingCanvas.SavedImageURL
    
  • I would use a drawing canvas. You can paste both the sprite and the 9patch on it, and then drag the canvas object.

    > -> DrawingCanvas: Paste object Sprite with effects
    -> DrawingCanvas: Paste object Mask with effects
    

    Or save the canvas image and then load it into another sprite.

    > -> System: Wait 0.1 seconds (use time scale: True)
    -> DrawingCanvas: Save image (PNG, quality 75, offset 0, 0 size 0 x 0)
    -> System: Wait for previous actions to complete
    -> AnotherSprite: Load image from DrawingCanvas.SavedImageURL
    

    That's exactly what I've done - but the problem is that the cropped corners are black not transparent.

  • ...

    Any ideas?

    ...

    fex.net/s/4amtbay

    Hi, there's also an option using an HTML element, where you can round the corners using CSS.

    But it offers fewer customization options than a sprite.

  • Hi, there's also an option using an HTML element, where you can round the corners using CSS.

    But it offers fewer customization options than a sprite.

    Thank you! This is working pretty well with a few tweaks - I removed the shadow but couldn't understand why there was still some kind of border - looks like pixels from the opposite side of the image or something, so I forced a 0px border and that fixed it.

    Then added two invisible sprites to pin the buttons to so they can be dragged around. Then disabled mouse input on the buttons so that touch reaches the sprites.

    Then move the sprite/button pair to the top if dragged.

    The only small issue is that if you drag the second one over the first then click/touch somewhere where they both overlap, the second one drags (correct), but the first one is now brought to the top (IINCORRECT) - need to have a play to see how I can fix that.

    UPDATED VERSION: https://drive.google.com/file/d/1kzXGUD67byN33c5F6c8sazWi44PiBm6z/view?usp=sharing

    EDIT - now fixed by using "on DragDrop start" as the trigger to move the sprite/button pair to the top.

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • An alternate to using css, blend modes, or the drawing canvas to do it would be to use a mesh distort.

    dropbox.com/scl/fi/tstr83o5l7mixoeayie2v/Rounded_sprite_mesh.c3p

    You could use the approach to crop to any convex shape and even some concave ones, but not all.

  • An alternate to using css, blend modes, or the drawing canvas to do it would be to use a mesh distort.

    https://www.dropbox.com/scl/fi/tstr83o5l7mixoeayie2v/Rounded_sprite_mesh.c3p?rlkey=l8o4t6jyqtpx4yu67m7v86yt3&st=5ayndkm9

    You could use the approach to crop to any convex shape and even some concave ones, but not all.

    Oh this is very slick - thank you. At the moment, I'm too far down the route of using CSS - had some hurdles to get over as the images are coming from local storage - so will continue but if I get into more difficulties, I'll probably try this mesh solution.

    One small issue (and the maths is beyond me!) - there's noticable zig-zagging on the corners. I tried increasing res to 10 and that helped a bit, but increasing it beyong that didn't seem to make a difference.

  • Ah, it's just that the mesh edges aren't anti-aliased, but that doesn't seem like something we can control in construct. Guess you could paste to a canvas at double size and scale down to get some edge smoothing.

    Another option could be to make an effect to do the corner rounding. That would allow you to have antialiasing but you'd also lose the collision benefits.

  • Ah, it's just that the mesh edges aren't anti-aliased, but that doesn't seem like something we can control in construct. Guess you could paste to a canvas at double size and scale down to get some edge smoothing.

    Well, I got stuck trying to get touch scrolling working whilst touching the HTML buttons that I was using with CSS rounded corners so I've gone with your mesh solution (thanks again!). I'm targetting mobile, so the aliasing isn't so noticeable on smaller screens.

    (Next problem I had was detecting whether the mid-point of a sprite was overlapping another instance when dropped after dragging. I had to store the dropped sprite's X & Y, then pick all, discard the dropped one, then use the "overlapping at a point" condition to get the ID of the sprite I dropped the dragged one on top of. (Couldn't simply use "is overlapping" as it may have been overlapping more than one)).

    Another option could be to make an effect to do the corner rounding. That would allow you to have antialiasing but you'd also lose the collision benefits.

    So a shader? Time to learn skymen's CAW Shader? Why would that lose collisions? All I need to be able to do is detect when one's been dragged on top of another as described above.

  • If you ever have the chance I’d recommend trying to replicate the drag n drop behavior with events. It’s not too complex and can give some more flexibility. But sounds like you got what you want working with the behavior.

    By losing collision detection, I meant at the transparent bits at the corners. If it’s just an image or effect, clicking on the transparent parts will still select the object. With the mesh you will be able to click through it. You could utilize the sdf of a rounded rectangle to do the collision detection, and actually the sdf of a rounded rectangle will be the basis of the effect if you look into doing that.

  • I asked Gemini if it could create a shader for me - every attempt failed, so after about 10 iterations, I handed the project over to ChatGPT and it fixed it in 3 attempts.

    If anyone's interest, it's here:

    drive.google.com/file/d/1zE1s13RzZPtttzZrjiOLmEyAa1NL8Av_/view

    Three parameters - radius, width and height (you need to set the latter two to the size of the sprite).

    Thanks for everyone's help.

  • I asked Gemini if it could create a shader for me - every attempt failed, so after about 10 iterations, I handed the project over to ChatGPT and it fixed it in 3 attempts.

    If anyone's interest, it's here:

    https://drive.google.com/file/d/1zE1s13RzZPtttzZrjiOLmEyAa1NL8Av_/view?usp=sharing

    Three parameters - radius, width and height (you need to set the latter two to the size of the sprite).

    Thanks for everyone's help.

    That's an awesome result-now that's what I call putting AI to good use!

    Not only did you solve the problem, but you also shared the solution with the community!

  • You are doing something wrong.

    https://www.dropbox.com/scl/fi/v3u7hjcc50k3k3dge7bmh/CanvasPastingWithBlendModes.c3p?rlkey=3s20z2qgw2l5sq8uw2ue8e6gy&st=ejh2dmkv&dl=0

    Figured out what I was doing wrong - I saved the image as JPG which doesn't support transparency!

    Just in case anyone stumbles across this thread and wants to crop the corners off an image, this is a summary of the methods I tried (read the whole thread for details):

    1. Used a 9Patch with blend mode = destination atop on a layer with "force own texture" - worked great until one image is dragged over another
    2. As above, but take a canvas snapshot and save the image with its corners cropped - make sure to save your drawing canvas as a PNG
    3. CSS / HTML button - worked great but I couldn't detect touch dragging if over the button
    4. Mesh - too much aliasing
    5. Shader - this is what I ended up using
  • Wait.., you can do this easily by using a pre-made rounded corner mask. You only need a single mask object, along with the sprites that you want to have its corner rounded.

    Steps:

    1) After creating each sprite, spawn the mask below it (1 z-index below it)

    2) Pin the mask to the sprite

    3) Set the mask's blend mode to "Destination Out"

    3) Set the sprite's blend mode to "Destination Over"

    Also, keep in mind that enabling "Force own texture" can slightly reduce performance on mid-range devices but this method does NOT require it.

Jump to:
Active Users
There are 0 visitors browsing this topic (0 users and 0 guests)