fisholith's Recent Forum Activity

  • Thanks for helping to test it out

    Good catch too, I hadn't thought to test the canvas2d renderer.

    I just tried the canvas2d renderer, and I can confirm what you said:

    The pixel distortion seems to occur on webGL, but not with canvas2d.

    Likewise, both renderers still exhibit the Z-order problem.

    I also just added a note to the first post mentioned that the Z-order problem is dependent only on the Z-order at game start. I kind of mentioned this in the capx, but I realized it should be in the main post.

    • Importantly, it is the Z-order at game start that matters here. Once the game is running, the Z-order can be rearranged, but the cross-instance render contamination will still come from whichever instance had the back-most Z-order when the game started. So in my example capx, if you want to see the effect of a different instance acting as the back-most contaminant-instance, you'll need to change the Z-order in the editor and relaunch the game.
  • I've noticed some pretty weird render artifacts when using 9Patch objects.

    (See the images below)

    Questions

    Is it possible that this is a bug? (I don't want to jump to conclusions as I've only investigated this on one computer.)

    If anyone knows a workaround for the following issues, please let me know.

    Image 1: Pixel shape distortion

    Shown, several instances of a few test patterns, and a stone block from a game of mine, in which I first began investigating the occasional 9Patch runtime render issues. Both are zoomed to 8x scale. The Editor is at 800% zoom, and the "In game" runtime has the layout scaled by a factor of 8 via events.

    (click to enlarge)

    Some background

    I make pixel-style games that incorporate some custom post-processing effects to keep everything properly pixilated, and for a long time I thought that my processing chain was occasionally causing these weird 9Patch render artifacts.

    A day ago, I finally decided to investigate and fix the issue, once and for all, but after fiddling with the math in various stages of my processing chain to no avail, I began disabling stages of the chain, until I had disabled everything, but the artifacts remained.

    I then tried reproducing the 9Patch render artifacts in a new blank project. It took a while to figure out, but it turns out it's pretty simple to set up.

    Example capx

    Here's an example capx.

    The capx has two layouts, one shows the effect in "Image 1", and the other layout shows the effect seen in "Image 2".

    In the first layout there are also two extra 9Patch objects that should look okay even during runtime as they have their margins set so that the sub-zones of the source texture all have power-of-two dimensions. The power-of-two dimensions does not fix the Z-order issue, explained below.

    Image 2: Z-order issue

    As far as I can tell, the Z-order artifacts are a totally separate phenomenon from the distorted pixels described above and shown in "Image 1".

    Given a set of 9Patch instances, with different margin properties, the properties of the lowest Z-order instance (back-most and first to be rendered) will contaminate the rendering processes of all subsequent instances.

    Specifically, any subsequent instance will use its own margin properties to partition its internal space into corner, edge, and fill zones, however it will then use the margin properties of the back-most instance when determining how to sample the source texture to fill those zones. This causes the smearing (UV clamping), and partially missing (UVs run off the edge) edge and fill artifacts seen in the image below.

    [edit] Importantly, it is the Z-order at game start that matters here. Once the game is running, the Z-order can be rearranged, but the cross-instance render contamination will still come from whichever instance had the back-most Z-order when the game started. So in my example capx, if you want to see the effect of a different instance acting as the back-most contaminant-instance, you'll need to change the Z-order in the editor and relaunch the game.

    (click to enlarge)

    Reproducing the issues

    • 1. Set the project to use "point sampling".
    • 2. Add a "start of layout" event to scale up the layout by 8x or so at runtime (as you might do for pixel/retro-looking games).
    • 3. Add a32x32 9Patch object with any detailed per-pixel pattern.
    • 4. In the 9Patch properties, set all margins to 4px.
    • 5. Set Fill and Edges to "Tile".
    • 6. Set Seems to "Exact".
    • 7. Resize the 9Patch so that corner, edge, and fill zones are all visible.
    • 8. Run the game. (Make sure the 9Patch is centered as you'll be zooming in 8x.)

    Result: In the runtime window, you should see distortion artifacts in the 9Patch pixels, similar to those shown in "Image 1". Conversely, if you look at the same 9Patch in the editor, zoomed to 800% (use Ctrl + Shift + MouseWheel), it should look correct, with no distortion.

    • 9. Now, create another instance of the same 9Patch object but set all its margins to 8px. (You should now have an 8px-margin instance of the 9Patch object, in addition to the original 4px- margin instance.)
    • 10. Run the game.

    Result: In the runtime window, you should see distortion, just as before, but you should also see that the new 8px-margin instance is tiling its edges and fill in what looks like a smeared and chopped up jumble.

    It took me a while to figure out what exactly was happening. I made a texture to help visualize the UV mapping. It appeared that the 8px-margin instance was correctly partitioning its interior into 9 sub-zones using the 8 pixel margin metrics set earlier. However, it was filling in those sub-zones by sampling the source texture as if it were using the 4 pixel margins set for the back-most instance.

    This works the same way for whichever instance is back-most in Z-order. All other instances erroneously use the margin metric set in the properties of the back-most instance when sampling the source texture. (You can see this in "Image 2")

    Again, this may be something locally weird on my computer, so if anyone else has encountered this, tries the example capx, or reproduces any of these issues, I'd be interested to hear what you found.

    Thanks for enduring my wall of text. :)

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • What you're looking for is exactly what R0J0hound mentioned. <img src="{SMILIES_PATH}/icon_e_smile.gif" alt=":)" title="Smile">

    Setting the origin point

    If you double click on the collision sprite object, the image editor should open.

    In the image editor, on the left-hand toolbar, choose the 2nd tool from the bottom (looks like a crosshair). This is the "Set origin and image points" tool.

    With this tool selected you can set the origin point of your object wherever you want. You can also use the number-pad on your keyboard to quickly snap the origin point to the center edges or corners of the sprite image, though Num-Lock must be enabled for this.

    If the default images of your sword and character face rightward, then for your collision sprite, you'll probably want to put the origin point on the far left edge. You can press numpad-4 to do this, if Num-Lock is enabled.

    Accept the changes and then try it out in the editor by holding down Ctrl + Shift and Dragging one of the corner resize handles on your collision object. It should now scale around the new origin point you just set.

    (You'll want to undo that resize afterwards of course. Be careful not to also undo the change to the origin point.)

    Flipping the sprite

    As for flipping or mirroring the object, in that object's actions, in the Appearance group, you can use the "Set Mirrored" action to flip the object horizontally, and the "Set Flipped" action to flip the object vertically.

    C2 Manual Page on Image Points

    https://www.scirra.com/manual/63/image-points

  • Hey Nitari,

    One possible approach, instead of using "overlapping at offset", you could use a second invisible sprite as a collision object, and stretch it wider as the sword range increases.

  • Awesome! Glad it worked out.

  • Hey brandesign

    By chance, I happened to write a post on detecting full rotations a while back.

    Below is a link, and a copy of my first post in that thread.

    If you get a chance to visit the link, my second post (not included below, because it's long) goes into more detail,

    My second post also has a demo capx I made showing the tracking method in action.

    Here is my demo capx for angle tracking.

    Here is a link to my post on tracking angle changes.

    • - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Text of my first post:

    (Edit) I just checked the System >> "angleDiff" expression, and it always gives a zero or positive answer, meaning it doesn't give you the direction of the change in the angle, so it won't work here.

    One possible approach is to calculate the change in angle between ticks,

    store that change in a running total,

    and track that running total instead of tracking the objects rotation property directly.

    Here is a formula that will give you the change in angle as the shortest CW or CCW rotation, and it works seamlessly across the 360-to-0 transition.

    angle_delta = ( ( ( a - b ) + 180 ) - floor( ( ( a - b ) + 180 ) / 360 ) * 360 ) - 180

    Where a and b are your two angles.

    e.g.

    a = 5, b = 355: ... ( ( ( 5 - 355 ) + 180 ) - floor( ( ( 5 - 355 ) + 180 ) / 360 ) * 360 ) - 180 355: ... = 10

    a = 355, b = 5: ... ( ( ( 355 - 5 ) + 180 ) - floor( ( ( 355 - 5 ) + 180 ) / 360 ) * 360 ) - 180 355: ... = -10

    Remember, if you compare two angles with a difference greater than 180 degrees, the angles will be treated as a shorter rotation in the opposite direction.

    e.g. A raw difference of +270 is treated as -90.

    As long as the total distance rotated per tick is less than 180 degrees that shouldn't be a problem though.

    So, to use this in place of directly tracking the object's angle property, you can do the following:

    Create a custom variable "unwrapped_angle".

    Every tick, get the change in angle between ticks, angle_delta( currentAngle , angleRecordedLastTick ), and add it to "unwrapped_angle".

    Then you should be able to use the unwrapped_angle in place of the objects built-in angle property.

    • - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  • Hey iScream,

    If I understand the events correctly, I think that the first sub event is unpausing the game, and the second sub event is immediately pausing it again.

    Consider the following walkthrough of the events:

    Timescale = 0.

    > User presses Escape.

    Event: On Escape pressed >>> TRUE

    __ Sub-Event: Timescale = 0 >>> TRUE - because Timescale = 0

    ____ Action: Menutext set invisible >>> Menutext is now invisible.

    ____ Action: Set timescale to 1 >>> Timescale is now 1.

    __ Sub-Event: Timescale does not equal 0 >>> TRUE - because Timescale = 1

    ____ Action: Menutext set visible >>> Menutext is now visable.

    ____ Action: Set timescale to 0 >>> Timescale is now 0 again.

    You'll need to make sure that only one OR the other sub event runs.

    You can use an ELSE condition to achieve this. Manual page for the ELSE condition

    Using the ELSE condition, would look like this:

    Event: On Escape pressed

    __ Sub-Event: Timescale = 0

    ____ Action: Menutext set invisible

    ____ Action: Set timescale to 1

    __ Sub-Event: ELSE (This will only run if the prior event, at the same indentation level, was false.)

    ____ Action: Menutext set visible

    ____ Action: Set timescale to 0

    Hope that helps out.

  • Ah, yeah, containers will take everything down with them if they get destroyed.

    Below are a few possible alternatives that might work in place of containers.

    Also, I posted the link to the tutorial you mentioned at the very end.

    UIDs & Private Variables

    As an alternative to containers, you can store the UID of the ArmObj in a private variable of the ArmDetectorObj.

    Then if ArmDetectorObj collides with lava, you can,

    Pick ArmObj by UID, (using the UID you stored earlier), and Destroy just the ArmObj.

    To make sure the UID gets stored correctly, you can Have the ArmObj's "On created" event be responsible for creating the ArmDetectorObj, and saving the ArmObj's UID into a private variable of ArmDetectorObj.

    Thus, whenever you create an ArmObj, it will automatically instantly create and link its very own unique ArmDetectorObj .

    Pin Behavior & "PinnedUID" Expression

    In some cases, if you are already using the Pin Behavior, you can use it's built in PinnedUID expression to get the UID of the pinned object, though this is more of a special case.

    Manual page: Pin Behavior

    Store Reference Behavior

    Another option that might be worth looking into is the third-party "Store Reference" behavior.

    It can be added to objects to make linking them in events simpler and easier to read.

    Forum page & Download: Store Reference Behavior

    • - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    Here's the link to the tutorial you mentioned

    Understanding UID, IID, Health, Cards and Rocket smoke trail.

  • Hey SandvichEater,

    By odd chance I happened to have just finished responding to another question that had a very similar potential solution, so I hope you don't mind if my response below is a little cut-and-pastely.

    Because each enemy is comprised of a collection of unique object types, (some for the image and some for the detectors), you might be able to use the "Containers" feature of Construct 2, to associate all the objects of an enemy.

    Each enemy would get it's own set of detectors that would be automatically contextually picked whenever the parent enemy is picked, and vice versa.

    Containers will work as long as an enemy only needs one of each object type.

    For instance, if an enemy has a body and two ledge detectors, all as separate objects, then you'd need the ledge detectors to each be unique objects (e.g. leftLedgeObj, rightLedgeObj), as you can't put the same object (e.g. ledgeObj) in a Container twice. At least not to my knowledge.

    Containers page of Scirra's C2 Manual

  • Hey Mario4President,

    If each enemy is made up of a set of unique object types, then you might be able to use the "Containers" feature of Construct 2, to associate all the objects of an enemy.

    This will work as long as an enemy only needs one of each object type.

    For instance, if an enemy has a body and two arms, all as separate objects, then you'd need the arms to each be unique objects (e.g. leftArmObj, rightArmObj), as you can't put the same object (e.g. armObj) in a Container twice. At least not to my knowledge.

    Containers page of Scirra's C2 Manual

  • Hey YetAnotherSuperhero,

    One possible approach might be, rather than rotating the next segment around the middle of the edge, make each segment rotate around whichever corner is on the outer side of the bend.

    This way you don't have to fix gaps after the fact by moving things, since there will never be gaps in the first place.

    e.g.

    If the tunnel is moving rightward, then when the tunnel bends down, you rotate the next segment around the top corner.

    When the tunnel bends up, you rotate around the bottom corner.

    This means the tunnel segments will always be fully overlapping where they join.

    Here is an example capx.

    GaplessWindingPath

    In this example, the path segments have been made semi-transparent, so you can see how they overlap.

  • Hey Minjaware,

    It sounds like you might be using the standard Text object. If so, that might be the issue.

    Sprite Fonts vs Standard Text

    If you use a Sprite Text object instead of standard Text object you should be able to get exactly the same result across all browsers. By contrast, the standard text object may not always get rendered as the same font from browser to browser, much less be rendered in exactly the same position.

    The unpredictability of font rendering across browsers is not a bug in C2, as far as I know, but is just a side effect of different browsers all using their own method for rendering text.

    By using a sprite font, you guarantee that C2 is directly responsible for rendering the text, directly from bitmap images, and so it will appear consistent everywhere.

    Using Sprite Fonts

    While it is a bit less convenient to work with Sprite Fonts, there are a few community made tools that make using them much easier.

    Sprite Font Generator - v2

    Sprite Font Generator is a freeware stand-alone font to sprite font conversion tool. It also generates all the JSON code needed by C2 to space and size sprite font characters, and it has a graphical interface.

    Sprite font +

    Sprite font + is a plugin for C2 that can take the JSON code for sprite fonts as a parameter, and will display (in the editor) the correctly sized and spaced character as they will appear at runtime.

    Tutorial, for Sprite font +

    Tutorial showing how to use "Sprite Font Generator" with "Sprite font +"

    Hope this helps out.

fisholith's avatar

fisholith

Member since 8 Aug, 2009

Twitter
fisholith has 2 followers

Connect with fisholith

Trophy Case

  • 15-Year Club
  • Forum Contributor Made 100 posts in the forums
  • Regular Visitor Visited Construct.net 7 days in a row
  • RTFM Read the fabulous manual
  • Email Verified

Progress

19/44
How to earn trophies