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

comfy chair

  • Content count

  • Joined

  • Last visited

Community Reputation

847 Good

About comfy chair

  • Rank
  1.         /// <summary>         /// the coordinate map that tells what region(color!) a subtile belongs to         /// </summary>         public ushort[][] AllSubtiles; This array uses the most memory. It covers the whole map and can be about 750 * 750 in size. That's about 1 MB. Then there is some additional data also, and each faction has 3-6 of these region maps... I am thinking now about subdividing the map into square sections, about half a screen wide. The flood fill would stop at the border between sections. Then, the region maps that belong to factions could disregard most of the sections, and just leave them empty. When I create the graph, I could link up with the underlying, full region map whenever there is a hole/empty section.  
  2. In my game, I create high-level maps at runtime that I use for answering distance and accessibility queries. They are not used for pathfinding. I call them "region maps". The region maps cover the whole playfield.   The region maps are made by flood filling the terrain map grid with a small cutoff limit so the map consists of many small regions. Connections between neighbouring regions are stored in a graph and used for lookup.   There is a general region map for the base terrain that can be used by all agents. In addition, each faction has a few region maps which are made from the terrain data with threat data overlaid.   In total, this means that each faction (a single independent agent is also a faction) has a memory footprint of 7 MB.   How can I make the factions' region maps smaller. Most of the information in them is similar to the underlying terrain anyway. It is only the nearby threats that the factions know about which make their region maps different.
  3. With the changes to the struct (uint instead of long, vectors instead of Matrix) I got down to 28 MB. That's good enough for now I think.    Thanks for the help.
  4. Yes, I should of course do that when possible. The build time is long enough already.
  5. Yes, I already made sure that I use the same interpolation method in preprocessing and at runtime. SLERP was necessary to use because LERP sometimes gave crazy errors.   I asked the animator if we ever used scaling, the answer was "don't know". But now I think it will probably be needed at some point, if it isn't being used already.
  6. So I need to choose if I want to support scaling, or not. Actually, I don't think I will ever need it.
  7.   I eliminated these frames also and I am now down to 44 MB. Perhaps I can compress it a bit further by increasing the comparison threshold without hurting the playback quality.
  8. Alright then. But L. Spiro used the same term... I am trying to replace this, inside BoneKeyFrame: /// <summary> /// The transform for the keyframe. /// </summary> public readonly Matrix Transform; with a custom class/struct. It should contain an optional translation vector, optional scale vector (when different from 1) and a rotation quaternion.  How can I design it so it becomes as compact as possible...  The point is to reduce the size of the BoneKeyFrame array.  
  9. I found some useful information here: http://www.digitalrune.com/Support/Blog/tabid/719/EntryId/131/Character-Animation-Compression.aspx
  10. I have eliminated the redundant key frames (frames that have the same transform matrix as the preceding one) and have now reduced the size to 84 mb.   I am wondering if there are more low-hanging fruits that can bring it down further....       Yes, what I have is 4*4 matrices, likely quaternions. If I decompose them into vectors, I would need to change the runtime animation code to use vectors instead... I am not sure if I want to do that at this point...   This is what the struct looks like: /// <summary> /// Represents a keyframe in an animation track. /// </summary> public struct BoneKeyframe { /// <summary> /// Creats a new BoneKeyframe. /// </summary> /// <param name="transform">The transform for the keyframe.</param> /// <param name="time">The time in ticks for the keyframe.</param> public BoneKeyframe(Matrix transform, long time) { this.Transform = transform; this.Time = time; } /// <summary> /// The transform for the keyframe. /// </summary> public readonly Matrix Transform; /// <summary> /// The time for the keyframe. /// </summary> public readonly long Time; } Most of the keyframes are just hanging around in memory. How could I compress it until the transform is needed..?         I have already eliminated the frames that are equal. But is the situation really that common in animation that a handmade animation sequence is similar to a SLERP? How would I detect this case. How do I select the endpoints in the animation sequence to compare, when doing the loop I posted above?  
  11. I reduced the sampling rate to 30 frames per second from 60. The memory used went down from 206 mb to 108 mb, while animation quality looks the same. I will try to reduce it a bit further, then I will probably try removing the redundant key frames as was suggested.  
  12.   If your code (properly) interpolates animation data at runtime, do you need to do anything other than just load the data? I.e., game assets in general should be "ready to load" at runtime.     The code I posted only runs at build time. It creates the key frame arrays that the game interpolates between during runtime. My problem was that these arrays were so huge.
  13. else // Else the adjacent frames have identical transforms and we can use // the current frames transform for the current keyframe. { keyframe = new AnimationKeyframe(new TimeSpan(time), channel[currentFrame].Transform); } Here, I might as well not store any keyframe at all. I wonder how much data could be saved that way.
  14. Yes, but the code i posted above suggests that everything that gets exported is overridden in a resampling loop.
  15. I am looking at the code that pre-compiles the animation data coming from the exporter. It looks like it is storing 60 keys per second, regardless of what it receives from the exporter. Here is the code:   // Step through time until the time passes the animation duration while (time <= animationDuration) { AnimationKeyframe keyframe; // Clamp the time to the duration of the animation and make this // keyframe equal to the last animation frame. if (time >= animationDuration) { time = animationDuration; keyframe = new AnimationKeyframe(new TimeSpan(time), channel[channel.Count - 1].Transform); } else { // If the channel only has one keyframe, set the transform for the current time // to that keyframes transform if (channel.Count == 1 || time < channel[0].Time.Ticks) { keyframe = new AnimationKeyframe(new TimeSpan(time), channel[0].Transform); } // If the current track duration is less than the animation duration, // use the last transform in the track once the time surpasses the duration else if (channel[channel.Count - 1].Time.Ticks <= time) { keyframe = new AnimationKeyframe(new TimeSpan(time), channel[channel.Count - 1].Transform); } else // proceed as normal { // Go to the next frame that is less than the current time while (channel[currentFrame + 1].Time.Ticks < time) { currentFrame++; } // Numerator of the interpolation factor double interpNumerator = (double)(time - channel[currentFrame].Time.Ticks); // Denominator of the interpolation factor double interpDenom = (double)(channel[currentFrame + 1].Time.Ticks - channel[currentFrame].Time.Ticks); // The interpolation factor, or amount to interpolate between the current // and next frame double interpAmount = interpNumerator / interpDenom; // If the frames are roughly 60 frames per second apart, use linear interpolation if (channel[currentFrame + 1].Time.Ticks - channel[currentFrame].Time.Ticks <= ContentUtil.TICKS_PER_60FPS * 1.05) { // context.Logger.LogImportantMessage("Lerp between frames {0} and {1}, interpAmount: {2}", currentFrame.ToString(), (currentFrame + 1).ToString(), interpAmount.ToString()); // input.Duration.Ticks.ToString(), ((long)(durationFactor * input.Duration.Ticks)).ToString()); keyframe = new AnimationKeyframe(new TimeSpan(time), Matrix.Lerp( channel[currentFrame].Transform, channel[currentFrame + 1].Transform, (float)interpAmount)); } else // else if the transforms between the current frame and the next aren't identical // decompose the matrix and interpolate the rotation separately if (channel[currentFrame].Transform != channel[currentFrame + 1].Transform) { // context.Logger.LogImportantMessage("Slerp between frames {0} and {1}, interpAmount: {2}", currentFrame.ToString(), (currentFrame + 1).ToString(), interpAmount.ToString()); // input.Duration.Ticks.ToString(), ((long)(durationFactor * input.Duration.Ticks)).ToString()); keyframe = new AnimationKeyframe(new TimeSpan(time), ContentUtil.SlerpMatrix( channel[currentFrame].Transform, channel[currentFrame + 1].Transform, (float)interpAmount)); } else // Else the adjacent frames have identical transforms and we can use // the current frames transform for the current keyframe. { keyframe = new AnimationKeyframe(new TimeSpan(time), channel[currentFrame].Transform); } } } // Add the interpolated keyframe to the new channel. outChannel.Add(keyframe); // Step the time forward by 1/60th of a second time += ContentUtil.TICKS_PER_60FPS; } But at runtime, interpolation is performed again. So as some of you mentioned, I may be able to reduce this data and still get smooth playback.