fisholith's Recent Forum Activity

  • 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.

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • 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.

  • Hey andreyin.

    If I'm not mistaken, dt is the amount of time (in seconds) that has passed since the last tick. So, if your game runs at 60 frames (ticks) per second, then dt will always be a value around 0.0166 (i.e. 1/60). It may fluctuate a little, if you get some lag between frames.

    So every tick, lerp( 0 , 30 , 3 * dt ) evaluates to approximately ...

    = lerp( 0 , 30 , 3 * 0.0166 )

    = lerp( 0 , 30 , 0.0498 )

    = 1.494

    So if 1.494 looks like it could be the value you were getting, then that may be the issue.

    To get gradual changes in a value, you can use two variables, a Target variable that stores the desired target value, and a Follower variable that continually computes a time-smoothed version of the Target's value. The Follower variable essentially just gradually approaches the value stored in the Target variable.

    I actually just posted an explanation of this Target/Follower setup with a list of events in another topic.

    The example I give there shows a linear follower setup, but I generally use multiplicative follower setups in my projects, since the follower can be set every tick with only one event.

    (Some day ... some day I will get that 4th egg.)

  • Hey Leaufai,

    The following might do what you're looking for.

    In your layout, place a layer above all your other layers.

    Add the "Adjust HSL Mask" effect to this layer. (You can click the layer in the layer panel and edit it's properties in the properties panel.)

    Set the layer's "Transparent" property to "No".

    You should now be able to post-process the entire game with the "Adjust HSL Mask" effect.

    To smoothly fade in an fade out the effect, create two number variables.

    "targetSatValue"

    "followSatValue"

    We'll use these to control the effect's saturation parameter.

    In this example, I'll use functions as the triggers for starting and stopping the desaturation effect, but you could use anything you want.

    * On function "desatOn": Set "targetSatValue" to 100.

    * On function "desatOff": Set "targetSatValue" to 0.

    * Every tick, if followSatValue < targetSatValue: Add 1 to "followSatValue".

    * Every tick, if followSatValue > targetSatValue: Subtract 1 from "followSatValue".

    * Every tick: Set "Adjust HSL Mask" param 1 (the saturation) to "followSatValue".

    (Actions in italics.)

    When the function "desatOn" is called, the targetSatValue is set to 100, and the followSatValue will begin gradually counting up to the target. When the targetSatValue is set to 0, then followSatValue will count back down to the new target value.

    Hope that helps.

  • No problem. Glad it worked out.

  • Hey Sir LoLz,

    Would something like this do what you're looking for?

    flagSlotsRemaining = maxcarry - currentcarry

    Event:

    * Pick selected units.

    * Loop - For each unit.

    * flagSlotsRemaining >= 1. // If one or more slots are remaining.

    Actions:

    * Call function "assignUnitTNextAvailableFlagSlot", Param 0 = unit.uid. //Or however you assign them.

    * Deselect unit.

    * recompute flagSlotsRemaining.

    To make the above a little cleaner, you could break the "flagSlotsRemaining >= 1" condition into a sub-event, and place all the actions on that sub-event. And for a further, though likely negligible, optimization the sub-event could have a companion ELSE sub-event that breaks out of the loop if there are no more slots. That way, if there is only one slot left, and you select 100 units, you only run 1 loop iteration instead of 100 iterations.

    You could also replace the "For each unit" loop with a "For each unit (ordered)" loop, and use the distance from the unit to the flag as the ordering formula. This would assign units to the flag, with priority going to the closest units first. (Closest may not always = shortest travel path in an RTS, but you might not want to compute a path length for all selected units just to start the loop.)

  • No problem,

    Sorry I was a bit vague there. So, when I wrote out the "[ p1 , p2 , p3]" looking depictions of the array, I was just using this as a shorthand for showing what was in the array, so it's not a formal way of representing data in Construct 2.

    To add each item into the array we push them in one at a time. That may sound tedious, because it is almost the same action 12 times in a row, push "p1", push "p2", push "p3", etc, but fortunately we can use a loop to do that tedious part for us.

    To push all the values "p1", "p2", "p3", etc into the array we can do the following.

    Event:

    * On start of layout.

    Actions:

    * [Array] Set size to (0,1,1).

    Event:

    * On start of layout.

    * Loop from 1 to 12.

    Actions:

    * [Array] Push: Where <back>. Value <"p" & loopindex>. Axis <X>

    (without the < > angle brackets)

    Image version:

    [attachment=0:37lnnfil][/attachment:37lnnfil]

    A few notes on what's going on:

    The loop event runs from 1 to 12, meaning it will run its actions 12 times. Construct gives us a variable named "loopindex" that we can use in expressions, to get the number of the current loop step. On the first of our 12 loop steps, loopindex = 1, and on the last step loopindex = 12.

    So, that loop will run the action multiple times, creating the following effect:

    * [Array] Push: Where <back>. Value <"p" & 1>. Axis <X>

    * [Array] Push: Where <back>. Value <"p" & 2>. Axis <X>

    * [Array] Push: Where <back>. Value <"p" & 3>. Axis <X>

    ...

    * [Array] Push: Where <back>. Value <"p" & 12>. Axis <X>

    What is this <"p" & loopindex> thing?:

    "p" & 1 creates "p1"

    "p" & 2 creates "p2"

    "p" & 3 creates "p3"

    etc ...

    Push Back vs Front?:

    It actually doesn't matter if we push from the back or the front when adding the values into the array, since they will be pulled back out randomly. However, if we push from the back, we'll get all the items in order, in case that becomes important later.

    Debugging:

    Remember, you can run the game in debug mode if you want an easy way to look inside the array, to verify that it got set up correctly. You could also use another loop to read the values back out into a text object.

    Anyway, I hope that clarifies things.

  • Spacedoubt has a good suggestion here, (and a cool name).

    There is a tradeoff with this solution. Creating a built in blur in Photoshop will give you a colored halo, but not a glow, as a colored halo will be alpha blended into the backdrop rather than additively blended or screen blended into the backdrop. Alpha blending *can* look like an okay approximation of a glow in some cases, particularly when the background is quite dark and unsaturated (more grey than colored), or when the halo is pure white, or very close to pure white. Both of these special cases produce a result that is mathematically and visually close to screen blending.

    As a benefit of the Photoshop method, you will not need to use a WebGL effect, and this could improve performance depending on the platform.

    As a drawback, an alpha blended halo will actually darken the backdrop when the backdrop is brighter than the halo color. This darkening occurs on a per RGB channel basis, so a blue alpha blended halo will darken green and red values in any backdrop the halo overlaps, and this can look like an anti-glow. Another consideration is that since the glow is precomputed for a single image, it won't work for tile-based objects or objects that will be dramatically stretched or resized, as the glow would also be proportionally stretched.

    One possibility to cut out the semi-intensive blur WebGl effect and still get a true additively blended glow, is to use a hybrid approach.

    For each (source) object you want to glow, create a new object and make its image a Photoshop blur of the source object's image. Place this blurry object under the source, and match the source's position, angle, etc. Finally set the blurry object to use the additive blend mode, or give it a single dodge or screen effect.

  • Hey wossi,

    I think what you're looking for is doable. I'll go over the problem and then two possible solutions.

    The glow effect is based on a Gaussian blur, and this is where the problem arises.

    Normally using two Gaussian blurs at right angles will produce a radially uniform (smooth corners) Gaussian blur, (a very cool and special mathematical property of Gaussians). Unfortunately this special property of perpendicular Gaussian blurs only works when they're combined multiplicatively. (Using a horizontal blur to blur the result of a vertical blur is effectively multiplicative.) Unfortunately, adding or "screening" them together, which is what Construct 2's "Glow" effects do when stacked in series, does not preserve this special Gaussian behavior. So the result of perpendicular "Glows" is not radially uniform.

    So, stacking a regular H-blur and V-blur will give you the smooth corners you want, but it won't glow.

    Stacking H-glow and V-glow will glow, but it will give you sharp corners.

    What you need to do is create a blur-glow system within Construct2.

    With a canvas object (maybe):

    Disclaimer: I've never used the canvas plugin (3rd party I think), but if you can paste objects or layers into it then it might make a glow effect semi-simple.

    1. Place a layer below the foreground objects and above the background.

    (May need to set the scale and scroll rate for this new layer to "0".)

    2. Stretch a canvas object across that layer to fill the window.

    3. Every tick, clear the canvas to transparent, and then paste into it all the objects you want to glow.

    4. To the canvas, add the effects "horizontal blur" and "vertical blur", then add the "Screen" OR "Dodge" effect.

    Done.

    Using only native C2 stuff - (no canvas):

    Without the canvas it is still doable, but it takes a little more work and clutter.

    For a given (source) object that you want to glow, you create a sprite with an identical image, and set it to match the position, angle, and animation frame (if animated) of the source object. This copy object must have a Z-index below the source, which you can set with events. To this copy object, add the effects "horizontal blur" and "vertical blur", then add the "Screen" OR "Dodge" effect.

    "Dodge" vs "Screen":

    Dodge and Screen are both glow-ish style blend modes, in that they will make an object transparent, such that it brightens the backdrop.

    "Dodge" (sometimes "linear dodge") is literally just "Addition". It's that simple.

    Blend result = BG + FG.

    "Screen" is exactly the same as "multiply", but upside-down. Where "multiply" pushes all brightness values towards black, but never past black; "screen" pushes all brightness values towards white, but never past white;

    Blend result = invert ( invert BG * invert FG )

    i.e.

    Blend result = 1 - (1 - BG * 1 - FG ), where black is 0 and white is 1.

    Practically speaking why use one vs the other?

    "Dodge"/"Addition" is good when you want a vibrant intense look, with the potential for blown-out overexposed areas. The results for additive blending can be brighter than white, so they will be clipped to white. This is good for fire, electricity, and other intense eye-burningly bright effects.

    "Screen" is good when you want soft glow, or bright-but-smooth looking glow effects. Screen can produce pure white in cases where the FG or BG is pure white, but it will never blow-out or overexpose areas, because the mathematical result of "screen" blending is always between 0 and 1, so no clipping can occur.

    Hope that helps.

  • Hey ai4ns,

    It sounds like you want to show a random layout as if drawing it from a deck of shuffled cards, and allowing the deck to run out over successive draws.

    We can use the Array object to get this effect. At the start of the game, we can fill it with layout names (making our deck), and then pull the layout names (cards) out of it at random, and discard them as we jump to that layout.

    We want a simple 1-dimensional array. The Array object in Construct 2 will work just fine, but be aware that it's a 3-dimensional array, a cuboid with X-width, Y-height, and Z-depth. So we'll just need to be careful.

    To get a 1-dimensional array, we will only be dealing with the X-width axis, so we will set the Y-height and Z-depth both to "1" and forget about them.

    Add an array object to the layout.

    On start of layout, set its (x,y,z) size to (0,1,1).

    (Just as a brief example, at this point if we were to add 5 cells into the X axis, the array size would then be (5,1,1), a 1 by 1 snake that is 5 cells long. Written out, [ cell-0 , cell-1 , cell-2 , cell-3 , cell-4 ].)

    Okay, so we have a (0,1,1) array.

    Still on start of layout, we run a loop to create 1 array entry for each layout you want to go to (3 to 14), and add (push) them into the array. Rather than filling the array with layout numbers (since I'm not sure you can jump to a layout by number), lets use the layout names. For this example I'll assume that layouts 3 to 14 are named "p1" to "p12". ("p" for page).

    We get:

    [ p1 , p2 , p3 , p4 , p5 , p6 , p7 , p8 , p9 , p10 , p11 , p12 ]

    Now when you want to choose a new layout, we pick one of those cells at random and save the cell number we picked in a custom local variable "cellIndex", then store the number we find in that cell in another local variable "cellValue". Finally, we remove the cell at "cellIndex" from the array. We can then jump to the layout "cellValue".

    So the whole event will look like this:

    Event: <We need to jump to a new layout>

    Action: [System]: Set local variable "cellIndex" to: floor( random( Array.Width ) )

    Action: [System]: Set local variable "cellValue" to: Array.At( cellIndex )

    Action: [Array]: Delete index cellIndex from X axis.

    Action: [System]: Go to layout (by name) cellValue.

    So as an example of how this would work:

    Starting with

    [ p1 , p2 , p3 , p4 , p5 , p6 , p7 , p8 , p9 , p10 , p11 , p12 ]

    We pull out a random cell "p3" and go to that layout. And the array is now missing that cell.

    [ p1 , p2 , p4 , p5 , p6 , p7 , p8 , p9 , p10 , p11 , p12 ]

    Now if we pull out another random cell "p11", we get

    [ p1 , p2 , p4 , p5 , p6 , p7 , p8 , p9 , p10 , p12 ]

    etc... Eventually we have used up all the cells.

    []

    Sorry the explanation is verbal rather than a capx.

    Anyway, I hope that helps.

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