Jump to content
  • Advertisement
boagz57

Pitfalls of pixels as unit in game

Recommended Posts

So I've been trying to develop my own little c++, 2d fighting game from scratch and I'm hung up on what exactly I'm suppose to use as 'units' for my game. Currently, as suggested here on another game dev site, my game screen is thought of as a 160x90 grid. So if my game is being run at 1080p screen resolution, that would equal exactly 12 pixels per 1 grid unit (which I call a world unit). For example, I will have code in my game where I will tell my sprite to move 10.0 units/sec in the positive x direction. This means at 1080p my sprite will move 120 pixels/sec when run (12 pixels/unit * 10 units). 

Recently though, I've started trying to add some collision detection to my game and I've run into a bit of an issue with when to convert my world units into pixels and getting my collisions to work properly. While I'm sure I can fix this after some time, this got me thinking what exactly are the problems with just assuming a certain screen resolution and working strictly with pixels in my game? So instead of saying 'move my sprite 10 game units/sec' just say 'move my sprite 100pixels/sec', avoiding and unit conversion techniques. Then, if I want to, I can come up with some way just to upscale to higher res images or whatever for denser screen resolutions. The reason I ask is on a lot of forums people seem to be against using pixels as units when it comes to collision and physics, even for 2d games.

Share this post


Link to post
Share on other sites
Advertisement

Do never ever convert your pixels to units or vice versa for any math computations! Thats a rule of thumb.

Just use your world units directly, which should be float or double. Integer is not great when you want to smooth movement.

The conversion for world to screen units is only done in rendering or for screen to world conversions (mouse picking for example). You can precalculate a factor which you can multiply your world coordinates to convert to screen coordinates and vice versa.

Building up your world from tiles/grid is totally fine and i do this too like this:

static constexpr f32 TILE_SIZE = 0.5f;
static constexpr u32 TILE_COUNT_FOR_WIDTH = 40;
static constexpr u32 TILE_COUNT_FOR_HEIGHT = 22;
static constexpr f32 GAME_ASPECT = TILE_COUNT_FOR_WIDTH / (f32)TILE_COUNT_FOR_HEIGHT;
static constexpr f32 GAME_WIDTH = TILE_COUNT_FOR_WIDTH * TILE_SIZE;
static constexpr f32 GAME_HEIGHT = GAME_WIDTH / GAME_ASPECT;
static constexpr f32 HALF_GAME_WIDTH = GAME_WIDTH * 0.5f;
static constexpr f32 HALF_GAME_HEIGHT = GAME_HEIGHT * 0.5f;

Also my worlds are always built in a right handed coordinate system - which is the same as opengl. So negative Y is going down and positive Y is going up and half the screen dimension is added to X and Y so the world coordinate 0, 0 is always the center of the screen - without taking any translation into account of course.

Keep in mind, that you need to take the aspect ratio into account as well - so you should letterbox your game view, so it will fit on any display. I do this for every frame once and store the result:

// Calculate a letterboxed viewport offset and size
// @NOTE: Scale is used later for doing unprojection
viewSize = Vec2f(halfGameWidth, halfGameHeight) * 2.0f;
viewScale = (f32)windowSize.w / (halfGameWidth * 2.0f);
Vec2i viewportSize = Vec2i(windowSize.w, (u32)(windowSize.w / aspectRatio));
if (viewportSize.h > windowSize.h) {
  viewportSize.h = windowSize.h;
  viewportSize.w = (u32)(viewportSize.h * aspectRatio);
  viewScale = (f32)viewportSize.w / (halfGameWidth * 2.0f);
}
Vec2i viewportOffset = Vec2i((windowSize.w - viewportSize.w) / 2, (windowSize.h - viewportSize.h) / 2);
viewport.size = viewportSize;
viewport.offset = viewportOffset;

// Update view projection
Mat4f proj = Mat4f::CreateOrthoRH(-halfGameWidth, halfGameWidth, -halfGameHeight, halfGameHeight, 0.0f, 1.0f);
Mat4f model = Mat4f::Identity;
viewProjection = proj * model;

 

Edited by Finalspace

Share this post


Link to post
Share on other sites

It depends on the engine.

The first pitfall to using pixels directly is that, of course, you can't easily change the resolution. However, this might not necessarily be true if you can just set the old pixels as "world units" with little hassle. So that's going to depend on the engine.

The second possible pitfall is that pixels are by definition integers; you can't have a real half-pixel, so you can't be at pixel position 4.2. This is of course imprecise. But it's trivial to just keep pixel positions as floating-point and round or truncate them at display time. It's just a more simplistic "world units" conversion at that point, really. The engine itself can even transparently handle it.

