fisholith's Forum Posts

  • ---

    Hey very cool Bro7hers.

    You might already know, but you can save example images like the ones I include in my posts with the "Save Preview" button at the top of the application. It will save a preview of the normal colors or the selected colors depending on which is visible when clicked.

    I made some preview images of your Justice_Night theme as an example,

    --- Cassianno

    Thanks Cassianno!

    If you get a chance to make a theme you'd like to share, I'd love to see it.

    Just a heads up, there are still a few things I'd like to get around to adding in to the program, but the main one is that the "condition boarder" and "action boarder" are currently the only elements not shown in the selection preview mode, but I'll add that into the next update when I have time to get to it. In the mean time, it generally suffices to make them a lighter or darker shade of their respective background colors.

  • Good news everyone!

    [Solved]

    When applying forces, specifying image point "0" will apply to the center-of-mass, and image point "-1" will apply to the origin point set in the image editor.

    I'm not sure if there's a good way to get in touch with Ashley, but it would be handy to have this added to the "Physics behavior" manual page for the "Physics actions: Forces" section, since it's a pretty nice feature.

    :)

    Thanks for the replies makotto and R0J0hound.

    I appreciate the suggestion makotto, and it turns out that due to the special image point addressing system for joints and forces, it should work without even having to worry about imparting problem torque.

    Likewise, thanks for the article link R0J0hound, as it will help with answering another question I was going to bring up relating to the conversion between gravity units and force units, which appear to be different. For my project, the acceleration caused by "gravity = 10" seems to be equivalent to the acceleration of "force = 0.2 * objectMass". That seems to agree with the "0.02" scaling factor you gave in the linked post.

  • Is there a way to disable or enable gravity for individual objects?

    [Solved]

    Set global gravity to 0.

    Use downward force on individual objects to replicate gravity.

    The amount of force should be ( original gravity value * 0.02 ) * the object's mass.

    (The "0.02" just converts C2-pixel-units to Box2D-units.)

    When applying the force, specify image point "0", to use the center-of-mass.

    (When applying forces, specifying image point "0" will apply to the center-of-mass, and image point "-1" will apply to the origin point set in the image editor.)

    e.g. If your original global gravity was "10", then to recreate it with force on an object, you apply a force of 0.2 * the object's mass.

    ---- (original text continued) ----

    Currently two iffy approximations come to mind, but they both have weird issues that separate them from being actual gravity.

    Downward force - as gravity?

    Globally disable gravity,

    Then, for objects that should experience gravity, apply a downward force proportional to object mass.

    This is kind of close to gravity, except that in the physics behavior I can only find actions that apply a force vector to a single point on the object. If this point is not the center of mass (or does not lie on a line through the center of mass), then the object will experience torque.

    I figured there would be a way to retrieve the center of mass coords from the physics behavior, and there is, but I can't find an action in the physics behavior to apply a force on an object that uses XY cords as parameters. The only point parameter is an image point selection.

    For simple symmetrical objects where the center of mass is always dead center, you can just put an image point there and use that, but it's not a generally applicable solution. By contrast the built-in global gravity will work correctly regardless of the specific shape of the collision polygons of the affected objects. I would like to use something that general if it exists.

    Direct velocity manipulation?

    The other option would be to directly add to the object's velocity, which has it's own issues. Framerate independence being the main one that comes to mind. Even with the incorporation of "dt" with an integration step I'd be concerned about mixing both force and velocity level alterations to the object's state, as well as mixing by-hand framerate compensation and integration (as in mathematical integral) with whatever the Box2D asm.js physics engine is doing internally to handle framerate independence and integration. I think this might also bypass friction and linear damping.

    Any thoughts or suggestions are welcome. :)

    (Minor update)

    Image point "0" & "-1" for joints

    In the Physics behavior manual page, in the "Physics actions: Joints" section, there is a mention that, for "Create distance joint" and "Create revolute joint" actions, image point "0" specifies the center of gravity instead of the origin image point, and "-1" specifies the origin image point. I don't know if this is also the case for applying forces, as nothing to that effect is mentioned for force actions. I'll test it out and report back.

  • Happy to help, TheZinc and :)

    > Firstly, I love you! Secondly, I'm going to have to put these into practice to get a complete understanding of the application and limitations..

    I've found that sometimes it can be handy to open a second copy of Construct 2, just to try something out in a simple blank-slate environment, before adding it to a complex project. Not sure if it's applicable in this case, but I figured I'd mention it.

    > In terms of monitor framerates, isn't it something that can be capped? Can I not set it to 60 fps and any PC or device playing the game will limit fps?

    I believe Construct 2 leaves the scheduling of the frames (basically the framerate) up to whatever HTML5 engine is running the game, whether that's Firefox, or Chrome, or NW.js (NodeWebkit).

    This means that you can't really rely on a given framerate, because each platform may behave differently. Even if you could cap it, it would only limit the maximum framerate, but wouldn't necessarily change the variability of the framerate.

    That said, there's another important side to this, which is that you might not want to limit the maximum framerate in the first place.

    If you can make your game truly framerate independent, it will run correctly at any monitor refresh rate, rather than being 60 Hz only, and it will look very smooth and fluid on high refresh rate monitors.

    My recommendation would be to always aim for framerate independence if possible, unless the project absolutely requires a fixed framerate.

    Construct 2 already allows you to export for multiple platforms, so also setting up a game to run on multiple monitor types just gets you that much closer to having a game that can run on anything. :)

    I should have assumed this in advance, but Ashley put together a nice tutorial article on using "dt" for framerate independence:

    Delta-time and framerate independence

    This is another nice article I found that covers framerate independent acceleration, and shows a few different integration formulas. (Euler, Verlet, and RK4)

    Integration Basics

    (Remember, "integration" is just a method of eliminating that stair-step error I mentioned in the first post. It does it by calculating what you would see if you could increment in finer steps, infinitely finer steps actually.)

    > I imagine these are some of the problems you had to solve on Down Ward

    Yes indeed. :)

    Down Ward is framerate independent, using "dt" in relevant time dependent expressions, and the Physics behavior in "Framerate independent" mode.

    The first game I built framerate independence into from the ground up was my prior game-jam game ArcherOpteryx. After seeing how smooth it looked at a 144 hz refresh rate, and after seeing that my prior game-jam games didn't run correctly on any refresh rate other than 60 Hz, I decided that I would incorporate framerate independence into every future project. After that I retroactively updated Neon Phoenix to be framerate independent. I eventually hope to similarly update my first two game-jam games Owl Camp and Lucid which are currently not framerate independent.

    My recommendation would be to always aim for framerate independence if possible, unless the project absolutely requires a fixed framerate.

    It's actually not as hard as it might seem at first, because almost everything can be made framerate independent just by multiplying "dt" to rate values in expressions.

    The "calculus" type stuff only ever shows up for very few special cases, when you're dealing with stuff that's non-linear over time, like acceleration for physics. Likewise, even if you go the completely from-scratch rout, the only "calculus" based math you'll encounter is actually just some basic multiplication and addition done in the right places. The reason it works is related to calculus, the term used to describe the process ("integration") comes from calculus, but the actual math that makes it work is just basic multiplication and addition.

    As for the jetpack problem, my first game-jam game Owl Camp actually does involve a jetpack, and (if I recall) it is thrust limited in the fashion I described in my prior post. :)

    > Looking forward to it

    Thanks TheZinc. You can actually try out the open alpha of Down Ward right now if you're interested.

    Down Ward (alpha)

    Happy to hear you're looking forward to it. I'm working on the next update now actually. :)

  • Hey TheZinc,

    If I understand, you're interested in simulating low gravity, and a jetpack with a capped maximum speed.

    I'm not sure what stuff you already know, so I'll just go over the things that might help out.

    Summary:

    Frame rate independent acceleration can be tricky, but is doable with "delta time", some math, and also even more math.

    C2's Physics behavior can do it all automatically.

    Try ignoring Jetpack thrust when player is over desired speed cap.

    Low Gravity

    In a low gravity environment, like the moon, physics will behave exactly the same way as on Earth, except that the global downward acceleration on all objects will be a lower value.

    On earth the downward acceleration (gravity) is

    32 ft/s^2 "feet per second ... per second"

    Meaning every "second", a falling object picks up an extra 32 "feet per second" of speed.

    On the moon the downward acceleration is about

    5 ft/s^2 "feet per second ... per second"

    Meaning every "second", a falling object only picks up an extra 5 "feet per second" of speed.

    In Construct 2 terms this is like saying every second add 5 (feet per second) to an object's Y velocity.

    Acceleration per tick

    So, we could make a C2 event that said:

    "Every second add 5 to an object's Y velocity."

    Unfortunately that accelerates by an amount of 5 in a big burst every 1 second.

    What we really want, is to accelerate by an amount of 5, but smoothly spread out over 60 ticks per second:

    Every tick (60th of a second) add "5 * (1/60)" to an object's Y velocity.

    Now after 1 second of ticks we will have added 60 of those "5 * (1/60)" slices, which is a total increase of "5" for Y velocity, over 1 second. Success!

    This almost works, but remember that not everyone's monitor is capped at 60 frames per second. Some will be 120 fps, or 144 fps, or on a slower machine, you might get 30 fps.

    So if you cant count on 60th of a second ticks, and multiplying by 1/60; but you also can't count on 120th of a second ticks, and multiplying by 1/120; then what do you do?

    It would be handy if C2 could tell you exactly how short a tick was right at the moment the calculation was being done. Fortunately it can, and that value is called "dt" for "delta time", meaning the fraction of a second since the last tick.

    When the frame rate is 60 fps, dt will be 1/60th.

    When the frame rate is 120 fps, dt will be 1/120th.

    It's exactly what we need.

    So instead of saying:

    Every tick (60th of a second) add "5 * (1/60)" to an object's Y velocity.

    We now say:

    Every tick (delta sized sliver of a second) add "5 * (dt)" to an object's Y velocity.

    In practical terms, using a lower gravity value will mean the player jumps higher than in normal gravity, and the arc of motion will appear to be in slow motion.

    Curse of Calculus

    So all the above fiddling with "dt" gets us the right velocity regardless of tick rate, but there's still a problem.

    It doesn't get us the right position, because position is based on velocity over time.

    If your game runs at 1 fps, a dropped stone will have the correct velocity after 1 second, but it won't have gone anywhere yet, because before that first second it's velocity was zero, so it covered no distance at all, for that whole second.

    Drop the same stone, using a faster frame rate (like 60 fps), and after 1 second the velocity will be exactly the same as in the prior example, but the stone will have traveled downward on every tick after the first one.

    In the real world, if you graphed the increase of velocity over time, you'd get a nice increasing diagonal line.

    In the game world you are stuck with ticks, so the velocity is changing in stair steps, and the notches (stairs) are the error. Making the time slices (stairs) smaller makes this error smaller, but this just means the size of the error will vary with the speed of the frame rate.

    Now this error might not be a huge issue, but if you want to eliminate it, you can use Euler integration or Verlet integration, which both attempt to account for the missing stair step area, regardless of step size. Verlet is kind of like an interpolated version of Euler.

    Another way to eliminate it is just to use a pre-built physics engine that handles all this stuff, like C2's built in Physics Behavior, or a comparable 3rd party Physics solution like Chipmunk Physics (which another C2 dev built a plugin for). Note, I think you have to set C2's physics to be frame rate independent with an event, if you want it to do all that "dt" stuff I described above, but it basically just has an "on switch" for that mode.

    Jetpack velocity cap

    One way to cap the power of the jetpack is to make it apply thrust only when the player's upward speed is below a threshold.

    e.g.

    If player is pressing Thrust key,

    AND

    If the player's upward velocity is below 100 pixels a second,

    THEN

    Add +1 to upward velocity.

    Just remember that in Construct 2 upward velocity is actually negative "Y".

    So the above code written in Construct would look like this:

    If player is pressing Thrust key,

    AND

    If the player's Y velocity > -100.

    THEN

    Add -1 to upward velocity.

    Hope that helps out.

  • Hey cornfl4ke,

    edit: I just noticed that I hadn't seen that there was a page 2 for this post with some existing answers. Well here's another then...

    If I understand correctly, it sounds like you want to arrange for the following:

    1. A player can always pick up an item by tapping it.

    2. A single tap that picks up an item won't activate a room.

    3. If an item is sitting somewhere on a room , the player should be able to tap anywhere else on that room to activate the room without picking up the item.

    Just to clarify #3, given a room with an item sitting on the northern half, a player should be able to tap the southern half of the room to activate the room without "touching" the item.

    So, when the user taps,

    you first check if the tap was on an item, and if it was, you then run the item pickup actions.

    Or ELSE, (if the tap was NOT on an item),

    then check if the tap was on a room, and if it was, you then run the room activation actions.

    The events would look like this.

    • - On touch:
      • - Is touching object (item):
        • (Place the actions for touching an item here.)
      • - ELSE - Is touching object (room):
        • (Place the actions for touching a room here.)

    Note that the "ELSE" and the "Is touching object (room)", are two conditions together in the same event.

    To create an "ELSE" condition, select an event and press X to create an ELSE below it.

    Or, right click an event (a whole event not just a condition) and choose Add > Add Else.

    Hope that helps out.

  • Hey Isaske, <img src="{SMILIES_PATH}/icon_e_smile.gif" alt=":)" title="Smile">

    Yes "Sort Z order" is probably what you want. There are other ways to Z order objects, but this new action is the fastest.

    The online C2 manual has a pretty good overview, which I included below, along with a link to the page.

    Sort Z order:

    "Sort the Z order of instances of a given object according to an instance variable. This effectively removes all instances from their Z order, sorts them, then inserts the sorted sequence back in to the holes left behind.

    This means if the instances are spread across a range of layers, they will be sorted in the same Z order locations, maintaining the same order relative to other instances on those layers.

    Note this action is much faster than using an ordered For each with an action like Send to front/back, so this action should be the preferred way to sort the Z order of large numbers of instances."

    (source: https://www.scirra.com/manual/125/system-actions)

  • Hey derboo,

    Point & Linear

    I don't think you can change the sampling type at runtime.

    I'm not sure, but I think it might be because the canvas has to be set up differently, at the HTML5 level, for either render mode.

    You can change the pixel-rounding mode, at runtime, but that just snaps object visuals to integer coords for rendering, it doesn't affect the way textures are sampled. Though combining snapping with the pixelate effect shader might get you part way to recreating the look of point sampling, and it would be toggleable at run-time. Though there would be some discrepancies, when compared with actual point sampling.

    Just out of curiosity, why is it that you were interested in changing the sampling type at runtime?

    I vaguely remember looking for a way to do that quite a while back, but I don't recall why.

    Anyway, even if there's not a direct way to get the effect you want, there might be a workaround that could approximate what you're looking for. I'd be happy to suggest anything I can think of.

    I do have a thought on how you could effectively build your own custom point sampling system on top of the built-in Linear mode, in a way that would allow you to toggle it at runtime, though its efficiency might become an issue depending on the game and target platform. You could run the game in linear mode, use effects to pixelate individual objects (point sample their textures), and then pixelate the entire screen (point sample the canvas). I think that might almost perfectly recreate the point sampling look. Though the pixelate scale would need to match the scaling factor of the entire game. It could be a handful to set up and maintain, but the effect could be toggled on and off at runtime.

    Fullscreen in browser

    As for the "Fullscreen in browser" project property, I don't know of any way to change it at runtime, though I believe the "Crop" mode gives you enough freedom to recreate the appearance of any of the other scaling modes, though you'd need to build them yourself via events.

    For instance, the game I'm currently working on runs in Crop mode, but I have a custom scaling system (via events) that fits a GameBoy sized screen (160 x 144) into arbitrary monitor dimensions by integer up-scale. Likewise, I have a custom letterboxing system that can toggle letterbox bars to clip the screen, to show only the GameBoy screen (the 160 x 144 zone), or just let the game screen extend beyond GameBoy res to fill the monitor.

  • Glad it worked out. :)

    And oh, man, I know what you mean about taking a break, coming back, and beholding the madness of yesterday's 4am attempts at productivity. :]

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • Happy to help.

    I also noticed that my final version of the example disappeared somehow.

    The image I added is from the final version, but the download link is to an earlier version. I could not find a saved copy of the final version so I rebuilt the last few parts, added in the glideSpeed variable along with quite a bit of commentary on it, and it should now match the posted image, and support deleting blocks with middle-click.

    (also edited my first post to use the v2 example)

    Array Glide Reorder - v2

  • Ah, good catch with the missing glideSpeed,

    I was going to add it in so it would be easy to change the X and Y lerp speed in one place.

    Also, sorry if my reply being directed at you seemed strange. I accidentally referred to your name when I started typing up the post, instead of the OP's name. I edited the starting line to include czar.

    Though, I did take a look at your example capx, and it was cool.

    I like that the reordering is specific to a zone you can drag blocks in and out of, and so ordering is restricted to just that area. It seems like a really practical way to approach a UI element, as I can see how with multiple zones you could drag blocks between them, for things like inventory or card decks.

  • Hey czar and allan,

    (edit: derp, I meant to copy the OP's name.)

    One approach is to add a second private variable to the Block that smoothes out changes in the index variable. Then use that smoothed value to position the Blocks instead of the actual index.

    So in the example I linked below, each block has two private variables, index and indexAnim.

    Where index is the block's sequence in the row of blocks,

    and indexAnim is a variable updated every tick to glide towards the value currently in index.

    So if index changes from 0 to 1, then indexAnim will smoothly transition over several ticks from 0 to 1.

    An easy way to set up indexAnim to do this smooth attraction to the value in index is with the following event.

    Every tick: Set indexAnim to: lerp( indexAnim , index , 0.1 )

    This means that every tick, the indexAnim value will move towards the index value by an amount of 0.1 (10%) of the distance currently between them.

    Example capx

    Here's a commented example capx.

    Array Glide Reorder - v2

    Controls

    Left-click drag blocks.

    Right-click to create new blocks.

    Middle click to destroy blocks.

    Mousewheel to change cell width.

  • Hi Blamitall,

    If I understand correctly, I think you might want the following:

    Set Block1.Y to:

    Block2.Y - ( (Block2.Height /2) + (Block1.Height/2) )

    This adds the radius of B1 and B2, and then subtracts that whole value from the B2.Y.

    Place & move method

    Another handy approach in this kind of situation might be, to use two actions:

    1. B1: "Set position to another object", use B2 as the target object.

    2. B1: "Move at angle" a distance of ( ( B1.h / 2 ) + ( B2.h / 2 ) ), at angle -90.

    This approach separates out the relative offset, which can help make the code a little easier to understand/edit at a glance.

    It's not quite as efficient as setting the cords directly, but the slight difference in efficiency will likely only be noticeable if you do it 10,000 times a tick.

    So this method isn't strictly better or worse, it just has different pros and cons.

  • Hey spacedoubt,

    So, if I understand correctly, I believe the short answer would be this:

    snapX = ( round( mouse.y / 32 ) % 2 = 0 ) ? ( round( mouse.x / 128 ) * 128 ) : ( ( round( ( mouse.x + 64 ) / 128 ) * 128 ) - 64 )

    snapY = round( mouse.y / 32 ) * 32

    That said, I've also included an explanation of this solution below:

    The math

    What it sounds like you want to do is snap to a diamond shaped grid; basically a rectangular grid with every odd row shifted half a cell length.

    Let's start by thinking of the rectangular un-shifted version of the grid.

    From your capx, it looks like you want a horizontal snap distance of 128, and a vertical snap distance of 32. Now 32 might sound too small, but remember that as soon as we shift every odd row, it will suddenly look like the vertical snap distance is 64, because the vertical separation between tiles will appear to skip a row. But it really isn't skipping a row, and it really isn't 64, it's still 32.

    Unshifted
    #---#---#---#
    #---#---#---#
    #---#---#---#
    #---#---#---#
    
    Shifted
    #---#---#---#
    ..#---#---#---#
    #---#---#---#
    ..#---#---#---#[/code:315nwg0m]
    Now if we shift every odd row by half a cell width, we'll have a diamond grid that will snap 128 x 64 pixel tiles.
    
    [b]Vertical snap[/b]
    So lets start with the vertical snapping since it will be the same regardless of the row.
    We need to snap to steps of 32 pixels.
    
    tileY = round( mouse.y / 32 ) * 32
    
    We are squeezing the 32 pixel tile size down to the size of integers, then using round() to chop off the decimal part, then expanding the rounded result back to the 32 pixel tile size.
    
    [b]Horizontal snap[/b]
    Next lets do the horizontal snapping, but for simplicity, our first version here will not account for the shifting on odd rows.
    It's basically the same as the vertical snapping, but with bigger steps.
    
    tileY = round( mouse.x / 128 ) * 128
    
    Same deal, we squeeze, round, and expand back to normal.
    Now that formula works fine for the even rows, but what about the shifted odd rows?
    Well lets make a similar, but slightly adjusted version of the formula for the odd rows.
    We want to shift the tiles over by half the horizontal step width of 128. So we'll shift by 64.
    
    tileY = ( round( ( mouse.x + 64 ) / 128 ) * 128 ) - 64
    
    So it's basically exactly the same as the even-row formula, except we add a 64 offset to the input "mouse.x", and we subtract it back off after we end.
    Why? Well remember that the heart of our snapping system is the round() function. When we shift everything by half a step width (64), and then divide by an entire step width (128), as far as the round() is concerned we are shifting by "0.5"; and since round() will snap to the nearest integer, it will be snapping exactly halfway between the spots we'd get from the even-row formula. 
    
    But wait, even though we shifted the input, round() is still just snapping to integers, so shouldn't it just expand back to the same snap points that the even-row formula gave us? Yes, it would [b][i]except[/i][/b], remember that we also un-offset the result by half a step width, which is the "- 64" at the very end.
    
    [b]Picking Even or Odd formula[/b]
    Okay, so we have two formulas, but now we have to choose one or the other depending on the row.
    We'll need a formula that tells us if we're on an odd or even row.
    
    round( mouse.y / 32 ) % 2
    
    We squeeze the Y coord from counting pixels down to counting rows by dividing, then use round() to chop off the decimal fluff, leaving us with the integer row number. We then mod the row number by 2, meaning we'll get "0" if the row is even, and "1" if the row is odd. 
    
    Now we just need to say, IF ( row is even ) THEN ( even formula ) ELSE (odd formula).
    You could do this with events, and that would be just fine, but there is a slightly more compact way to handle the IF / THEN / ELSE case, and it's called the "ternary" operator, sometimes called the one-line-IF-statement.
    
    The ternary operator looks like this when used:
    
    ( name = "world" ) [b]?[/b] ( "hello world" ) [b]:[/b] ( "hello person who is suspiciously not world" )
    
    and means this:
    
    [b]IF [/b]( name = "world" ) [b]THEN[/b] ( "hello world" ) [b]ELSE[/b] ( "hello person who is suspiciously not world" )
    
    [i](Note: The "ternary" operator is named for the fact that it takes three arguments, where most operators (like "+" and "-") take only two.)[/i]
    This is exactly what we want to do. 
    We just need to plug in the parts we want to use.
    
    [b]IF [/b]( round( mouse.y / 32 ) % 2 = 0 )
    [b]THEN [/b]( round( mouse.x / 128 ) * 128 )
    [b]ELSE [/b]( ( round( ( mouse.x + 64 ) / 128 ) * 128 ) - 64 )
    
    Using the ternary operator we get this:
    
    ( round( mouse.y / 32 ) % 2 = 0 )   [b]?[/b]   ( round( mouse.x / 128 ) * 128 )   [b]:[/b]   ( ( round( ( mouse.x + 64 ) / 128 ) * 128 ) - 64 )
    
    [b]Final X &Y formulas[/b]
    snapX = ( round( mouse.y / 32 ) % 2 = 0 )   ?   ( round( mouse.x / 128 ) * 128 )   :   ( ( round( ( mouse.x + 64 ) / 128 ) * 128 ) - 64 )
    snapY = round( mouse.y / 32 ) * 32
    
    [b]Modulo operator[/b]
    The JavaScript Modulo operator (%) is ... tricky, to put it diplomatically.
    
    Unlike the more common operators like plus and minus, there's actually no universal standard definition for exactly how modulo is supposed to work, and so there are a few very subtly different versions of it. The version that JavaScript uses (and by extension Construct 2) is one of the weird ones, which does not behave uniformly for positive and negative numbers. 
    There's a nice visual comparison of the mod variations on the [url=http://en.wikipedia.org/wiki/Modulo_operation]modulus wiki page[/url].
    
    This is especially a problem when writing snapping formulas that make use of JS's modulo, as it means the snapping behavior will likewise not behave consistently across positive and negative input coordinates. If you are absolutely certain that you will never feed in a negative value then it's safe-ish to use the JS modulo, though if you inadvertently change that later in a project without realizing it, you may introduce some very subtle bugs as a result of its weird behavior. I personally never use it for anything. I instead use an alternate version of the mod function described below.
    
    There is a version of the modulo operator that does behave uniformly, and that's the "floored division" version.
    Here is the formula for the "floored division" modulo.
    
    [b]mod([/b] val [b],[/b] div [b])[/b] ... = ... val - ( floor( val / div ) * div )
    
    So if you just used substitution to modify the original even-odd-detector formula we made, we'd go from this,
    ( round( mouse.y / 32 ) % 2 = 0 )
    to this,
    ( ( round( mouse.y / 32 ) - ( floor( round( mouse.y / 32 ) / 2 ) * 2 ) ) = 0 )
    
    Not very pretty, but it will work. it would be nicer to be able to simply use a floored division mod function like any other function.
    Well, you can use C2's Function object to create a custom "floored division" style mod function.
    I actually explained how to do this a while back in another post if you're interested, in the subsection [url=https://www.scirra.com/forum/detecting-360-degree-rotation_p883148?#p883148]Getting "floored division" mod into C2[/url] (towards the end of the post).
    
    Hope that helps out.
  • Hey frodoe7,

    Another similar method is to use multiple sprites stacked together.

    Suppose you have a tank in your game, and you want to be able to change the color of the body, the treads, and the turret separately.

    One way to do this is to create a sprite for the body, a sprite for the treads, and a sprite for the turret, and for each one include color variations. The variations can either be in frames as Tetriser suggested, or in their own separate animations within the sprite.

    You can then use the "Pin" behavior to keep all the sprites together.

    This approach can be especially handy if you want to allow for a lot of variations, as the number of color combinations is the product (multiplicative total) of the number of color variations in each sprite.

    So if the tank has 8 colors for each sprite (body, treads, and turret), then the total number of color arrangements is 8 * 8 * 8, which is 512 combinations. It adds (multiplies) up fast.