R0J0hound's Recent Forum Activity

  • Computing the exact path an object will move is a tricky problem. Between collisions we can calculate the path exactly but when the collisions occur will vary. The reason for this is motion if done in steps so once a collision is detected it’s usually overlapping a bit already. Typically the exact point where the objects just started colliding would be somewhere between the steps.

    Two solutions come to mind.

    The first is to calculate the exact time of collision. Fairly complex but basically when an object isn’t colliding one step then overlaps the next you’d find the position in between where the objects touch. Then you’d have it bounce and do the calculation again for the remainder of the step. You’d need to do this both for the predicted motion and normal motion. You’d probably want full continuous collision detection with swept volumes to not miss glancing collisions with corners. Anyways you could get a pretty accurate path that way. But there is always some precision loss with the calculations so the actual path will diverge from the predicted path a bit the further down the predicted path you go.

    Another idea is use a fixed timestep to calculate the path of the object. That would give a consistent path. Then to move the object just move it over that calculated path. Basically you’d calculate a list of xy positions with the time at those points. Then you can interpolate the moving objects position over that in a frame independent way. So you could for example simulate the path at a fixed 30hz and no matter the screen refresh rate it would follow the exact path.

    The main annoyance of that is you wouldn’t really be able to use behaviors for the motion anymore, but I guess the same can be said about the other idea.

    I’ll see if I can drum up an example of the second idea later.

  • dop2000

    Actually it does more than match them by pairs

    For example

    Enemy: set width to box.width

    Becomes:

    for(let n=0; n<enemy.pickedCount; n+=1)
    — enemy[n].width = box[n%box.pickedCount].width

    So yeah if the count of both is the same they are paired. But if there are more enemies than boxes then it will loop over the boxes again.

    Anyways related to the original question. For each is needed whenever you want to do things to each object individually when more than one object is picked. That’s the easiest rule of thumb to me. Although you can get away without a for each in some cases.

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • In a loop to predict the path of an object I’d recommend using a fixed value instead of dt. Probably 1/60 would be fine. That would eliminate the shake completely.

    Ideally the object’s motion is framerate independent so the path would be the same no matter what fixed value you used. The only thing that would vary is when the collision is detected. Unless you’re doing some kind of calculation to find the time of collision.

  • Dt is just the time from the previous frame and should be approximately 1/screenRefreshRate. Although construct has settings to clamp that value

    You can improve things if you’re dropping frames. For example since it appears you have a 120hz screen then dt would be 1/120. if most frames are ~1/120 but some are 2/120. That means you should try to reduce the cpu/gpu usage to avoid dropping frames.

    However if frames aren’t being skipped we have no control over that small variation.

    If you want stable values you could use a fixed value instead of dt. Ideally 1/refreshRate but there is no direct way to access the refresh rate. Construct provides fps and ticksPerSecond i think. You could let the game run a bit and say, when time=1 then set a step variable to 1/ticksPerSecond. Alternately you could just average the value of dt from 100 frames and use that instead.

  • Probably best to read up on picking and the event system works. The manual and tutorials can help. Also what has helped me is experimenting with the events to pin down what specific conditions do and whatnot.

    Generally events work with lists of object instances.

    Conditions, such as comparing instance variables, will filter down the picked instances.

    Actions will then run for each of the picked instances.

    Expressions will reference the currently picked instance, or if more than one is picked it will pick the first picked instance.

    “For each” will pick one instance from the picked instances one by one. That’s why sprite.pickedcount=1 after a “for each sprite”.

    “Pick all” will pick all the instances again. That’s why after a “pick all sprite” the pickedcount=count.

    At least that’s some basics. I’m unable to effectively cover all cases. It also doesn’t help that some conditions do something else entirely.

  • Conditions can do several things. For an object type it filters the list of picked objects. The actions of an object type will run for each instance.

    For example

    Sprite: big=1
    — sprite: set size to 25x25

    Is equivalent to:

    // fist pick sprites
    Var Sprite = list of all sprite instances
    Var Picked = [] // empty list
    For (var i=0; i<sprite.length; i+=1)
    __if(sprite[i].big==1)
    ____picked.append(sprite[i])
    For (var i=0; i<picked.length; i+=1)
    __picked[i].setSize(25,25)

    And oddly enough adding a for each after the condition will do the same thing.

  • Loop over all the keys in the dictionary and create a card for each one?

  • There’s always many ways to do things. One way could be:

    Use an array or json object to store a list of all the cards. In it you could store things like the name of the card, the file name of the image, and if it’s owned.

    Then you could make a second list of owned cards or use find() with the name to filter the list. Basically by looping over the complete list and building the filtered list from that.

    Now to display those cards you’d loop over the filtered list and create the cards and position them like dop suggests.

    If looping over the lists becomes too slow you could only loop over part of the lists per frame.

    You could also possibly not have to create all the cards from the filtered list to display them. Depending how you display them you could calculate what cards would be visible and only create those.

    Finally if video memory becomes an issue with so many unique cards you would need to do some kind of memory management. So instead of adding all the card images to the card sprites animation, you’d add them to the files folder of your project. Then you’d load/remove the images on the fly to the card sprite as needed at runtime. It’s probably more tedious to do than it sounds. You’d want to keep track of what images were loaded to avoid repeated loading.

    Anyways, that’s a fairly low level overview of what might be needed. There are probably many simplifications or shortcuts.

  • If both triangles are about the same size you could just check if their positions are about the same. For example abs(tri1.x-tri2.x)<8, and the same for y. 8 would be how close is ok.

    Another idea is to check if all three corners of one triangle are overlapping the other triangle. You’d do that by adding an image point to all three corners and use the system condition “pick overlapping point”.

  • Hi.

    The “compare: dt>0” is correct. Dt can be 0 in construct but we don’t want that since we divide by dt, and dividing by 0 would give infinity.

    And yes, we are setting diff twice but the second one is using the result of the first. Basically what that’s calculating is the signed angle difference or: singnedAngleDiff(a,b)=angle(0,0,cos(a-b),sin(a-b))

    Or another way to think about it is first we set diff=a-b then we normalize the angle to the range -180,180.

    The third action had a typo. “da” should have been “diff”. My apologies. The formula defines a damped spring.

  • Giving something momentum basically means you give it velocity and instead of changing the position or angle, you’d change the velocity.

    It’s pretty popular to use lerp() to do an ease out but I don’t think that’s suitable to use with momentum.

    So you’d add a angvel variable to the sprite and then one way you can change the angular velocity is with a damped spring. Diff is the signed angle difference which is like the anglediff() expression but it’s negative if ccw. In the expression that sets the angvel you’ll see 0.1. You can change those in the range of 0-1 to adjust the spring stiffness and the amount of damping.

    Var diff=0

    Compare: dt>0

    — set diff to sprite.angle-angle(0,0,gamepad.axis(0,2),gamepad.axis(0,3))

    — set diff to angle(0,0,cos(diff),sin(diff))

    — sprite: add -0.1*diff/dt-0.1*self.angvel to angvel

    — sprite: rotate self.angvel*dt degrees clockwise.

  • Well one way would be to have one sprite type and call it “card”. You’d have all the different looks of the cards as different animation frames, and you’d set the animation speed to 0. Basically you’d create or destroy individual cards to add or remove cards you own.

    You’d then select certain cards from that with conditions to pick them.