Personally, I prefer to define the game at a particular resolution and just use pixels for distances and movement and such, for two reasons:

  1. It's more simple to do it that way. It means there's no need to worry about whether I'm talking about the display or the game world; it's all the same.
  2. Changing the resolution would involve changing each individual image anyway, so making it easier to code that change would be of little consequence as I see it.

Of course, this is for 2-D games that use raster graphics. If you use vector graphics or 3-D graphics, I definitely see merit in not using pixels as a measurement; after all, you're not working with pixels in that case.

Share this post


Link to post
Share on other sites

Also consider fixed point (you can for example divide a pixel into 256 units).

If you are using pixel perfect sprites there is more of a reason to use some kind of pixel unit, whereas with pure 3d there isn't such a concept as a pixel, so the pixel may not make sense, but you still may choose to use integers.

There are benefits to both floats and ints. Although floats are often seen as the 'default choice' these days, integers are good for consistent behaviour, compression, packing, some people use them for units on large scale maps.

Share this post


Link to post
Share on other sites

@JulieMaru-chan 

3 hours ago, JulieMaru-chan said:

Personally, I prefer to define the game at a particular resolution and just use pixels for distances and movement and such

What about for things like collision detection and physics? Do pixels still work out okay for these kinds of calculations?

@lawnjelly

1 hour ago, lawnjelly said:

If you are using pixel perfect sprites there is more of a reason to use some kind of pixel unit

What about for a 2d game using vector graphics?

Share this post


Link to post
Share on other sites

Physics and collision response can work okay.  You'll likely end up using your own internal representations, but it won't hurt anything.

Also note that many games people think of as pixel based have higher precision internally.  For example, the original Super Mario Bros had 8 bits of sub-pixel data for position and speed, which enabled variations in running versus walking. Visually players saw the player moving a pixel or not, but internally there was more data.

That is, I think, what was being referred to earlier in the discussion as fixed-point data. 

What you see on the screen does not need to precisely match what the simulator is doing internally.  Games tend to keep far more information than is shown to the player, and tend to keep information at a higher precision than the player thinks about.

Share this post


Link to post
Share on other sites
8 hours ago, frob said:

That is, I think, what was being referred to earlier in the discussion as fixed-point data. 

Yes, on our 8/16/32/64 bit computers it makes far more sense to divide a pixel into 256 then say, 100, because you can use bitshifts, bitmasks etc. The fixed point can refer to the number of bits given to the fraction and the number to the whole number, instead of referring to the position of a decimal point.

http://x86asm.net/articles/fixed-point-arithmetic-and-tricks/

Share this post


Link to post
Share on other sites
8 hours ago, frob said:

What you see on the screen does not need to precisely match what the simulator is doing internally.  Games tend to keep far more information than is shown to the player, and tend to keep information at a higher precision than the player thinks about.

While rounding high precision positions to whole pixels for rendering purposes only should be the default strategy to deal with pixels (both for fixed point and for floating point) in some cases deliberately and selectively quantizing positions, times, velocities etc. in the game engine might make sense.

For example, suppose you need to execute a long jump to a ledge in a platformer or to run into a narrow opening in a racing or flying game: the player cannot tell whether his sprite is actually aligned with the pixel grid or slightly off, and therefore basing success or failure (through high precision collision detection) on unavailable information would be unfair.

Share this post


Link to post
Share on other sites
5 hours ago, LorenzoGatti said:

For example, suppose you need to execute a long jump to a ledge in a platformer or to run into a narrow opening in a racing or flying game: the player cannot tell whether his sprite is actually aligned with the pixel grid or slightly off, and therefore basing success or failure (through high precision collision detection) on unavailable information would be unfair.

That's not going to factor in to this realistically. No human can possibly be precise enough to be pixel-perfect on a consistent basis anyway. It might even literally be impossible if the speed is too high. So I wouldn't worry about an edge case such as this.

Share this post


Link to post
Share on other sites

