R0J0hound's Forum Posts

  • Yeah referencing the bounding box doesn’t really work for that. Mesh coords are relative to the oriented box of the sprite if it had no distort.

    Basically the unlerp would only work if the sprite wasn’t rotated and if the bounding box was the same as if there was no distort.

  • Realized you probably what the layout position from mesh point coordinates too. I made an old post about it but search isn’t cooperating.

    You’d start with the position from the json, then using the original sprite’s position and size you convert to a layout position. The third action is if the original sprite had any rotation.

    Sprite2: set position to JSON.Get("w.mesh.points.0.0.x"), JSON.Get("w.mesh.points.0.0.y")

    Sprite2: set position to (self.x-0.5)*sprite.width+sprite.x, (self.y-0.5)*sprite.height+sprite.y

    Sprite2: set position to (self.x-sprite.x)*cos(sprite.angle)-(self.y-sprite.y)*sin(sprite.angle)+sprite.x, (self.x-sprite.x)*sin(sprite.angle)+(self.y-sprite.y)*cos(sprite.angle)+sprite.y

    Anyways hope that helps.

    Edit:

    Forgot to talk about the 0.5 part in the formulas. That would be the origin position of the sprite. 0.5,0.5 for center, and 0,0 for top left.

    Edit2:

    For zelevation too it would be:

    Sprite2: set zelevation to JSON.Get("w.mesh.points.0.0.z")+sprite.zelevation

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • Add the json object to your project and in events json: parse sprite.asJSON.

    Then you can access mesh points with

    JSON.Get("w.mesh.points.0.0.x")

    The 0.0. part is the row then the column.

    Heres how I found that. I added a sprite and set the mesh size to 2,2 and then set point 0,0 to have an xy of 0.5, 0.5. Then looking at the mesh part of the sprite.json we have:

    "mesh":{"cols":2,"rows":2,"points":[[{"x":0.5,"y":0.5,"z":0,"u":0,"v":0},{"x":1,"y":0,"z":0,"u":1,"v":0}],[{"x":0,"y":1,"z":0,"u":0,"v":1},{"x":1,"y":1,"z":0,"u":1,"v":1}]]}

    So all the mesh data is fairly easily accessible.

  • This page has a lot of useful info on how that fake kind of 3d can be done. It’s not construct specific but you can possibly find some older posts on here that made some examples based on this. I know I did at least once.

    extentofthejam.com/pseudo

    That said it’s probably easier to just use real 3d similar to that example posted. Changing the graphics, camera angle and movement can probably get you pretty close.

  • I'm also getting mostly 0s, but occasionally I get values. When I get a value it's mainly when barely hitting like a glancing hit.

    Why? Who could say, but it seems like the contact points are available on the following frame (construct has too many things that are only calculated at the end of a frame).

    So, a user fix could be to do events like this:

    every tick:
    -- signal "nextFrame"
    
    Ball1: collides with Ball2
    -- wait on signal "nextFrame"
    -- ... get contact info

    I suppose you could still miss hits if physics detects a collision with the circle, but construct doesn't detect a collision with the polygon since they both have their own collision detection.

    Another idea could be an expression like:

    Ball1.Physics.ContactCount>0

    and you'd get contact points from ball1 hitting anything. You could find what was hit as a secondary collision check.

  • Logging stuff can be useful to debug things but I only use the browser console for JavaScript stuff. When just logging stuff with events I just append stuff to a textbox, and even then it’s only temporary.

    You’ll have to indicate the location when you log manually. Usually it’s not a big deal but there isn’t an automated way to get the location when you log with events or JavaScript.

    Now if you made an addon to do the logging it can know the location on the event sheet it was called from. It seemed possible in C2’s addon sdk but no one ever used it. You’d need to investigate c3’s addon sdk to still see if you can do that. But it’s easier and faster to just manually specify the location than to make a plug-in to help with that.

  • Here's a few ideas:

    If you want to compare the visual overlap area you can do that by looking at pixels with a drawingCanvas. Basically draw one sprite to the drawingCanvas, snapshot the canvas, and then loop over the pixels and count the number of then with an alpha>50. That will give the Initial area. If the sprite isn't changing sizes save that to a variable, so you don't have to recalculate it every time. Then you paste the second object to the canvas with the "destination out" blend. That will erase the overlapping part from from the first sprite. Then you'd snapshot the canvas, loop over the pixels and count the pixels with an alpha>50. That will give the number of pixels not overlapping. Finally, the calculation will be percentCovered = 1 - (pixels not overlapping)/(initial area).

    Overall, that will take a few frames to complete since it involves a few async operations. Looping over all the pixels can be a bit heavy, so you'd want the canvas to just be big enough to cover both objects, and/or you could just sample some of the pixels like igortyhon suggested.

    Another way is to check the percentage the collision shapes are overlapping. It can be done in one tick but you'd need to use "object overlaps point" to sample stuff. The con is it's only approximate based on how many points you sample.

    You can also access the polygon points and if both objects have convex collision polygons you can calculate the exact area covered by the polygon and use a line clipping algorithm to clip one polygon by the other to get the intersecting polygon. The main complexity here is to clip the polygons and calculate the areas. It's not hard but won't be a one liner.

    If the objects are both unrotated boxes or circles, then you can do something even simpler.

    For example, if both are unrotated boxes you'd calculate the coverage with:

    Sprite1: overlaps Sprite2

    --- percent = (min(sprite1.bboxBottom, sprite2.bboxBottom)-max(sprite1.bboxTop, sprite2.bboxTop))*(min(sprite1.bboxRight, sprite2.bboxRight)-max(sprite1.bboxLeft, sprite2.bboxLeft))/(Sprite1.width*sprite1.height)

    Circles could be a relatively simple option too. Basically come up with the math from the two radii and the distance between the centers.

  • Here's a few ideas.

    First idea is to use two distance joints. One from the end to the base, and one end to the end position. The curve is then purely decorative. I just placed a series of sprites in a curve with the qarp expression. Using a DrawingCanvas or a distort mesh are also options.

    dropbox.com/scl/fi/8zpim87vy5dtsv3i1snj8/wobbler.c3p

    Second idea is to position the pieces in a curve and connect them with limited revolute joints. I first tried starting them in a straight line and making it curve by adjusting the limit angles. The physics behavior didn't like that much so the curve was looking kinked. I then just positioned the pieces in a curve before adding the joints which was better. To help it support it's own weight I made the mass less toward the end.

    dropbox.com/scl/fi/iql8dep887mag2122mkpa/wobbler2.c3p

  • The basic idea is to take a distort mesh and wrap it into a circle. Take a sprite and give it a mesh size of 33x2. Then the first row will be set to the edge sprite positions, and the second row will be set to the midpoint of all the edge sprites. You can also set the uvs of the mesh points so that when the shape is a circle the image isn't distorted at all.

    I needed a testbed for an example, so I tried to replicate the ball from boxes connected by joints. Ended up using two sprite types to do that since the free version doesn't have families. I'm guessing you used limited revolute joints to connect the objects. That did give soft ball behavior, but it seemed to be adding energy which caused the ball to spin off to the left or right. It was related to the order the joints were added. I imagine adding the joints in a balanced way could help but instead I used normal revolute joints and distance joints which gave more tuning control of how springy the ball was.

    Anyways, here is the example of one way to distort the mesh to a circle.

    dropbox.com/scl/fi/2vktya0r9fqji0hft5qfo/physics_ball.c3p

  • As mentioned above the drawing canvas uses xy coordinates relative to the canvas not normal layout coordinates.

    What that means is instead of adding points at (sprite.x,sprite.y) you need to do (sprite.x-drawingcanvas.bboxLeft, sprite.y-drawingcanvas.bboxtop)

  • I was more focused on getting the math right than the expressions write when I wrote it in the previous post. So velocityX should have been self.8direction.vectorX but the idea is the same.

    We aren't setting the angle with that; we are only measuring it.

    A quick fix for the shaking could be to multiply w1 and w2 by 0.5 or something when correcting the velocity.

    A more correct fix would be to calculate the relative velocity between the two objects in the angle between them and using the weights (w1,w2) in the same way.

    Here's an iteration of that:

    dropbox.com/scl/fi/jrr6hko1kq0xwy77mqxr4/tetherObjects_noDragging2.capx

    The angle can still shake though. That mostly has to do with how the angle is set from the angle of motion. Instead, you probably want the angle to be set to the angle the player is trying to go.

  • I ended up implementing it and simplifying the math a bit.

    No dragging:

    dropbox.com/scl/fi/3dpr622etyygcxk4cuom7/tetherObjects_noDragging.capx

    Older example with dragging:

    dropbox.com/scl/fi/sflsjyje1eqwgtxhk9qjb/tetherObjects.capx

    As to understanding the formulas, maybe this will help a bit. The w1,w2 formulas are basically the calculated speed along an angle.

    speedAlongAngle = velocityX*cos(angle)+velocityY*sin(angle)

    It's positive if moving along the angle, and negative if moving the other way. We only want the speed moving away so we clamp it with -min or max so we only have positive speeds.

    Then we calculate the distance for the two objects to move back toward each other with (d-radius). That needs to be split between the two objects, and I'm using w1/(w1+w2) and w2/(w1+w2). They add together and give one so it's a complete split. It's mostly so if only one object is moving only it will be moved and vice versa.

    The last part is to cancel out any velocity trying to move the objects further apart. We already have the speeds moving apart w1,w2 and we just need to convert the angle, speed to xy components with: x=speed*cos(a), y=speed*sin(a).

    The negatives are just to invert the direction. Anyways, maybe some of that explination helps. It's a combination of a lot of simple things.

  • The no dragging part seems like an interesting twist. You can limit the position of one player or the other with:

    Dist = distance(p1.x,p1.y,p2.x,p2.y)
    Ang = angle(p1.x,p1.y,p2.x,p2.y)
    P1: move max(0, dist-radius) at angle ang
    Or
    P2: move -max(0, dist-radius) at angle ang

    Which works well if only p1 is moving or p2 is moving. If both are moving then both should only move apart by a percentage. I’d think using the speed at which each is moving away from each other should give a good percentage.

    Dist = distance(p1.x,p1.y,p2.x,p2.y)
    Ang = angle(p1.x,p1.y,p2.x,p2.y)
    W1 = max(0,p1.velocityx*cos(ang+180)+p1.velocityY*sin(ang+180))
    W2 = max(0,p2.velocityx*cos(ang)+p2.velocityY*sin(ang))
    P1: move max(0, dist-radius)*w1/(w1+w2) at angle ang
    P2: move -max(0, dist-radius)*w2/(w1+w2) at angle ang

    Id have to test it though. Also it doesn’t cancel the velocity going away from the radius. I’m pretty sure that could be done with:

    p1 set velocityx to velocityx-w1*cos(ang+180)
    p1 set velocityy to velocityy-w1*sin(ang+180)
    p2 set velocityx to velocityx-w2*cos(ang)
    p2 set velocityy to velocityy-w2*sin(ang)

    But again I’ve yet to test it.

  • Is there any game with such a thing?

    If you did it straight, then just do it curved. Place multiple sections down, each angled a bit more, then create the joints.

    Look again at the actions of the physics behavior. You can disable physics collisions between objects.

    Or you could just have the end have physics with a spring joint moving it back into place and have the the rest just be sprites without physics positioned in a curve with qarp() or something.

    I don’t even know if the physics behavior has a spring joint. Anyways you could do a spring by constantly applying a force toward a rest position.

    ForceX = -k*(self.x-restx)/dt-b*self.velocityX

    And the same for y force, just with y stuff. K and b are the spring stiffness and damping. Usually in the range of 0 to 1 but you’ll just have to fiddle with it. Probably will want to put that under a condition of dt>0 since dt can be 0 which would give infinite force.

  • I don’t have an example. But since you only use C2 a non third party solution could be to load the image you want to sheer into the sprite’s animations as a sprite sheet. So say the image is 320x64 you’d import that image with spriteSheet import with 1,64. That would give you a bunch of 1 pixel tall strips of the image. Be sure to set the animation speed to 0. And probably set the origin to the top left.

    Next is to place it. It’s a pain to place 64 instances and set the frame of each one so you can do that with some events:

    Start of layout
    Repeat 64 times
    — create sprite at (0, 480-64+loopindex)
    — sprite: set animation frame to loopindex

    Then to sheer right you can do:

    Sprite: set x to self.x+lerp(10,100, self.iid/64)*dt

    Where 10 is the speed of the top row and 100 is the speed of the bottom. Tune the values to your liking. Moving left would just be subtracting.

    You can avoid the image slicing step by using a tiledbg. The con with that is there will be more overdraw and the sides of the sheer will look off

    Start of layout
    Repeat 64 times
    — create tiledbg at (0, 480-64)
    — tiledbg: set height to 64-loopindex

    And

    Tiledbg: set x to self.x+lerp(100,10, self.iid/64)*dt

    Notice the 10 and 100 are reversed.

    Beyond that you could use a third party plugin to do a sheer. Paster is one option with its draw textured quad action. You’d basically just select a sprite to get the texture, and set the four corner positions.