ID:112975
 
Note: In case you missed it (because this post will knock my other one off the front page), I just posted a huge update to my pixel movement library. Check out this post for all the details.

Introduction

Pixel movement is a feature that is highly demanded and often misunderstood. BYOND's support for it has changed over time and so has the availability and quality of pixel movement demos and libraries. This leaves a lot of questions - what is it? how do you make it? can BYOND handle it? why do you need it?

A while ago (almost a year ago, I think), it became my goal to create a solid pixel movement implementation for BYOND. BYOND had some demos and libraries for pixel movement (here's a list), and they show that it's indeed possible, but they weren't polished enough that people could really use them. Many of those were just executable demos that didn't include code. People weren't implementing it as a feature, they were implementing it as a flasy trick. I wanted to change that - by making a library that anyone can use to make pixel movement, it would no longer be impressive for people to say "hey look, I made something that has pixel movement". People could move on and start making games that use pixel movement.

The result is that I've created two libraries for pixel movement, one for sidescrollers, and one for top-down/isometric games. However, these libraries don't address the confusion and mystery surrounding "pixel movement".

The purpose of this article is to answer some of the questions about pixel movement and to de-mystify the feature. I think it's one of those features that people want because they think it'll improve their games (like isometric maps), but once they have the feature and they find out it's not a magical "make my game awesome" button, they're not sure what to do with it.


"What is 'pixel movement'?"

BYOND's default movement system is tile-based. When you press the right arrow key you move right one tile. When you press the left arrow key you move back to the first tile. You move a tile at a time. "Pixel movement", or "pixel-based movement", is a movement system where the player can move in smaller increments than whole tiles. The next unit of measure smaller than the tile is the pixel, so these finer movements are measured in pixels.


"Do I need pixel movement?"

Maybe! It depends on the kind of game you're making. Pixel movement gives the player finer control over their character. In an action-based game this can be very important. In a turn-based RPG it might make no difference.

Tile-based movement is a rare thing. Even on the NES, where all graphics were tile-based, most games didn't use tile-based movement. Those that did tended to be from a few specific genres. People don't expect games to be tile-based, so even though it's commonly seen as a limitation of BYOND, people who aren't familiar with BYOND won't understand this limitation and will just think the game is bad.

Using pixel movement almost requires a higher framerate. While people see this as a bad thing because it'll "cause more lag", it's actually a good thing (people are too afraid of lag anyway, but more on that later). BYOND's default framerate of 10 frames per second is most likely because BYOND was started back when 56k internet connections were fast. Unfortunately, 10 frames per second isn't enough for animation that's visually appealing. Read Wikipedia's history of cinema, by 1895 technology had advanced past the 10 frames per second mark. Even if you don't use pixel movement, you should strongly consider dropping world.tick_lag to 0.5 (from it's default of 1.0) to get a framerate of 20 fps.


"How does it work? I've heard all this stuff about collision detection..."

A pixel-based movement system augments BYOND's existing tile-based movement system. You can use BYOND's built-in pixel_x and pixel_y variables to change a mob's position by any number of pixels. But that's not all there is to movement, you also have to check for collisions too.

Checking for collisions is easy in BYOND's default movement system. When a dense mob tries to move to a tile, you just have to check if the tile is dense or if it has any dense objects inside of it. If it's clear, the mob moves into the tile. If it's not clear, the mob doesn't move into the tile. With pixel-based movement there are more complicated ways that collisions can happen and more complicated ways that collisions need to be resolved.

Luckily, a pixel movement library will handle all of these things for you. This is similar to how you can use BYOND's default tile-based movement. There are some things you can customize (ex: you can override a turf's Entered() proc). There are also some things that BYOND gives you that you can't override - you don't have to tell BYOND that there's a grid of turfs and you don't have to tell BYOND what it means for a mob to have a loc, it just knows. It handles these low-level details and you don't have to worry about it. This is how my pixel movement libraries work - you can override some things to customize behavior (technically you can override it all), but there's also some messy internal stuff that is better off left alone.


"What are bounding boxes? And what is 'pixel-based collision checking'?"

Bounding boxes can be used to simplify how you check for collisions. You use a simple shape (ex: a rectangle or circle) to approximate the shape of a mob. Then, to check if the mob is inside of a wall, you check if it's bounding box is in the wall. My pixel movement libraries both use rectangles as bounding boxes for all atoms (technically, the sidescroller library uses rectangles, the pixel movement library uses rectangular prisms).

