R0J0hound's Recent Forum Activity

  • You could set a variable inside the function when you knockback the player. Then just check to see if that variable is set in the function to prevent repeats. Then you’d just reset the variable later. Either at the end of the frame or after some time later.

    Or some variation of that.

    Another idea could be to accumulate the impulse into variables then a one point in your events clamp the value and apply it.

  • Construct physics doesn't provide the ability to intercept a collision to do your own logic. The underlying library probably does but it’s not exposed.

    You could go the route of using a js library to do the physics with that. You’d just need to add code to sync the physics sim with construct objects and vise versa. Main annoyance would be to get the library to use construct object collisions. Especially for some objects like tilemap. Anyways then you’d use a postCollide callback or something in the library to intercept the collision response and do your own thing.

    There may be something simpler you can do. If you kept tract of the objects previous position and velocity you could set the object to that after a collision with a slope and manually advance the object till its in contact with the slope. Could be fiddly if you end up having to fight the physics behavior.

    Logic for that would be to save the position and velocity to some variables at the end of every tick. Then under a player “collides with slope” condition you’d know that the physics hit and slid down the slope a bit in the last update so you’d set the position and velocity to the saved values. Next to close the gap you could manually advance the position till in contact with a loop similar to:

    repeat 100 times
    — player: move 0.5 pixels at angle angle(0,0,self.physics.velocityX, self.physics.velocityY)
    — player: overlaps slope
    — — stop loop
    — — player: set velocity to 0,0
    — — //any other logic you want

    You can adjust the step size to be more accurate. That assumes linear motion in the last step so to incorporate the acceleration from gravity you’d set the position instead of moving at angle which would look similar to this:

    Set x to self.x+self.vx*step
    Set y to self.y+self.vy*step+0.5*gravity*step*step

    Units are strange in the physics behavior so you may have to modify the gravity value a bit by a factor of 50. Either /50 or *50 but I forget. For step you’d use a value smaller than dt to get a more accurate collision.

    Some may argue that you could use a raycast to calculate where the object may hit the slope. However, it would miss collisions near the edges and would only work well for round players.

    Rolling your own physics with events may be viable too depending how complex you want it. Biggest chunk would be collision detection and resolution. But if you want to have rotating physics objects then it may just be easier to use the physics behavior instead or calculating contact points.

    Revisiting the idea of doing your own collision detection. The idea I posted above is basically moving things in sub-steps to get a semi accurate collision point. If you wanted to get the collision normal then you’d need to use some raycasts in that care to find that (especially if your slopes are just rotated walls) or maybe you could cheese it by utilizing the angle of the wall.

    There are more elaborate collision detection that both detect collision and give you the closest directing to move objects apart (but that will result in sliding). Some kind of shape casting algorithm can get you the position exactly where the objects touch without sliding, but that’s in straight lines and isn’t trivial for all shapes. But I’m rambling a bit.

  • Well we can’t change things on a different layout than the one we are on. You could make the ingredients global so they transcend layouts. Aka, they won’t get destroyed when you change layouts. But you’d need to clean up the ones you didn’t want to transfer.

    You could just store a list of the ingredients in an array or global variable, then when you move to the other layout you’d look at that the list and create objects from that.

    Simpler still to me could be to make the game all it one layout. Just jump the scroll position between the two areas.

    Anyways, just some ideas.

  • I'm less concerned with a way to mask the fluids inside the container than I am to figure out how high the fluid should be to have a certain volume. It ends up simpler to calculate the area of a polygon than it is to calculate the amount of fluid pixels in an image.

    If we are just talking masking, then what I ended up doing is using blend modes to mask out an area and draw within it. By controlling the draw order, you can do this multiple times on the same layer as long as you fill in the mask completely before moving to the next object. Destination-out to define the mask shape, and destination-atop to draw in the mask.

    Masking with a shader or a clipped polygon have their own sets of quirks and shortcomings.

    Anyways, if you want to check out how I made those images here is a modified project you could pick apart to get ideas.

    dropbox.com/scl/fi/t1bjw1ybu5gaptqwnwj4s/testtube_fill2.c3p

    The algorithm takes about 52 iterations to converge on a near perfect result, but it's good enough with a lot less. I could see it converging faster by interpolating the areas between y's but that would complicate it a bit. The loops could be eliminated altogether by making an approximate area vs y graph formula for multiple angles and interpolating between them.

  • I was messing around with a way to adjust the fluid levels so that the amount of fluid is the same no matter the test tube angle or even no matter the shape. For example, all four of these containers have the same amount of fluid.

    The strategy is to define the container as a polygon, then you can clip the poly by the fluid level and then you can calculate the area of the clipped poly. I just adjusted the level in a trial-and-error loop till the area is at a certain area. Doubt I'll post a c3p at this point since it's a cluttered 14 events. It did satisfy my puzzle solving urge for the moment though.

    I realize you may not be looking for technical solutions at this point. However, from a design perspective you may want to add a lot more to make it more fun than say the dozens of games like that.

  • You can just create the mirrored side with events if you like:

    + System: On start of layout
    + System: For each Sprite
    -> System: Create object Sprite on layer 0 at (320-(Sprite(loopindex).X-320), Sprite(loopindex).Y), create hierarchy: False, template: ""
    -> Sprite: Set size to (Sprite(loopindex).Width, Sprite(loopindex).Height)
    -> Sprite: Set angle to 180-Sprite(loopindex).Angle degrees

    320 can be changed to whatever the center x position on the screen is.

    EDIT:

    Wait, you can just select all the sprites, press enter to wrap the selection and change the width to mirror it too.

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • Shaders manipulate pixels and have access to the depth so you can do 3d lighting stuff already. Couldn't you already do 3d water similar to the 2d water shader?

    Or maybe you mean vertex shaders? Like what mesh distorts do but run in a shader? Since construct mostly just draws quads I guess moving the corners around isn't too interesting at this point.

    I guess it could be more powerful if we were able to provide more data to shaders besides just number uniforms. For example: arrays, additional images, matrices and vectors. But that all may be out of the scope of what construct wants to provide.

  • Well, in general the file (png/jpg) is loaded into memory an uncompressed and finally copied into video memory as a texture. In the browser/construct world the image file is loaded into an html img element before it's copied over to a webgl/webgpu texture. Presumably the browser may also load the image to a different texture too if it were to display the image onto the page outside of construct's renderer. However, the exact details of the browser renderer and even construct's renderer are a black box.

    But we can still calculate how much video memory an image would take up. For example, if a 4k image is 4096x2160 then the uncompressed size would be approximately 34mb. (width*height*4/1024/1024).

    1. Seems reasonable that loading three images instead of one would use more memory. For the html image to display it has to load into vram before the browser can render it. The question as to why the amount of vram usage is bigger than we calculate is largely due to the black box nature of the browser and construct's renderer. Maybe they need more textures to composite stuff or whatever.

    2. Yes, when you clone the object types it duplicates the images. Guess you could make a request to have construct check to see if images are duplicated to save memory but that would slow down export times a lot.

    3. Yes, but you could have tested that. Instances of the same type will share textures.

    4. Presumably it loads a new texture.

    5. It's likely more performant to just render everything onto the canvas instead of layering the canvas with html images. Also, you can't do the same things with html images as you can do with sprites. But luckily, you can do whatever you like.

  • Motion is an illusion on computers where objects will jump from one position to another. So yeah, if you move very fast the jump in position can pass over objects so collisions are missed.

    In general in don’t think it’s possible to make events run faster than the refresh rate without a lot of additional logic. Maybe a loop that checks in between positions between the previous and current frame.

    Another idea is to have an invisible sprite that you stretch between the previous and current mouse position and check for overlap with that instead of the mouse.

  • To do the masking one way would be to have a few sprites stacked bottom to top with different blend modes:

    1. TubeInterior - destination-out

    2. Fluid1- destination atop

    3. Fluid2- destination atop

    4. Back (solid color rect that covers tube) - destination atop

    5. TubeOutline - normal

    Effectively you’re erasing a hole and drawing in that. Lets you mask a lot of things at once.

  • It’s probably not a true fluid simulation. Ignoring the ripples you can probably get most of the way there by using blend modes to mask the colored rectangles inside the test tubes. If you calculate the areas that the fluid makes in the tube you probably can adjust the height of the rectangles to make it more convincing, but you may be able to get by without that.

    The pouring mostly just would involve checking if the top of a rectangle was higher than the lip of the tube, then placing a vertical column for the pouting into the tube below. Then just gradually lowering and raising the two rectangle heights. You could adjust the column width based on the rate or whatnot.

    The ripples could be added later. They probably are just looping animations, but I guess you could use mesh distort to move the top edge of the sprite in a since wave. Seems fiddly though.

    Considering the behavior of the pouring is very consistent in those games I’d imagine they mostly just reuse a bunch or premade animations instead of something technical.

    Four animations for pouring out of a test tube at the four levels, and four for pouring in for the four levels. Probably less if they are clever.

  • Well, say you have 52 card instances on the layout. They are all the same type and each has a different animation frame. It's probably easier to create all the instances with events, just make sure you have a "card" sprite with an animation with images for all 52 card images, and the animation speed is 0. Then the events to create all the cards would be:

    start of layout
    -- card: destroy
    
    start of layout
    repeat 52 times
    -- create card at (-1000, 0)
    -- card: set animation frame to loopindex

    We place them at -1000 to just get then off screen, but you could put them anywhere.

    Next we want to setup the player's deck of 8 cards. You likely have some way you want to have the player select them but we will just pick 8 random ones to use. Add an instance vaariable to card called "playerDeck" with a default value of 0, then add an event like this:

    start of layout
    for each card ordered by random(1) ascending
    compare: loopindex<8
    -- card: set playerDeck to 1

    Now we want to pick four random cards from the players deck to put in the player's hand. Add an instance variable to card called "playerHand" with a default value of 0, and add an event like this:

    start of layout
    card: playerDeck=1
    for each card ordered by random(1) ascending
    compare: loopindex<4
    -- card: set playerHand to 1

    Then picking a random card from the player's hand is just a matter of two conditions:

    card: playerHand=1
    system: pick random card instance

    To remove a card from the player's hand you'd just set playerHand back to 0.

    Anyways, that covers the picking of the cards. It's up to you how you'd move them around.

    It's one idea at least.