ID:120974
 
Since BYOND added native pixel movement the Sidescroller library had two modes, "native" and "library". In native mode the library uses BYOND's built-in pixel movement to check for and handle collisions. In library mode the library uses the pixel movement functions that it has implemented in DM code.

I'm working on adding a third mode called "hybrid". The hybrid mode uses the pixel movement code from library mode but uses some built-in procs to speed it up. For example, here's how the library checks if a mob is standing on the ground in library and native modes:

// library mode
for(var/atom/a in nearby())
if(!can_bump(a)) continue

while(1)
if(a.pleft == a.pright)
if(py != a.py + a.pheight) break
else
if(py != a.height(px,py,pwidth,pheight)) break

// If you're not lined up horizontally we can also ignore the object
if(px >= a.px + a.pwidth) break
if(px + pwidth <= a.px) break

on_ground |= (1 | a.flags | a.flags_top)
break

// native mode
for(var/atom/a in obounds(src, 0, -1, 0, -pheight + 1))
if(!can_bump(a)) continue
on_ground |= (1 | a.flags | a.flags_top)

The code for library mode looks much more complex but that's not what made it slower. What made it slower is that the for loop uses nearby() instead of obounds(). The nearby() proc essentially returns a list of atoms in oview(1), the obounds() proc returns a list of atoms that occupy the space directly below the mob.

The idea behind hybrid mode is that it can make use of procs like obounds. All the library has to do is set the step_x, step_y, bound_width, and bound_height of the player and obounds() will return the proper list of atoms. Hybrid mode uses these procs to speed up things in ways that library mode can't (because it only used its own px, py, pwidth, and pheight vars, not step_x, step_y, bound_width, and bound_height).
The key is that hybrid mode still uses its own collision detection and resolution code, which means that it's possible to support ramps (and other things not supported by BYOND's native pixel movement).
There are still some kinks to work out but so far this looks promising. I created a new demo where mobs move randomly around the map. I ran the test in each mode with 10 mobs. Each test ran until the pixel_move proc was called 25,000 times (about a minute). This table shows the average execution times for the three big pixel movement procs the library has.
+------------+---------------------------+
|            | Time (in microseconds)    |
| Proc       +--------+--------+---------+
|            | Native | Hybrid | Library |
+------------+--------+--------+---------+
| pixel_move |  115.1 |   76.8 |   167.9 |
+------------+--------+--------+---------+
| set_pos    |   47.3 |   34.4 |    90.3 |
+------------+--------+--------+---------+
| set_flags  |   50.5 |   48.1 |    89.1 |
+------------+--------+--------+---------+
As I said, there are still some kinks to be worked out but this is very promising. The hybrid mode outperformed native mode! It'll take more work to get this added to the pixel movement library, but hopefully these same improvements will make it possible to have ramps and 3D movement in the Pixel Movement library with performance that's on par with BYOND's native pixel movement.
Sounds pretty great, can't wait to see it! I've been tossing around a small game idea that would use pixel movement and this sounds very helpful.
If you're using pixel movement in a top-down game (i.e. there's no jumping) then this won't make much of a difference, not initially at least. This does create the possibility to more easily extend the collision detection to support other shapes. For now, the biggest difference will be the performance increase for games that use ramps.
Could you take the keyboard handling out and make it a library? That way, the pixel libraries can include your keyboard by default, while I use my own keyboard stuff.

Will "3D movement" work in a topdown/side map perspective?
Kaiochao wrote:
Could you take the keyboard handling out and make it a library? That way, the pixel libraries can include your keyboard by default, while I use my own keyboard stuff.

I could, but the keyboard handling is closely related to how the library works. The library expects certain keyboard vars to exist and work a certain way, so you'd have to replace it with something identical. If there's some benefit this buys you I'd be better off improving the library's keyboard code to add this benefit right into the library.

Will "3D movement" work in a topdown/side map perspective?

Yes. In the hybrid mode everything will work like it does in the current "library" mode, which supports 3D movement in isometric maps or side maps.
I posted the update to the Sidescroller library. The new hybrid mode is the default mode so that all features work (ex: you don't have to switch modes for demos that have ramps to work). Performance appeared to be better in the hybrid mode when I first made this post and I've made some slight tweaks since then that would only improve performance more.

I hope the hybrid mode will phase out the other two modes. The only benefit library mode had over native mode was support for ramps, but now hybrid mode has that covered. Native mode had a big performance boost over library mode, but hybrid mode is comparable to native (or slightly better). With only one mode to worry about I can focus on cleaning up the code - I'd like to fix up the collision detection and resolution code to make it easier to extend. That way people could add support for bounding circles or different kinds of ramps.
I made a post about this update on the developer forum, but I figured I'd post some of the information here too.

Here are the results of profiling each mode:
Native Mode
proc Time Calls Avg
pixel_move 7.895 100439 78.6
set_flags 4.386 100439 43.7
set_pos 2.580 100439 25.7
TOTAL 148.0

Hybrid Mode
proc Time Calls Avg
pixel_move 7.168 100190 71.5
set_flags 4.602 100190 45.9
set_pos 3.401 100190 33.9
TOTAL 151.4

Library Mode
proc Time Calls Avg
pixel_move 26.832 101460 264.5
set_flags 10.965 101460 108.1
set_pos 14.205 101460 140.0
TOTAL 512.5

The library mode numbers are included to show how much better each of the other modes are, and to show that the difference of 3.4 μs (that's 3.4 millionths of a second) between native and hybrid modes is rather insignificant.

The differences between hybrid and native modes are what I'd expect. Hybrid mode's set_flags proc takes slightly longer. This is the proc that sets your on_ground, on_left, on_right, and on_top vars. The reason it takes slightly longer is because additional logic has to be added to handle ramps - other than that the procs are the same for each mode.

Hybrid mode's set_pos proc has to handle updating your loc. Since native mode's pixel_move proc calls the mob's Move() proc, these updates are not handled in native mode's set_pos proc making it faster. This could also explain why native mode's pixel_move proc is slower.
That looks really promising! I am looking forward to seeing if this can be used to add a more 3d world to isometric mode.
Jmurph wrote:
That looks really promising! I am looking forward to seeing if this can be used to add a more 3d world to isometric mode.

That's already possible using the "library mode". This will improve the performance but won't initially add any new features.
The sidescroller library seems really neat, but I'm wondering how good BYOND is at handling multi-player sidescroller games? I haven't seen any popular ones so I don't have much to go off of.
Writing A New One wrote:
The sidescroller library seems really neat, but I'm wondering how good BYOND is at handling multi-player sidescroller games? I haven't seen any popular ones so I don't have much to go off of.

The only thing that'd make sidescrollers perform poorly in multiplayer is the increased framerate. A sidescroller running at 40 fps will run over a network just like a top-down game will run at 40 fps. You're not going to support 100 players in a server because, at 40 fps, you won't support 100 players in any kind of game (sidescroller or not).

I try to catch A Miner Adventure whenever its online to see how it runs. With 4-6 people the only time I had a problem was when the host was in Europe (and most of the clients were in the US). Otherwise, the performance has been fine and the game has a few things going against it:

* dynamic lighting - lots of icon states need to be updated whenever players move.
* it doesn't use native pixel movement.
* flowing water - this uses a lot of moving objects and updates to icon states.

The table in comment #6 here shows that improvements to the sidescroller library have cut CPU usage to one-third of what it used to be. Since the game was posted before native pixel movement it's using an older, slower version of the library. Even with these things going against it I've almost always found it to be playable.