Pixel-based collision checking means that you look at the actual pixels in the icon to see if there's a collision. If the icons of two objects have pixels in the same position on the screen, there's a collision. Unfortunately, this is a stupid feature that people think is necessary (because it sounds impressive), but it's not necessary. In fact, it's often wrong. For example:


Above: Showing why pixel-based collision is actually something you don't want.

On the left side of the picture, the circle cannot move up or right because it's hitting the wall. If we treated the mob as a circle we could realize that the round shape moving upwards would get pushed away from the wall and we could allow the upward movement. Because we just treat it as a collection of pixels and only want to know if things overlap, we'd see a collision and not allow the movement.

On the right side we have a mob that should be able to walk in front of the wall. Because the icons aren't from a strictly top-down perspective they show height, the mob should be able to walk in front of the wall in such a way that the icons overlap but the mob isn't really hitting the wall. If you're using pixel-based collisions, the move wouldn't be allowed because the icons overlap.


"I've heard that BYOND can't handle pixel movement..."

There are a few reasons why people say this:

1. Pixel movement is not a built-in feature of BYOND, it's something you have to create with DM. Luckily, BYOND has all the things you need to create a pixel-based movement system. Some people think "if we were supposed to do it, it would be built in", but this doesn't make sense.

BYOND doesn't have a built-in chat system, it just gives you the ability to get text input from a player and output that text to all other players. The reason it's not a built-in feature of BYOND is because there are lots of ways you might want the chat system to work. By leaving the implementation up to each developer, you're free to customize your chat system however you need to. The same is true for pixel movement. Not every game will use it in the same way. Some games might have the players walking around in 4 directions, some might have the player driving around a car with 360 degree movement, some might be sidescrollers.

2. BYOND is slow. There are a few reasons why BYOND is slow:

2.A. Some people run BYOND on old laptops with poor graphical capabilities. BYOND's graphics aren't impressive by modern standards so they don't look demanding, but refreshing the screen 30 times per second can be too much to ask of a ten year old laptop.

2.B. BYOND used to have a fixed framerate (10 fps) and bad networking code (the server was not efficiently determining what information needed to be sent to clients). Both of these issues have been fixed. You can now use world.tick_lag to make games run faster than 10 frames per second and BYOND's netorking code has been improved so that the server can handle sending more updates per second to every client.

3. BYOND doesn't provide pixel movement and, for a long time, the pixel movement libraries and demos were not very helpful. Because of that, people have gotten used to making games with only tile-based movement. In fact, people have gotten so used to tile-based movement that they don't think pixel movement is necessary.

