R0J0hound's Forum Posts

  • Just make the number a string with str().

    I don’t understand the statement about json. It’s a plugin you can use.

  • That sounds fine to have a value per type in the family. If you wanted a value per instance you could use cards.uid as the key.

    If you wanted multiple values per type or instance you could just use another dictionary or append something like “:value1” to the key or something. For example cards.uid&“:value1”

  • I had a quick look but can’t test since I’m not on a pc.

    Bear in mind that using a ray cast only approximates the collision normal between two overlapping polygons. Thats probably at least partially why it doesn’t work well between two solids. A more elaborate algorithm such as SAT (separating axis theorem) would give a more precise normal between polygons, or you may be able to to do multiple raycasts and maybe average the normals to get a better approximation.

    Another reason you may want to do multiple ray casts is one ray will only hit one of the solids and it won’t necessarily be the one the player is overlapping. Even so, it still seems a bit hit and miss doing it with raycasts vs SAT.

    After the ray cast and comparing the normal you push out of the solids with a loop. First you say you try to push out left then right. The push out right is not doing what you think it’s doing. You’re just moving at the opposite angle which is back into the solids.

    I also see you’re using the reflection angle when doing the pushing. You possibly could try using the normal instead.

  • There are actions to change the zorder of objects. So even though you can’t sort by y with one action like you can with sprites, there are other ways.

    One way could be two use an array to store the y and uid of all the objects you want to sort. Then you’d sort the array and loop over it and pick the objects by uid and move them to front.

    Another way could be to zsort all the sprites, then loop over the tiledbg objects by y and pick the sprite with the lowest y greater than the tiledbg y. Then you’d set the zorder to be behind the sprite.

    There may be other schemes you could try too.

  • Glad it was somewhat useful. SDF stands for signed distance field, which basically lets you have a formula that gives the closest distance from a point to a shape. In the example the shape is a rotated box. It’s not exactly made for collision detection, but can be used for it. Specifically it’s simple enough to use to find a collision between a circle and a shape. Also it’s fairly simple to use to get the contact point and collision normal.

  • Here's my tests with the ideas I mentioned.

    With this you simulate the path and simply reuse that same path when you want to move along it. You can make the simulation step anything, but when moving along the path it moves in a framerate independent way.

    dropbox.com/scl/fi/ksuj6rfhow2q5gf19jdcq/path_perdict.capx

    Here's an iteration on the idea. The previous capx simulates by moving, and once a collision is detected it uses the normal to push the object out and bounce. This one finds the time of collision by assuming motion is linear between steps and interpolating when the collision occurs and moving to that point before bouncing. This could be done even better, but it seems fine.

    dropbox.com/scl/fi/70e4s84lsjz1wyxo65lwi/path_perdict_percise_contact.capx

    Anyways, just some examples to demonstrate the ideas I mentioned.

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • Well, the 8-direction behavior works by doing the horizontal and vertical axis of motion separately. When a key is pressed it accelerates toward that direction, and if the velocity is opposite that direction, then it adds the deceleration to the acceleration to allow sharper turning and make the motion less floaty. And finally, it applies deceleration if no keys are pressed on a given axis.

    Changing it to work with any angle is similar but different enough to not be a simple tweak.

    Here is one attempt. Acceleration can be applied to any angle. Deceleration is added to the acceleration when the velocity is in the opposite direction to allow faster turning. It also applies deceleration to velocity perpendicular to the acceleration. And finally, it applies deceleration when no acceleration is applied.

    dropbox.com/scl/fi/igrj1axj136hhuycmpp5w/360direction_movement.capx

    I don't have a joystick, so I used a touch screen one. Collision detection and response (wall sliding) is done with an SDF. Player is a circle, and obstacles are any number of rotated boxes.

    Seems to work alright.

    Now you could do a hybrid approach to reuse as much of the 8-direction behavior as possible. Read the velocity and apply an acceleration at an angle. One key idea to make it less floaty and turn faster is to add the deceleration to the acceleration. You can find the velocity along an angle with vx*cos(a)+vy*sin(a) where vx,vy is the velocity and "a" is the angle. It will be negative if "a" is in the opposite direction from the angle of motion. You may also need to decelerate the perpendicular velocity, but after that just set the velocity of the behavior and it will handle slowing down if there are no keys pressed, and it will handle the collision detection and response.

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

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