• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.


  • Content count

  • Joined

  • Last visited

Community Reputation

1468 Excellent

About Tispe

  • Rank
    Advanced Member
  1.   I can see that it is slow doing random array access on entities using indices to update data in response to unpredictable input. But there is only one way to layout data in memory at one time without duplication, and it seems reasonable to me that the data layout should best suit the heaviest workload for the most gains in terms performance(fps).   I thought that when doing heavy CPU calculations such as physics/collision, it is preferable to streamline dataflow from memory to cpu cores/threads. Meaning we want to structure and pack data only relevant for those operations as closely and as contiguous as possible, am I missing something?
  2. The unique ID is supposed to be global for all entities, not just players. Over a network in client-server-client situations IDs would be consistent.   If I reserve the ID #42 for "m_Players[42]" then what would then happen if I want to to something with "m_SomeObjects[42]", for example: m_Players[13]->shoot(42,9000)? Should someObjects[42] be hit or should "m_Players[42]"? I would between different types of entities have to translate first from local ID(index) to a global ID then back down to the appropiate entity container.   Another situation for example is when a large number of players or entities are spawned, such that you end up with IDs with values in the thousands. Then later on most of them could be cleared away leaving behind some entities with large ID values. I'm thinking I could be making more problems then I solve.
  3. Hello   I want to know more about how to effectively index players by ID.   Suppose I have a vector that store all players in one place (yes I can break them apart for ECS but for the purpose of the question I have them together): struct player { unsigned int ID; char name[32]; float xpos, ypos, zpos; float xvel, yvel, zvel; int health; // more to come }; std::vector<player> m_Players;  Each player has a unique ID of type unsigned int which can be anything. If there are 6 players and one of them has for some reason has the highest ID value: 9999, then I don't want to have an allocated array of players of size 9999 where 9993 of them are unused to address them directly by ID(myPlayer = m_Players[9999]). I want a array of players of size 6, and I want an array of indices mapping IDs to their position in the player array, such that I can access each player by ID. The reason I don't directly want to use a std::map<id,player> is that I want to effectively traverse the player array in another places. std::unordered_map<unsigned int, unsigned int> m_Index; bool update(const unsigned long ID, float xvel, float yvel, float zvel) { auto search = m_Index.find(ID); if (search == m_Index.end()) return false; auto index = search->second; if(index >= m_Players.size()) return false; auto& myPlayer = m_Players.at(index); if(ID != myPlayer.ID) return false; myPlayer.xvel = xvel; myPlayer.yvel = yvel; myPlayer.zvel = zvel; return true; } void advance(const float timeDelta) { for(auto& myPlayer : m_Players) { myPlayer.xpos += xvel*timeDelta; myPlayer.ypos += yvel*timeDelta; myPlayer.zpos += zvel*timeDelta; } } /* void advance_parallel(const float timeDelta) { parallel_for(auto& myPlayer : m_Players) { myPlayer.xpos += xvel*timeDelta; myPlayer.ypos += yvel*timeDelta; myPlayer.zpos += zvel*timeDelta; } } */  Now, different players can be in different situations, for example, some players might be culled away, some players might be on differnt teams and so on. So I want to know if index maps could be suitable for these purposes: std::unordered_map<unsigned int, unsigned int> m_Index_inactivePlayers; std::unordered_map<unsigned int, unsigned int> m_Index_renderablePlayers; std::unordered_map<unsigned int, unsigned int> m_Index_redTeamPlayers; std::unordered_map<unsigned int, unsigned int> m_Index_blueTeamPlayers; void redTeamHealthBoost(int health) { for(auto& [ID, index] : m_Index_redTeamPlayers) { if(index >= m_Players.size()) continue; auto& myPlayer = m_Players.at(index); if(ID != myPlayer.ID) continue; myPlayer.health += health; } }  Any thoughts, input or comments is much appreciated.
  4. I think I am close to finding what I am looking for. I have to fiddle public, protected and private inheritance to get messages to be accessible after assignment. class WindowBase { public: std::vector<std::tuple<UINT, WPARAM, LPARAM>> m_messages; WindowBase& operator<<=(WindowBase& other) { if (this != &other) { std::swap(m_messages, other.m_messages); } return *this; } }; class WindowMessages : protected WindowBase { public: WindowMessages& operator<<=(WindowMessages& other) { if (this != &other) { std::swap(m_messages, other.m_messages); } return *this; } }; class Window : public WindowMessages { public: Window(); ~Window(); bool initialize(HINSTANCE hInstance); bool postMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); private: HWND m_hWnd = nullptr; HINSTANCE m_hInstance = nullptr; WNDCLASSEX m_wc; }; Window myWindow; WindowMessages messages; messages <<= myWindow;
  5. Hear me out, could I solve this using private inheritance and move assignment overloaded with std::swap? class WindowMessages { public: std::vector<std::tuple<HWND, UINT, WPARAM, LPARAM>> m_windowMessages; WindowMessages& operator=(WindowMessages&& other) { if (this != &other) { std::swap(m_windowMessages, other.m_windowMessages); } return *this; } } class Window : private WindowMessages { public: Window(); ~Window(); bool initialize(HINSTANCE hInstance); // std::vector<std::tuple<HWND, UINT, WPARAM, LPARAM>> moveMessages(); // replaced with move assigment operator in parent bool postMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); private: bool filterMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); HWND m_hWnd = nullptr; HINSTANCE m_hInstance = nullptr; WNDCLASSEX m_wc; }; bool Application::processWindowMessages() { m_windowMessages = m_Window; // WindowMessages messages = m_Window; for (auto& windowMessage : m_windowMessages) { UINT message = std::get<0>(windowMessage); WPARAM wParam = std::get<1>(windowMessage); LPARAM lParam = std::get<2>(windowMessage); switch (message) { //... // Handle messages //... } } return true; }
  6.   Yes, by design. I coded it that way to make it hard for object B to fail because of object A.     C++ provide tools to prevent that, and C++ continues to evolve with new features for this purpose.   It steals the representation of m_messages, leaving m_messages unvalid. I need to swap representations.   If possible, somehow overload the move assignment operator for objectA messages& operator=(objectA&& other) { std::swap(m_messages, other.m_messages); } auto messages = ObjectA; ObjectB += messages; Or perhaps if possible overloading the stream << operator with move semantics. auto result = ObjectC << ObjectB << ObjectA;
  7.   http://puu.sh/sW9MJ/7b018f1c9f.mp4     I have not done testing myself, if there could be situations where tuple would perform better as the post from stackoverflow claims. I will admit I took it at face value.   But it points out much of the problems I have when it comes to programming, which is reading/perceiving conflicting information from different sources. When I read a tutorial and then use that to code my own program I sometimes run into problems. And often the solution does not seem right as I begin to recall information I have read previously. I don't find it very motivating to spend most of my time coding "tricks" just to get things working. So I seek out designs where problems become very localized. I really don't want to worry about object A being in a bad state so that object B causes undefined behaviour.   I don't think users set out to abuse code, they want it working and not breaking. If the string in your example is to be shared with outside code, return a shared pointer.
  8.   So why do we need things private when we can just put a warning label "don't touch" on it? I thought encapsulation  was more about making it hard/impossible to use the class incorrectly. 
  9.     Yes? std::unique_ptr<Thing> p_thingy = std::make_unique<Thing>(); auto refString = thingy->getStr(); //.. // p_thingy is destroyed //.. std::cout << refString.at(i) // oopsie, thingy no longer exist!
  10.   wiki - Encapsulation is the hiding of information to ensure that data structures and operators are used as intended     Tuple is faster than a default struct http://stackoverflow.com/a/40308910, I can take out members that I don't need from MSG, it has move semantics from STL, and I can inline the tuple layout in code.
  11. The above code solve for encapsulation as nothing will hold a reference or pointer to private members. So I can guarantee no dangling pointers or references. I avoid reallocations by moving the vector in and out. The only problem I can think of with that code is a caller might move in a vector that is already gutted from a previous move. I would love to give what I have now a cosmetic makeover and extend it for multiple vectors.
  12.   Look at this code, encapsulation is maintained, no reallocations, no pointers, no references, no consts, no nothing. But it kinda smells, and what if I want swap multiple vectors, I need to pack a tuple.  bool Application::processWindowMessages() { // Temporary relinquish ownership of vector by passing it by rvalue to Window m_windowMessages = m_Window->swapMessages(std::move(m_windowMessages)); for (auto& windowMessage : m_windowMessages) { UINT message = std::get<0>(windowMessage); WPARAM wParam = std::get<1>(windowMessage); LPARAM lParam = std::get<2>(windowMessage); switch (message) { //... // Handle messages //... } } return true } std::vector<std::tuple<UINT, WPARAM, LPARAM>>& Window::swapMessages(std::vector<std::tuple<UINT, WPARAM, LPARAM>>&& messages) { std::swap(messages, m_messages); m_messages.resize(0); return messages; // return by rvalue, giving back ownership }
  13. I can't really see that there is a difference between "information transfer and object transfer". Afaik move semantics are for transferring ownership to ensure proper deletion of the aquired resources that is being moved. Why wouldn't the move semantic be equally valid for both move construction (for a new object) and move assignment (for an existing object)? It has to be true that it is the ownership of resources that is moved, or better put; the responsibility to release resources is moved. If object A gives object B something using move semantics, object A is giving object B not only the resource, but also the responsibility to release the resource.         So ensuring basic encapsulation is wrong in this case? When a member value is private, is it not expected that only the object gets to fiddle with it?       And anything less then move is to be avoided according to Bjarne Stroustrup.
  14.       I want to transfer ownership of data from one part of the program to another. That is what move semantics is about. I don't want one object to own data while another object uses the data. I want decoupled code. I don't plan on making things unnecessary. Object A retrives data from API, ownsership of data is moved from object A to object B, object B processes the data, ownership of processed data is moved from object B to object C, object C writes data to API. Objects A, B and C does not need to know about eachother. It is the application that take handles to data to move it from one object to another as information progresses through the game. And to accomplish that I asked "how do I properly return a private class member vector using move semantics".