fisholith's Forum Posts

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

    The color change effect you're seeing in the waterfall is coming from the "Lens" effect on the WaterfallTintParticle object. The Lens zooms the background, but it does so relative to the center of the window area, no matter where the effected object is. As far as I know that is the intended behavior for the Lens shader. It gives you a consistent 3D zoom kind of effect across multiple objects regardless of where they are on the screen.

    To your other question, yes, you could modify the shaders yourself to get the behavior your looking for. As Ashley mentioned this can get a little complicated. If you want to counteract layout translation, rotation, and scaling, you'll need to have parameters that allow you to feed the current translation, rotation, and scale info to the shader. Since rotation and scale will have a center point that they are rotating or scaling around, you'll have to have parameters that allow you to feed in those cords as well. But it is doable.

    What complicates things is that C2 will sometimes automatically account for the translation, rotation, and scaling of an object when rendering shaders, and other times it won't.

    To easily see an example of this,

    1. Create a new project.

    2. Create a red square, and add the "Scan lines" effect to it.

    3. If you rotate the square, you'll notice that the lines rotate with it.

    4. Leave the square rotated to a diagonal angle.

    5. Now add a "Multiply" effect, and place it *above* the "Scan lines" effect, in the effect list.

    6. By being the 2nd item in the effect chain, the "Scan lines" effect no longer rotates or translates with the object.

    What you can't see with the "Scan lines" effect is that scale is also no longer driven by the object.

    If you want to modify an effect to make it completely immune to those issues, you'll have to account for this sometimes-on sometimes-off behavior in your modification as well, and provide a parameter that allows you to disable some of your translation, rotation, and scaling parameters, so that you don't *double* account for those transformations in cases where C2 is already doing it automatically. Also the Y axis is upside down for effects from slot 2 onwards, so you may need to handle that as well, depending on what kind of directional aspects the effect has.

    If you just want to try adding in a pair of translation parameters, which might be enough to solve the translation issue you're seeing in the ripples, parameters are set up in an effect's .xml file. The parameters can then be used as variables in the shader code of the effect's .fx file.

    This website http://shdr.bkcore.com/ is an in-browser GLSL editor, and a handy way to test proper compilation of shader code, before trying to open the shader in a project.

    One really important thing to know when working in GLSL code, is that, unless you explicitly want a number to be an integer, you must add a decimal point and decimal digit to it, even if the digit is zero. (e.g. Use "27.0" NOT "27") It's weird, but it's one of my most common bugs when I'm coding shaders.

    The Construct 2 SDK has a template effect that describes how the various parts of the two effect files work. https://www.scirra.com/manual/15/sdk

  • Hey again TGeorgeMihai.

    I'd actually assumed you wanted it to be a layer relative grid, though I didn't realize you were also interested in using a TileMap.

    What I was originally thinking was that you could paper over the object's bounding box with grid tile objects (aligned to the layer), and then, with a single condition, remove the ones that don't overlap.

    With a tile map, you'll need to use an overlap-check object like Aphrodite suggested. Though you can still use the bounding box method I described, to search only the area over the circle's bounding box, instead of the entire tile map.

    Although instead of looping over the bounding box to remove non-overlapping tiles, you would simply add overlapping tiles. That's because there's no way to remove all non-overlapping tiles with a single condition, when using a TileMap object. (Which is not a bad thing at all, TileMap is actually more efficient for what you want, it just doesn't natively support collision checking, as far as I know.)

    So, I also built an example capx, though Aphrodite beat me to it. :3

    [attachment=0:1cjpbdsi][/attachment:1cjpbdsi]

  • Hey TGeorgeMihai,

    You could try covering the circle's entire bounding box with a solid grid of squares, (using a pair of nested X Y loops). Once you're done, destroy any squares that are not overlapping the circle. You should be left with only the overlapping squares.

  • No problem, glad I could help.

  • Hey Kan,

    I think there are two problems you might be encountering.

    1: (see line 2)

    "On touched" is a triggered condition, not a per-tick condition, so when it is triggered, it will only simulate the up movement for a single tick, and then stop until it is triggered again by a new touch. By contrast, holding down the up arrow key on the keyboard, is the equivalent of executing the "simulate up movement" action every tick (every frame), for as long as the key is held. (You can recognize triggered conditions, by the green arrow icon that always appears next to them.)

    2: (see line 5)

    For the condition, when the player is "jumping", AND while Keyboard Up arrow is NOT pressed, the corresponding action is cutting your upward speed in half every tick (60 times a second).

    This isn't an issue when using the keyboard controls, because you actually are holding down the up arrow key when jumping.

    However, it *is* an issue when "touching" the up button in the game, because you are now not holding down the keyboard up arrow key, so your upward speed is getting cut in half every tick because of that event.

    Try the following...

    Line 2:

    Change the condition

    "? On touched arrow_up"

    to

    "Is touching arrow_up"

    Line 5:

    Find the event containing the condition shown below, and disable that entire event, (not just the condition):

    "? Up arrow is down" condition (line 5).

    That should make the jumps identical, but now you can't make a small jump.

    To fix this, enable the line 5 event again, and split the "? Up arrow is down" condition into its own subevent (under the "Platform is jumping" event), and move the action onto this new sub event.

    Finally, to the new subevent, add the condition "Is touching arrow_up", and then invert that condition, to create "? Is touching arrow_up".

    Now your upward speed will only be cut short if, you're not holding the up key, AND you're not holding the on-screen up button.

    Hope that does what you're looking for.

  • Hey noisetank,

    Lets assume our number is stored in a variable named "num", and we want to format it as an integer part, always followed by two decimal digits, even when either or both are zeros.

    There are a few ways to go about this.

    The method I'm showing below converts the number to text and then inserts a "." into the correct spot.

    We create a text variable named "digits".

    digits = zeropad( round( num * 100 ) , ( 2 + 1 ) )

    Formated string = left( digits , ( len( digits ) - 2 ) ) & "." & right( digits , 2 )

    Done.

    To make it clearer what is going on in the above steps, I've created two examples below that show the evaluation of the expressions from beginning to end, so you can see how each part of the expression works.

    Example #1

    If num = 888.123

    digits = zeropad( round( 888.123 * 100 ) , ( 2 + 1 ) )

    digits = zeropad( round( 88812.3 ) , ( 2 + 1 ) )

    digits = zeropad( 88812 , ( 2 + 1 ) )

    digits = "88812"

    Formated string = left( "88812" , ( len( "88812" ) - 2 ) ) & "." & right( "88812" , 2 )

    Formated string = left( "88812" , ( len( "88812" ) - 2 ) ) & "." & "12"

    Formated string = left( "88812" , ( len( "88812" ) - 2 ) ) & "." & "12"

    Formated string = left( "88812" , ( 5 - 2 ) ) & "." & "12"

    Formated string = left( "88812" , 3 ) & "." & "12"

    Formated string = "888" & "." & "12"

    Formated string = "888.12"

    Example #2

    If num = 0.071

    digits = zeropad( round( 0.071 * 100 ) , ( 2 + 1 ) )

    digits = zeropad( round( 7.1 ) , ( 2 + 1 ) )

    digits = zeropad( 7 , ( 2 + 1 ) ) // This zero pad makes sure we have at least 1 digit in the 1's place, even if it's a "0".

    digits = "007"

    Formated string = left( "007" , ( len( "007" ) - 2 ) ) & "." & right( "007" , 2 )

    Formated string = "0" & "." & "07"

    Formated string = "0.07"

    Hope that helps.

  • Hi all,

    Is there a way to give a playing sound multiple tags?

    tl;dr (preemptively) - C2 doesn't support this as far as I can tell, and I have a partial solution but its got issues, so I figured it was worth asking.

    Goal:

    I'm looking to create a tag system for audio, such that when I play a sound, I can add multiple tags to that sound, allowing later access to all currently playing sounds that share a given tag, like "ambiance" or "water".

    Problem:

    Presently the C2 Audio object allows you to specify a "tag" when playing a sound, but you can only provide a single string. And you can only lookup playing sounds by matching that exact string. So I couldn't, for instance, get a list of all playing sounds with tags containing the substring "ambiance" or "water".

    Why I'm interested:

    There are a few reasons.

    More flexible interaction with sounds:

    I would like to be able to access a playing sound by either its exact name ("footStep03"), or by its sample-set name ("footStep"), or by its category ("player"). Likewise, it would be nice to be able to trigger "On ended" events in response to sounds with specific tags.

    More flexible Menu control over sounds:

    I'd like to be able to make an audio menu with volume sliders for different categories of sound, for instance "Music", "Voice", "Ambience", "Sound effects", and "User interface". In particular, for sounds that are currently playing, like any actively looping ambience, adjusting the slider in the menu would need to affect the sounds while they were playing, rather than "next time" they get played.

    My current partial solution:

    So far I've got something that sort of works, but with some ugly side effects.

    I'm using a custom "playSound" function I created via the function object. The function will play a sound and tag it with a unique numeric ID, that increments with each call. At the same time, a key with that same ID will be added to a dictionary, and the associated value will be a comma separated list of the tag strings I want to attach to that sound.

    This allows me to access playing sounds by looping through the dictionary and searching for specific tag strings in the values. Each value is tokenized (comma delimited) into individual tag strings. Because each key links back to a single unique sound, this system can map an arbitrary number of tag strings to individual playing sounds.

    Removal issue:

    There is a problem, though. I can't trigger the removal of a sound entry from the dictionary when the sounds stops playing. The reason is that there is no way to use the "On ended" event generically, as C2 requires you to name the exact tag of the sound that is ending. I would need to check to see if *any* sound is ending, and then remove the ending sound's dictionary entry in response. (You can do this kind of generic detection with the Keyboard object, and the Gamepad object, but not the Audio object.)

    System Wait:

    I can't quite use System Wait with the duration of the sound as the wait time, because System Wait is slaved to the timescale, so I could get weird behavior whenever the game was paused.

    Timeout dictionary:

    I could potentially save the expected end time in a 2nd timeout dictionary, and every few seconds loop through it to see if any entry's time is up. Basically periodic garbage collection. Though that seems a bit ugly, and might cause a periodic performance hit. Maybe not, I don't know.

    "On ended" inside a loop:

    One weird possibility that might work, depending on how C2 handles loops and triggered events, is to create a "For Each Key" loop and then use that to check every key (sound ID) in the "On ended" event, every tick. I don't think that should work if the "On ended" event is a true triggered event, but if it's a "fake" triggered event (as described in the C2 plugin SDK documentation) then it might. Even if it does, that doesn't sound very efficient.

    Suggest feature:

    I could suggest multiple tags for audio as a feature. I think it would be pretty handy, but I have no idea if interest would be wide spread enough to make it a worthwhile implementation.

    Mod Audio object:

    This is what I looking into now. Building a modified version of the Audio plugin. The downside is that my modified version would not get updated with the rest of C2, and that would probably become a bigger and bigger problem as time goes on.

    If you got this far, I appreciate you taking your time to read through this, sorry about the length.

    Thanks in advance for any replies, and any suggestions are welcome.

  • No problem,

    As for sharing to social media, I'm not sure off hand. You might be able to do something like that by adding one of the "Platform Specific" objects to your project. I believe Construct 2 has a Facebook object and a Twitter object, and either of those might have the functionality you're looking for.

  • Hey uzet1,

    If the entire game environment fits inside the game window:

    You could use the action System > "Snapshot canvas".

    If the environment is larger than the game window:

    You could zoom out until it fits, and then snapshot it, though this won't give you a 1-to-1 resolution image of your world, but it might be a nice way to create a map.

    Alternatively, you might be able to use the 3rd party Canvas object. I've never used it, but if you can make it as large as the world, and then paste the world into it, you might be able to save the Canvas as an image. Again, I've never used it so I don't know if you can.

    You may not be able to paste things off-screen into the Canvas, but you might be able to solve this by scrolling the screen chunk-by-chunk across the world pasting as you go.

  • Hey Prazon,

    Hopefully I'm interpreting this right, it sounds like there are 14 different selectable characters in the game, and you have a generalized character rig setup that has a spot for the selected character in the middle, and then 4 boxes situated around the character, representing attack zones to the left, right, top, and bottom of the character.

    You want a control input, like Towards + C, to trigger a unique action depending on the chosen character.

    Two options come to mind, global variables is one, and a callback function system is the other. The global variable method is easier but a little less flexible, though it should still work just fine in this case.

    Global variables:

    You can use a global variable to store the name of the character chosen by the player, and only trigger that character's attack if their name is found in the global.

    e.g.

    * Event: If keyboard pressed Left + C.

    * * SubEvent: If global characterName = "lulu". -- Action: Call function "luluShield".

    * * SubEvent: If global characterName = "veigar". -- Action: Call function "veigarStun".

    * * SubEvent: If global characterName = "teemo". -- Action: Call function "teemoSelfDestruct".

    Callback functions:

    You can create a Dictionary object, that maps control input events (Dictionary keys) to function names (Dictionary values). At the point that a player selects a character, you can populate the Dictionary with the chosen character's functions. These functions will execute the character's actions.

    e.g.

    * Event: Player chooses "lulu".

    Actions:

    Add to Dictionary key = "Left+C", value = "luluShield" .

    Add to Dictionary key = "Right+C", value = "luluSpeedUp".

    etc ...

    * Event: If keyboard pressed Left + C. -- Action: Call function ( Dictionary.getValue( "Left+C" ) ).

    Note: Dictionary.getValue( "Left+C" ) will return "luluShield", which we added earlier, and so the action evaluates to [Call function ( "luluShield" ).]

    * Event: On function "luluShield". -- Action: Execute the stuff that's supposed to happen when Lulu uses her shield ability.

    Hope that helps.

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • Hey iac249,

    You could try breaking the doorway into 2 parts, with the near side and top in the foreground, and the far side and bottom in the background, as shown in the image below. By "foreground" and "background" I simply mean Z order relative to the character.

    [attachment=0:3epux70b][/attachment:3epux70b]

  • Hey AeleaS,

    Two possibilities come to mind that might work.

    To set the angle of the arrow, you can either use the "Set angle towards position" action, or you can just use the "Set angle" action and as the parameter use a handy built in system expression in Construct2 called angle() which will get the angle between two points.

    e.g.

    • angle( 0 , 0 , 100 , 100) = 45
    • angle( Obj.X , Obj.Y , Mouse.X , Mouse.Y ) = The angle of a line from Obj to Mouse.

    Fixed length arrow - (uses one sprite)

    1. Create a sprite arrow pointing right (0 degrees).

    2. Place the hotspot at the tail of the arrow. (This should be the middle of the left edge of the image.)

    3. Set the arrow sprite to the position of the billiard ball (or whatever you're interacting with), and set the angle of the arrow to the angle you want.

    e.g. Below I'll assume we want the arrow to go from a billiard ball to the mouse cursor.

    Event:

    * Every Tick.

    Actions:

    * Set Arrow to position of BilliardBall.

    * Set Arrow angle to look at coord ( Mouse.X , Mouse.Y ).

    Resizable length arrow - (uses two sprites)

    To create an arrow that can change length, you can create the arrow in two parts.

    1. Create the tail, by making a simple 4x4 pixel block filled with a solid color.

    2. Place the hotspot at the left center edge of this sprite.

    3. Create an image point named "headAttachPoint" at the right center edge.

    4. Now create a new sprite that looks like an arrow head pointing right, and place the hotspot at the left edge.

    5. Put the Arrow tail and arrow head sprites in a Construct2 "container".

    6. In the event editor add the following events:

    e.g. Below I'll assume we want the arrow to go from a billiard ball to the mouse cursor.

    Event:

    * Every Tick.

    Actions:

    * Set ArrowTail to position of BilliardBall.

    * Set ArrowTail angle to look at coord ( Mouse.X , Mouse.Y ).

    * Set ArrowTail width to distance( Self.X , Self.Y , Mouse.X , Mouse.Y ) // This sets the arrow length.

    * Set ArrowHead to position of ArrowTail, at image point "headAttachPoint".

    * Set ArrowHead angle to ArrowTail angle.

    Hope that helps out.

  • You can also use the "distance(x1,y1,x2,y2)" expression in a condition to verify that the touch is a certain distance from the character, as it sounds like you are also interested in triggering the effect only when close enough to the character.

  • Hey RenatoB,

    There are quite a few ways to do this, so I'll give a simple example, that will hopefully be a good starting point. But more complex setups are certainly possible.

    Body:

    1. Create a Sprit object for your character.

    2. In the image editor, create an image for your character, but leave the eye area blank (i.e. skin colored).

    3.Still in the image editor for the character's body, click the "Image point" button on the left-hand toolbar. (Second from bottom, and looks like a crosshair.)

    You should get an extra side window titled "Image points".

    4. In the "Image points" window, add two image points, named "eyeLeft" and "eyeRight". Select the "eyeLeft" image point and click on your character image, to place the image point where the left eye should go. Do the same for the "eyeRight" image point.

    Eyes:

    5. Create a Sprit object to act as an eye. The eye will be a white circle, with a black pupil circle, however the pupil circle will be positioned to the right of center, as if the eye is looking to the right.

    6. For the eye Sprite object, add an text instance variable named "attachPoint". (We will use this variable to name the image point that the eye is supposed to attach to.)

    7. Make a copy of the eye Sprite, so you have two eyes.

    8. For one of the eyes, set its "attachPoint" variable to "eyeLeft" (without quotes)

    9. For the other eye, set its "attachPoint" variable to "eyeRight" (without quotes)

    Positioning eyes:

    10. Open the event editor, and add the following event:

    Event:

    * Every tick.

    Actions:

    * Eye: Set Eye position to position of Character, at image point Eye.attachPoint.

    Explanation: For each Eye, we are setting the Eye to be positioned on the Character, at one of the Character's 2 image points. We get the name of the appropriate image point from the Eye's "attachPoint" instance variable, the one we made earlier. So, the Eye with the attachPoint variable set to "eyeLeft" will attach to the Character's "eyeLeft" image point. Same idea for the other Eye and "eyeRight".

    You can try running the game at this point to make sure the eyes are getting positioned correctly.

    Aiming eyes:

    11. add the following event:

    Event:

    * Every tick.

    Actions:

    * Eye: Set Eye angle to look at position, <whatever position you want them to look at>.

    Hope that helps.

  • No problem, happy to help.

    Okay, I think what is happening is that you actually are successfully deleting an array item, right before you jump to a new layout, but when the next layout starts, that new layout is running the "On start of layout" events (lines 17 & 18 in your image), and that is re-clearing and re-filling the array.

    I'll refer to the process of clearing and then filling the array as "initializing" the array.

    You'll need a way of initializing the array only once during the whole game.

    Two solutions come to mind.

    Solution 1: You could initialize the array on a unique layout that only runs once, like the title screen of the game.

    Solution 2: You could keep the initialization on start of layout, (the way you have it now), and add a global variable to disable initialization after the first time the array is initialized.

    Solution 2 - explained:

    To disable initialization after the first time the array gets initialized, you can create a global number variable "gb_initLayoutArray", with a starting value of 1.

    As the last step of the initialization process, set "gb_initLayoutArray" to 0.

    Finally, in the "On start of layout" events, add the condition, "gb_initLayoutArray" = 1.

    Now those "On start of layout" events should only run once.

    And if you ever need to initialize the array again later, just set the "gb_initLayoutArray" back to 1, and on the next layout you'll restart with a full "deck" of layout cards in your array again.

    (The "gb_" in the variable name is just my way of indicating that a variable is global "g", and should be treated like a Boolean "b". It doesn't mean anything special to Construct.)

    Let me know if that fixes it.