• 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.

Zipster

Members
  • Content count

    7151
  • Joined

  • Last visited

Community Reputation

2358 Excellent

About Zipster

  • Rank
    GDNet+
  1. It's entirely acceptable (and virtually necessary) to maintain multiple models and representations of your game world for different gameplay or engine components that need to see and interact with the world in different ways. For instance, a list of tiles works well for field placement (stone, grass, etc.) and general pathfinding, while continuous 2D coordinates work best for collision, rendering, physics, etc. As long they're kept in sync, or the data you need can be easily derived, everything is happy. Instead of trying to bend your logic to work around the limitations of any particular view, you simply have multiple views that you keep in sync. It moves the burden from your game code to your "sync" code, which is another problem that has to be solved, but typically this code can be written in an abstract, non-game-specific manner that makes it highly reusable. Take a graphics library as an example. It doesn't know anything about your "game", it only sees the world as a hierarchical scene comprised of nodes, meshes, lights, etc. It's the job of your game engine to build this scene based on the specifics of your game and keep it updated as the game world changes (update transforms, visibility, etc.). This is some extra work, however the process of converting "game objects" to "graphics objects" can usually be abstracted and generalized to a point where you can reuse the process for any number of games, truly limiting the amount of rework you have to do per-game to actual, game-specific logic.
  2. It sounds to me as though the grid is really only used to place tiles and discretize player movement. Other than that, everything else can be done in continuous 2D coordinates. In other words, the grid is used as a constraint, but not necessarily as an actual model. For instance, when the player clicks on position (x,y), you determine that location to be inside tile (m,n), and translate the action to "move to the center of (m,n)". When you create the level and say that a grass tile exists at tile (a,b), that can be translated to position (z,w) based on the size of tiles. However the grid in these cases is really only used as a tool to guide level creation and constrain movement. The rest of your logic doesn't have to know this grid exists at all, and can just operate in traditional 2D space.
  3. Bounding boxes seem reasonable to me. I wouldn't try and automate the process though, since this style of game relies pretty heavily on deliberate placement and selection of the camera at any given time. Since it's just a box, I don't see any reason not to just use Blender to place them. I'm not familiar with that tool in particular, so I can't comment on how you'd tag the boxes with additional information so the engine knows they're camera triggers (so they shouldn't be rendered). But I assume something like that is possible... One thing you want to watch out for however are the effects of hysteresis. In this case, that would occur if the player is right on the border of two adjacent camera boundaries and moves slightly back and forth across the boundary, causing the camera to jump back and forth in a jarring and jittery fashion. To get around this, you would make your bounding boxes overlap by a certain amount, and only change the camera when the player leaves a bounding box, as opposed to just when they enter a bounding box. This creates a spatial buffer where the current camera "sticks" a little longer.
  4. In this case, you'd only ever save one of these three for turn N (depending on the precise moment save is pressed during the turn): Turn = N, X = 10 Turn = N, X = 10, A = click on tile 20 Turn = N+1, X = 20 Note that X is either 10 or 20, and that the change is atomic. The fact that X appears to continually transform between 10 to 20 is just to provide visual feedback to the player, but isn't relevant to the logical game state. If you were making a chess game and a piece was moved from A1 to A3, you might see the piece move over A2 as part of its animation, but you'd never actually save that position. You could just as easily remove all animation, have pieces teleport instantaneously to their final position, and still have a functioning game. But that wouldn't be nearly as interesting or fun
  5. I find it helpful to think of a turn-based game from a functional perspective. You start with game state X, apply player input A using some game logic, and end up with game state Y. X is always known at any given time, but A is something you have to wait for. In other words: Y = gameLogic(X, A) If the player saves before providing any input, then all you have is X. In that case, just save X. If the player saves after providing A, then you have X and A. Save X and A, even if game logic is currently running. Once the game logic is complete and you have Y, then Y for turn N immediately becomes X for turn N+1. Rinse and repeat. Note that this applies generally to any transition between valid game states, not just "turns" (however they may be defined by your game). If you load a game that only has X, then just restore that game state and continue waiting for player input A. If you load a game with both X and A, then you restore the game state and apply input A as you would normally. As you can see, it doesn't matter when the player saves, because this process is invariant on how much time it takes to perform the game logic and produce Y. You always save X, and sometimes A if it's available.
  6. * looks back to see when he joined.... 11 Mar 2000 Yikes, I'm definitely old then :)
  7. A good rule of thumb to follow when working with locks is to try and minimize their scope as much as possible. While putting a lock at the top of the update may technically work, you're spending way more time in the lock than you really need to and potentially increasing contention. From what I can tell, the only shared state in the update is sourceIDs (and possibly soundStreams but I don't know enough about your audio system to say for sure). Instead of locking the entire update, make a copy of the sourceIDs array/vector at the top of the update from within a lock scope and use that instead. When you clear the source, instead of clearing it right away, add it to a 'to-be-cleared' list and remove them all at once at the end of the update (again from inside the lock). This limits the scope of the lock to when you actually need to interact with the shared state, and allows the rest of the update method to take as long as it needs to without impacting the performance of other systems.
  8. Why make the on-disk layouts exactly match the in-memory layouts? What are you gaining by bulk-copying entire structures instead of individual fields? Why place the burden of managing and maintaining the subtleties of portability and implementation-defined behavior (which are easy to overlook and often difficult to debug) on the developer when they can be largely avoided? If you keep your on-disk layouts compact and express all data in terms of simple primitive types, then you can copy/assign one field at a time and the compiler will generate the correct code for you in all cases. That being said, once you're at a point you can profile and determine if this is an actual bottleneck, then you can go back to exposing these responsibilities to the developer if the performance improvements are worth it. But I wouldn't start down this road initially, when you don't have any actual performance data to support the up-front developer cost and additional overhead. For dealing with data schema that could be variable at run-time for whatever reason (i.e. savegames), I've found it's largely an issue of finding and using an appropriate model. JSON for instance works quite well for this because you can easily query and manipulate in-memory objects and utilize that meta-information to transform the data how your please, especially when working from a holistic view of the data. I've had to work with serialization systems that tried to manage versioned data using static structures and limited/partial access to the entire dataset, and it was an absolute nightmare.
  9. Unity

    I don't disagree that there are any number of implementations, but without providing any details it's difficult to analyze further and discuss specific pros and cons. I've often found that the process of translating a concept into an implementation itself can give you a wealth of insight, simply because a tangible representation of an idea can shed light on hidden flaws or benefits that you didn't even realize existed before you had something physical to examine and tinker with. That's partly why I posted basic, high-level implementation details for (my interpretation of) your idea, to at least provide a reference that others could discuss, build upon, tear apart, etc., in concrete form. That, and because your post validated some of my own musings, so thanks!
  10. Unity

    I believe I get what you're going for, if only because I've had similar musings recently  :D If I may be so bold, perhaps the reason why you're not getting the responses you're hoping for is because you're focused on explaining and demonstrating the mechanics of something, but haven't really described what that "something" actually is or why anyone would want to use it? You've shown what is it to invert the dependencies on objects into dependencies on data, but I think you've stopped short of answering the next logical question, which is "who owns the data source"? And if this example is extended to all game data, then certainly this data has to exist in an organized fashion somewhere. So the next question would be, "what does this system or architecture for storing and manipulating data look like"? In my mind, what's essentially happening is that you're divorcing the data model from the object model, which allows the two models to exist independently but function cooperatively. Going back to the controller/camera example, conventional wisdom would dictate that each camera object own its own position, and anyone who wants to update or retrieve the position would have to go through the camera. This forces the structure of your data to follow the structure of your objects, which might not always be ideal. But by using a "data source" instead, the camera no longer owns its position and instead just queries some external source, which is also happens to be updated by the camera controller from time to time. In this sense, neither really own the data. You just have objects that manipulate some shared state, to which we've applied the semantic meaning of "camera position". My own thoughts on the subject lead me to envision some sort of simple hierarchy, where each data "node" can either be an instance of type T, an array of type T, or an association (dictionary) of string to type T. Think JSON, but with the ability for T to also be a pointer to others nodes in the model (for the in-memory representation). The object model can then be created separately, but still reference or "bind" itself to the different parts of the data model. Provide the camera controller with a read/write interface to the position data, and the camera a read-only interface to the position data. If multiple observers want to inspect the position, they too can get read-only interfaces to the position data. If another camera controller comes along and wants a write interface to the position, then the ownership semantics can be handled centrally and uniformly as a feature of the data model. The same goes with push/pull and events/polling. Allow the model to trigger events or callbacks when data changes, and/or for a timestamp or a change flag to be set, and both methods just become opt-in features that allow objects to decide how they want to interact with the model. Then it becomes clearer how such an architecture could provide you with all the advantages you mentioned in your first post, because everything only has to deal with a single, universal model that's designed specifically around managing data ownership and relationships. This makes replication, serialization, debugging, replays, etc. easier because object relationships and state that's only applicable to the current execution context can be ignored completely. Hopefully this is somewhat along the lines of what you've been attempting to explain?
  11.   Each asset needs a unique ID. As it turns out, the full path to the asset not only tells you its location, but can also serve as this unique ID. But if you change any part of this path, you also change the ID, and anything referencing it has to be fixed up. There aren't any shortcuts or solutions that avoid this problem, since it's one of semantics and not engineering, but there are ways to make the process easier (tools, scripts, find/replace, etc.). You can also do what Hodgman does and flatten the asset hierarchy when they're compiled. I've worked on engines that do this and I have mixed feelings about it. Since every filename has to be unique, what usually ends up happening is the artists develop a convention for naming files that "encodes" the same information that would have been in the path, into the filename. For example, what would have been level1/concrete.tga and level2/concrete.tga is now level1/level1_concrete.tga and level2/level2_concrete.tga (or just level1_concrete.tga and level2_concrete.tga).  If someone renames a level, they're not just going to change the path (i.e. level3/level1_concrete.tga) and call it a day, violating their own naming conventions and confusing everyone. They're also going to change the filename, because it contains identifying information, and you're back at square one having to fix up references. Over the years, I've come to prefer an approach that takes a step back and allows the filesystem to function as everyone already knows and expects one to, without the engine jumping in and applying its own special rules and restrictions. As I mentioned earlier, it all comes down to the identification of an asset. If you encode the identity of a level into an asset's identity, to distinguish it from assets of a similar purpose belonging to other levels, then when the identity of the level changes, the identity of the asset (and thus references) must change as well. It doesn't matter whether you've encoded this information in the path or the filename or anywhere else. So really, either approach works just as well. I just cringe when I see foo/foo_ground.tga and bar/bar_ground.tga everywhere  :)
  12. Allow me to clarify: As the game developer, you're providing the base set of assets available to all user content. So it's risky to remove any of the base assets, because there could be any number of published user mods that depend on the removed content, and they would break. If the base game needs to fix or change an asset, you're better of creating a new version and allowing the old one to remain so user mods don't break outright. If user mods record which version of the game they're compatible with, then you can easily display a warning to the user when the game is updated but a mod hasn't been republished and could be using old assets. User content on the other hand doesn't generally depend on other user content (unless such a dependency is explicitly stated), so they can usually remove/rename assets without much fear of breakage. Since they own the content, they can also fix up any references. You as the developer aren't responsible for this.
  13. Changing asset names (which is essentially a remove/add as far as any versioning scheme is concerned) is prone to breakage regardless of the loading approach you use. It's often much better to just create a new asset and deprecate the old one, rather than remove anything. This is especially true if there's user content you don't necessarily control.
  14. Instead of explicit mount points, it might be better to use absolute paths directly in the packages and assume they're all mounted at the root. This allows user-defined content to unambiguously reference both its own assets and external assets (i.e. provided by other packages and/or the base game) without requiring any additional configuration.
  15. I've found unity builds to provide the most improvement to build times, since they tackle the biggest time sink (I/O) head-on by simply eliminating those redundant disk operations. Of course an SSD helps too, but the absence of I/O is always fastest ;) IncrediBuild also helps a bit, but since it addresses build times from the CPU processing side, it really relies on having lots of idle agents sitting around to handle your requests. Even then, it maxes out somewhere around 20 cores per build (IIRC). However, *combining* it with unity builds is definitely a winning combination. We were once able to take a codebase that built in 90 minutes (vanilla Visual Studio build) down to 8 minutes. As a matter of fact, the full rebuild was sometimes faster than the incremental build...