The edge case of caring for pixel-perfect positioning is fairly common in old, low resolution games where 1 pixel is actually a large distance and 1 frame is a long time. When I refer to racing or flying games I mean things like aiming for ramps in Micro Machines or bullet gaps in Space Invaders, not forgiving 3D games.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
  • Advertisement
  • Popular Tags

  • Similar Content

    • By MarcusAseth
      Hi guys, I'm having a problem rendering with DWrite, and I don't understand why, can you help me figure it out?
      As you can see in the image below, if you look carefully you'll notice that the top of R8 is cut (missing 1 row of pixels), the bottom of R11 is cut again, the 4 in R14 is rendered weird compared to the 4 in R4 and so on, if you look closely you'll spot more yourself.
      I can't figure out why 😕
      Under the image I'll also leave the code, in case I'm doing something wrong like with type conversion or stuff. Any help is much appreciated

      #include "GBAEmulator_PCH.h" #include "Disassembler.h" #include "GBAEmulator.h" Disassembler::Disassembler(LONG width, LONG height, HINSTANCE hInstance, GBAEmulator* emuInstance) : D2DWindowBase(width, height, hInstance, emuInstance), m_background(0.156f, 0.087f, 0.16f, 1.f), m_textFormat{ nullptr } { //Init Window std::string className = "Disassembler"; std::string windowName = "Disassembler"; WNDCLASSEX clientClass{}; clientClass.cbSize = sizeof(WNDCLASSEX); clientClass.style = CS_HREDRAW | CS_VREDRAW; clientClass.lpfnWndProc = GBAEmulator::DisassemblerWinProc; clientClass.hInstance = m_hInstance; //clientClass.hIcon =; TODO: Add Icon clientClass.hCursor = LoadCursor(m_hInstance, IDC_ARROW); clientClass.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1); clientClass.lpszClassName = className.c_str(); //clientClass.hIconSm =; TODO: Add Icon DWORD windowStyle = WS_VISIBLE | WS_CAPTION | WS_MINIMIZEBOX | WS_TABSTOP | WS_SYSMENU; m_isValid = InitWindow(windowName, clientClass, windowStyle, false); //Init DWrite if (m_isValid) m_isValid = InitDWrite(); std::vector<std::wstring> tempEntries{ L"PC: ", L"R0: ", L"R1: ", L"R2: ", L"R3: ", L"R4: ", L"R5: ", L"R6: ", L"R7: ", L"R8: ", L"R9: ", L"R10: ", L"R11: ", L"R12: ", L"R13: ", L"R14: ", L"R15: ", L"R16: " }; std::wstring value = L"-UNDEFINED-"; FLOAT left{}, top{}, right{ 300.f }, bottom{ 50.f }; for (auto& s : tempEntries) { m_entries.emplace_back(TextEntry{ s, value, D2D1_RECT_F{ left, top, right, bottom} }); top += 30.f; bottom += 30.f; } } bool Disassembler::InitDWrite() { //Set Text Format HRESULT hr; hr = m_DWriteFactory->CreateTextFormat( L"consolas", NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, 22.f, L"en-US", &m_textFormat ); if (FAILED(hr)) { MessageBox(NULL, "Failed to create TextFormat", "Error", MB_OK); return false; } //Set Colors m_renderTarget->CreateSolidColorBrush( D2D1::ColorF(D2D1::ColorF::SkyBlue), &m_fillBrush1 ); m_renderTarget->CreateSolidColorBrush( D2D1::ColorF(D2D1::ColorF::Crimson), &m_fillBrush2 ); return true; } Disassembler::~Disassembler() { DestroyWindow(m_hwnd); if (m_textFormat) m_textFormat->Release(); if (m_fillBrush1) m_fillBrush1->Release(); if (m_fillBrush2) m_fillBrush2->Release(); } void Disassembler::Updade(float deltaTime) { } void Disassembler::Draw() { m_renderTarget->BeginDraw(); m_renderTarget->Clear(m_background); for (auto& entry : m_entries) { DrawEntryWithShadow(entry); } m_renderTarget->EndDraw(); } void Disassembler::DrawEntryWithShadow(const TextEntry& entry) { //shadow offset D2D1_RECT_F shadowPos = entry.position; shadowPos.top += 1.05f; shadowPos.left -= 0.95f; //draw text DrawEntry(entry.text, shadowPos, m_fillBrush2); DrawEntry(entry.text, entry.position, m_fillBrush1); D2D1_RECT_F valuePos = entry.position; FLOAT valueOffset = 50.f; valuePos.left += valueOffset; valuePos.right += valueOffset; shadowPos.left += valueOffset; shadowPos.right += valueOffset; //draw value DrawEntry(entry.value, shadowPos, m_fillBrush2); DrawEntry(entry.value, valuePos, m_fillBrush1); } void Disassembler::DrawEntry(const std::wstring& text, const D2D1_RECT_F& pos, ID2D1SolidColorBrush* brush) { m_renderTarget->DrawTextA( text.c_str(), static_cast<UINT>(text.size()), m_textFormat, pos, brush, D2D1_DRAW_TEXT_OPTIONS_NONE ); }  
    • By Catalin Danciu
      Hello,
      In the hopes that my thread is not off-topic or offensive in any way, I dare to ask the following "noob" question:
      what would be the correct way to create sprite animations from 2D *.bmp files?
      I have for reference the 2001 game  Desperados:Wanted Dead or Alive.
      with the help of some tools i found , I was able to extract files containing what seems to be animation frames and frame shadow masks for animating a horse.
      Attached are the archived assets.
      My goal is to recreate the demo level of the game using Unity, for educational purposes.
      I have started by loading the background map layer (also a large bmp file), and next step is to load a 2d character object and animate on the perspective.
       
      Horse_Brown.rar
    • By Alberto Muratore
      Hello, my name is Alberto Muratore and I'm a young game developer specialized in programming.

      Last summer I finished working on Abstract Arena, my first completed project published on Steam. During the development, lasted more than 1 year, I created every aspect of the game except for the audio sector. I previoulsy joined small competitions and had collaborations within the amateur scene, since I started having fun with game development when I was a kid. In the recent months I also started writing videogames reviews for a english-italian website about indie games.

      Abstract Arena Steam page: http://store.steampowered.com/app/678230/Abstract_Arena/
      Abstract Arena website: http://www.abstractarena.com/

          

      I'm currently offering my skills as freelancer in the role of programmer: what I'm searching for is a project that only lacks of the coding part. I'm very good at using the GameMaker: Studio engine, and I already own a license to export on Android platform. I can write code for any genre of 2D games, and I already have experience with the peculiarities of the Android platform (multiple touch controls, accelerometer). I will be able to start working full time only during September, so be aware of that.

      The plan is the following:
      1 - you have an idea about your next project (2D game of any kind, for Windows and/or Android platform),
      2 - you (or your team) create all of the graphics and audio resources,
      3 - I write the whole code for the game (gameplay, menus and anything within the game) putting everything togheter [during September],
      4 - if you like my work you can choose how much to pay for it, and you (or your team) keep the rights to sell the game without sharing any percentage with me.

      Thank you for reading my announcement
      If you have any question, please write me at the following address: albertomurat@gmail.com
    • By N Drew
      I am working on a 2D SideScroller game in my own made game engine using SFML and C++.I am searching for 2D artists,especially pixel artist for making and animating characters,backgrounds and other props that can be made in any Drawing Program.The artist will become part of the team of Hammer Studios and he got a part of the Revenue Sharing.If you are interested send me a mail at:ghiurcutaandrei@gmail.com .If you are not an artist but you want to be a part of our Team,Soon we will be recruiting an C++ AI programmers that worked in SFML/OpenGL.
      We work together using Discord.

    • By MelonCollie
      Hi Everyone,

      My name is Bob Pepek, I'm an audio post production engineer for film / TV. I'm looking to try my hand at Game Audio. Did you know that great sound design is rarely ever noticed but is always felt by an audience? That's where I can help.
      I've worked as the dialogue editor and sound designer for Sprout / NBC's Saturday morning cartoon Astroblast. I sound design for the web-series Channelate (hosted by Explosm / Cyanide and Happiness). Though most notably work as the go-to sound designer for the hundreds of the LEGO Star Wars / Marvel / Ninjago product animations and mini-movies.

      My past sound design clients include NBC, ESPN, LucasArts, LEGO, Sprout Network, Disney, Sci-Fi Network, Walmart,  Sesame Street, The list goes on and on! Below I've included a link to my demo reel as well as other projects I have done sound design for:

      Sound Design Reel
      https://vimeo.com/214093302

      Other Work (Channelate, Explainer Vids, Ads)
      meloncollieproductions.com/work/

      360 Sound Designs (LEGO Star Wars / Avengers: Infinity War)
      https://www.youtube.com/watch?v=-Gdss2fANPQ
      https://www.youtube.com/watch?v=mj7Leyaq780
      https://www.youtube.com/watch?v=LJzPu_tw6eY

      Recent Film Work:
      https://www.youtube.com/watch?v=hbFXobIMAgM
      https://vimeo.com/273203490
      https://vimeo.com/229448486

      If you're looking for a sound designer I'd love to help out! Feel free to reach out at bobpepek@gmail.com. 

      Cheers,
      Bob
    • By Ds ds
      Hi, my name is Andres, I'm a programmer with a technician degree and a Diploma in C#, looking for a project in Unity to start my career in game development. I don't do it for a paid but a recognition and start a portfolio, preferably a 2D game. Thanks for read, have a nice day. 
       
    • By Doommy
      If someone could assist me through this I would be really grateful. I'm using SharpDX/C#/WinForms but I think this could more apply to directx in general.
      I'm very new to graphics programming and I'm really just trying to do something as simple as displaying a rectangle to the screen.
      Here is my issue:
      I have the below code:
      ----------------------------------------------------------
       var desc = new SwapChainDescription()
                  {
                      BufferCount         = 1,
                      ModeDescription     = new ModeDescription(1024, 768, new Rational(60, 1), Format.R8G8B8A8_UNorm),
                      IsWindowed          = false,
                      OutputHandle        = form.Handle,
                      SampleDescription   = new SampleDescription(1, 0),
                      SwapEffect          = SwapEffect.Discard,
                      Usage               = Usage.RenderTargetOutput
                  };
      I'm not sure if the window is loading in full screen. Actually to make it go full screen I actually have to set the forms property to: this.WindowState        = FormWindowState.Maximized; but that only seems lke Im using a C# code to maximize the form. For instance if I don't set the form to maximize, the form loads at the original size if IsWindowed is set to false. I recall with directx programing using dx7, when I set full screen you could actually see what looked like a display resolution change. I'm not seeing that. It pretty much looks like the form is loaded at the same size as the screen and not the value I provide in modeDescription. This is not what I want as well because I want to set the display to 1024x768 to avoid stretching of my graphics in wide screens.
      Can someone help me make sense of this please.
    • By HomeBrewArcana
      Hey All,
      I'm looking to get into the gaming industry. I've skirted around the idea for a long time, always thinking that I couldn't do it. I've finally decided to take the plunge.
       
      My question is whether it's worth going to school for game design/coding etc. I've been writing content for paper games for a while, and have a good idea of story and some basic design. But I have next to no technical know how. 
       
      My instinct is that such things can be learned with a lot of practice, video tutorials, and more practice. I've also heard that a degree is not really that important, since you get hired based on your portfolio/prototypes. Why not just make the games?
      But won't a degree help with contacts and mentoring--I'm not a great networker.
       
      Of course, it'll plunge me into more debt, but...
      If anyone has advice, let me know. Also any idea of a program to start with: Game Maker, Unity, Godot, Construct, Stencyl--I've heard good things about them all, so much so that I don't know which would be best to start with!
       
      Thanks
    • By bartekm777
      Hello
      About me
      Lvl 28   Programmer (day job: non-gamedev-programmer, making games as a hobby for about 2 years) Some vector art experience - tried to make some assets on my own using vector software and scripts   Some design experience (designing my own games ) About game
      Turn-based fantasy rpg inspired by games like Heroes 3 (also WoG mod), NEO Scavenger, Battle Brothers I would like to create easy to use editor for creating custom scenarios (similar to the one from Heroes 3) World and story are clean slate, I did some drafts but I'm not good at it so it's possibly subject to change I decided to create graphics using vector software + scripts to make it faster (rpg's tend to have lots of assets), also it's more precise and easier to create tileable graphics (for example: rivers, paths) No sound/music work has been done yet Who do I look for?
      Definitely someone with 2d art skills  I would like to focus more on programming 2D animator (skletal animations are preferred) Additional programmer could make development faster Someone for creating sounds/music/both It's a hobby project, I work on it in my free time. In case the project make it to the finish line and get shipped  - I can offer rev-share  
      Below should be few screens of what I already did (about 2 months of work) - some graphics, editor prototype screenshot and game prototype screenshot




    • By Luca Falco
      https://www.youtube.com/watch?v=UMoc52DEoC8     ABOUT THE GAME: Room54 is a first-person Horror/adventure  Videogame for pc,mac and linux users. the game is currently under development by a very small team, we put so much effort in this project and we are keep doing our best for that we are going to launch a kickstarter campaing in order to reach our ideal budget to complete the project, we hope the GameDev community can help us a lot                      STORY:   Daniel is a family father like many other, one day he decide with your wife and his daughter  to spend her winter holidays at their mountain house that they have recently buy in  mountain ,a  wonderful place surrounded by the nature of the woods,  Completely far away from the caotic city life. During their holidays Daniel and his family will understand that they are not welcome there and they will discover an  hided and disturbing part of the valley that they have never seen before                       GAMEPLAY:   You will play as Daniel, a father that will try to save his family, your gameplay will be focused on discovering secrets places around valley,investigating and trying to survive, you will find object that will help you solve enigma and to stay alive. The immersive audio and  environment will make you feel constantly follow by an high anxiety dose  during the game.                         SOCIAL PAGES:     Follow us to get the latest development news and insights     IndieDB:     http://www.indiedb.com/games/room54   Twitter:       https://twitter.com/Room54Thegame   facebook:   https://www.facebook.com/Room54/
  • Advertisement
  • Popular Now

  • Forum Statistics

    • Total Topics
      631379
    • Total Posts
      2999666
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!