I know Forum_account's Pixel Movement libraries handle it very nicely, but what I want to know is if there's a very basic algorithm for fractional pixel movement. What I mean by that is, of course, moving by fractions of a pixel at a time. The importance of that to me comes from usage of math slightly more complex than addition and subtraction (mainly trig).
The current basic "native pixel movement" requires you to shift positions by integer(s) at a time. This inaccuracy is problematic in a number of cases. Mainly, at higher frames-per-second, the minimum speed limit of 1p/t(pixel per tick) really noticeable. There are also obvious rounding issues with trig functions. They simply won't work with low speeds, causing you to only be able to move one of the 8 directions at rounded speeds. Using the "simple" Move(loc, dir, step_x + dx, step_y + dy) won't use BYOND's awesome pixel-perfect collision detection, where, if an object's bounding box intersects (or possibly even overshoots?) another, it is instantly pushed back.
What I ask for is the simplest fully-functional method that best uses BYOND's native pixel movement support while providing fractional displacements. Forum_account's technique is to build up the fractional parts and add the integer parts. Is there a simpler way that replaces less of BYOND's native functionality?
ID:151264
Jan 4 2012, 2:55 pm (Edited on Jan 28 2012, 5:39 pm)
|
|
#1 Jan 4 2012, 3:33 pm
|
|
You are referring to projectiles?
| |
I'm referring to all movers being able to have velocities between integers. I can get projectile collisions by calling bound() on an arbitrary coordinate.
| |
It'd be much more difficult to have things collide on a fractional level, you'd have to basically rewrite the whole collision detection system.
But for fractional movement, just divide the velocities into two components (x and y) and add those components to the fractional position of the object. (Fractional position isn't actual pixel position.) Then have the movement procs "check" to see if after adding the velocity to the fractional position that the new object would be better positioned in the next pixel over. That would be the case if the object should be overlaying more than half of it's pixel neighbor. If that is true, then move the object a step closer to this neighbor and subtract 1 from the total saved fractional position. | |
#4 Jan 5 2012, 11:50 am
|
|
Move(), step_x, and step_y don't support fractional values. If you want actual fractional positions, you'll have to handle movement yourself. If you want to use BYOND's native movement, you'll have to use a similar method as mine (accumulating fractional parts). I can't think of any other way.
It's not that hard to split that part out of the library - it used to use this method with BYOND's native feature. | |
#5 Jan 6 2012, 1:18 am
|
|
you could scale all your graphics up 2:1 and display them at half that. then you'd gain 0.5 of a pixel.
| |
FIREking wrote:
you could scale all your graphics up 2:1 and display them at half that. then you'd gain 0.5 of a pixel. You wouldn't truly move half of a pixel by doing that. It would only appear that way, which if the isometric support hasn't taught us, nobody is interested in making things appear to be something they're not. | |
Kumorii wrote:
FIREking wrote: well just so you know, there is no such thing as half a pixel. only a visual effect. even open gl has to map something to a pixel. its the smallest increment you have in graphics. | |
While this is all an interesting point to make...
You wouldn't just be gaining half-a-pixel, you'd also be doubling the amount of pixels that the collision calculations would need to be done for. It's clear the issue-at-hand is not a graphical one, but a physical one. (The fact that pixels are the smallest thing in graphics is irrelevant to the physics engine. Or, at least, it should be.) | |
All numbers in BYOND are floating point, I'm pretty sure.
| |
FIREking wrote:
True. But I don't think you'll ever see floating point accuracy in byond. What makes you think that? | |
#12 Jan 27 2012, 5:41 am
|
||
Kaiochao wrote:
What I ask for is the simplest fully-functional method that best uses BYOND's native pixel movement support while providing fractional displacements. Forum_account's technique is to build up the fractional parts and add the integer parts. Is there a simpler way that replaces less of BYOND's native functionality? I thought I had replied to this, but I guess not. Maybe it was a similar post somewhere else. Accumulating the fractional parts doesn't replace any of BYOND's native functionality. That method can work just fine with calling mob.Move() - that's how the library used to work. You can do something like this:
You're still using the built-in Move() proc to handle the pixel movement, you're simply adjusting the parameters you're passing into it based on the fractional parts of moves that you've accumulated. | ||
#13 Jan 28 2012, 1:32 am
|
||
At first, I didn't want to use "fractional part accumulation" to handle this because it seemed cheap. After making use of that extremely simple method, I have a much better understanding of its simplicity. It's really not that complicated and it provides very decent results.
If this topic was in Code Problems, I'd vote up your post, F_a. Aaand... this is my implementation.
| ||
#14 Oct 21 2012, 1:35 am
|
||
If density isn't an issue, this is what I use in BYONDfall:
px and py are absolute coordinates and are stored/adjusted on the mover. The only problem with this that I've encountered is that if the Move() fails, px and py are still adjusted, so the object will just stay still until it gets to a position that it can actually get to. The larger the distance moves, the harder it is to deal with collision detection. I just wish there was a built-in translate(dx, dy) proc that moves the object in a straight line, taking obstacles into account for each discrete step in between. I can do this by cutting the displacement vector down to a unit vector and performing multiple moves, but it's just not practical when you're moving lots of things at arbitrary velocities. And, of course, when moving tiny amounts per tick, fractional moves should be conserved! | ||
#15 Oct 21 2012, 10:12 am
|
|
What I did in one of my game was create a proc that gets a heading for movement (basically, the slope of a line for it to travel), then using the formula for a circle it takes the x and y coordinate and then makes the atom take 2 separate steps, one to the east/west and one to the north/south. It allows for easy pixel movement in any direction, which I find to be significantly better than being limited to 8 directions. Since it still uses the built-in step() functions, it handles obstacle collisions just fine.
If you need to see example code, let me know. EDIT: The movement also handles tracking the remainder from any non-integer values... initially it was rounding for every step, but after 20-30 steps it was ending up way off from where it was intended to be. | |
#16 Oct 21 2012, 7:56 pm
|
|
Knick-knack, this thread is back!
| |
#17 Oct 22 2012, 8:50 am
|
|
I haven't used BYOND for awhile, but you need to overwrite proc which handles collision and add own code to take in mind floating point values.
Second possible solution it to make all atoms bigger by 1 pixel in each direction, then when Cross() is called you could make extra check. Though this somewhat prevents Uncross() from working correctly. | |
#18 Oct 22 2012, 2:00 pm
|
|
I still don't understand the original post here. You can't move a fraction of a pixel. That's not how pixels work. If the value is non-integer, then how would you conceivably display a move of "half a pixel"?
| |