• Advertisement


Popular Content

Showing content with the highest reputation since 12/22/17 in all areas

  1. 12 points
    I'm gonna call [citation needed] on that one. We don't really know what consciousness is yet. Not all of us believe in souls or the supernatural, incidentally. From my point of view, dismissing AI on the grounds that it can't possibly have something that we haven't demonstrated to even exist, never mind form a fundamental aspect of consciousness, seems... premature. This looks like an attempt to have a religion thread...
  2. 10 points
    Beginners don't understand how game development works. They think game X hasn't been made just because no one thought to do it; they never think that it wasn't made because it's either unfun or too difficult to program, or both. There are people who do the same with science, assuming that the only reason science doesn't accept something is because no one came up with the idea. It's a form of the Dunning-Krueger Effect, really. Beginners also tend to underestimate costs and assume that because their idea is obviously so perfect, people are going to swarm in and volunteer to do all the work for free just for a cut of "the profits", which they imagine must be millions and millions of dollars that just keep on coming. So they don't understand how markets work, either. More Dunning-Krueger here. I'm not innocent; I was one of those idiot beginners.
  3. 9 points
    I've always loved video games. As a child, I spent hours playing on my Atari 2600, on our home PC, or at a friend's house on his Nintendo and Super Nintendo. As time went on, I discovered QBasic and started to learn to make simple programs. It clicked - this is how the creators of the games were doing it! From there, I became very interested in learning about the creation process. I experimented, read articles in magazines, and as the World Wide Web took off I ventured online to learn more. Games got bigger and fancier, and some of them in special editions with documentaries about the creation, and I loved all of it. Well funded teams of hundreds of people were now working to create fantastic games with hours of gameplay and breathtaking visuals. I read articles and watched "making of" documentaries which described how developers would work long hours, forgoing days off, working late nights, and sometimes even sleeping in the office to meet deadlines. I was so impressed with the effort and dedication they put in. How much must you love a product to give up your nights and weekends, and spend time away from your family to finish it off? This was how great games were made, and I was in awe of the industry and the process. This was what I idolized. This was what I aspired to. I was wrong. The process I have described above is not necessary, and it is not cool. Developers do not need to sacrifice their free time, their sleep, and their health to create great games. The science is in. Numerous studies have shown that well-rested people are more productive and less prone to mistakes. The stress of this schedule and lack of sleep is profoundly damaging to people's health, causes burnout, and drives talented developers away from our industry. Just think about a cool feature that you loved in a AAA game. If the team went through a period of crunch, the developer who created that feature may have burned out and left the industry - they might not be creating awesome things for gamers anymore. We should not idolize a process that is harmful to developers. When we hear about crunch, the overwhelming reaction should be that this is not ok. Crunch is not cool, and developers still using this process should work towards a better way. Happier, healthier developers will produce better work, and in the long run, they will produce it more efficiently. Happier, healthier developers are more likely to stay in our industry rather than seeking greener pastures, resulting in more people with extensive experience who can then work on more advanced tasks and ideas, and push the industry forward. Thankfully, a growing number of developers have moved on or are moving on from this toxic culture of overtime and crunch, and a growing number of people are willing to speak up. Unfortunately, it's far from everyone, and there are many developers still exploiting workers. I'm putting my foot forward to say that I do not support a culture of overtime and crunch. We can do better, and we need to do better. I'm not the first person to share these sentiments, and I'm not an influential person, but I hope I won't be the last, and if I can convince even one more developer to stand up for better treatment of workers, then hopefully I've made some small difference. If you agree with me, next time you hear someone discussing crunch as if it's just a normal part of the process, let them know that there's a better way and that you don't support crunch and overtime. Let them know that crunch isn't cool.
  4. 9 points
    I think a big factor is that video games aren't physical things, but just data. Game development does - at least in theory(!!) - not require any money, supporters or physical resources beyond what most people (at least in rich countries) already own anyway. With infinite time and infinite knowledge, you could really create any sort of game completely on your own. You don't need to buy anything (all required software is available for free), you usually don't need to care about laws, and there is nobody you depend on who could just say "no" for whatever reason. Compare this to constructing a building: Even if you had all the knowledge that is required for all aspects of the construction, you still need to buy land to build on, you need to buy building material and machines, many tasks are probably physically impossible to do alone, and you need to folllow a ton of regulations to avoid being shut down. Without all these things, it is not so surprising that the efforts of game development are drastically underestimated by many people. Two more thoughts: - Since there is no initial risk involved at all, fantasizing about crazily huge unrealistic software development projects is just much less frightening. All you need to invest is some time, and if you fail, you haven't lost anything other than that time.. - The less you understand about software development, the less you can imagine how much work it is. Everbody has somewhat of an idea of what it takes to build a house, because you can see people doing it frequently somewhere in your town. But in a non-developer's everyday life, you usually don't see people working on video games, so how could you get a realistic impression of it?
  5. 8 points
    You're doing this: http://highexistence.com/spiritual-bypassing-how-spirituality-sabotaged-my-growth/ http://highexistence.com/10-spiritual-bypassing-things-people-total-bullshit/ Even if our brains are some kind of magical antenna that channels in a magical spirit consciousness from another plane of existence... what's stopping us from building our own mechanical antennae that channel magical spirit consciousness into our AI's?
  6. 6 points
    It sounds like you have several good reasons to accept the new job. It's up to you to consider what "committed to a 3-month long project" means, as in what type of commitment you made. You dont tell us. So, it's your call as to whether you're breaking some moral code of yours. But generally I'll say that if the company put all their eggs in one basket, so to speak, by having a new project that relies so heavily on just one person, then they are the ones who put the "company in that position" and not you. But again, I dont know what commitment you made to them. Maybe you just accepted the project, or maybe you gave your word that you would be there until completion. Those are different levels of commitment. Assuming your "commitment" was just to accept the project, then I'd say you should take the new job because of all the reasons you gave. You need to do what's best for you and your family, and let the company do what's best for them. If the tables were turned and the company thought it would be best to let you go, they might feel very badly about it, but at the end of the day I'd expect that they'd do what's best for the company. You can also offer to help them with the transition to a new engineer on the project. I'm not sure what the specific details of that would be, but maybe it's something to consider. Maybe you could even work for them on a freelance basis for a while to help them transition, and ask the new company if they'd allow you to work there part-time while you do that. I dont know, you have to think about it. But there might be some way to mitigate the transition for your old company if you really want to.
  7. 6 points
    Yep, here is my contribution to GameDev 2018 Missile Command. The source code is inside the zip :https://github.com/wybifu/missile_command/archive/master.zip github: https://github.com/wybifu/missile_command Windows users: Windows_version.exe Linux users: Linux_version or just compile it for any other OS. language: C library: SDL2 I feel that I have to explain myself as the code is awful: I was just writing as I was thinking when a new Idea popup I just hardcoded it and didn't care if it fits the rest of the code that can provide strange lines like: if (((Agent *)(((Agent *)(a->ptr0))->ptr1)) != NULL) ((Agent *)(((Agent *)(a->ptr0))->ptr1))->visible = BKP_F YEAH !! Absolutely horrible. a small video of gameplay : another shootscreen for pleasure:
  8. 6 points
    This is in no way limited to game development - every teenager with an electric guitar thinks they will be the next Jimi Hendrix too. It's easy to underestimate the difficulty of anything, before you have tried and failed a few times.
  9. 6 points
    If that's a problem, give up game development. It's largely thankless, so if you're not doing it for yourself, you shouldn't do it at all.
  10. 6 points
    I n some cases it's because they have what I call a "glorious vision" of what their game will be. They are imagining that they will re-create reality when, and that in their game things are going to be like reality. It's not until they actually try to make the game that they will realize that, just like everyone else's games, their game will necessarily function in the same simple ways as everyone else's games do. You can imagine the combat in your game being just like in real life right up to the point that you attempt to actually implement it. That is when reality sets in. This is one of the better reasons for creating a detailed design document, one that works out exactly and specifically how key aspects of the game will actually work. Because this is the process that shatters the "glorious vision" and brings you back to the reality of how simple it is actually going to be in the end compared to the wishful thinking of your "glorious vision".
  11. 5 points
    In my own opinion, this is NOT a bad thing. Being competitive and striving to be the best is a very good thing. Such competitive, over-ambitious, overzealous and talented youngsters only need to be mentored and well directed by an experienced guru in the field Imagine a very talented sports person (footballer, ...) but he or she is playing in a team without a manager. The consequence is that they be will all over the place, without proper overarching strategy, without good structure and will be learning from their mistakes the hard way I was like that... without a mentor, so I followed only my instincts and I paid dearly for that. A lot of wasted years. Probably not fully recovered yet. But it wasn't because of my over-ambitions and competitiveness, rather it was because I wasn't mentored or guided.
  12. 5 points
    Realistically speaking it's nearly impossible to find people who will be as motivated and driven as yourself towards your own project. It does happen, but there's a reason why entry level positions are typically filled with people who provide crappy service. Think of it like this; the person who pumps gas likely doesn't want to do that forever, they likely would rather own the gas station. Therefore you get someone who is 'just doing a job' and likely isn't providing the best service possible. People who do provide the best service possible likely get promoted, and then someone else fills their spot at the bottom ensuring that quality service is always hard to find. Ultimately a really driven person would likely want to rise through the ranks and then start their own business in the field they rose up through. It's the same with any field of work. Finding someone who will give you 100% as an employee/team member is truly a diamond in the rough. If you compare the above example to game development, you can't really expect everyone who might want to work with you to be as driven and dedicated as you are. When you do find someone as driven as you are it's likely that they will be using their position to gain experience to one day lead their own team. Some people are fine staying in the middle, and providing 100%, but it's tough to find those kinds of driven people. The passion for your project has to come from you. As leader of a project you then work to inspire those on your team to work with you and be as passionate about the project as you are, lead by example. Most teams lead by two people are married, siblings or long time friends. There's a reason for this, it's because they share the same passions and work well together. Finding one person to work in perfect harmony with you is rare, having that with an entire team is nearly unheard of. As for "wasting your life making a product that is never gonna be as good as the rest of the industry", your life is yours to do with as you please. If you enjoy the creation process, then to me, it's not a waste at all. A sense of purpose for ones life should come from many things, not just work, but social life, hobbies, recreation, etc, it's a balancing act. That way if any one thing doesn't work out it's not such a far fall from being content. Comparing your work or the potential of your work to 'the rest of the industry' to me is counter productive if its uninspiring to you. Remember that there can only be one 'the best', and only a few 'top of the game'. There are billions of people on the planet, the odds are stacked against you. It's also important to remember that what you see as an end user is a polished product, not a prototype. So you're seeing the best that could be brought forward. Each individual on a team has their own respective portfolios of work that also represents their current best, and it's something they update as they get better. What we as end users rarely see is the crappy stuff that doesn't make release, the 'unpolished' work if you will. Think of a painter who has their work on exhibition at a gallery. Everything we see at the gallery is what they believe to be their best work. Now think of their studio, the stuff left behind wasn't good enough to make the cut at the gallery. On top of that they will have scores of work they didn't like and never completed, not the mention the work from X years before they were finished mastering their skill that they no longer show anyone. Something I always remember is that it'll take you around 10,000 hours in each skill to get good enough to be professional. If you're trying to develop a game then whatever asset skill you have will take that same 10k hours. If you lead the team, then team leadership is another skill requiring 10k hours. Each skill you will use will take you 10k hours. Some skills will overlap and allow you to 'level up' at the same time, others wont. This is why most people work on one skill at a time, or join teams in order to only be in charge of one skill. They can then learn from each other and master other skills together. If you've ever watched interviews or behind the scenes of some of your favorite productions, be it videos games, music, movies, stand-up comedy, etc, one thing you'll notice is most artists will be unhappy with work they were once happy with. This is a representation of their skills improving as an artist. Clerks by Kevin Smith is one of my favorite movies, he talks smack about it all the time, because he's evolved as a writer/director. Another good example of the things I've mentioned are some of the costume concepts for the superhero movies over the years. Some of them are super bad, and needed to be entirely reworked, but ultimately we as end users got something that looked really good on screen. Without looking behind the scenes, the average user never knows how much work went into making something perfect. Stand-up comedy is the same, we don't often get to see comedians in their early years bombing at 50 person bars, we see their 1 hour specials a decade into their career. Many assume that what we see came out perfect on the first try, when in reality it's far from that easy. In the end it's important that you enjoy the creation process, and are truly dedicated to making your project/skill as perfect as possible within reason. If you don't enjoy it, then why bother? It doesn't matter what others think, art typically shines best when you make it for yourself and not for others.
  13. 4 points
    Hello there. I'm not really the blogging type. This is my first ever blog. So I'll do my best. I've been trying to showcase my video game engine from scratch in different professional forums with scant mixed results. I’m currently a happily employed 3D Graphics Programmer in the medical device field who also loves creating graphics programs as a side hobby. It's been my experience that most people who aren't graphics programmers simply don't appreciate how much learning goes into simply being able to code a small fraction of this from scratch. Most viewers will simply compare this to the most amazing video game they’ve ever seen (developed by teams of engineers) and simply dismiss this without considering that I’m a one-man show. What I’m hoping to accomplish with this: I’m not totally sure. I spent a lot of my own personal time creating this from the ground up using only my own code (without downloading any existing make-my-game-for-me SDKs), so I figured it’s worth showing off. My design: Oct Tree for scene/game management (optimized collision-detection and scene rendering path) from scratch in C++. 1. All math (linear algebra, trig, quaternion, vectors), containers, sorting, searching from scratch in C++. 2. Sound system (DirectSound, DirectMusic, OpenAL) from scratch in C++. 3. Latest OpenGL 4.0 and above mechanism (via GLEW on win32/win64) (GLSL 4.4). Very heavy usage of GLSL. Unusual/skilled special effects/features captured in video worth mentioning: 1. Volumetric Explosions via vertex-shader deformed sphere into shock-wave animation further enhanced with bloom post-processing (via compute shader). 2. Lens Flare generator, which projects variable edge polygon shapes projected along screen-space vector from center of screen to light-position (again, in screen-space: size and number of flares based on intensity and size of light source). 2. Real-time animated procedural light ray texture (via fragment shader) additively blended with Volumetric explosions. 3. Active camouflage (aka Predator camouflage). 4. Vibrating shield bubble (with same sphere data in Volumetric explosion) accomplished using a technique very similar to active camouflage 5. Exploding mesh: When I first started creating this, I started out using fixed-function pipeline (years ago). I used one vertex buffer, one optimized index buffer, then another special unoptimized index buffer that traces through all geometry one volume box at a time. And each spaceship “piece” was represented with a starting and ending index offset into this unoptimized index buffer. Unfortunately, the lower the poly-resolution, the more obvious it is what I was doing. Unfortunately, as a result, when the ship explodes you see the triangle jaggies on the mesh edges. My engine is currently unfortunately somewhat married to this design—which is why I haven’t redesigned that part yet (It’s on the list, but priorities). If I were to design this over again, I’d simply represent each piece with a different transform depending upon whether or not the interpolated object-space vertex (input to the pixel shader) was in-front of or behind an arbitrary “breaking plane”. If the position was beyond the breaking point boundary planes, discard the fragment. This way, I can use one vertex buffer + one optimized index buffer and achieve better looking results with faster code.
  14. 4 points
    I think your terminology is a bit off -- a descriptor heap is a huge area of memory where descriptors can be allocated. You can only have a single combined SRV/CBV/UAV-type descriptor heap bound to the device at a time, and changing this binding is expensive, so you're encouraged to only ever have a single one bound. You can create extra ones as staging areas where you can pre-create SRV's which can later be copied into your main/bound heap. Within a heap, you create descriptor-tables, which get bound to the root signature. The resource binding model in our engine has 8 "resource list" slots, which each contain an array of SRV's. In D3D11, each "resource list" is mapped to a contiguous range of t# registers in the shader. e.g. If a shader has ResList#0 with 4 textures and ResList#1 with 2 textures, the binding system is configured to copy ResList#0 into SRV slots [0,3] and ResList#1 into SRV slots [4,5]. In D3D12, each "resource list" is mapped to a root-descriptor-table parameter. Each shader generates a root-signature where param#0 is a table of CBV's, and param #1,2... are the res-list SRV tables. When submitting a draw-call, we determine if any res-list slots have changed since the previous draw-call (or if the previous draw-call used a different root signature). If so, a descriptor table is allocated for each new res-list within a ring-buffer, the SRV's for that root signature are copied into that new allocation from a non-shader-visible (staging) descriptor heap, and these new tables are set as root parameters. When creating a texture, it's SRV is pre-created in the non-shader-visible descriptor heap, while the shader-visble descriptor heap is just a ring-buffer of these transient tables.
  15. 4 points
    First thing's first, let's address what is perhaps the greatest flaw any open world game has, emptiness. I'm not saying that every open world game has this flaw, but if this flaw goes unchecked, it can cripple an otherwise brilliant game. Many games have overcome this and have risen to be legends such as The Witcher 3: The Wild Hunt, Assassin's Creed: Origins, and (my personal favorite) Legend of Zelda: Breath of the Wild. However, the one thing that no-one can deny about these games is that they have limits. I'm not saying that's a bad thing, rather the fact that those games have limits is probably what made them great because the developers could work extra hard to make everything they offered the finest they could. Be it through a colorful and motley cast of characters, utterly unique content, and compelling gameplay. But I'm not here to talk about your average ordinary Open World games, I'm talking about a special, new, and somewhat unrefined form of video game that offers an endless world to explore. An example: No Man's Sky. No Man's Sky was incredibly appealing because it offered a game world whose vastness was beyond compare. It offered an endless amount of places to go, but that was it's undoing. Video games aren't just about going places, they are about doing things. When I played No Man's Sky, what I got most interested in was finding upgrades for the ship and multi-tool. But it lost it's appeal to me because I realized that despite the fact that you had an endless amount of places to go, you had a severely limited amount of things to do. Sure you could interact with the different species and scan the local fauna, but it was all the same to me, the multi-tool was your primary method of interacting with the world, but you could only interact with the world in certain particular ways. Another example: Minecraft. Minecraft came close to defeating the flaw of an endless open world to the point where No Man's Sky tried to mimic it to save itself. You can build anything in Minecraft, and because of that, it can offer an endless amount of things to do. But it isn't the kind of thing that appeals to everyone, probably because not everyone has fun being creative just for the sake of creativity. The most creative thing I built was a flat-sided square building, first out of cobblestone, then out of solid stone, to serve as a home base for exploration, but what really appealed to me was crafting because crafting was doing something that could enhance future ways to do other things. I did have fun exploring, but once you've seen one cave, you've seen them all. So in a nutshell, Minecraft offered an endless world and an endless amount of things to do, but it did so in a way that they didn't match up well and doesn't appeal to everyone. Some of my favorite games were (and are) Super Mario Sunshine, Banjo Kazooie, Banjo Tooie, Ty The Tasmanian Tiger 1, 2, and 3, Okami, Rayman 3, Far Cry 4 and Primal, and Sonic Adventure 1 and 2. What they all have in common is that they're sandbox games. Orthodox sandbox games generally revolve around collecting things or fulfilling goals to collect things, but collecting those things rarely serves to enhance gameplay other than to make a way to collect more of those things. But despite this, I keep coming back to those games. After thinking long and hard, I decided that what keeps me coming back is discovery and testing the limits of my skills. Now to the hypothesis. The appeal to an open world game is endless discovery and endless things to do. But even with procedural generation, it is impossible to make a game like that without things getting a little stale and similar. Even if the game implements discoverable things that add new mechanics, eventually the players will run out of new things to discover and new things to do. But there might be a method to do it in a way which can allow the player to have a number of mechanics, tactics, and methods at their disposal so great that it would be impossible for one player to uncover them all. Instead of a discovery being just an achievement or new gameplay element, it should also offer the possibility to unlock more achievements and elements depending on how the player matches up or arranges the discovery with others. That way even if the number of discoveries is limited, the possibilities each discovery offers are beyond what anyone could do by themselves. And maybe a good way to go about it is to make the number of uses each discovery has limited so that the player has to constantly venture out in the world to get the most out of their favorite discoveries. But above all, the challenges offered to the player must not call for one specific mechanic, there might be a few that would make the challenge easier, but even if using any other mechanic would make conquering the achievement harder, it would encourage players to test the limits of their creativity and skills without making them feel restricted. How could something like this be implemented? I don't know. That's why I'm posting it here like a thesis so that maybe someone with the right capabilities would read this and make the game I and possibly many others have been waiting a very long time for. I had a few ideas myself, but that is a post for another time. A few games that I feel helped me realize these ideas were Megaman Battle Network and Castlevania: Aria of Sorrow (Because of the number of abilities and mechanics they offered) Magika (Because of the mixing up of abilities) and Super Mario Odessey (for the different captures changing up the mechanics). Like my ideas, want to add or expand on them, or have some of your own? Please, leave a reply!
  16. 4 points
    Like always, it comes down to what your ultimate goals are. But in general I'd say yes. Refactoring code is usually a good learning experience, especially when you're doing so with the goal of making it more cross-platform compatible or you're factoring out engine components to use later. You will end up with a set of tools that you can reuse, and you'll understand better what the different parts are and how they relate to each other.
  17. 4 points
    I'm not Bregma, but one thing that comes to mind is that it allows you use the enum value as "type code" at runtime. That has a number of use cases, but the one that comes to mind is cases where you convert between ID types and you want to validate at runtime that your ID points at what you think it's pointing at. For example, you might have an object hierarchy where Animal and Tree both inherit from Actor; you have ActorID, AnimalID, and TreeID. AnimalID and TreeID can be converted to ActorID and vice versa. Now you have a potential case where an ActorID that actually points at an Animal could be converted to a TreeID, which you probably want to validate at runtime! You don't strictly NEED to use an enum for the type code, but it simplifies the problem of having unique IDs per type. Especially in an environment where RTTI is disabled. This article illustrates an example of how to set up a handle type that uses "indices with type code" handles: http://gamesfromwithin.com/managing-data-relationships Another thought that comes to mind is that you might want to use the "type code" itself as an index or key. For example, suppose you have some content that specifies a table mapping object type onto some parameter that's uniform across all objects of those types, because the designers don't want to have to set that parameter on every single object definition of that type in content. If you have a type code that's mappable to a simple array index, you can have a flat array in the content and just index into that to get the value you're looking for. Another option that hasn't been mentioned is specializing your handle type on the actual type it's supposed to refer to, eg. struct Animal { // ... }; using AnimalID = IDType<Animal, unsigned int>; This obviates the need for an extraneous type that never gets used just for the tag.
  18. 4 points
    Once a project has been selected (depending on who holds the purse strings), management will usually select some sort of broad resource plan for the whole project, deciding how many programmers/designers/artists/etc will work on the project, and at which stages in the project lifetime. The project is often divided up into milestones, which act as checkpoints to verify that the project is being delivered as expected and on time. Less formal projects might have a handful of milestones, whereas big publisher-funded projects often have a formal milestone delivery process where the build is explicitly handed over every so often (monthly, or six-weekly, or quarterly, etc) to be assessed. Each milestone typically has a bunch of intended 'deliverables' - they are ideally working features, but can also be assets that may or may not yet be integrated into a feature. And there can be different expectations for the state of a deliverable (e.g. "prototype", "working", "finished", etc). The actual state of those deliverables, relative to what was promised, dictates whether the milestone is 'passed' or 'failed'. In the latter case the team is usually expected to fix up those failed deliverables before the next milestone is handed over. If you keep failing milestones, the publisher may terminate the project, as they lose confidence in your ability to complete it. Scheduling within a milestone is usually done via some sort of agile planning process. With a given set of deliverables in mind, the heads of each department and the project management team ("producers") come up with a list of prioritised tasks and decide who to allocate them to. Those people receive the task descriptions and implement them. The day-to-day work of each person depends entirely on their job and their task. There may be a 'daily standup' meeting or Scrum where people briefly discuss what they're working on and ask for help if they're stuck. Beyond that, they communicate via conversation/meetings/email/Slack to resolve ambiguities and discuss details. The rest of the time, they're probably at their computer, executing their current task by creating code, art, whatever.
  19. 4 points
    Hi everyone! It has been more than two months since I released I Am Overburdened and since I wrote a devlog entry. Please accept my apology for this, I was super busy with the release and support of the game. But now I’m back with an in-depth analysis how the overall production and final numbers turned out . Summary I want to do a fully detailed breakdown of the development and business results, but I don’t want break it up into a typical postmortem format (good, bad, ugly). I’ve drawn my conclusions, I know what I have to improve for my upcoming projects, but I don’t want to dissect the I Am Overburdened story this way, I want emphasize how much work goes into a game project and focus more on how a journey like this actually looks and feels like. If you really want know my takeaways, here it goes in a super short format: I consider the game a success from a development perspective (good), but I failed from a marketing and sales standpoint (bad and ugly). Now I go into the details, but will focus more on the objective “what happened, how it went, what it took” parts. Development The game started out as a simple idea with a simple goal in mind. I partially abandoned my previous project, because it ballooned into a huge ball of feature creep, so I wanted to finish a more humble concept in a much shorter time period. The original plan was to create a fun game in 4 months. I really liked the more casual and puzzle-y take on the roguelike genre like the classic Tower of the sorcerer game, or the more recent Desktop dungeons and the Enchanted cave games so I set out to create my own take. I designed the whole game around one core idea: strip out every “unnecessary” RPG element/trope and keep only the items/loot, but try to make it just as deep as many other roguelikes regardless of its simplicity. From this approach the “differentiating factor” was born, a foolishly big inventory, which helped me to define and present what I Am Overburdened really is. A silly roguelike full of crazy artifacts and a “hero” who has 20 inventory slots. Most of the prototyping and alpha phases of the development (first two months) went smoothly, then I had to shift gears heavily… Reality check After 3 months of development, when all of the core systems were in place and when I deemed big parts of the content non-placeholder, the time came to show the game to others. I realized something at that point, forcing me to make a huge decision about the project. The game was not fun . The idea was solid, the presentation was kind-of ok, but overall it was simply mediocre and a month of polishing and extra content in no way could change that! Back than I was super stressed out due to this and I thought about this as my hardest decision as a game maker, but looking back I think I made the right choice (now I feel like I actually only had this one). I decided to postpone release, explore the idea further even if it doubles!!! the originally planned development time (and it happened ) and most importantly I decided to not make or release a “shovelware”, because the world really isn’t interested in another one and I’m not interested in making/publishing one… Final scope So after 4 months of development, feeling a bit glum, but also feeling reinvigorated to really make the most out of I Am Overburdened I extended the scope of the design & content and I also planned to polish the hell out of the game . This took another 4 months and almost a dozen private beta showings, but it resulted in a game I’m so proud of, that I always speak of it as a worthy addition to the roguelike genre and as a game that proudly stands on its own! Some numbers about the end result: It takes “only” around 30 to 40 minutes to complete the game on normal mode in one sitting, but due to its nature (somewhat puzzle-y, randomized dungeons & monster/loot placements + lots of items, unlocks and multiple game modes), the full content cannot be experienced with one play-through. I suspect it takes around 6 to 12 full runs (depending on skill and luck) to see most of what the game has to offer so it lends quite a few hours of fun . There are 10 different dungeon sets and they are built from multiple dozens of hand authored templates, so that no level looks even similar to the other ones in one session. They are populated by 18 different monsters each having their own skill and archetype (not just the same enemy re-skinned multiple times). And the pinnacle, the artifacts. The game has more than 120 unique items, all of them having a unique sprite and almost all of them having unique bonuses, skills (not just +attributes, but reactive and passive spells) and sound effects. This makes each try feel really different and item pickup/buy choices feel important and determinative. The game was also localized to Hungarian before release, because that is my native language so I could do a good job with the translation relatively fast and this also made sure, that the game is prepared to be easily localized to multiple languages if demand turns out to be high. Production numbers How much code I had to write and content I had to produce all in all to make this game? It is hard to describe the volume/magnitude with exact numbers, because the following charts may mean a totally different thing for a different game or in case of using different underlaying technologies, but a summary of all the asset files and the code lines can still give a vague idea of the work involved. Writing and localization may not sound like a big deal, but the game had close to 5000 words to translate ! I know it may be less than the tenth of the dialogue of a big adventure or RPG game, but it is still way larger than the text in any of my projects before… I’ll go into the detailed time requirements of the full project too after I painted the whole picture, because no game is complete without appropriate marketing work, a super stressful release period and post-release support with updates and community management work . Marketing If you try to do game development (or anything for that matter) as a business, you try to be smart about it, look up what needs to be done, how it has to be approached etc… I did my homework too and having published a game on Steam before I knew I had to invest a lot into marketing to succeed, otherwise simply no one will know about my game. As I said this is the “bad” part and I’ll be honest. I think I could have done a much better job, not just based on the results, but based on the hours and effort I put in, but let’s take it apart just like the development phase. Development blog/vlog I started writing entries about the progress of the game really early on. I hoped to gather a small following who are interested in the game. I read that the effectiveness of these blogs are minimal, so I tried to maximize the results by syncing the posts to at least a dozen online communities. I also decided to produce a video version because it is preferred over text these days + I could show game-play footage too every now and then. I really enjoyed writing my thoughts down and liked making the videos so I will continue to do so for future projects, but they never really reached many people despite my efforts to share them here and there… Social media I’ve tried to be active on Twitter during development, posting GIFs, screen-shots and progress reports multiple times a week. Later on I joined other big sites like Facebook and Reddit too to promote the game. In hindsight I should have been more active and should have joined Reddit way earlier. Reddit has a lot of rules and takes a lot more effort than Twitter or Facebook, but even with my small post count it drove 10 times more traffic to my store page, than any other social media site. Since the game features some comedy/satire and I produced a hell of a lot of GIFs, I tried less conventional routes too like 9gag, imgur, GIPHY and tumblr, but nothing really caught on. Wishlist campaign I prepared a bunch of pictures up-front featuring some items and their humorous texts from the game. I posted one of these images every day starting from when the game could be wishlisted on Steam. I got a lot of love and a lot of hate too , but overall the effectiveness was questionable. It only achieved a few hundred wishlists up until the release day. Youtube & Twitch For my previous Steam game I sent out keys on release day to a 100 or so Youtubers who played any kind-of co-op game before, resulting in nearly 0 coverage. This time I gathered the contact info of a lot of Youtubers and Twitch streamers upfront. Many were hand collected + I got help from scripts, developer friends and big marketing lists ! I categorized them based on the games they play and tried talking to a few of those who played roguelikes way before release to peak their interest. Finally I tried to make a funny press release mail, hoping that they will continue reading after the first glance. I sent out 300 keys the day before release and continued the following weeks, sending out 900 keys total. And the results?! Mixed, could be worse, but it could be much better too. 130 keys were activated and around 40 channels covered the game, many already on release day and I’m really thankful for these people as their work helped me to reach more players. Why is it mixed then? First, the videos did generate external traffic, but not a huge one. Second, I failed to capture the interest of big names. I also feel like I could have reached marginally better results by communicating lot a more and a lot earlier. Keymailer I payed for some extra features and for a small promotion on this service for the release month. It did result in a tiny extra Youtube coverage, but based on both the results and the service itself all in all it wasn’t money well spent for me (even if it wasn’t a big cost). Press This was a really successful marketing endeavor considering the efforts and the resulting coverage. I sent out 121 Steam keys with press release mails starting from the day before release. Both Rock Paper Shotgun and PC Gamer wrote a short review about it in their weekly unknown Steam gems series and the game got a lovely review from Indiegames.com. Also a lot of smaller sites covered it many praising it for being a well executed “chill” tongue-in-cheek roguelike . The traffic generated by these sites was moderate, but visible + I could read some comforting write-ups about the quality of the game. Ads I tried Facebook ads during and a bit after the release week + in the middle of the winter sale. Since their efficiency can not be tracked too well I can only give a big guesstimate based on the analytics, sales reports and the comparison of the ad performances. I think they payed back their price in additional sales, but did not have much more extra effect. I believe they could work in a bigger scale too with more preparation and with testing out various formats, but I only payed a few bucks and tried two variants, so I wouldn’t say I have a good understanding of the topic yet. Some lifetime traffic results: So much effort and so many people reached! Why is it “bad”, were the results such a mixed bag? Well, when it comes to development and design I’m really organized, but when it comes to marketing and pr I’m not at all. As I stated I never were really “active” on social media and I have a lot to learn about communication. Also the whole thing was not well prepared and the execution especially right at the release was a mess. The release itself was a mess . I think this greatly effected the efficiency! Just to be more specific I neglected and did not respond in time to a lot of mails and inquiries and the marketing tasks planned for the launch and for the week after took more than twice as much time to be completed as it should have. I think the things I did do were well thought out and creative, but my next releases and accompanying campaigns should be much more organized and better executed. Time & effort I don’t think of myself as a super-fast super-productive human being. I know I’m a pretty confident and reliable programmer and also somewhat as a designer, but I’m a slowpoke when it comes art, audio and marketing/pr. For following my progress and for aiding estimations I always track my time down to the hour level. This also gives me confidence in my ability to deliver and allows me to post charts about the time it took to finish my projects . Important thing to note before looking at the numbers: they are not 100% accurate and missing a portion of the work which were hard to track. To clarify, I collected the hours when I used my primary tools on my main PC (e.g.: Visual Studio, GIMP), but it was close to impossible to track all the tasks, like talking about the game on forums & social media, writing and replying-to my emails, browsing for solutions to specific problems and for collecting press contact information, you get the idea… All in all these charts still show a close enough summary. 288 days passed between writing down the first line in the design doc and releasing the game on Steam. I “logged” in 190 full-time days. Of course more days were spent working on the game, but these were the ones when I spent a whole day working and could track significant portion of it + note that in the first 4 months of the project I spent only 4 days each week working on I Am Overburdened (a day weekly were spent on other projects). Release So how the release went? It was bad, not just bad, “ugly”. After I started my wishlist campaign, close to the originally planned date (2017. Oct. 23.) I had to postpone the release by a week due still having bugs in the build and not having time to fix them (went to a long ago planned and payed for vacation). I know this is amateurish, but the build was simply not “gold” two weeks prior to release . Even with the extra week I had to rush some fixes and of course there were technical issues on launch day. Fortunately I could fix every major problem in the first day after going live and there were no angry letters from the initial buyers, but having to fight fires (even though being a common thing in the software/game industry) was super tiring while I had to complete my marketing campaign and interact with the community at the same time. The game finally went live on Steam and itch.io on 2017. Nov. 2 ! I did not crunch at all during development, but I don’t remember sleeping too much during the week before and after launching the game. Big lesson for sure . I saw some pictures about the game making it to the new and trending list on Steam, but it most probably spent only a few hours there. I never saw it even though I checked Steam almost every hour. I did saw it on the front-page though, next to the new and trending section in the under 5$ list . It spent a day or two there if I remember correctly. On the other hand, itch.io featured it on their front page and it’s been there for around a whole week ! With all the coverage and good reviews did it at least sale well, did it make back it’s development costs, if not in the first weeks at least in the last two months? Nope and it is not close to it yet… Sales In the last two months a bit more than 650 copies of I Am Overburdened were sold. Just to give an overview, 200 copies in the first week and reached 400 by the end of November, the remaining during the winter sale. This is not a devastating result, it is actually way better than my first Steam game, but I would be happier and optimistic about my future as game developer with reaching around 3 to 4 times the copies by now. To continue as a business for another year in a stable manner around 7 to 8 times the copies total (with price discounts in mind) during 2018 would have to be reached. I’m not sure if the game will ever reach those numbers though . If you do the math, that is still not “big money”, but it could still work for me because I live in eastern Europe (low living costs) + I’m not a big spender. Of course this is an outcome to be prepared for and to be expected when someone starts a high-risk business, so I’m not at all “shocked” by the results. I knew this (or even a worse one) had a high chance. No matter how much effort one puts into avoiding failure, most of the game projects don’t reach monetary success. I’m just feeling a bit down, because I enjoyed every minute of making this game, a.k.a. “dream job” , maybe except for the release , but most probably I won’t be able to continue my journey to make another “bigger” commercial game. I may try to build tiny ones, but certainly will not jump into a 6+ months long project again. Closing words It is a bit early to fully dismiss I Am Overburdened and my results. It turned out to be an awesome game. I love it and I’m super proud of it. I’m still looking for possibilities to make money with it (e.g.: ports) + over a longer time period with taking part in several discount events the income generated by it may cover at least a bigger portion of my investment. No one buys games for full price on PC these days, even AAA games are discounted by 50% a few months after release , so who knows… If you have taken a liking to play the game based on the pictures/story you can buy it (or wishlist it ) at Steam or at itch.io for 4.99$ (may vary based on region). As an extra for getting all the way here in the post, I recorded a “Gource” video of the I Am Overburdened repository right before Christmas. I usually check all the files into version control, even marketing materials, so you can watch all the output of almost a year of work condensed into 3 minutes. Enjoy ! Thank you very much for following my journey and thanks for reading. Take care!
  20. 4 points
    Isn't that field of science called psychology? Or science itself is just applied philosophy at the end of the day... BTW, they already have metrics for measuring whether an object is conscious or not, which have been demonstrated to be able to tell the difference between normal awake brains, sleeping brains, dreaming brains, anesthetized brains, vegetative comatose brains, minimally conscious brains, and "locked in syndrome" brains (which would otherwise appear similar to other comatose brains, but on this metric, shows high levels of consciousness). Science does peer into those mechanisms. People's free will is surprisingly easy to influence... Again, that's psychology (or hypnotism too, if you like). The exact mechanisms of exactly how this process works though -- or any specific human action, when trying to explain the entire chain of consequence from genesis of thought to action -- are too complex for any human to ever understand (a thousand trillion synaptic connections, multiplied by all the other variables is an inconceivable amount of data, even when just considering a single moment in time...). There's also the camp who believes that the actual physical mechanisms behind thought is rooted in quantum behavior, which is probabilistic, which makes the whole thing "just physics" without having to say that it's deterministic (keeping the "free" part of "free will" free, and leaving the door open for a God who rolls dice).
  21. 4 points
  22. 4 points
    None of this makes any sense.
  23. 4 points
    I don't believe @Alberth could have explain that better, the problem is that it isn't a very simple thing to do; So I added images to show some details. Sorry I am at work and don't have the time to make it at a great quality. So I will show you what Alberth said: First you need what is known as tiling textures, these are the rectangles: The important part is that you can make a larger image from them because they tile. Next you need a mask, this is the form of your country: It's common for masks to be gray scale or black and white, this saves a lot of data. The way a mask works is that you will tell your fragment shader to render the grass texture where the white is, because white = (1,1,1) and any number times 1 = it self. Example 0.5 * 1 = 0.5. You can just multiply the color of the texture with the white. Black = (0,0,0) and Any number times black = 0. Your end result should look like this: Next you tell your fragment shader just to skip all pixels that is Black (0,0,0) and it should render only the grass part. After rendering the grass part you do the same using your rock texture. Then you render first the rock texture a bit lower and to the left of the image, then you render the grass where you want it. Click image for full size. For the edge you just use an edge detect or you can also store it in the mask. Using tiling textures and a mask you can create all the content you need.
  24. 4 points
    As others mentioned, it isn't just games, and it isn't just beginners. It can be that you'll lose an unrealistic amount of weight as your new years resolution, or you'll finish an assignment by some deadline, or you're Apple releasing a watch a week after the official release date, or Duke Nukem Forever released about 15 years late. The problem has been around for all of humanity. A bit of web searching shows even in the ancient world, the ancient Roman, Greek, and Babylonian cultures made assorted promises and resolutions each new year, including documented promises to return objects, pay debts, and follow better care. People have been setting (and failing to meet) overambitious unrealistic goals for all of recorded history. It doesn't matter even if we have experience. We KNOW we aren't going to drop that much weight, but we think that THIS TIME we might be able to. We KNOW that every year we wait to file taxes but we commit to THIS TIME doing it earlier. We KNOW that similar assignments have required more time, but we think that THIS TIME we can make it by an earlier deadline. We KNOW a game like the one we see has a 15-minute long scrolling list of names in the credits, but we think we can do it. As typical, Wikipedia's got a writeup listing a bunch of proposed reasons with references. It looks like something psychologists have been writing about since the 1960s. Given the history of new year's promises, I can imagine Hammurabi reading the stone tablet newspaper at the new year describing how he can help keep his goals of losing weight and keeping it off.
  25. 4 points
    We are the music-makers, And we are the dreamers of dreams, Wandering by lone sea-breakers And sitting by desolate streams; World losers and world forsakers, On whom the pale moon gleams: Yet we are the movers and shakers Of the world for ever, it seems. With wonderful deathless ditties We build up the world’s great cities. And out of a fabulous story We fashion an empire’s glory: One man with a dream, at pleasure, Shall go forth and conquer a crown; And three with a new song’s measure Can trample an empire down. We, in the ages lying In the buried past of the earth, Built Nineveh with our sighing, And Babel itself with our mirth; And o’erthrew them with prophesying To the old of the new world’s worth; For each age is a dream that is dying, Or one that is coming to birth. From "Ode" by Arthur O'Shaughnessy
  26. 4 points
    It's been a few months since the last staff blog update, and I apologize for that. It was a busy end of 2017. We've recently announced several new community features here on GameDev.net that I'd like to go through - if you haven't spent time exploring all of GameDev.net then you might have missed these! GameDev Challenges Spawned from this forum request: GameDev Challenges is a new community "game jam"-like event for developers looking to test their skills or learn through short-form projects intended to take no more than a month or two to develop. Developers who complete the challenges in the allotted time earn a badge on their profile. Of course, developers can complete challenges after the allotted time, but right now the badges are not awarded. Right now we are using the GameDev Challenges forum to manage these (Forums -> Community -> GameDev Challenges), and we're currently on the 3rd challenge where developers need to create a clone of the arcade classic Missile Command. The first two challenges were for a Pong! clone and an Arcade Battle Arena along the lines of the classic Bubble Bobble. I encourage everyone to check out the threads and entries for all the challenges! In the near future we'll integrate Challenges with our latest announcement: Projects and Developer Profiles. Projects As we announced: The Project profile is pretty extensive. We recommend setting up a developer blog for each Project, which can then be used to provide updates for the Project and will show on your Project page. A Gallery is also automatically created for your Project (if you don't already have one), and from there you can upload screenshots and videos of your Project - these will also show in your Project page. The rest of your Project profile includes links to your Project homepage, store links, descriptions, platforms, and other details about your project. You can even upload and manage files for others to download. Here's the feature list from the announcement: Browse, download, and comment on projects from other Developers Provide updates to your project by linking your GameDev.net Blog Create your own Developer profile, including with a GameDev.net subdomain (in progress)! Showcase your Project with screenshots from your project's linked GameDev.net Album Manage your projects through your Developer Dashboard Market your project's website, Facebook, Twitter, Steam, Patreon, Kickstarter, and GameDev.Market pages Track project views and downloads through Google Analytics Upload and manage file downloads for your Project, allowing others to try it out and give feedback Link to your project with an embeddable widget (link auto-embeds on GameDev.net) Showcase your project with a trailer on YouTube or Vimeo Import your project from IndieDB or itch.io Developer Profiles Developer Profiles are a new feature of your GameDev.net profile for showcasing your development team(s). We have basic features for this right now with plans to expand it. You'll find all the settings for your Developer Profile in the Project Dashboard mentioned earlier. NeHe Source Code on GitHub Also mentioned recently is that we've put all of the NeHe tutorial source code on GitHub at https://github.com/gamedev-net/nehe-opengl. We will accept updates to the source code via pull request. NeHe is our long-running OpenGL tutorial site for developers wanting to learn OpenGL in a very accessible, straightforward manner, and is available at http://nehe.gamedev.net. GameDev Loadout Podcast And finally, if you're into podcasts then I suggest checking out our new Podcast section. We've recently partnered with Tony at GameDev Loadout to showcase his podcasts on GameDev.net. Tony interviews industry professionals and indie developers about a number of game development related topics. He's approaching his 80th episode, which is quite a feat! Next? We have bigger plans with Projects, Developer Profiles, and GameDev Challenges, so keep an eye out for more updates. We'll also be re-evaluating the home page in the near future (yes, again) to try to make it easier to find content you're interested in seeing across the entire site. Oh, one last announcement - the Game Developers Conference is quickly approaching, and GameDev.net members can get 10% off All Access and GDC Conference passes using this code: GDC18DEV As always, please share any thoughts and feedback in the comments below!
  27. 4 points
    I caught wind of the Missile Command challenge earlier in the month and figured I'd knock it out during Christmas break. I was planning on coding more on my Car Wars prototype but the challenge took up most of my programming time. Sleeping late, hanging out with my family, and playing video games took up the rest of my free time. All in all, it was a great way to slide into the new year. I spent some effort keeping the code clean (mostly) and even did a couple of hours worth of commenting and code reorganization before zipping up the package. Many sample projects are quick and dirty affairs so aren't really a good learning resource for new programmers. Hopefully my project isn't too bad to look at. What went right? Switching to Unity a few years ago. This was definitely the right call for me. It helped me land my dream job and allows me to focus on making games rather than coding EVERYTHING from the ground up. KISS (Keep It Simple Stupid) - I started thinking about doing my own take on Missile Command but decided on doing just a simple clone. The known and limited scope let me keep the project clean and kept development time down to something reasonable. Playing the original at http://my.ign.com/atari/missile-command was a big help for identifying features I wanted. Getting the pixel perfect look of old-school graphics was a little bit tricky, but thanks to a well written article I was able to get sharp edges on my pixels. https://blogs.unity3d.com/2015/06/19/pixel-perfect-2d/ I had done some research on this earlier so I knew this would be a problem I'd have to solve. Or rather see how someone else solved it and implement that. Using free sounds from freesound.org was a good use of time. There are only 4 sound effects in the game and it only took me an hour or two to find what I felt were the right ones. What went ok? Making UI's in Unity doesn't come naturally to me yet. I just want some simple elements laid out on the screen. Sometimes it goes pretty quickly, other times I'm checking and unchecking checkboxes, dragging stuff around in the heirarchy, and basically banging around on it until it works. I got the minimal core features of Missile Command, but not all of it. You don't really think about all the details until you start making them. I'm missing cruise missiles, bombers, and the splitting of warheads. Dragging the different sprites into position on the screen was manual and fiddly. There's probably a better way to do this, but it didn't take too long. You can't shoot through explosions, which makes the game a little more challenging. And you can blow up your own cities if you shoot defense warheads too close to them. It was easy enough to fix, but I left it in there. What went wrong? I spent a ton of time getting the pixel perfect stuff right. Playtesting in editor, it was set to Maximize on Play. There wasn't quite enough room to see the full screen so the scale was at 0.97 making the display 97% what it should be and thus, blurred all my sharp edges. I didn't see that setting though... >.< I pulled my hair out trying to see the problem in my math, and even downloaded a free pixel perfect camera which was STILL showing blurry stuff. Finally, I built the game and ran it outside the editor and saw things were just fine. There's also an import setting on sprites for Compression that I cleared to None. I'm not sure if this second step was necessary. I've been bit by the Editor not being 100% accurate to final game play and wished I would have tried that sooner. I had trouble with the scoring screen. I wanted to put the missiles up on the score line like Missile Command does, but ran into trouble with game sized assets and canvas sized UI elements. After 45 minutes or so I said screw it, and just put a count of the missiles and cities up. I didn't data drive the game as much as I wanted. The data is in the code itself so users can't mod the game without downloading the source code. I'm also only using one set of colors for the level. If I put any more time into this, I'll probably tackle this issue next, and then worry about the features I missed out on. Final thoughts Working on this project makes me appreciate how awesome the programmers of old really were. With the tools I have (Unity, Visual Studio, etc.) it took me a couple of weekends. And even then I didn't recreate all the features of the original. I'm including a link to the zipped up project in case anyone wants to see the source code to play around with it. Hopefully someone finds it useful. If so, let me know. EcksMissileCommand.zip - Executable if you want to play. EcksMissileCommand_Source.zip - The project if you want to mess around with it. Sound Credits freesound.org https://freesound.org/people/sharesynth/sounds/344506/ - Explosion.wav https://freesound.org/people/sharesynth/sounds/344525/ - LevelStartAlarm.wav LevelStartAlarm_Edit.wav - I used Audacity to edit the above sound. I took the first six beeps then faded them to silence. https://freesound.org/people/Robinhood76/sounds/273332/ - MissileLaunch.wav https://freesound.org/people/sharesynth/sounds/341250/ - ScoreCount.wav
  28. 4 points
    You started to big with your project (I have seen your posts on the forum). You should have made a small game first, you would have gotten to the reward faster. Then you should have made a small team project, 2-3 members and only after that should you have dived into your large project and assembling a large team. It takes around 12 years for you to reach the point where you can make your "The Game" and only the possible parts.( I still can't make that talking AI I wanted.) Making games is hard, it's expensive, the people you make it for will hate for it and others will tell you it isn't a real job. Find some reason to make games, without it you will be crushed. I don't believe that a hobby team of around 12 people with random skills and around $500 000 budget, could match 250-500 dedicated professionals with a $40 000 000 budget. Even Big Indie developers spend millions on there games. For indie developers the goal should be something like Minecraft or Five Nights At Freddy's; special games that isn't too expensive to make and breaks the mold.
  29. 4 points
    This question is pretty vague. I'll just describe how I generally do the main game loop, but this is just one of many ways that it can work. I have an object Game... this is the object that contains the main game loop. It also contains a member called ActiveGameScene which implements the interface IGameScene. The IGameScene has three primary responsibilites... Respond to a request, Update the GameState or Render the gamestate. The IGameScene contains a list of IGameSystems. Game Systems are very tightly focused "functionality packets" so, one system may be my input system and another may be my rendering system and there may be many more... lighting systems, ai systems etc. Each System has methods ProcessRequest, Update, and Render. So, the Game contains a Scene which contains a set of Systems and the main game loop is //Pseudo Code //In Game while(running) { while(requestsPending) Scene.ProcessRequest(request); Scene.Update(); Scene.Render(); } //In GameScene ProcessRequest(){ Foreach(ISystem sys in Systems) sys.ProcessRequest(request); } Update(){foreach(ISystem sys in Systems) sys.Update();} Render(){foreach(ISystem sys in Systems) sys.Render();} Then, it's in the specific systems where the interesting things happen. Maybe there is an AI System... //In AI System ProcessRequest(request){ } Update(){ Foreach(AIUnit){ if (AIUnit.CurrentAction==null) { AIUnit.CurrentAction = AIUnit.ChooseNextAction(); } switch(AIUnit.CurrentAction) { case Idle : Break; case Attack: AIUnit.Attack(); break; case Move: AIUnit.Position+= (AIUnit.Dest-AIUnit.Pos).Normalize(); } } }
  30. 4 points
    My turn. Source file and exec are in the zip here https://github.com/wybifu/missile_command/archive/master.zip and also : and album
  31. 4 points
    Seems you need to do your debugging yourself Did you try to output variables to screen one after another, something like: SkyColors[DTID.xy] = float4(X,Y,r, 1); You can make some conclusions based at the colors you see. If this does not help you can create a debug buffer, store variables there, read back to CPU and print them so you can spot NaNs or infinites. That's annoying but once set up you can use that debugging for each shader.
  32. 4 points
    The title is vague, so I'll explain. I was frustrated with UI dev (in general), and even more-so when working with a application that needed OpenGL with embedded UI. What if I wanted to make a full application with OpenGL? (Custom game engine anyone?) Well I did want to. And I'm working on it right now. But it started me onto making what I think is a great idea of a styling language; I present KSS (pron. Kiss) The multitudes more programmable version of CSS.... (only for desktop dev) /* It has all the 'normal' styling stuff, like you'd expect. */ elementName { /*This is a styling field.*/ font-color: rgb(0,0,0), font: "Calibri", font-size: 12px } .idName { color: rgba(255,255,255,0) } uiName : onMouse1Click{ color: vec3(0,0,0) } BUT It also has some cool things. I've taken the liberty to add variables, templates (style inheritance), hierarchy-selection, events (as objects), native function calls, in-file functions. var defaultColor: rgb(0,0,0) var number : 1.0 /*Types include: rgb, rgba, vec2, vec3, vec4, number, string, true, false, none (null), this*/ fun styleSomeStuff{ .buttons{ color: defaultColor, text-color: rgb(number,255,number) } } template buttonStyle{ color: rgb(255,255,0) } .buttons{ use: buttonStyle, otherTemplateName /*copies the templates styling field*/ color: defaultColor; } .buttons : onMouse1Click{ /* events not assigned as a value are initialized when read from file*/ styleSomeStuff();*/* call the in-file function*/ *nativeFunctionCall();/*call a native function that's binded*/ var a : 2; /*assign a variable, even if not initially defined.*/ } /*storing an event in a 'value' will allow you to operate on the event itself. It is only ran when 'connected', below.*/ val ON_CLICK2 = .buttons : onMouse2Click{ use: templateName } connect ON_CLICK2; disconnect ON_CLICK2; /*you can make a function to do the same.*/ fun connectStuff{ connect ON_CLICK2; } But wait, you ask... what If I need to select items from a hierarchy? Surely using element names and id's couldn't be robust enough! Well: /*We use the > to indicate the item next element is a 'child' to itemA in the hierarchy*/ itemA > itemAChild : onMouse1Click{ } .itemId > .itemAChild > itemAChildsChild{ } /*want to get all children of the element at hand?*/ elementName > .any{ /*this will style all the elements children*/ } /*What about if we want to use conditional styling? Like if a variable or tag inside the element is or isnt something?*/ var hello : false; var goodbye : true; itemA [var hello = false, var goodbye != false] { /*passes*/ } itemA [@tagName = something]{ /*passes is the tag is equal to whatever the value u asked.*/ } The last things to note are event-pointers, how tagging works, 'this', and general workflow. Tagging works (basically) the same as Unity, you say @tagName : tagValue inside a styling field to assign that element a tag that's referable in the application. You have the ability to refer to any variable you assign within the styling sheet, from say.. source-code. The backend. As such, being able to set a variable to 'this' (the element being styled) allows you to operate with buttons who are currently in focus, or set the parent of an item to another element. All elements are available to use as variables inside and outside the styling sheet, so an event can effectively parent an element or group of elements to a UI you specify. Ill show that in a figure below, Event pointers are so that you can trigger an event with a UI component, but affect another, below- /*We use the -> to point to a new element, or group of elements to style.*/ .buttons : onMouse1Click -> .buttons > childName{ visible : false parent: uiName; } /* In this case, we style something with the name "childName" whos parented to anything with the id 'buttons'. Likewise, we if there was a element with the name 'uiName', it would parent the childName element to it. */ Lastly: The results/workflow. I'm in the process of building my first (serious) game engine after learning OpenGL, and I'm building it with Kotlin and Python. I can bind both Kotlin and Python functions for use inside the styling sheet, and although I didn't show the layout-language (cause its honestly not good), this is the result after a day of work so far, while using these two UI languages I've made (In the attachments.) It's also important to note that while it does adopt the CSS Box-model, it is not a Cascading layout. That's all I had to show. Essentially, right now Its a Kotlin -backed creation, but can be made for Java specifically, C++, C#, etc. I'm planning on adding more into the language to make it even more robust. What's more, it doesn't need to be OpenGL backed- it can use Java paint classes, SFML, etc etc. I just need to standardize the API for it. I guess what I'm wondering is, if I put it out there- would anyone want to use it for desktop application dev? P.S. Of course the syntax is subject to change, via suggestion. P.S.[2] The image in the middle of the editor is static, but wont be when I put 3D scenes in the scene-view.
  33. 4 points
    What exactly is an Octree? If you're completely unfamiliar with them, I recommend reading the wikipedia article (read time: ~5 minutes). This is a sufficient description of what it is but is barely enough to give any ideas on what it's used for and how to actually implement one. In this article, I will do my best to take you through the steps necessary to create an octree data structure through conceptual explanations, pictures, and code, and show you the considerations to be made at each step along the way. I don't expect this article to be the authoritative way to do octrees, but it should give you a really good start and act as a good reference. Assumptions Before we dive in, I'm going to be making a few assumptions about you as a reader: You are very comfortable with programming in a C-syntax-style language (I will be using C# with XNA). You have programmed some sort of tree-like data structure in the past, such as a binary search tree and are familiar with recursion and its strengths and pitfalls. You know how to do collision detection with bounding rectangles, bounding spheres, and bounding frustums. You have a good grasp of common data structures (arrays, lists, etc) and understand Big-O notation (you can also learn about Big-O in this GDnet article). You have a development environment project which contains spatial objects which need collision tests. Setting the stage Let's suppose that we are building a very large game world which can contain thousands of physical objects of various types, shapes and sizes, some of which must collide with each other. Each frame we need to find out which objects are intersecting with each other and have some way to handle that intersection. How do we do it without killing performance? Brute force collision detection The simplest method is to just compare each object against every other object in the world. Typically, you can do this with two for loops. The code would look something like this: foreach(gameObject myObject in ObjList) { foreach(gameObject otherObject in ObjList) { if(myObject == otherObject) continue; //avoid self collision check if(myObject.CollidesWith(otherObject)) { //code to handle the collision } } } Conceptually, this is what we're doing in our picture: Each red line is an expensive CPU test for intersection. Naturally, you should feel horrified by this code because it is going to run in O(N^2) time. If you have 10,000 objects, then you're going to be doing 100,000,000 collision checks (hundred million). I don't care how fast your CPU is or how well you've tuned your math code, this code would reduce your computer to a sluggish crawl. If you're running your game at 60 frames per second, you're looking at 60 * 100 million calculations per second! It's nuts. It's insane. It's crazy. Let's not do this if we can avoid it, at least not with a large set of objects. This would only be acceptable if we're only checking, say, 10 items against each other (100 checks is palatable). If you know in advance that your game is only going to have a very small number of objects (i.e., asteriods), you can probably get away with using this brute force method for collision detection and ignore octrees altogether. If/when you start noticing performance problems due to too many collision checks per frame, consider some simple targeted optimizations: 1. How much computation does your current collision routine take? Do you have a square root hidden away in there (ie, a distance check)? Are you doing a granular collision check (pixel vs pixel, triangle vs triangle, etc)? One common technique is to perform a rough, coarse check for collision before testing for a granular collision check. You can give your objects an enclosing bounding rectangle or bounding sphere and test for intersection with these before testing against a granular check which may involve a lot more math and computation time. Use a "distance squared" check for comparing distance between objects to avoid using the square root method. Square root calculation typically uses the newtonian method of approximation and can be computationally expensive. 2. Can you get away with calculating fewer collision checks? If your game runs at 60 frames per second, could you skip a few frames? If you know certain objects behave deterministically, can you "solve" for when they will collide ahead of time (ie, pool ball vs. side of pool table). Can you reduce the number of objects which need to be checked for collisions? A technique for this would be to separate objects into several lists. One list could be your "stationary" objects list. They never have to test for collision against each other. The other list could be your "moving" objects, which need to be tested against all other moving objects and against all stationary objects. This could reduce the number of necessary collision tests to reach an acceptable performance level. 3. Can you get away with removing some object collision tests when performance becomes an issue? For example, a smoke particle could interact with a surface object and follow its contours to create a nice aesthetic effect, but it wouldn't break game play if you hit a predefined limit for collision checks and decided to stop ignoring smoke particles for collision. Ignoring essential game object movement would certainly break game play though (ei, player bullets stop intersecting with monsters). So, perhaps maintaining a priority list of collision checks to compute would help. First you handle the high priority collision tests, and if you're not at your threshold, you can handle lower priority collision tests. When the threshold is reached, you dump the rest of the items in the priority list or defer them for testing at a later time. 4. Can you use a faster but still simplistic method for collision detection to get away from a O(N^2) runtime? If you eliminate the objects you've already checked for collisions against, you can reduce the runtime to O(N(N+1)/2), which is much faster and still easy to implement. (technically, it's still O(N^2)) In terms of software engineering, you may end up spending more time than it's worth fine-tuning a bad algorithm & data structure choice to squeeze out a few more ounces of performance. The cost vs. benefit ratio becomes increasingly unfavorable and it becomes time to choose a better data structure to handle collision detection. Spatial partitioning algorithms are the proverbial nuke to solving the runtime problem for collision detection. At a small upfront cost to performance, they'll reduce your collision detection tests to logarithmic runtime. The upfront costs of development time and CPU overhead are easily outweighed by the scalability benefits and performance gains. Conceptual background on spatial partitioning Let's take a step back and look at spatial partitioning and trees in general before diving into Octrees. If we don't understand the conceptual idea, we have no hope of implementing it by sweating over code. Looking at the brute force implementation above, we're essentially taking every object in the game and comparing their positions against all other objects in the game to see if any are touching. All of these objects are contained spatially within our game world. Well, if we create an enclosing box around our game world and figure out which objects are contained within this enclosing box, then we've got a region of space with a list of contained objects within it. In this case, it would contain every object in the game. We can notice that if we have an object on one corner of the world and another object way on the other side, we don't really need to, or want to, calculate a collision check against them every frame. It'd be a waste of precious CPU time. So, let's try something interesting! If we divide our world exactly in half, we can create three separate lists of objects. The first list of objects, List A, contains all objects on the left half of the world. The second list, List B, contains objects on the right half of the world. Some objects may touch the dividing line such that they're on each side of the line, so we'll create a third list, List C, for these objects. We can notice that with each subdivision, we're spatially reducing the world in half and collecting a list of objects in that resulting half. We can elegantly create a binary search tree to contain these lists. Conceptually, this tree should look something like so: In terms of pseudo code, the tree data structure would look something like this: public class BinaryTree { //This is a list of all of the objects contained within this node of the tree private List m_objectList; //These are pointers to the left and right child nodes in the tree private BinaryTree m_left, m_right; //This is a pointer to the parent object (for upward tree traversal). private BinaryTree m_parent; } We know that all objects in List A will never intersect with any objects in List B, so we can almost eliminate half of the number of collision checks. We've still got the objects in List C which could touch objects in either list A or B, so we'll have to check all objects in List C against all objects in Lists A, B & C. If we continue to sub-divide the world into smaller and smaller parts, we can further reduce the number of necessary collision checks by half each time. This is the general idea behind spatial partitioning. There are many ways to subdivide a world into a tree-like data structure (BSP trees, Quad Trees, K-D trees, OctTrees, etc). Now, by default, we're just assuming that the best division is a cut in half, right down the middle, since we're assuming that all of our objects will be somewhat uniformly distributed throughout the world. It's not a bad assumption to make, but some spatial division algorithms may decide to make a cut such that each side has an equal amount of objects (a weighted cut) so that the resulting tree is more balanced. However, what happens if all of these objects move around? In order to maintain a nearly even division, you'd have to either shift the splitting plane or completely rebuild the tree each frame. It'd be a bit of a mess with a lot of complexity. So, for my implementation of a spatial partitioning tree I decided to cut right down the middle every time. As a result, some trees may end up being a bit more sparse than others, but that's okay -- it doesn't cost much. To subdivide or not to subdivide? That is the question. Let's assume that we have a somewhat sparse region with only a few objects. We could continue subdividing our space until we've found the smallest possible enclosing area for that object. But is that really necessary? Let's remember that the whole reason we're creating a tree is to reduce the number of collision checks we need to perform each frame -- not to create a perfectly enclosing region of space for every object. Here are the rules I use for deciding whether to subdivide or not: If we create a subdivision which only contains one object, we can stop subdividing even though we could keep dividing further. This rule will become an important part of the criteria for what defines a "leaf node" in our octree. The other important criteria is to set a minimum size for a region. If you have an extremely small object which is nanometers in size (or, god forbid, you have a bug and forgot to initialize an object size!), you're going to keep subdividing to the point where you potentially overflow your call stack. For my own implementation, I defined the smallest containing region to be a 1x1x1 cube. Any objects in this teeny cube will just have to be run with the O(N^2) brute force collision test (I don't anticipate many objects anyways!). If a containing region doesn't contain any objects, we shouldn't try to include it in the tree. We can take our subdivision by half one step further and divide the 2D world space into quadrants. The logic is essentially the same, but now we're testing for collision with four squares instead of two rectangles. We can continue subdividing each square until our rules for termination are met. The representation of the world space and corresponding data structure for a quad tree would look something like this: If the quad tree subdivision and data structure make sense, then an octree should be pretty straight forward as well. We're just adding a third dimension, using bounding cubes instead of bounding squares, and have eight possible child nodes instead of four. Some of you might wonder what should happen if you have a game world with non-cubic dimensions, say 200x300x400. You can still use an octree with cubic dimensions -- some child nodes will just end up empty if the game world doesn't have anything there. Obviously, you'll want to set the dimensions of your octree to at least the largest dimension of your game world. Octree Construction So, as you've read, an octree is a special type of subdividing tree commonly used for objects in 3D space (or anything with 3 dimensions). Our enclosing region is going to be a three dimensional rectangle (commonly a cube). We will then apply our subdivision logic above, and cut our enclosing region into eight smaller rectangles. If a game object completely fits within one of these subdivided regions, we'll push it down the tree into that node's containing region. We'll then recursively continue subdividing each resulting region until one of our breaking conditions is met. At the end, we should expect to have a nice tree-like data structure. My implementation of the octree can contain objects which have either a bounding sphere and/or a bounding rectangle. You'll see a lot of code I use to determine which is being used. In terms of our Octree class data structure, I decided to do the following for each tree: Each node has a bounding region which defines the enclosing region Each node has a reference to the parent node Contains an array of eight child nodes (use arrays for code simplicity and cache performance) Contains a list of objects contained within the current enclosing region I use a byte-sized bitmask for figuring out which child nodes are actively being used (the optimization benefits at the cost of additional complexity is somewhat debatable) I use a few static variables to indicate the state of the tree Here is the code for my Octree class outline: public class OctTree { BoundingBox m_region; List m_objects; /// /// These are items which we're waiting to insert into the data structure. /// We want to accrue as many objects in here as possible before we inject them into the tree. This is slightly more cache friendly. /// static Queue m_pendingInsertion = new Queue(); /// /// These are all of the possible child octants for this node in the tree. /// OctTree[] m_childNode = new OctTree[8]; /// /// This is a bitmask indicating which child nodes are actively being used. /// It adds slightly more complexity, but is faster for performance since there is only one comparison instead of 8. /// byte m_activeNodes = 0; /// /// The minumum size for enclosing region is a 1x1x1 cube. /// const int MIN_SIZE = 1; /// /// this is how many frames we'll wait before deleting an empty tree branch. Note that this is not a constant. The maximum lifespan doubles /// every time a node is reused, until it hits a hard coded constant of 64 /// int m_maxLifespan = 8; // int m_curLife = -1; //this is a countdown time showing how much time we have left to live /// /// A reference to the parent node is nice to have when we're trying to do a tree update. /// OctTree _parent; static bool m_treeReady = false; //the tree has a few objects which need to be inserted before it is complete static bool m_treeBuilt = false; //there is no pre-existing tree yet. } Initializing the enclosing region The first step in building an octree is to define the enclosing region for the entire tree. This will be the bounding box for the root node of the tree which initially contains all objects in the game world. Before we go about initializing this bounding volume, we have a few design decisions we need to make: 1. What should happen if an object moves outside of the bounding volume of the root node? Do we want to resize the entire octree so that all objects are enclosed? If we do, we'll have to completely rebuild the octree from scratch. If we don't, we'll need to have some way to either handle out of bounds objects, or ensure that objects never go out of bounds. 2. How do we want to create the enclosing region for our octree? Do we want to use a preset dimension, such as a 200x400x200 (X,Y,Z) rectangle? Or do we want to use a cubic dimension which is a power of 2? What should be the smallest allowable enclosing region which cannot be subdivided? Personally, I decided that I would use a cubic enclosing region with dimensions which are a power of 2, and sufficiently large to completely enclose my world. The smallest allowable cube is a 1x1x1 unit region. With this, I know that I can always cleanly subdivide my world and get integer numbers (even though the Vector3 uses floats). I also decided that my enclosing region would enclose the entire game world, so if an object leaves this region, it should be quietly destroyed. At the smallest octant, I will have to run a brute force collision check against all other objects, but I don't realistically expect more than 3 objects to occupy that small of an area at a time, so the performance costs of O(N^2) are completely acceptable. So, I normally just initialize my octree with a constructor which takes a region size and a list of items to insert into the tree. I feel it's barely worth showing this part of the code since it's so elementary, but I'll include it for completeness. Here are my constructors: /*Note: we want to avoid allocating memory for as long as possible since there can be lots of nodes.*/ /// /// Creates an oct tree which encloses the given region and contains the provided objects. /// /// The bounding region for the oct tree. /// The list of objects contained within the bounding region private OctTree(BoundingBox region, List objList) { m_region = region; m_objects = objList; m_curLife = -1; } public OctTree() { m_objects = new List(); m_region = new BoundingBox(Vector3.Zero, Vector3.Zero); m_curLife = -1; } /// /// Creates an octTree with a suggestion for the bounding region containing the items. /// /// The suggested dimensions for the bounding region. /// Note: if items are outside this region, the region will be automatically resized. public OctTree(BoundingBox region) { m_region = region; m_objects = new List(); m_curLife = -1; } Building an initial octree I'm a big fan of lazy initialization. I try to avoid allocating memory or doing work until I absolutely have to. In the case of my octree, I avoid building the data structure as long as possible. We'll accept a user's request to insert an object into the data structure, but we don't actually have to build the tree until someone runs a query against it. What does this do for us? Well, let's assume that the process of constructing and traversing our tree is somewhat computationally expensive. If a user wants to give us 1,000 objects to insert into the tree, does it make sense to recompute every subsequent enclosing area a thousand times? Or, can we save some time and do a bulk blast? I created a "pending" queue of items and a few flags to indicate the build state of the tree. All of the inserted items get put into the pending queue and when a query is made, those pending requests get flushed and injected into the tree. This is especially handy during a game loading sequence since you'll most likely be inserting thousands of objects at once. After the game world has been loaded, the number of objects injected into the tree is orders of magnitude fewer. My lazy initialization routine is contained within my UpdateTree() method. It checks to see if the tree has been built, and builds the data structure if it doesn't exist and has pending objects. /// /// Processes all pending insertions by inserting them into the tree. /// /// Consider deprecating this? private void UpdateTree() //complete & tested { if (!m_treeBuilt) { while (m_pendingInsertion.Count != 0) m_objects.Add(m_pendingInsertion.Dequeue()); BuildTree(); } else { while (m_pendingInsertion.Count != 0) Insert(m_pendingInsertion.Dequeue()); } m_treeReady = true; } As for building the tree itself, this can be done recursively. So for each recursive iteration, I start off with a list of objects contained within the bounding region. I check my termination rules, and if we pass, we create eight subdivided bounding areas which are perfectly contained within our enclosed region. Then, I go through every object in my given list and test to see if any of them will fit perfectly within any of my octants. If they do fit, I insert them into a corresponding list for that octant. At the very end, I check the counts on my corresponding octant lists and create new octrees and attach them to our current node, and mark my bitmask to indicate that those child octants are actively being used. All of the left over objects have been pushed down to us from our parent, but can't be pushed down to any children, so logically, this must be the smallest octant which can contain the object. /// /// Naively builds an oct tree from scratch. /// private void BuildTree() //complete & tested { //terminate the recursion if we're a leaf node if (m_objects.Count <= 1) return; Vector3 dimensions = m_region.Max - m_region.Min; if (dimensions == Vector3.Zero) { FindEnclosingCube(); dimensions = m_region.Max - m_region.Min; } //Check to see if the dimensions of the box are greater than the minimum dimensions if (dimensions.X <= MIN_SIZE && dimensions.Y <= MIN_SIZE && dimensions.Z <= MIN_SIZE) { return; } Vector3 half = dimensions / 2.0f; Vector3 center = m_region.Min + half; //Create subdivided regions for each octant BoundingBox[] octant = new BoundingBox[8]; octant[0] = new BoundingBox(m_region.Min, center); octant[1] = new BoundingBox(new Vector3(center.X, m_region.Min.Y, m_region.Min.Z), new Vector3(m_region.Max.X, center.Y, center.Z)); octant[2] = new BoundingBox(new Vector3(center.X, m_region.Min.Y, center.Z), new Vector3(m_region.Max.X, center.Y, m_region.Max.Z)); octant[3] = new BoundingBox(new Vector3(m_region.Min.X, m_region.Min.Y, center.Z), new Vector3(center.X, center.Y, m_region.Max.Z)); octant[4] = new BoundingBox(new Vector3(m_region.Min.X, center.Y, m_region.Min.Z), new Vector3(center.X, m_region.Max.Y, center.Z)); octant[5] = new BoundingBox(new Vector3(center.X, center.Y, m_region.Min.Z), new Vector3(m_region.Max.X, m_region.Max.Y, center.Z)); octant[6] = new BoundingBox(center, m_region.Max); octant[7] = new BoundingBox(new Vector3(m_region.Min.X, center.Y, center.Z), new Vector3(center.X, m_region.Max.Y, m_region.Max.Z)); //This will contain all of our objects which fit within each respective octant. List[] octList = new List[8]; for (int i = 0; i < 8; i++) octList = new List(); //this list contains all of the objects which got moved down the tree and can be delisted from this node. List delist = new List(); foreach (Physical obj in m_objects) { if (obj.BoundingBox.Min != obj.BoundingBox.Max) { for (int a = 0; a < 8; a++) { if (octant[a].Contains(obj.BoundingBox) == ContainmentType.Contains) { octList[a].Add(obj); delist.Add(obj); break; } } } else if (obj.BoundingSphere.Radius != 0) { for (int a = 0; a < 8; a++) { if (octant[a].Contains(obj.BoundingSphere) == ContainmentType.Contains) { octList[a].Add(obj); delist.Add(obj); break; } } } } //delist every moved object from this node. foreach (Physical obj in delist) m_objects.Remove(obj); //Create child nodes where there are items contained in the bounding region for (int a = 0; a < 8; a++) { if (octList[a].Count != 0) { m_childNode[a] = CreateNode(octant[a], octList[a]); m_activeNodes |= (byte)(1 << a); m_childNode[a].BuildTree(); } } m_treeBuilt = true; m_treeReady = true; } private OctTree CreateNode(BoundingBox region, List objList) //complete & tested { if (objList.Count == 0) return null; OctTree ret = new OctTree(region, objList); ret._parent = this; return ret; } private OctTree CreateNode(BoundingBox region, Physical Item) { List objList = new List(1); //sacrifice potential CPU time for a smaller memory footprint objList.Add(Item); OctTree ret = new OctTree(region, objList); ret._parent = this; return ret; } Updating a tree Let's imagine that our tree has a lot of moving objects in it. If any object moves, there is a good chance that the object has moved outside of its enclosing octant. How do we handle changes in object position while maintaining the integrity of our tree structure? Technique 1: Keep it super simple, trash & rebuild everything. Some implementations of an Octree will completely rebuild the entire tree every frame and discard the old one. This is super simple and it works, and if this is all you need, then prefer the simple technique. The general consensus is that the upfront CPU cost of rebuilding the tree every frame is much cheaper than running a brute force collision check, and programmer time is too valuable to be spent on an unnecessary optimization. For those of us who like challenges and to over-engineer things, the "trash & rebuild" technique comes with a few small problems: You're constantly allocating and deallocating memory each time you rebuild your tree. Allocating new memory comes with a small cost. If possible, you want to minimize the amount of memory being allocated and reallocated over time by reusing memory you've already got. Most of the tree is unchanging, so it's a waste of CPU time to rebuild the same branches over and over again. Technique 2: Keep the existing tree, update the changed branches I noticed that most branches of a tree don't need to be updated. They just contain stationary objects. Wouldn't it be nice if, instead of rebuilding the entire tree every frame, we just updated the parts of the tree which needed an update? This technique keeps the existing tree and updates only the branches which had an object which moved. It's a bit more complex to implement, but it's a lot more fun too, so let's really get into that! During my first attempt at this, I mistakenly thought that an object in a child node could only go up or down one traversal of the tree. This is wrong. If an object in a child node reaches the edge of that node, and that edge also happens to be an edge for the enclosing parent node, then that object needs to be inserted above its parent, and possibly up even further. So, the bottom line is that we don't know how far up an object needs to be pushed up the tree. Just as well, an object can move such that it can be neatly enclosed in a child node, or that child's child node. We don't know how far down the tree we can go. Fortunately, since we include a reference to each node's parent, we can easily solve this problem recursively with minimal computation! The general idea behind the update algorithm is to first let all objects in the tree update themselves. Some may move or change in size. We want to get a list of every object which moved, so the object update method should return to us a boolean value indicating if its bounding area changed. Once we've got a list of all of our moved objects, we want to start at our current node and try to traverse up the tree until we find a node which completely encloses the moved object (most of the time, the current node still encloses the object). If the object isn't completely enclosed by the current node, we keep moving it up to its next parent node. In the worst case, our root node will be guaranteed to contain the object. After we've moved our object as far up the tree as possible, we'll try to move it as far down the tree as we can. Most of the time, if we moved the object up, we won't be able to move it back down. But, if the object moved so that a child node of the current node could contain it, we have the chance to push it back down the tree. It's important to be able to move objects down the tree as well, or else all moving objects would eventually migrate to the top and we'd start getting some performance problems during collision detection routines. Branch Removal In some cases, an object will move out of a node and that node will no longer have any objects contained within it, nor have any children which contain objects. If this happens, we have an empty branch and we need to mark it as such and prune this dead branch off the tree. There is an interesting question hiding here: When do you want to prune the dead branches off a tree? Allocating new memory costs time, so if we're just going to reuse this same region in a few cycles, why not keep it around for a bit? How long can we keep it around before it becomes more expensive to maintain the dead branch? I decided to give each of my nodes a count down timer which activates when the branch is dead. If an object moves into this nodes octant while the death timer is active, I double the lifespan and reset the death timer. This ensures that octants which are frequently used are hot and stick around, and nodes which are infrequently used are removed before they start to cost more than they're worth. A practical example of this usefulness would be apparent when you have a machine gun shooting a stream of bullets. Those bullets follow in close succession of each other, so it'd be a shame to immediately delete a node as soon as the first bullet leaves it, only to recreate it a fraction of a second later as the second bullet re-enters it. And if there's a lot of bullets, we can probably keep these octants around for a little while. If a child branch is empty and hasn't been used in a while, it's safe to prune it out of our tree. Anyways, let's look at the code which does all of this magic. First up, we have the Update() method. This is a method which is recursively called on all child trees. It moves all objects around, does some house keeping work for the data structure, and then moves each moved object into its correct node (parent or child). public void Update(GameTime gameTime) { if (m_treeBuilt == true) { //Start a count down death timer for any leaf nodes which don't have objects or children. //when the timer reaches zero, we delete the leaf. If the node is reused before death, we double its lifespan. //this gives us a "frequency" usage score and lets us avoid allocating and deallocating memory unnecessarily if (m_objects.Count == 0) { if (HasChildren == false) { if (m_curLife == -1) m_curLife = m_maxLifespan; else if (m_curLife > 0) { m_curLife--; } } } else { if (m_curLife != -1) { if(m_maxLifespan <= 64) m_maxLifespan *= 2; m_curLife = -1; } } List movedObjects = new List(m_objects.Count); //go through and update every object in the current tree node foreach (Physical gameObj in m_objects) { //we should figure out if an object actually moved so that we know whether we need to update this node in the tree. if (gameObj.Update(gameTime)) { movedObjects.Add(gameObj); } } //prune any dead objects from the tree. int listSize = m_objects.Count; for (int a = 0; a < listSize; a++) { if (!m_objects[a].Alive) { if (movedObjects.Contains(m_objects[a])) movedObjects.Remove(m_objects[a]); m_objects.RemoveAt(a--); listSize--; } } //recursively update any child nodes. for( int flags = m_activeNodes, index = 0; flags > 0; flags >>=1, index++) if ((flags & 1) == 1) m_childNode[index].Update(gameTime); //If an object moved, we can insert it into the parent and that will insert it into the correct tree node. //note that we have to do this last so that we don't accidentally update the same object more than once per frame. foreach (Physical movedObj in movedObjects) { OctTree current = this; //figure out how far up the tree we need to go to reinsert our moved object //we are either using a bounding rect or a bounding sphere //try to move the object into an enclosing parent node until we've got full containment if (movedObj.BoundingBox.Max != movedObj.BoundingBox.Min) { while (current.m_region.Contains(movedObj.BoundingBox) != ContainmentType.Contains) if (current._parent != null) current = current._parent; else break; //prevent infinite loops when we go out of bounds of the root node region } else { while (current.m_region.Contains(movedObj.BoundingSphere) != ContainmentType.Contains)//we must be using a bounding sphere, so check for its containment. if (current._parent != null) current = current._parent; else break; } //now, remove the object from the current node and insert it into the current containing node. m_objects.Remove(movedObj); current.Insert(movedObj); //this will try to insert the object as deep into the tree as we can go. } //prune out any dead branches in the tree for (int flags = m_activeNodes, index = 0; flags > 0; flags >>= 1, index++) if ((flags & 1) == 1 && m_childNode[index].m_curLife == 0) { m_childNode[index] = null; m_activeNodes ^= (byte)(1 << index); //remove the node from the active nodes flag list } //now that all objects have moved and they've been placed into their correct nodes in the octree, we can look for collisions. if (IsRoot == true) { //This will recursively gather up all collisions and create a list of them. //this is simply a matter of comparing all objects in the current root node with all objects in all child nodes. //note: we can assume that every collision will only be between objects which have moved. //note 2: An explosion can be centered on a point but grow in size over time. In this case, you'll have to override the update method for the explosion. List irList = GetIntersection(new List()); foreach (IntersectionRecord ir in irList) { if (ir.PhysicalObject != null) ir.PhysicalObject.HandleIntersection(ir); if (ir.OtherPhysicalObject != null) ir.OtherPhysicalObject.HandleIntersection(ir); } } } else { } } Note that we call an Insert() method for moved objects. The insertion of objects into the tree is very similar to the method used to build the initial tree. Insert() will try to push objects as far down the tree as possible. Notice that I also try to avoid creating new bounding areas if I can use an existing one from a child node. /// /// A tree has already been created, so we're going to try to insert an item into the tree without rebuilding the whole thing /// /// A physical object /// The physical object to insert into the tree private void Insert(T Item) where T : Physical { /*make sure we're not inserting an object any deeper into the tree than we have to. -if the current node is an empty leaf node, just insert and leave it.*/ if (m_objects.Count <= 1 && m_activeNodes == 0) { m_objects.Add(Item); return; } Vector3 dimensions = m_region.Max - m_region.Min; //Check to see if the dimensions of the box are greater than the minimum dimensions if (dimensions.X <= MIN_SIZE && dimensions.Y <= MIN_SIZE && dimensions.Z <= MIN_SIZE) { m_objects.Add(Item); return; } Vector3 half = dimensions / 2.0f; Vector3 center = m_region.Min + half; //Find or create subdivided regions for each octant in the current region BoundingBox[] childOctant = new BoundingBox[8]; childOctant[0] = (m_childNode[0] != null) ? m_childNode[0].m_region : new BoundingBox(m_region.Min, center); childOctant[1] = (m_childNode[1] != null) ? m_childNode[1].m_region : new BoundingBox(new Vector3(center.X, m_region.Min.Y, m_region.Min.Z), new Vector3(m_region.Max.X, center.Y, center.Z)); childOctant[2] = (m_childNode[2] != null) ? m_childNode[2].m_region : new BoundingBox(new Vector3(center.X, m_region.Min.Y, center.Z), new Vector3(m_region.Max.X, center.Y, m_region.Max.Z)); childOctant[3] = (m_childNode[3] != null) ? m_childNode[3].m_region : new BoundingBox(new Vector3(m_region.Min.X, m_region.Min.Y, center.Z), new Vector3(center.X, center.Y, m_region.Max.Z)); childOctant[4] = (m_childNode[4] != null) ? m_childNode[4].m_region : new BoundingBox(new Vector3(m_region.Min.X, center.Y, m_region.Min.Z), new Vector3(center.X, m_region.Max.Y, center.Z)); childOctant[5] = (m_childNode[5] != null) ? m_childNode[5].m_region : new BoundingBox(new Vector3(center.X, center.Y, m_region.Min.Z), new Vector3(m_region.Max.X, m_region.Max.Y, center.Z)); childOctant[6] = (m_childNode[6] != null) ? m_childNode[6].m_region : new BoundingBox(center, m_region.Max); childOctant[7] = (m_childNode[7] != null) ? m_childNode[7].m_region : new BoundingBox(new Vector3(m_region.Min.X, center.Y, center.Z), new Vector3(center.X, m_region.Max.Y, m_region.Max.Z)); //First, is the item completely contained within the root bounding box? //note2: I shouldn't actually have to compensate for this. If an object is out of our predefined bounds, then we have a problem/error. // Wrong. Our initial bounding box for the terrain is constricting its height to the highest peak. Flying units will be above that. // Fix: I resized the enclosing box to 256x256x256. This should be sufficient. if (Item.BoundingBox.Max != Item.BoundingBox.Min && m_region.Contains(Item.BoundingBox) == ContainmentType.Contains) { bool found = false; //we will try to place the object into a child node. If we can't fit it in a child node, then we insert it into the current node object list. for(int a=0;a<8;a++) { //is the object fully contained within a quadrant? if (childOctant[a].Contains(Item.BoundingBox) == ContainmentType.Contains) { if (m_childNode[a] != null) m_childNode[a].Insert(Item); //Add the item into that tree and let the child tree figure out what to do with it else { m_childNode[a] = CreateNode(childOctant[a], Item); //create a new tree node with the item m_activeNodes |= (byte)(1 << a); } found = true; } } if(!found) m_objects.Add(Item); } else if (Item.BoundingSphere.Radius != 0 && m_region.Contains(Item.BoundingSphere) == ContainmentType.Contains) { bool found = false; //we will try to place the object into a child node. If we can't fit it in a child node, then we insert it into the current node object list. for (int a = 0; a < 8; a++) { //is the object contained within a child quadrant? if (childOctant[a].Contains(Item.BoundingSphere) == ContainmentType.Contains) { if (m_childNode[a] != null) m_childNode[a].Insert(Item); //Add the item into that tree and let the child tree figure out what to do with it else { m_childNode[a] = CreateNode(childOctant[a], Item); //create a new tree node with the item m_activeNodes |= (byte)(1 << a); } found = true; } } if (!found) m_objects.Add(Item); } else { //either the item lies outside of the enclosed bounding box or it is intersecting it. Either way, we need to rebuild //the entire tree by enlarging the containing bounding box //BoundingBox enclosingArea = FindBox(); BuildTree(); } } Collision Detection Finally, our octree has been built and everything is as it should be. How do we perform collision detection against it? First, let's list out the different ways we want to look for collisions: Frustum intersections. We may have a frustum which intersects with a region of the world. We only want the objects which intersect with the given frustum. This is particularly useful for culling regions outside of the camera view space, and for figuring out what objects are within a mouse selection area. Ray intersections. We may want to shoot a directional ray from any given point and want to know either the nearest intersecting object, or get a list of all objects which intersect that ray (like a rail gun). This is very useful for mouse picking. If the user clicks on the screen, we want to draw a ray into the world and figure out what they clicked on. Bounding Box intersections. We want to know which objects in the world are intersecting a given bounding box. This is most useful for "box" shaped game objects (houses, cars, etc). Bounding Sphere Intersections. We want to know which objects are intersecting with a given bounding sphere. Most objects will probably be using a bounding sphere for coarse collision detection since the mathematics is computationally the least expensive and somewhat easy. The main idea behind recursive collision detection processing for an octree is that you start at the root/current node and test for intersection with all objects in that node against the intersector. Then, you do a bounding box intersection test against all active child nodes with the intersector. If a child node fails this intersection test, you can completely ignore the rest of that child's tree. If a child node passes the intersection test, you recursively traverse down the tree and repeat. Each node should pass a list of intersection records up to its caller, which appends those intersections to its own list of intersections. When the recursion finishes, the original caller will get a list of every intersection for the given intersector. The beauty of this is that it takes very little code to implement and performance is very fast. In a lot of these collisions, we're probably going to be getting a lot of results. We're also going to want to have some way of responding to each collision, depending on what objects are colliding. For example, a player hero should pick up a floating bonus item (quad damage!), but a rocket shouldn't explode if it hits said bonus item. I created a new class to contain information about each intersection. This class contains references to the intersecting objects, the point of intersection, the normal at the point of intersection, etc. These intersection records become quite useful when you pass them to an object and tell them to handle it. For completeness and clarity, here is my intersection record class: public class IntersectionRecord { Vector3 m_position; /// /// This is the exact point in 3D space which has an intersection. /// public Vector3 Position { get { return m_position; } } Vector3 m_normal; /// /// This is the normal of the surface at the point of intersection /// public Vector3 Normal { get { return m_normal; } } Ray m_ray; /// /// This is the ray which caused the intersection /// public Ray Ray { get { return m_ray; } } Physical m_intersectedObject1; /// /// This is the object which is being intersected /// public Physical PhysicalObject { get { return m_intersectedObject1; } set { m_intersectedObject1 = value; } } Physical m_intersectedObject2; /// /// This is the other object being intersected (may be null, as in the case of a ray-object intersection) /// public Physical OtherPhysicalObject { get { return m_intersectedObject2; } set { m_intersectedObject2 = value; } } /// /// this is a reference to the current node within the octree for where the collision occurred. In some cases, the collision handler /// will want to be able to spawn new objects and insert them into the tree. This node is a good starting place for inserting these objects /// since it is a very near approximation to where we want to be in the tree. /// OctTree m_treeNode; /// /// check the object identities between the two intersection records. If they match in either order, we have a duplicate. /// ///the other record to compare against /// true if the records are an intersection for the same pair of objects, false otherwise. public override bool Equals(object otherRecord) { IntersectionRecord o = (IntersectionRecord)otherRecord; // //return (m_intersectedObject1 != null && m_intersectedObject2 != null && m_intersectedObject1.ID == m_intersectedObject2.ID); if (otherRecord == null) return false; if (o.m_intersectedObject1.ID == m_intersectedObject1.ID && o.m_intersectedObject2.ID == m_intersectedObject2.ID) return true; if (o.m_intersectedObject1.ID == m_intersectedObject2.ID && o.m_intersectedObject2.ID == m_intersectedObject1.ID) return true; return false; } double m_distance; /// /// This is the distance from the ray to the intersection point. /// You'll usually want to use the nearest collision point if you get multiple intersections. /// public double Distance { get { return m_distance; } } private bool m_hasHit = false; public bool HasHit { get { return m_hasHit; } } public IntersectionRecord() { m_position = Vector3.Zero; m_normal = Vector3.Zero; m_ray = new Ray(); m_distance = float.MaxValue; m_intersectedObject1 = null; } public IntersectionRecord(Vector3 hitPos, Vector3 hitNormal, Ray ray, double distance) { m_position = hitPos; m_normal = hitNormal; m_ray = ray; m_distance = distance; // m_hitObject = hitGeom; m_hasHit = true; } /// /// Creates a new intersection record indicating whether there was a hit or not and the object which was hit. /// ///Optional: The object which was hit. Defaults to null. public IntersectionRecord(Physical hitObject = null) { m_hasHit = hitObject != null; m_intersectedObject1 = hitObject; m_position = Vector3.Zero; m_normal = Vector3.Zero; m_ray = new Ray(); m_distance = 0.0f; } } Intersection with a Bounding Frustum /// /// Gives you a list of all intersection records which intersect or are contained within the given frustum area /// ///The containing frustum to check for intersection/containment with /// A list of intersection records with collisions private List GetIntersection(BoundingFrustum frustum, Physical.PhysicalType type = Physical.PhysicalType.ALL) { if (m_objects.Count == 0 && HasChildren == false) //terminator for any recursion return null; List ret = new List(); //test each object in the list for intersection foreach (Physical obj in m_objects) { //skip any objects which don't meet our type criteria if ((int)((int)type & (int)obj.Type) == 0) continue; //test for intersection IntersectionRecord ir = obj.Intersects(frustum); if (ir != null) ret.Add(ir); } //test each object in the list for intersection for (int a = 0; a < 8; a++) { if (m_childNode[a] != null && (frustum.Contains(m_childNode[a].m_region) == ContainmentType.Intersects || frustum.Contains(m_childNode[a].m_region) == ContainmentType.Contains)) { List hitList = m_childNode[a].GetIntersection(frustum); if (hitList != null) { foreach (IntersectionRecord ir in hitList) ret.Add(ir); } } } return ret; } The bounding frustum intersection list can be used to only render objects which are visible to the current camera view. I use a scene database to figure out how to render all objects in the game world. Here is a snippet of code from my rendering function which uses the bounding frustum of the active camera: /// /// This renders every active object in the scene database /// /// public int Render() { int triangles = 0; //Renders all visible objects by iterating through the oct tree recursively and testing for intersection //with the current camera view frustum foreach (IntersectionRecord ir in m_octTree.AllIntersections(m_cameras[m_activeCamera].Frustum)) { ir.PhysicalObject.SetDirectionalLight(m_globalLight[0].Direction, m_globalLight[0].Color); ir.PhysicalObject.View = m_cameras[m_activeCamera].View; ir.PhysicalObject.Projection = m_cameras[m_activeCamera].Projection; ir.PhysicalObject.UpdateLOD(m_cameras[m_activeCamera]); triangles += ir.PhysicalObject.Render(m_cameras[m_activeCamera]); } return triangles; } Intersection with a Ray /// /// Gives you a list of intersection records for all objects which intersect with the given ray /// ///The ray to intersect objects against /// A list of all intersections private List GetIntersection(Ray intersectRay, Physical.PhysicalType type = Physical.PhysicalType.ALL) { if (m_objects.Count == 0 && HasChildren == false) //terminator for any recursion return null; List ret = new List(); //the ray is intersecting this region, so we have to check for intersection with all of our contained objects and child regions. //test each object in the list for intersection foreach (Physical obj in m_objects) { //skip any objects which don't meet our type criteria if ((int)((int)type & (int)obj.Type) == 0) continue; if (obj.BoundingBox.Intersects(intersectRay) != null) { IntersectionRecord ir = obj.Intersects(intersectRay); if (ir.HasHit) ret.Add(ir); } } // test each child octant for intersection for (int a = 0; a < 8; a++) { if (m_childNode[a] != null && m_childNode[a].m_region.Intersects(intersectRay) != null) { List hits = m_childNode[a].GetIntersection(intersectRay, type); if (hits != null) { foreach (IntersectionRecord ir in hits) ret.Add(ir); } } } return ret; } Intersection with a list of objects This is a particularly useful recursive method for determining if a list of objects in the current node intersect with any objects in any child nodes (See: Update() method for usage). It's the method which will be used most frequently, so it's good to get this right and efficient. What we want to do is start at the root node of the tree. We compare all objects in the current node against all other objects in the current node for collision. We gather up any of those collisions as intersection records, and insert them into a list. We then pass our list of tested objects down to our child nodes. The child nodes will then test their objects against themselves, then against the objects we passed down to them. The child nodes will capture any collisions in a list, and return that list to its parent. The parent then takes the collision list received from its child nodes and appends it to its own list of collisions, finally returning it to its caller. If you count out the number of collision tests in the illustration above, you can see that we conducted 29 hit tests and recieved 4 hits. This is much better than [11*11 = 121] hit tests. private List GetIntersection(List parentObjs, Physical.PhysicalType type = Physical.PhysicalType.ALL) { List intersections = new List(); //assume all parent objects have already been processed for collisions against each other. //check all parent objects against all objects in our local node foreach (Physical pObj in parentObjs) { foreach (Physical lObj in m_objects) { //We let the two objects check for collision against each other. They can figure out how to do the coarse and granular checks. //all we're concerned about is whether or not a collision actually happened. IntersectionRecord ir = pObj.Intersects(lObj); if (ir != null) { intersections.Add(ir); } } } //now, check all our local objects against all other local objects in the node if (m_objects.Count > 1) { #region self-congratulation /* * This is a rather brilliant section of code. Normally, you'd just have two foreach loops, like so: * foreach(Physical lObj1 in m_objects) * { * foreach(Physical lObj2 in m_objects) * { * //intersection check code * } * } * * The problem is that this runs in O(N*N) time and that we're checking for collisions with objects which have already been checked. * Imagine you have a set of four items: {1,2,3,4} * You'd first check: {1} vs {1,2,3,4} * Next, you'd check {2} vs {1,2,3,4} * but we already checked {1} vs {2}, so it's a waste to check {2} vs. {1}. What if we could skip this check by removing {1}? * We'd have a total of 4+3+2+1 collision checks, which equates to O(N(N+1)/2) time. If N is 10, we are already doing half as many collision checks as necessary. * Now, we can't just remove an item at the end of the 2nd for loop since that would break the iterator in the first foreach loop, so we'd have to use a * regular for(int i=0;i tmp = new List(m_objects.Count); tmp.AddRange(m_objects); while (tmp.Count > 0) { foreach (Physical lObj2 in tmp) { if (tmp[tmp.Count - 1] == lObj2 || (tmp[tmp.Count - 1].IsStatic && lObj2.IsStatic)) continue; IntersectionRecord ir = tmp[tmp.Count - 1].Intersects(lObj2); if (ir != null) intersections.Add(ir); } //remove this object from the temp list so that we can run in O(N(N+1)/2) time instead of O(N*N) tmp.RemoveAt(tmp.Count-1); } } //now, merge our local objects list with the parent objects list, then pass it down to all children. foreach (Physical lObj in m_objects) if (lObj.IsStatic == false) parentObjs.Add(lObj); //parentObjs.AddRange(m_objects); //each child node will give us a list of intersection records, which we then merge with our own intersection records. for (int flags = m_activeNodes, index = 0; flags > 0; flags >>= 1, index++) if ((flags & 1) == 1) intersections.AddRange(m_childNode[index].GetIntersection(parentObjs, type)); return intersections; } ;i++)> Screenshot Demos This is a view of the game world from a distance showing the outlines for each bounding volume for the octree. This view shows a bunch of successive projectiles moving through the game world with the frequently-used nodes being preserved instead of deleted. Complete Code Sample I've attached a complete code sample of the octree class, the intersection record class, and my generic physical object class. I don't guarantee that they're all bug-free since it's all a work in progress and hasn't been rigorously tested yet.
  34. 3 points
    You could start by writing very simple games. When people ask about how and what I keep suggesting the following: Take a simple game: 4Wins, Tic Tac Toe or Battleship. Decide up on a programming language you want to learn/use in order to write the game - It can be a mix of languages later, but you should start with one first. Could be C, C++, C#, Pascal, Python, that's really up to you. Then you start by writing your game for the little command line window, text output only. You will learn about text input and output, how to read from the keyboard and how to print your things on screen, probably reading and writing from files and to files. Once your - let's say Tic Tac Toe - works, because you figured out the game logic before, you extend your existing game. You could add a little menu, where you could select from "New Game", "Options", "Highscore", "Exit". New Game starts a new round, inside Options you could modify the text colour, highscore lists all your previous games and sorts them by the moves it took to win the game or something similar, and Exit returns to your OS. Once that works, you could introduce different game modes, Player vs Player, Player vs Computer, Computer vs Computer, maybe as a sub menu in the New Game menu Once that works, you could jump from a console window to something more sophisticated, 2D sprites, textures, colourful backgrounds. Either by handcrafting all the glue required for that or by using some existing libraries or frameworks like SDL, sfml, freeglut, plain old windows GDI+ or the linux/mac counterparts. Once you got that working, why not add music? Background music, Sounds for placing Xs and Os, Win/Loss, Menu music. Once that works, make the game more interesting, Fiddle with modes like the player only has ten/three/two/one seconds to decide on a spot to put his X or O or the game will be lost. As the counter runs down, the music could become more dramatic Once that works, why not look at networking. Players of your great game could gather in a lobby, with little chat rooms where they can just hang and talk about great Tic Tac Toe games from the past, or plan tactics on how to defeat certain players or computers. You probable need a new menu for that where you can start a game or join a game of some sort. Eventually you might add some matchmaking system taking rank and other aspects into account for people to play together. Maybe even have some ladder system, game of hall or similar. Depending wether you want your game to be 2D or 3D you could level up the dimensions of your game now. and make it a 3D Game. The battlefield becomes 3D and more plastic, instead of sprites you might use real objects, models. While writing that, I got another idea. If you add networking, players could even provide their own little figurine (sprite/model) to be used while rendering the playground instead of the default ones (could be an optional setting somewhere) Of course you don't write all that within a week. But you can create little tasks out of those chunks. Tasks which can be easily achieved and keep you motivated as you see yourself progressing. Create a little todo.txt, or create a project on those sites like GitHub, BitBucket, Gitlab . They all come with a ticketsystem, where you can organise your todos if you prefer that over a simple textfile. When you are stuck somewhere you grab your little duck and talk to it/her/him, listen to what he/she/it tells you or debug your things which don't work. If you can't figure it out, you join us here and ask for help. I hope any of what I said above makes any sense to anyone.
  35. 3 points
    Three weeks have passed, a few new people have installed the game. I had the chance to deploy the game also to juniors x86 tablet, where it currently crashes. The tablet does have a gyro sensor, which I thought worked fine when using it on Windows Phone, but apparently the code isn't crash proof enough. I've been looking mostly for crashes now, and a handful (well, two in the last 3 days) did appear. The crash info is all over the place. Some have a really great stack trace, other nothing. Some seem to be in between. I reckon this is heavily affected by fiddling with telemetry settings. What I'm also missing on a first glance is the configuration of the crashed app. Since the compile builds executables for x86, x64 and ARM it'd be nice to know which of these were the cause. What's always there is the name, IP, Windows build version and device type of the device that was running the game. While the stack traces sometimes help they are only that. You don't get a full dump or local watch info. So you can get lucky and the location of the problem is clear, or you're out of luck. In these last two crashes the stack traces hints on a null pointer on a method that is used throughout the game (GUI displaying a texture section). I suspect that it happens during startup and the code path went inside a function when it wasn't ready. In these cases I can only add a safety check and cleanly jump out of the function. Build, upload, re-certify and next try in 1 to 3 days. Currently I'm struggling getting remote debugging done on the tablet. I can deploy the app via enabled web portal, but the remote debugger is not properly recognized by Visual Studio. I was hoping for USB debugging as that works nicely on the phone, but had no luck with it. Well, here's to the next version hoping to get those crashes fixed!
  36. 3 points
    An engine is MUCH more than just showing a 3d model. I like to think engines as having a whole loop. Input, update, and render. It's then up to you to put in the data. Model loading and displaying is one of the most basic things an engine can do. Many languages offer .obj loading with a single line of code. For example Javascript can do it using p5 with a single loadmodel() function. If you want to display it, then it's just 14 lines of code. Often rendering something requires a sequence of events, and more than just "plugging in" something. However, both Unity and Blender use node editors for "plug in" effects. (Example picture is in the link). In blender's case each node is written in python and new ones are developed all the time. (I don't use Unity, but I think those nodes are written in C#) I think what you are proposing is a thing engines already do.
  37. 3 points
    During the interview for the job I have now, I told the interviewer that I felt it was my obligation to help my previous (then current) company finish an important project and asked them to let me start 2 months later. I expected that to be a problem for them, but quite the contrary: After the interview, they told me they had talked about that and found it meant I was a loyal person and that they felt assured that if I ever left the new company, I'd give them enough time to find a replacement, too. Have you tried talking to the new company about the issue? Maybe they are more open to it than you think.
  38. 3 points
    I haven't used GameMaker since before YoYo Games got involved, and did use it from version 2 to 5 off and on when Mark Overmars was the main man. I've never considered it an engine as I would consider something like Irrlicht, or Orge3D, nor has anyone else I've ever known. I've looked at it like a good starting tool that allows people to create 2D games within a limited environment that has added scripting for those wanting to get into GML as an entry level language (You may define it as an engine simply because it has GML, which is fine). My comment still stands, it's not at the same level as Unity, and I never said GameMaker was some useless toy. In fact, you can view my post history, I recommend it to a lot of new game developers as it has a lot of potential for people starting out. I've also seen some very good games created using the application. I understand where you're coming from about GameMaker. It wasn't a tool for me back then, and simply isn't a tool for me today considering I went all out into developing programming skills because I wanted more control and custom options, not to mention I really wanted to 'program'. I honestly cannot think of one friend back in 2000 that is currently using any GameMaker tool to date. Most of us are either using our own in house engines, or 3rd party commercial engines. " Hi i am a c++ programmer, Want to make games for mobile with c++ and compile it to android and ios. " Considering the original poster was referencing C++, for me to even suggest GameMaker would not be relevant as an option, and if you know C++ and intend on making games with it, why use GameMaker Studio? It would be better to start off with SDL, Allegro, or SFML if Unreal, or another engine if it's not an option. GameMaker Studio 2 is great for what it provides, and who it caters to, and is simply an entry level solution for non advanced programmers, or those who never intend on learning to program. Also, my "opinion" of what an engine is may also be wrong in this case under the 'true' definition of a game engine. GameMaker Studio 2 can very well be 'defined' as a game engine. I just don't look at it that way because I come from a different perspective and have always viewed GameMaker as a tool to create games. I just don't put it in the same category as Unity however.
  39. 3 points
  40. 3 points
    It's very easy to overcome emptiness. Here is how to do it: 1. You need the size of your world. Split the world into 256x256 pixel areas (or higher, lesser). 2. Create a trigger for the entrance of each area, so that when player enters it, either a big boss spawns, earthquake appears, music changes, player dies and etc. 3. Each area should have a decoration that is random and does not appear in the any area that is close to that one And etc.
  41. 3 points
    Hi all, I'm an indie app n game developer during my spare times; mainly focused on iOS for the time being ... recently having published a few simple 2d iOS games on the Apple App Store which can be found from my website http://techchee.com , would love to learn from peers how to promote or market mobile games or develop more sophisticated ones 😄
  42. 3 points
    Normally this is called a layered approach. Minecraft is a great example of just how far you can take this and how you can use it to build a looping progress mechanic. The reason why it's considered layers on not dimensions is because these parts of the games are linked in series. For example in XCOM to advance the campaign you do need to play the battles. A dimension approach would be something where the one play style doesn't effect the other. For example in 2D adding a value to X doesn't advance you on the Y axis. Dimension are independent, but by using both you can get to points where you want to be. Visual novels are more of a Dimension type of games. If you want to unlock some special parts of the stories you need to do something with one character, then something else with a other character; yet you can also just progress the game by just focusing on one character. Most common layers is often only 2-3 and often is combined with a story dimension tree. The only limits to both is physical. How many layers or dimensions can you make in 1-3 years, it's all about how much money and time you can spend planing it all out. If your a immortal with unlimited time you could add unlimited dimensions or layers to a game; or at least to the point where the game fills your computer with data.
  43. 3 points
    I call this "The Betty White Effect". In her later years Betty White did a few roles where she played an evil character. The fact that she seemed so over-the-top happy and nice just made her seem even more evil and she did very well in those roles, which you wouldn't expect her too. The opposite look and feel of what you are going for can sometimes actually enhance the effect, rather than detract from it as you would expect it too.
  44. 3 points
    I liked TLJ. Saw it twice, including premiere night. I know its a flawed film that has many other variants of the story could have been done differently. Regardless I like it. Daisy is amazing and I like how Rey's character has grown. I can explain my thoughts if you'd like. As for Mark's recent opinions, I care less. Admittedly a little of it is understandable. His acting was top notch and I think the way Luke went out was great.
  45. 3 points
    It looks like you're doing inheritance wrong. Done correctly you don't need to know what the concrete type is. If you find yourself doing a dynamic cast to a derived type, you are likely doing something wrong. The general principles have the acronym SOLID. I suggest you start reading from that article. You should have a well-designed abstract base interface that other code is derived from. All the derived versions should operate correctly on that interface. All objects should be replaceable with similar objects and still be correct. This is called Liskov substitution principle named after a famous person who described it. It is also called the Template Method pattern. This is also used in ECS systems and is a major reason they are popular, all components follow the well-defined interface. Then you should always work with the abstract type, not the derived classes. This is called the dependency inversion principle. This is used in many systems, including ECS systems, to prevent brittleness. In your example you would need to modify Derived1 any time you added any new functionality. It would quickly go to a long list of redirections detecting if it is Derived2, or Derived3, or Derived4, or Derived103. But if you always work with the abstract types the problem goes away. After that, I suggest you read this article. That's an example of the right way to implement virtual functions. And after that, recognize that most code in games is not about individual actions but about bulk actions. Many times people build objects and systems that work on single items, single data structures, single instances. But the code rarely operates on a single thing, instead working on bulk items, bulk data structures and array, collections of instances. Take whatever reasonable steps you can to convert to bulk actions rather than individual actions, which avoids considerable overhead and can be leveraged for cache benefits.
  46. 3 points
    We don't know. Is your game good? Fun to play? Does it look good? Does it look fun? How are you marketing it? Just being on Steam doesn't necessarily guarantee you any sales, it depends on your game and what you do to sell it. You will likely get at least a few sales just for being there, but there's really no guarantee.
  47. 3 points
    https://msdn.microsoft.com/en-us/library/windows/desktop/dn899209(v=vs.85).aspx edit - IIRC you can't put a texture SRV in the root.
  48. 3 points
    Linear means 4 corner and bilinear interpolation, period, either magnification or minification. The only difference is that relative to your screen, magnification will hit the same 4 corners and produce a smooth interpolation, while under minification, each screen pixel will hit texels far away from each other, but each pixel will still interpolate between the 4 neighbors. Your only way to have performance and not a mess of aliased texel is to generate mip maps offline. The mip maps are nothing more than an offline pre-convolution to respect the rule of signal processing. ( display need at least twice the resolution of the signal to prevent aliasing ). That process is offline because as you can imagine, the GPU does not have the power to integrate for each pixel to draw, large area of the texture
  49. 3 points
    The problem with Asimov's laws is that they set an impossibly high standard. Asimov's first law: "A robot may not injure a human being or, through inaction, allow a human being to come to harm.". Now, the global death rate is around 0.8% of the total population of the Earth per year. Given the current global population of 7.6 billion, that's around 60 million deaths per year, or 170 thousand per day. Just about all of these deaths are, in an abstract sense, preventable, which means that our hypothetical AI operating under Asimov's laws will have to prevent these 170 thousand deaths each day before it can even look at the second law. Some of these deaths will be relatively easy to prevent (1.25 million deaths per year from traffic accidents), some are going to be much harder (old age, freak accidents, deliberate murder and suicide), and some are going to be as good as impossible (mass starvation in an ever-increasing population once all other causes of death are eliminated).
  50. 3 points
    I noticed some other slowness and made some adjustments to the server. Managed to drop CPU utilization about 50% along with reductions in bandwidth and disk usage - long story short things appear to be much more responsive across the board.
  • Advertisement