R0J0hound's Recent Forum Activity

  • Well maybe something like:

    Var a=0
    Var r=0
    
    Create sprite at 320,240
    Set a to random(360)
    Set r to (random(1)^3)*100
    Sprite: set x to self.x+r*(cos(a)/4-sin(a))
    Sprite: set y to self.y+r*(cos(a)/4+sin(a))/2

    The logic is we create a random point in a circle. Which would be a random angle from 0-360 and a random radius from 0-100. Ah just noticed you wanted an oval so I added the /4 in there to indicate the x radius is 1/4 the y radius. Then you convert that to isometric. In general it’s simpler to just do the math in top view then covert it after.

    Anyways, the main addition is we can modify the distribution of the random points to favor the center instead of more uniformly by doing: (random(1)^3)*100 instead of random(100). You can change the 3 to make the center be favored more or less. Just an idea. There are probably other ways to have random points favor a point but nothing super simple comes to mind.

    Another idea to have them clump toward the center while not overlapping could be to move them to the center and push away from each other if they overlap. But that may be more involved.

  • I’ll have to look at your examples later.

    Most of the complexity of my example is replicating what the physics behavior does for you but I just like doing stuff from scratch.

    You can combine the physics behavior with other behaviors but I tend to prefer doing other things than working around behavior conflicts.

    Anyways, your physics terminology is a bit off. Presumably you could just set the angular and linear velocity of the car depending on if it’s moving forward or backwards and depending on the wheel turn. But that’s not really physics

    If you want to control everything with forces you’d do it with friction per tire.

    Inertia isn’t a force. It’s basically a property that controls how resistant an object is to changing its velocity.

    Maybe you’re just after finding a force to change the velocity in a specific way?

    You could get that by solving this for the force. Note you’d split that into two formulas for x and y.

    Force = mass * acceleration

    Force*time=mass*(velocityEnd-velocityStart)

    I guess time would be a timestep dt. But maybe it’s better to do that instantly so you could solve for impulse instead:

    Impulse = mass*(velocityEnd-velocityStart)

  • Sure. Just make a thin sprite angled in the direction you want it to go. Then starting with it short make it longer till it collides with something. That’s basically it.

    All the rest is doing things to make it faster and more accurate.

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • Inertia means it tends to keep going in the direction its moving. With a car it turns due to the friction on the tires opposing sliding sideways.

    Put another way, if you just apply forces and torque to the center of mass of an object you end up with floaty motion much like BB-8 or a vehicle that is rolling on one big ball.

    You can model a car much better by simulating wheels. Aka you'd apply force from the back two wheels and then apply a friction force to any sideways motion on each of the four wheels.

    Mouse up/down to adjust gas/reverse, Left/right to steer, and click for handbrake.

    dropbox.com/scl/fi/g9p9bdi5etv39r7jwz4tw/car_physics.capx

    Probably can be improved in many ways. One that comes to mind is instead of directly applying acceleration to the back tires we could just apply wheel spin and rely on friction to accelerate. Beyond that weight transfer per tire, but that may be delving more into 3d stuff. It would probably benefit by making a distinction between static and kinetic friction.

    I ended up not using the physics behavior but the idea can be applied there too. Here are some useful formulas as well:

    velocity along angle:

    vel: vx*cos(a)+vy*sin(a)

    velocity on point:

    vx: body.velx-body.angularVelocity*(pos.y-body.y)

    vy: body.vely+body.angularVelocity*(pos.x-body.x)

  • Order of events matter. You'll want to set up the rays first, then do the raycasting, and then do the wall overlap highlighting. Plus you are using just one ray so there isn't much to see.

    If you want some examples to mess with and get ideas from here are two.

    First one uses a binary search to find the ray hit points. Then it loops over the wall tilemap and places light squares on every tile that overlaps a ray. If you get gaps between lit walls then you probably need to increase the number of rays.

    dropbox.com/scl/fi/30gmdo3qc71oqmltzmzrs/ray_cast.capx

    Second one is similar to the stepping idea I first described but it's tuned to step a grid at a time. Resulted in a nice fov view too, and walls are lit as a side effect of that. Again, there can be gaps if the ray count is too low.

    dropbox.com/scl/fi/jcyk0b8qjzgrokxu0ti1y/ray_cast_tilestep2.capx

    Either are decently fast. When you have loops in the event sheet you can make them a lot faster by avoiding picking inside then when you have a high iteration count.

    Anyways, they provide some ideas to mess with. There are a lot of possible improvements with both but the satisfied my tinkering for the moment.

  • Anyways, here's an example using sprites and a 2d array. It works and is decently fast but it's all throwaway code. It's useful to tinker with to get some ideas from.

    dropbox.com/scl/fi/776vlqpflik48q8kgbj7i/falling_sand_simple.capx

  • You can do a ray cast with a sprite.

    Set its origin to the left and set its size to 0,0. Then set its position to the player and the angle to the direction you want to go. Events would look like:

    While
    Ray: width<100
    [X] ray: overlaps wall
    — ray: set width to self.width+1

    The 100 would be the distance limit and the 1 would be the step size. Notice the overlap condition is the inverted version. So you’re checking if the ray doesn’t overlap a wall.

    You can tune the step size to be as accurate as you like, and to see the rays you can make the height>0.

    If the walls are sprites you can light them up with something as easy as

    Ray: overlaps wall -> wall: set opacity to 50

    So you’d probably want a step size lower than 1, and a much lower max range for your tiny layout.

    There are better algorithms that can be utilized too. But that’s a simple one that can work well enough.

  • Both sound equally possible, but it largely depends on skill and knowledge I suppose.

  • The link in the first post was a cap file for Construct 1. It wouldn't be useful for C2 or C3.

    Have you tried doing the logic for the falling sand yourself? It's pretty simple. Move down if the space below the grain is empty. Or if that isn't empty try moving down left or down right if those spaces are empty.

    You have options with how to do it. Sprites, tilemap, or drawing canvas are options.

    If you do it with events you'd want to only use system compare and else's under a loop to avoid as much picking overhead as possible.

  • Fawk

    Here's an updated test that additionally tests using picking after the loops in the "first" and "middle" cases. Move the mouse up and down to see pics of the events to compare with the readings.

    dropbox.com/scl/fi/0qazj62jfevm0vuk2fvxp/event_timing_2.capx

    Jase00 The nesting of the events doesn't seem to affect the speed significantly.

    So far the fastest way to do things is to have the loop as the last thing after picking stuff, or you can use compares after the loop as long as they are in sub-events.

    KryptoPixel

    To change the internals it would require filing an issue, Ashley investigating it, and him possibly finding a fix to improve the performance.

    The value with this topic either way is seeing some more optimized ways to order things than others. Like from slowest way to fastest way is around 20x faster, which isn't bad.

  • We already know a system compare or evaluate is faster than picking events, but here is a performance test of variations of looping with two picking events. Half the instance's "a" variable is 0 and the other is 1. I also made them all invisible so we are just measuring how long the events take.

    It measures and averages the timings of each event with 10,000 instances. Made in C2 but tested in C3 r449.

    dropbox.com/scl/fi/xd5mz5kofj7c67ftbrhvo/event_timing.capx

    We are mostly measuring the performance of the loop and how many instances are being copied in the SOL. "First" and "Last" are taking advantage of some optimizations whereas middle does not. I tried variations of using sub events but that doesn't appear to be significant.

    The for each appears to roughly do this under the hood:

    save SOL copy
    for each sprite
    -- if(following conditions or sub-events do picking)
    -- -- load SOL copy
    -- select nth sprite
    -- do stuff

    The if may be if the loop is the last condition and sub-events don't do picking but I didn't dig too deep

    The "load SOL copy" is the heavier part.

    With the "first" tests it's not heavy since the copy is just all the instances so construct sets a flag so nothing needs to be copied.

    The "last" tests are able to skip the loading since the SOL isn't being modified past that point.

    And finally, "middle" is the slowest since it has to load a copy of half the instances every iteration.

    I can almost see a way to avoid loading the list of picked instances every iteration, but it's not my code. I'd say it still may be worth filing a report in regards to how slow the middle case is.

  • Even after looking a the runtime's source in C2 I'm having trouble coming up with consistent rules. C2 and C3 run similarly but C3 is faster.

    Anyways by default the picking system duplicates object lists a lot. Think at the top of every event block, with every iteration of a loop, and probably with some other special events. That is slow with a high amount of instances.

    But there are two major optimizations being used:

    1. When all the instances are picked then copying just sets a flag so nothing needs to be copied which is faster. That is why having the "for each" as the first condition is faster in 3 and 4.

    2. When exporting it keeps track if any of the following sub-events modify the SOL. And if they don't there's no reason to copy the SOL after that point. That's why 2 is fast. So effectively the loop would need to be the last condition in a block, and the sub events would need to do no picking to take advantage of that.

    The short version that's easier to remember is you'd want the loop to be the first or last condition in a code block. You can have non-picking events after the loop but it needs to be in a sub-event.

    The high cpu usage in 1 is from the worst case with no optimized code paths. And oddly enough number two performs just as bad if the "system compare" was directly below the loop instead of in a sub-event.