Of those issues, speed is the only real concern. Luckily, speed is just a temporary issue - computers and internet connections are getting faster all the time and the BYOND software is constantly being worked on by the BYOND staff. Games with pixel movement might experience some performance glitches in BYOND (I've found these two), but in order for the staff to fix these issues we have to first find them. BYOND will only get better and faster.


"Seriously? Pixel movement doesn't lag?"

Well I didn't say that. If you're playing a game over the internet there's going to be lag, it's just a question of how bad the lag is and how willing the player is to accept it. There are a few reasons why BYOND games lag:

1. Latency in communication. The trip from client to server will go through many devices (computers, routers, etc.). If there's one slow device along the way, all messages will be slowed down. You might be able to send messages quickly across the internet (ex: less than 0.1 seconds to get from client to server), but it's never instant.

2. A busy server. If the game has a lot of players the server's CPU or internet connection might be pushed to its limits. This happens in all games whether they use pixel movement or not.

3. Client-side processing. The BYOND game client has to draw the screen and manage the game's interface. If the game has a large viewing area and is displaying lots of objects, the client's computer might not be able to redraw the screen fast enough.

The lag in games that use pixel movement is more of a problem because these games tend to be action games. If you were playing chess, a slow-paced board game, you could tolerate a lot of lag. If you were notified of a move three seconds after your opponent made the move, that'd be ok - you'd still be able to play the game. Suppose you're playing an action-based shooter and you press down to duck for cover, if the server gets your message (the instruction to duck) even a tenth of a second late it could be the difference between dodging a bullet and getting your head blown off. The three second lag that was acceptable for the chess game would be absolutely game-ruining in the action game.

Games that use pixel movement tend to be action games and action games tend to have higher framerates. Pixel movement isn't what causes the lag (or what causes the lag to be a nuisance). A tile-based action game will have lag too.


"Okay, so what's this all mean?

It means that pixel movement is a good thing, an excellent thing. Now, this doesn't mean that you have to use it. Some projects won't benefit from it, this depends on the type of game. A game isn't good just because it uses it or bad just because it doesn't, but, if you're working on a game inspired by Metroid, tile-based movement probably won't cut it.

Lag is an issue, but it almost always is whether you use pixel-based movement or not. That's no reason to avoid pixel movement. Making an action-based game with a higher framerate is more demanding of the server and will limit how many players you can support in a single server (this is also true whether you use pixel movement or not). Instead of having 50-100 players you might have 5-10 players, but this is okay for a couple of reasons:

1. Action games tend to be small-group games. Look at Wikipedia's List of best-selling PC video games. Of the games on that list that even have multiplayer modes, most don't support more than 10 players.

2. The BYOND software is freely available so anyone can download and host your game. You can set up some game servers yourself, but you can also let people download the game and set up their own.

BYOND is an excellent platform for making action games that use pixel movement. If you want to make a game that would benefit from having pixel movement, don't let anything stop you and don't settle for tile-based movement.
Good read mate. While I don't disagree, I don't think people would think any less if a game has tile based movement. Tibia is an online MMORPG with tile based movement, and still going strong. Just something I felt like putting out there, because I know a few people who think they absolutely need pixel movement to have a successful game(Even though you addressed this, I just wanted to add this :D).
I understand what you're saying and agree completely. I mentioned that tile-based movement is fine in some cases, but maybe I should have added a section to elaborate on what those situations are. If you can understand why you'd use tile-based movement, you'd almost automatically understand why you'd use pixel-based movement.

Some games use tile-based movement to their advantage instead of using it just because it's easier. In games like chess, checkers, and othello, the grid is part of the game. It can be a very beneficial way to simplify things. In a strategy/RPG game you can give a magic spell a specific range and players are either inside its range of effect or they're not. Having pixel movement would allow for players to be on the boundary and it would just complicate things.
This is a great read. I've always questioned BYOND's ability to handle pixel movement in a server with 50 or so people though. Splitting these 50 people up into groups of 10 would ruin the point of the game, however.
I'm still under the impression nobody uses your pixel movement lib is because it's bloated with features most people might not want. Your keyboard handling stuff being the chief example of this, it has absolutely nothing to do with pixel movement and should be removed. Momentum is another example, it's a great feature to have but it's really just an extra game mechanic which should be moved to the included demos.

Another concern of mine is the way BYOND updates libs. Rather than doing a fresh download it sort of just mixes in the new files with the old. This can lead to problems where you don't know what's supposed to be there and what isn't.
I mentioned in a comment in another blog post that I'd like to add some "control scheme demos". Pixel movement is very open-ended, you could use it for people, cars, boats, spaceships - anything. The library assumes human-like movement, so I'd like to include demos that show how to create other control schemes. This would even include, as you mentioned, variations on human-like movement - some people might not want diagonal movement.

SuperAntx wrote:
I'm still under the impression nobody uses your pixel movement lib is because it's bloated with features most people might not want. Your keyboard handling stuff being the chief example of this,

Unfortunately, for the library to work "out of the box" it has to have integrated keyboard support.

I'm not sure if the problem is that it has features that people might not want, but that people would be put off by any amount of new features (even though many are essential). People spent time to learn how to use BYOND's tile-based movement system, they don't want to spend time learning more stuff.

But, I don't get much feedback from users so I'm really not sure why people don't use it. This is just my hunch.

Yut Put wrote:
Maybe having a start page in dream maker that shows featured libraries would help.

I've asked for this and the common response was "that sounds like it would be annoying, I'd want to disable it". Most IDEs have welcome pages, even ones like Microsoft Visual Studio that don't have the sense of community that BYOND does - if you run Dream Maker you're a member of the BYOND community and should be shown news related to the developer community. It's like how the BYOND staff's blog updates are shown in the pager - if you have information that's relevant to users and an easy way to reach those users, why not?
Many thanks for running an update on this Forum. I don't use the Sidescroller library and haven't really had a hardlook at it either so the updates to Pixel movement are extremely useful.

Im in the process of modifying it so that i can use a variable inside the player for speed that can be modified based on a number of conditions. such as mud, buffs, debuffs. and as such needs more then the generic 5 you supply.

In any case keep up the good work and i look forward to seeing more updates.
Midgetbuster wrote:
Many thanks for running an update on this Forum. I don't use the Sidescroller library and haven't really had a hardlook at it either so the updates to Pixel movement are extremely useful.

Thanks!

Im in the process of modifying it so that i can use a variable inside the player for speed that can be modified based on a number of conditions. such as mud, buffs, debuffs. and as such needs more then the generic 5 you supply.

Let me know how it turns out. I have an example of ice in a demo, but I want to add more examples of tiles that effect movement, like your mud example, or conveyor belts.
Hmm i couldn't really think of anything fancy for changing the speed of a player. but i did do a real basic form of movespeed altering.

mob
var
move_speed = 5 //the default this gets changed as its the max.
speed = 35 //the speed at which the player can move (the default is 30 so 3.5 pixels) at w.e rate the library does it

proc
get_speed()
return max(0,(src.speed/10)) //


move(d)
if(trace) trace.event("[world.time]: move: d = [d]")

var/limit_speed = 0
if(vel_x * vel_x + vel_y * vel_y <= move_speed * move_speed + 1)
limit_speed = 1

move_speed = get_speed()

if(d == EAST)
if(vel_x < move_speed)
vel_x += 1
else if(d == WEST)
if(vel_x > -move_speed)
vel_x -= 1
else if(d == NORTH)
if(vel_y < move_speed)
vel_y += 1
else if(d == SOUTH)
if(vel_y > -move_speed)
vel_y -= 1

if(limit_speed)
var/len = sqrt(vel_x * vel_x + vel_y * vel_y)
if(len > move_speed)
vel_x = move_speed * vel_x / len
vel_y = move_speed * vel_y / len


thats extremely basic and it hardly does much in the way of altering the rate of speed in which the character moves only allows for adapting to a faster speed which is pretty much a 3 vel_x increase at most without it being considered to fast

Any pointers on what areas i may need to modify to allow for a better speed altering without screwing over the library

but yea as i stated this is extremely basic and pretty much does nothing in the long run. The actual rate of moving pixels and stuff using the velocity would have to be changed i think for my plan to actually work. simply doing what i did wont do much expecially if i don't want to confine it to a non decimal number
~Midge
I'd probably create vars to store the player's base movement speed and to store anything that might modify the player's movement speed. Some of these modifiers don't need vars on the mob, we can look them up as we need to. Then, I'd just compute move_speed every tick:

mob
var
base_speed = 5
movement()
var/turf/t = loc
if(t)
move_speed = base_speed + t.slow
..()

turf
var
slow = 0
mud
slow = 2
Yea i figured the second var was pointless but i added it there anyway.

Yea the slowing and what not is pretty easy to cover inside the default enter procs of turfs and for ease of access also the Region library (for faster zoning).

The only problem that i really have posed to me is that i want to alter the rate at which the player moves greatly so that alot more speeds could come into play instead of say 1-10 of the current velocity.

The library itself is fine for people who just want a generic clean movement system thats not tile to tile and most would be happy but as i said earlier im trying to make it so i can alter speeds greatly.

e.g. a player moves at usually the speed of lets go with the current velocity 4 and we call that speed 40. but if he had a buff he could gain a 25% boost to speed so +10 speed giving him velocity 5. then lets say hes on mud but has the buff mud reduces speed by 15%. so 40+10-7.5 = 42 movespeed. which going off the current demo would be 4.2 velocity. Im not sure if your demo already supports this kind of thing though since i havn't really looked into this as much as i wanted to. been abit busy today
The library currently doesn't support fractional moves. Each time you move, your px, py, and pz are rounded off. I had removed this because it was causing problems but I'd like to add it back in. Hopefully I can get it working for the next update.
After getting a small step into programming through BYOND, and then learning actual programming and coming back, I most definitely found this as a major limitation to the BYOND platform. However, after learning to actually program at a decent level, I thought of coming back and integrating pixel-based movement into a creation of mine. Thanks to your library you should save me quite a bit of work, so thank you very much! I will make sure to give it a thorough look as soon as I refresh myself of this language.

More on-topic here, but pixel-based movement is simply more fun than tile-based. It was one of the reasons sidescrolling platformers on BYOND were so terrible. More people need to actually use this.