Creating a parabolic effect in 2D top-down view

1 favourites
From the Asset Store
Set of tiles to create a map for top-down games with island theme
  • I'm still working with a general understanding even after that explanation - for all my intelligence, some things still are slow to click with me. But in the end I'm extremely grateful for your help.

    If there is a way to fine-tune it so I might edit the parameters easier, I'd appreciate that. But, in the end, it works splendidly!

    OH! One thing I meant to ask...

    I was further wanting to make it "bounce" a time or two more after its initial bounce. I'd want to check for when it has "touched ground" again but I don't know/comprehend which value(s) to check for before making it bounce again (and at a smaller scale). Is there a "flow chart" you could list to explain the process?

    Thank you again.

  • Hi Rhindon, what I did was set a variable for ground level. Then make it go up agai (by introducing a new variable: bounce force or vector), and every time it comes back down (gravity), the bounce is less, because the bounce force also gets depleted every tick.

    But, I am sure others like R0J0Hound have more elegant ways to do this.

  • If you dont want to use parabolic formulars, you can achieve the same effect with Bullet behavior and change scaling according to the speed:!Ap_-qxoGKbDcg36Eo443iLPo3VaT

    Still refer to my example. I am not using parabolic equation but this may be independent from bouncing.

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • If it helps all the motion equations are defined by this equation:

    rate x time = distance

    vz is the rate that z is changing (the velocity)

    dt is the time is the duration of the frame

    so vz*dt is the amount that z changes in a frame

    In the same way we can apply gravity to the velocity, since gravity is an acceleration, which is the rate of change in velocity.

    So g*dt is the amount that dz changes in a frame.

    Or just simply:

    every tick:
    -- sprite: add g*dt to vz
    -- sprite: add self.vz*dt to z

    Next we need to decide what z value would be the ground. This is fairly arbitrary, you can pick any value. I initially used 1, then changed it to 100, mainly to simplify the math with the perspective scaling. We also need to decide what direction z goes, whether into the screen or out of it. It doesn't matter which, but it does affect the values you'd use for vz and g.

    Let's be simple and say z=0 is where the ground is. Let's also say that into the screen is positive z, and for our physics lets consider positive z as down.

    So if gravity is down then we can make g = 10. So the object will accelerate down into the screen.

    To make a nice arc instead of a freefall we'd make vz=-10 so it goes up first.

    Here's a nice diagram of our setup showing where the ground is, and the directions of gravity and the initial velocity:

    Next we can figure out when and how to bounce.

    Well it makes sense that a ball would bounce when it collides with the ground. So a collision would be when z=0? Yes, but the calculations can make the z move past 0. That would make a collision when the z is greater than or equal to 0. So viola we now can detect when the object is on the ground, aka this can be our condition.

    sprite: z>=0
    -- ...

    Here's a visual of the z position frame by frame and a possible example when a collision is detected:

    Notice the object can have moved past the ground before the collision is detected. Let's fix it by moving it to be on the ground.

    sprite: z>=0
    -- sprite: set z to 0

    Note: this pretty much does what I used the max() expression for in my op.

    Now that the object is safely resting on the ground, even when it tries to move past, we can now consider how to bounce.

    Bouncing is really simple, just reverse the direction of the velocity. We do that by making the velocity negative.

    sprite: set vz to -self.vz

    It will bounce to about the same height as it was dropped from. To make it bounce less we can just multiply the velocity by a number between 0 and 1 when we reverse it. Let's make each bounce go only half as high, so we'll use 0.5.

    sprite: set vz to -0.5*self.vz

    Sweet. So that would make the whole collision detection and bounce event this:

    sprite: z>=0
    -- sprite: set z to 0
    -- sprite: set vz to -0.5*self.vz

    All that takes care of the motion and bouncing, but it gives us no visuals. We want the sprite to scale as if it was getting closer or further from us as the z changes. So first lets look at how such scaling is done. A diagram is great for this:

    We see an eye, an object and the screen. The size of the object's shadow on the screen is the size we want to scale the object to to make it seem that close.

    Notice that the triangle from the eye to the object is a scaled version of the triangle from the eye to the screen. For those interested you can dirive the the equation for z scaling from this. I'll keep this simpler by just giving the equation:

    sprite: set scale to eyeDistance/(self.z + eyeDistance)

    In similar fashion you can move the xy position with something about the same for more effect.

    eyeDistance is the z distance from the eye to the screen. We just choose a value for this. 100 works well for our purposes, but we can change that to adjust the strength of the effect.

    Anyways here is the whole example:

    {Editor setup:}
    global number g = 10
    global number eyeDistance = 100
    every tick:
    -- sprite: add g*dt to vz
    -- sprite: add self.vz*dt to z
    sprite: z>=0
    -- sprite: set z to 0
    -- sprite: set vz to -0.5*self.vz
    every tick:
    -- sprite: set scale to eyeDistance/(self.z + eyeDistance)
  • Most awesome in-depth reply ever. I am going to study the R0j0hound bible as soon as I have time. :)

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