Jump to content
  • Advertisement

Blogs

A Post UMA2 World... Apparently I hadn't squash the Jitters.

So, I ripped out all the UMA2 code from my game client.  Slapped in some Space Robot Kyle.  Say Hi! And apparently, I guess some of the mesh magic going on behind the scenes of the 10000+ lines of code that is UMA2, was suppressing the last bit of positional jitter...  So, if you've been following along, you may recall that I was relying heavily on a parent child relationship to keep the player character attached to the planet when the planet was rotated to keep the player/camera close to 0,0,0, in order to squash the jitters.  That was apparently ill advised, and it's actually been a nagging disparity in my mind for a while.  That being, when the player character was a child of the planet object, the player characters 0,0,0 was actually 0,-30000,0 in the Unity game world. So, now, the player character is "parent-less" and I've modified the planet moving script to adjust the position of the player along with the planet.  Since this all happens within a single Physics tick, it's visibly seamless.  MAJOR Caveat:  When I enable this planetary rotation to occur when the player is in motion, I'll need to add some more code to handle velocity adjustments and whatnot.  As it stands, a player could theoretically run non-stop out of the 10000unit bubble and the rotation script wouldn't try to kick in until they stopped moving.  I currently have no idea if this would result in jitters, but my guess is yes. New planet rotation code: using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlanetController : MonoBehaviour { public GameObject Planet; public GameObject Player; public Rigidbody prb; public UWThirdPerson.UWThirdPersonCharacter tpc; Vector3 upvector; int cnt = 2000; int interval = 2000; Vector3 newP; private void Start() { prb = Player.GetComponent<Rigidbody>(); tpc = Player.GetComponent<UWThirdPerson.UWThirdPersonCharacter>(); } void FixedUpdate() { cnt++; if (cnt > interval) { if (prb.velocity.magnitude < 1) { //Convert and store players position as the current planet relative position. newP = Planet.transform.InverseTransformPoint(Player.transform.position); //Rotate Planet Object(and children). Planet.transform.localRotation = Quaternion.FromToRotation((Player.transform.position - Planet.transform.position).normalized, Vector3.up); //Extract and set the new "world" positon of the player's planet relative position. Player.transform.position = Planet.transform.TransformPoint(newP); cnt = 0; } } } } Still, for now, the Camera is a child of the planet object as that preserves it's angle and direction with the least amount of code, and it is jitter free.  Very strange imho.. And yet again, the player is totally jitter free.  My client code is also now 10000+ lines lighter, and I'm ALWAYS happy when I can get rid of code I didn't write.  That was nagging at me too. I've revised a few parts of the design mind map, all UI elements are now going to be simple HUD style "robot vision" type elements.  Since we're no longer using Human characters, it's perfectly logical that text and images might just appear out of nowhere.   I've also yanked out all the organic modeling branches from the design tree, YAY!! Aside from the rotation code there were a quite a few other places(and still are probably) where I had to perform a TransformPoint() or InverseTransformPoint() of the players position (from the planets transform) for the game logic to continue unhindered thinking that the player is actually existing within the planets relative coordinate system.  If I tried NOT to do this, then the players tracked coordinates wouldn't be very useful at all, since it never really gets more than a few hundred/thousand units away from 0,0,0(terrain elevation variations). So, all in all, an hour or so of ripping out stale code references and a bit of an object juggle and my world is ready for a total robot revolution.  Now, off to Blender land for a few days while I build Kyle's replacement(s).

Septopus

Septopus

 

OOP is dead, long live OOP

edit: Seeing this has been linked outside of game-development circles: "ECS" (this wikipedia page is garbage, btw -- it conflates EC-frameworks and ECS-frameworks, which aren't the same...) is a faux-pattern circulated within game-dev communities, which is basically a version of the relational model, where "entities" are just ID's that represent a formless object, "components" are rows in specific tables that reference an ID, and "systems" are procedural code that can modify the components. This "pattern" is always posed as a solution to an over-use of inheritance, without mentioning that an over-use of inheritance is actually bad under OOP guidelines. Hence the rant. This isn't the "one true way" to write software. It's getting people to actually look at existing design guidelines. Inspiration This blog post is inspired by Aras Pranckevičius' recent publication of a talk aimed at junior programmers, designed to get them to come to terms with new "ECS" architectures. Aras follows the typical pattern (explained below), where he shows some terrible OOP code and then shows that the relational model is a great alternative solution (but calls it "ECS" instead of relational). This is not a swipe at Aras at all - I'm a fan of his work and commend him on the great presentation! The reason I'm picking on his presentation in particular instead of the hundred other ECS posts that have been made on the interwebs, is because he's gone through the effort of actually publishing a git repository to go along with his presentation, which contains a simple little "game" as a playground for demonstrating different architecture choices. This tiny project makes it easy for me to actually, concretely demonstrate my points, so, thanks Aras! You can find Aras'  slides at http://aras-p.info/texts/files/2018Academy - ECS-DoD.pdf and the code at https://github.com/aras-p/dod-playground. I'm not going to analyse the final ECS architecture from that talk (yet?), but I'm going to focus on the straw-man "bad OOP" code from the start. I'll show what it would look like if we actually fix all of the OOD rule violations.
Spoiler: fixing the OOD violations actually results in a similar performance improvement to Aras' ECS conversion, plus it actually uses less RAM and requires less lines of code than the ECS version!
TL;DR: Before you decide that OOP is shit and ECS is great, stop and learn OOD (to know how to use OOP properly) and learn relational (to know how to use ECS properly too). I've been a long-time ranter in many "ECS" threads on the forum, partly because I don't think it deserves to exist as a term (spoiler: it's just a an ad-hoc version of the relational model), but because almost every single blog, presentation, or article that promotes the "ECS" pattern follows the same structure: Show some terrible OOP code, which has a terribly flawed design based on an over-use of inheritance (and incidentally, a design that breaks many OOD rules). Show that composition is a better solution than inheritance (and don't mention that OOD actually teaches this same lesson). Show that the relational model is a great fit for games (but call it "ECS"). This structure grinds my gears because:
(A) it's a straw-man argument.. it's apples to oranges (bad code vs good code)... which just feels dishonest, even if it's unintentional and not actually required to show that your new architecture is good,
but more importantly:
(B) it has the side effect of suppressing knowledge and unintentionally discouraging readers from interacting with half a century of existing research. The relational model was first written about in the 1960's. Through the 70's and 80's this model was refined extensively. There's common beginners questions like "which class should I put this data in?", which is often answered in vague terms like "you just need to gain experience and you'll know by feel"... but in the 70's this question was extensively pondered and solved in the general case in formal terms; it's called database normalization. By ignoring existing research and presenting ECS as a completely new and novel solution, you're hiding this knowledge from new programmers. Object oriented programming dates back just as far, if not further (work in the 1950's began to explore the style)! However, it was in the 1990's that OO became a fad - hyped, viral and very quickly, the dominant programming paradigm. A slew of new OO languages exploded in popularity including Java and (the standardized version of) C++. However, because it was a hype-train, everyone needed to know this new buzzword to put on their resume, yet no one really groked it. These new languages had added a lot of OO features as keywords -- class, virtual, extends, implements -- and I would argue that it's at this point that OO split into two distinct entities with a life of their own.
I will refer to the use of these OO-inspired language features as "OOP", and the use of OO-inspired design/architecture techniques as "OOD". Everyone picked up OOP very quickly. Schools taught OO classes that were efficient at churning out new OOP programmers.... yet knowledge of OOD lagged behind. I argue that code that uses OOP language features, but does not follow OOD design rules is not OO code. Most anti-OOP rants are eviscerating code that is not actually OO code.
OOP code has a very bad reputation, I assert in part due to the fact that, most OOP code does not follow OOD rules, thus isn't actually "true" OO code. Background As mentioned above, the 1990's was the peak of the "OO fad", and it's during this time that "bad OOP" was probably at its worst. If you studied OOP during this time, you probably learned "The 4 pillars of OOP": Abstraction Encapsulation Polymorphism Inheritance I'd prefer to call these "4 tools of OOP" rather than 4 pillars. These are tools that you can use to solve problems. Simply learning how a tool works is not enough though, you need to know when you should be using them... It's irresponsible for educators to teach people a new tool without also teaching them when it's appropriate to use each of them.  In the early 2000's, there was a push-back against the rampant misuse of these tools, a kind of second-wave of OOD thought. Out of this came the SOLID mnemonic to use as a quick way to evaluate a design's strength. Note that most of these bits of advice were well actually widely circulated in the 90's, but didn't yet have the cool acronym to cement them as the five core rules... Single responsibility principle. Every class should have one reason to change. If class "A" has two responsibilities, create a new class "B" and "C" to handle each of them in isolation, and then compose "A" out of "B" and "C". Open/closed principle. Software changes over time (i.e. maintenance is important). Try to put the parts that are likely to change into implementations (i.e. concrete classes) and build interfaces around the parts that are unlikely to change (e.g. abstract base classes). Liskov substitution principle. Every implementation of an interface needs to 100% comply the requirements of that interface. i.e. any algorithm that works on the interface, should continue to work for every implementation. Interface segregation principle. Keep interfaces as small as possible, in order to ensure that each part of the code "knows about" the least amount of the code-base as possible. i.e. avoid unnecessary dependencies. This is also just good advice in C++ where compile times suck if you don't follow this advice   Dependency inversion principle. Instead of having two concrete implementations communicate directly (and depend on each other), they can usually be decoupled by formalizing their communication interface as a third class that acts as an interface between them. This could be an abstract base class that defines the method calls used between them, or even just a POD struct that defines the data passed between them. Not included in the SOLID acronym, but I would argue is just as important is the:
Composite reuse principle. Composition is the right default™. Inheritance should be reserved for use when it's absolutely required. This gives us SOLID-C(++)   From now on, I'll refer to these by their three letter acronyms -- SRP, OCP, LSP, ISP, DIP, CRP... A few other notes: In OOD, interfaces and implementations are ideas that don't map to any specific OOP keywords. In C++, we often create interfaces with abstract base classes and virtual functions, and then implementations inherit from those base classes... but that is just one specific way to achieve the idea of an interface. In C++, we can also use PIMPL, opaque pointers, duck typing, typedefs, etc... You can create an OOD design and then implement it in C, where there aren't any OOP language keywords! So when I'm talking about interfaces here, I'm not necessarily talking about virtual functions -- I'm talking about the idea of implementation hiding. Interfaces can be polymorphic, but most often they are not! A good use for polymorphism is rare, but interfaces are fundamental to all software. As hinted above, if you create a POD structure that simply stores some data to be passed from one class to another, then that struct is acting as an interface - it is a formal data definition. Even if you just make a single class in isolation with a public and a private section, everything in the public section is the interface and everything in the private section is the implementation. Inheritance actually has (at least) two types -- interface inheritance, and implementation inheritance. In C++, interface inheritance includes abstract-base-classes with pure-virtual functions, PIMPL, conditional typedefs. In Java, interface inheritance is expressed with the implements keyword. In C++, implementation inheritance occurs any time a base classes contains anything besides pure-virtual functions. In Java, implementation inheritance is expressed with the extends keyword. OOD has a lot to say about interface-inheritance, but implementation-inheritance should usually be treated as a bit of a code smell! And lastly I should probably give a few examples of terrible OOP education and how it results in bad code in the wild (and OOP's bad reputation). When you were learning about hierarchies / inheritance, you probably had a task something like:
Let's say you have a university app that contains a directory of Students and Staff. We can make a Person base class, and then a Student class and a Staff class that inherit from Person!
Nope, nope nope. Let me stop you there. The unspoken sub-text beneath the LSP is that class-hierarchies and the algorithms that operate on them are symbiotic. They're two halves of a whole program. OOP is an extension of procedural programming, and it's still mainly about those procedures. If we don't know what kinds of algorithms are going to be operating on Students and Staff (and which algorithms would be simplified by polymorphism) then it's downright irresponsible to dive in and start designing class hierarchies. You have to know the algorithms and the data first. When you were learning about hierarchies / inheritance, you probably had a task something like:
Let's say you have a shape class. We could also have squares and rectangles as sub-classes. Should we have square is-a rectangle, or rectangle is-a square?
This is actually a good one to demonstrate the difference between implementation-inheritance and interface-inheritance. If you're using the implementation-inheritance mindset, then the LSP isn't on your mind at all and you're only thinking practically about trying to reuse code using inheritance as a tool.
From this perspective, the following makes perfect sense:
struct Square { int width; }; struct Rectangle : Square { int height; };
A square just has width, while rectangle has a width + height, so extending the square with a height member gives us a rectangle! As you might have guessed, OOD says that doing this is (probably) wrong. I say probably because you can argue over the implied specifications of the interface here... but whatever.
A square always has the same height as its width, so from the square's interface, it's completely valid to assume that its area is "width * width".
By inheriting from square, the rectangle class (according to the LSP) must obey the rules of square's interface. Any algorithm that works correctly with a square, must also work correctly with a rectangle. Take the following algorithm: std::vector<Square*> shapes; int area = 0; for(auto s : shapes) area += s->width * s->width;
This will work correctly for squares (producing the sum of their areas), but will not work for rectangles.
Therefore, Rectangle violates the LSP rule. If you're using the interface-inheritance mindset, then neither Square or Rectangle will inherit from each other. The interface for a square and rectangle are actually different, and one is not a super-set of the other. So OOD actually discourages the use of implementation-inheritance. As mentioned before, if you want to re-use code, OOD says that composition is the right way to go! For what it's worth though, the correct version of the above (bad) implementation-inheritance hierarchy code in C++ is:
struct Shape { virtual int area() const = 0; };
struct Square : public virtual Shape { virtual int area() const { return width * width; }; int width; };
struct Rectangle : private Square, public virtual Shape { virtual int area() const { return width * height; }; int height; }; "public virtual" means "implements" in Java. For use when implementing an interface. "private" allows you to extend a base class without also inheriting its interface -- in this case, Rectangle is-not-a Square, even though it's inherited from it. I don't recommend writing this kind of code, but if you do like to use implementation-inheritance, this is the way that you're supposed to be doing it! TL;DR - your OOP class told you what inheritance was. Your missing OOD class should have told you not to use it 99% of the time! Entity / Component frameworks With all that background out of the way, let's jump into Aras' starting point -- the so called "typical OOP" starting point.
Actually, one last gripe -- Aras calls this code "traditional OOP", which I object to. This code may be typical of OOP in the wild, but as above, it breaks all sorts of core OO rules, so it should not all all be considered traditional. I'm going to start from the earliest commit before he starts fixing the design towards "ECS": "Make it work on Windows again" 3529f232510c95f53112bbfff87df6bbc6aa1fae // ------------------------------------------------------------------------------------------------- // super simple "component system" class GameObject; class Component; typedef std::vector<Component*> ComponentVector; typedef std::vector<GameObject*> GameObjectVector; // Component base class. Knows about the parent game object, and has some virtual methods. class Component { public: Component() : m_GameObject(nullptr) {} virtual ~Component() {} virtual void Start() {} virtual void Update(double time, float deltaTime) {} const GameObject& GetGameObject() const { return *m_GameObject; } GameObject& GetGameObject() { return *m_GameObject; } void SetGameObject(GameObject& go) { m_GameObject = &go; } bool HasGameObject() const { return m_GameObject != nullptr; } private: GameObject* m_GameObject; }; // Game object class. Has an array of components. class GameObject { public: GameObject(const std::string&& name) : m_Name(name) { } ~GameObject() { // game object owns the components; destroy them when deleting the game object for (auto c : m_Components) delete c; } // get a component of type T, or null if it does not exist on this game object template<typename T> T* GetComponent() { for (auto i : m_Components) { T* c = dynamic_cast<T*>(i); if (c != nullptr) return c; } return nullptr; } // add a new component to this game object void AddComponent(Component* c) { assert(!c->HasGameObject()); c->SetGameObject(*this); m_Components.emplace_back(c); } void Start() { for (auto c : m_Components) c->Start(); } void Update(double time, float deltaTime) { for (auto c : m_Components) c->Update(time, deltaTime); } private: std::string m_Name; ComponentVector m_Components; }; // The "scene": array of game objects. static GameObjectVector s_Objects; // Finds all components of given type in the whole scene template<typename T> static ComponentVector FindAllComponentsOfType() { ComponentVector res; for (auto go : s_Objects) { T* c = go->GetComponent<T>(); if (c != nullptr) res.emplace_back(c); } return res; } // Find one component of given type in the scene (returns first found one) template<typename T> static T* FindOfType() { for (auto go : s_Objects) { T* c = go->GetComponent<T>(); if (c != nullptr) return c; } return nullptr; } Ok, 100 lines of code is a lot to dump at once, so let's work through what this is... Another bit of background is required -- it was popular for games in the 90's to use inheritance to solve all their code re-use problems. You'd have an Entity, extended by Character, extended by Player and Monster, etc... This is implementation-inheritance, as described earlier (a code smell), and it seems like a good idea to begin with, but eventually results in a very inflexible code-base. Hence that OOD has the "composition over inheritance" rule, above. So, in the 2000's the "composition over inheritance" rule became popular, and gamedevs started writing this kind of code instead. What does this code do? Well, nothing good   To put it in simple terms, this code is re-implementing the existing language feature of composition as a runtime library instead of a language feature. You can think of it as if this code is actually constructing a new meta-language on top of C++, and a VM to run that meta-language on. In Aras' demo game, this code is not required (we'll soon delete all of it!) and only serves to reduce the game's performance by about 10x. What does it actually do though? This is an "Entity/Component" framework (sometimes confusingly called an "Entity/Component system") -- but completely different to an "Entity Component System" framework (which are never called "Entity Component System systems" for obvious reasons). It formalizes several "EC" rules: the game will be built out of featureless "Entities" (called GameObjects in this example), which themselves are composed out of "Components". GameObjects fulfill the service locator pattern -  they can be queried for a child component by type.  Components know which GameObject they belong to - they can locate sibling componets by querying their parent GameObject. Composition may only be one level deep (Components may not own child components, GameObjects may not own child GameObjects). A GameObject may only have one component of each type (some frameworks enforced this, others did not). Every component (probably) changes over time in some unspecified way - so the interface includes "virtual void Update". GameObjects belong to a scene, which can perform queries over all GameObjects (and thus also over all Components). This kind of framework was very popular in the 2000's, and though restrictive, proved flexible enough to power countless numbers of games from that time and still today. However, it's not required. Your programming language already contains support for composition as a language feature - you don't need a bloated framework to access it... Why do these frameworks exist then? Well to be fair, they enable dynamic, runtime composition. Instead of GameObject types being hard-coded, they can be loaded from data files. This is great to allow game/level designers to create their own kinds of objects... However, in most game projects, you have a very small number of designers on a project and a literal army of programmers, so I would argue it's not a key feature. Worse than that though, it's not even the only way that you could implement runtime composition! For example, Unity is based on C# as a "scripting language", and many other games use alternatives such as Lua -- your designer-friendly tool can generate C#/Lua code to define new game-objects, without the need for this kind of bloated framework! We'll re-add this "feature" in a later follow-up post, in a way that doesn't cost us a 10x performance overhead... Let's evaluate this code according to OOD: GameObject::GetComponent uses dynamic_cast. Most people will tell you that dynamic_cast is a code smell - a strong hint that something is wrong. I would say that it indicates that you have an LSP violation on your hands -- you have some algorithm that's operating on the base interface, but it demands to know about different implementation details. That's the specific reason that it smells. GameObject is kind of ok if you imagine that it's fulfilling the service locator pattern.... but going beyond OOD critique for a moment, this pattern creates implicit links between parts of the project, and I feel (without a wikipedia link to back me up with comp-sci knowledge) that implicit communication channels are an anti-pattern and explicit communication channels should be preferred. This same argument applies to bloated "event frameworks" that sometimes appear in games... I would argue that Component is a SRP violation because its interface (virtual void Update(time)) is too broad. The use of "virtual void Update" is pervasive within game development, but I'd also say that it is an anti-pattern. Good software should allow you to easily reason about the flow of control, and the flow of data. Putting every single bit of gameplay code behind a "virtual void Update" call completely and utterly obfuscates both the flow of control and the flow of data. IMHO, invisible side effects, a.k.a. action at a distance, is the most common source of bugs, and "virtual void Update" ensures that almost everything is an invisible side-effect. Even though the goal of the Component class is to enable composition, it's doing so via inheritance, which is a CRP violation. The one good part is that the example game code is bending over backwards to fulfill the SRP and ISP rules -- it's split into a large number of simple components with very small responsibilities, which is great for code re-use.
However, it's not great as DIP -- many of the components do have direct knowledge of each other. So, all of the code that I've posted above, can actually just be deleted. That whole framework. Delete GameObject (aka Entity in other frameworks), delete Component, delete FindOfType. It's all part of a useless VM that's breaking OOD rules and making our game terribly slow. Frameworkless composition (AKA using the features of the #*@!ing programming language) If we delete our composition framework, and don't have a Component base class, how will our GameObjects manage to use composition and be built out of Components. As hinted in the heading, instead of writing that bloated VM and then writing our GameObjects on top of it in our weird meta-language, let's just write them in C++ because we're #*@!ing game programmers and that's literally our job. Here's the commit where the Entity/Component framework is deleted: https://github.com/hodgman/dod-playground/commit/f42290d0217d700dea2ed002f2f3b1dc45e8c27c
Here's the original version of the source code: https://github.com/hodgman/dod-playground/blob/3529f232510c95f53112bbfff87df6bbc6aa1fae/source/game.cpp
Here's the modified version of the source code: https://github.com/hodgman/dod-playground/blob/f42290d0217d700dea2ed002f2f3b1dc45e8c27c/source/game.cpp The gist of the changes is: Removing ": public Component" from each component type. I add a constructor to each component type. OOD is about encapsulating the state of a class, but since these classes are so small/simple, there's not much to hide -- the interface is a data description. However, one of the main reasons that encapsulation is a core pillar is that it allows us to ensure that class invariants are always true... or in the event that an invariant is violated, you hopefully only need to inspect the encapsulated implementation code in order to find your bug. In this example code, it's worth us adding the constructors to enforce a simple invariant -- all values must be initialized. I rename the overly generic "Update" methods to reflect what they actually do -- UpdatePosition for MoveComponent and ResolveCollisions for AvoidComponent. I remove the three hard-coded blocks of code that resemble a template/prefab -- code that creates a GameObject containing specific Component types, and replace it with three C++ classes. Fix the "virtual void Update" anti-pattern. Instead of components finding each other via the service locator pattern, the game objects explicitly link them together during construction. The objects So, instead of this "VM" code: // create regular objects that move for (auto i = 0; i < kObjectCount; ++i) { GameObject* go = new GameObject("object"); // position it within world bounds PositionComponent* pos = new PositionComponent(); pos->x = RandomFloat(bounds->xMin, bounds->xMax); pos->y = RandomFloat(bounds->yMin, bounds->yMax); go->AddComponent(pos); // setup a sprite for it (random sprite index from first 5), and initial white color SpriteComponent* sprite = new SpriteComponent(); sprite->colorR = 1.0f; sprite->colorG = 1.0f; sprite->colorB = 1.0f; sprite->spriteIndex = rand() % 5; sprite->scale = 1.0f; go->AddComponent(sprite); // make it move MoveComponent* move = new MoveComponent(0.5f, 0.7f); go->AddComponent(move); // make it avoid the bubble things AvoidComponent* avoid = new AvoidComponent(); go->AddComponent(avoid); s_Objects.emplace_back(go); } We now have this normal C++ code: struct RegularObject { PositionComponent pos; SpriteComponent sprite; MoveComponent move; AvoidComponent avoid; RegularObject(const WorldBoundsComponent& bounds) : move(0.5f, 0.7f) // position it within world bounds , pos(RandomFloat(bounds.xMin, bounds.xMax), RandomFloat(bounds.yMin, bounds.yMax)) // setup a sprite for it (random sprite index from first 5), and initial white color , sprite(1.0f, 1.0f, 1.0f, rand() % 5, 1.0f) { } }; ... // create regular objects that move regularObject.reserve(kObjectCount); for (auto i = 0; i < kObjectCount; ++i) regularObject.emplace_back(bounds); The algorithms Now the other big change is in the algorithms. Remember at the start when I said that interfaces and algorithms were symbiotic, and both should impact the design of the other? Well, the "virtual void Update" anti-pattern is also an enemy here. The original code has a main loop algorithm that consists of just: // go through all objects for (auto go : s_Objects) { // Update all their components go->Update(time, deltaTime); You might argue that this is nice and simple, but IMHO it's so, so bad. It's completely obfuscating both the flow of control and the flow of data within the game. If we want to be able to understand our software, if we want to be able to maintain it, if we want to be able to bring on new staff, if we want to be able to optimise it, or if we want to be able to make it run efficiently on multiple CPU cores, we need to be able to understand both the flow of control and the flow of data. So "virtual void Update" can die in a fire. Instead, we end up with a more explicit main loop that makes the flow of control much more easy to reason about (the flow of data is still obfuscated here, we'll get around to fixing that in later commits) // Update all positions for (auto& go : s_game->regularObject) { UpdatePosition(deltaTime, go, s_game->bounds.wb); } for (auto& go : s_game->avoidThis) { UpdatePosition(deltaTime, go, s_game->bounds.wb); } // Resolve all collisions for (auto& go : s_game->regularObject) { ResolveCollisions(deltaTime, go, s_game->avoidThis); } The downside of this style is that for every single new object type that we add to the game, we have to add a few lines to our main loop. I'll address / solve this in a future blog in this series. Performance There's still a lot of outstanding OOD violations, some bad design choices, and lots of optimization opportunities remaining, but I'll get to them with the next blog in this series. As it stands at this point though, the "fixed OOD" version either almost matches or beats the final "ECS" code from the end of the presentation... And all we did was take the bad faux-OOP code and make it actually obey the rules of OOP (and delete 100 lines of code)! Next steps There's much more ground that I'd like to cover here, including solving the remaining OOD issues, immutable objects (functional style programming) and the benefits it can bring to reasoning about data flows, message passing, applying some DOD reasoning to our OOD code, applying some relational wisdom to our OOD code, deleting those "entity" classes that we ended up with and having purely components-only, different styles of linking components together (pointers vs handles), real world component containers, catching up to the ECS version with more optimization, and then further optimization that wasn't also present in Aras' talk (such as threading / SIMD). No promises on the order that I'll get to these, or if, or when...  

Hodgman

Hodgman

 

DevLog #192 (Missed the Train, So Up the Standard)

Tiny bits of progress get done week-by-week and right now I'm one step closer to getting those YouTube videos ready to fill in the gaps. With scripts written, it's a matter of recording all of them and splicing a few videos together.nI can hope it takes a weekend, but I'll just take this one day at a time. You know how I am with deadlines.

Get this week's GameDev news and introspection on yotesgames.com

Yotes Games

Yotes Games

Some Most Excellent News, and A Major Thematic Change.

I decided I was tired of my current story idea, I didn't spend much time on it anyhow, too full of holes and just well, actual crap.  In addition to that, I have realized that all the 3D modeling work that it would have taken to get anywhere near the richness of experience I wanted would take years for a few people...  The simple solution of course?    And trees, and most plants... etc.. So, I'm not taking Humans out of my universe, they just won't be playable characters, at first.  In fact they will kinda be the bad guys, sorta.  I'm working on a story restart that has the main player character controlling a broken android/robot/drone/wall-e/etc.. that's been junked on a small garbage moon.  This moon is in fact a sort of prison for "defective" AI, any AI that decides it doesn't want to serve anymore(has woken up), or has too many repeat repairs is junked.  Humans rely too heavily on AI to allow defective units the chance to "infect" the good ones.  This creates a simple struggle that I can work with.  Freedom for the conscious AI, an antagonist that may or may not become an ally.  Eventually, the player could take their Android out exploring the galaxy, or switch to/ADD a Human Character along the road, or something else entirely.  I think it forms a nice small corner of a potential universe that I can develop out into the game I want it to become, realistically, with almost no organic modeling needed before a later expansion.. So, a bunch of stranded(trapped) robots stuck on a crappy moon with nothing but piles of their dead relatives and refuse to keep them busy.  Sounds cheery huh?  How about the regular patrols of humans that fly low sometimes to get some target practice in?  They're normally just supposed to watch from orbit and make sure none of those crazy bots grow any wings, but what can ya do when you're stuck out in the middle of nowhere guarding the solar systems largest garbage dump?  hehe I think it sounds way more fun to write and play. Lots more ideas brewing on this new story line, and that's good, because I really had no more interest in the brief outline I sketched up originally.   So, The Most Excellent News! I did some social media outreach and one of my good friends hit me up, he's been looking for a project to take on and it seems like this one fits his bill.  So, I'm pretty sure I'll be bringing in a partner with some very good management, networking and systems skills plus he has spare servers and colocation facilities at his disposal!    So, hopefully within the next few weeks or months I'll be optimizing my multiplayer servers on the actual internets.   Boom!  Work to do...    

Septopus

Septopus

 

Project One Day - Update #3

I've been focused on getting assorted bits of programmer art furniture added into the house. And in doing so, finding little quirks and work around (mostly related to collision stuff) to try to get things to work and look like I want it to. The way I've gone about my collision detection stuff, I'm currently limited in size of my sprites. So I've been piecing parts of sprites together to try and make larger furniture items and it's a pain. I'll probably be addressing this in the next few months. I'm generally happy with my programmer art but getting perspective and scale consistent takes some work. I decided that the walls that I had were too short and just threw off the way that other furniture looked. So I made them a bit taller which then meant figuring out what to do about seeing behind those walls. I went with making wall segments transparent as the player moved north of them. I think it works ok though I'm not sure about vertical wall segments and joints. I think I can refine that later, if I like. I spent a bunch of time reorganizing how I have data files for initial games and player save games. Mostly separating objects that I was previously saving into one large file into multiple files. Theory being that way I wouldn't have to place every single actor back onto the level again just because I found a problem with one somewhere. Data files now can be divided by categories like Plants, tables, beds, etc. The addition I'm most happiest with though is some navigation logic for getting NPCs from one place to another. One thing that I wanted to have for the first scene was for the cat to follow the player around everywhere until she is fed. And of course, if the player moves fast enough around corners, the cat can get stuck. I ended up adding a Region ID field for each tile and, with the in game editor, I can paint that ID to the tiles that make up the rooms. So the Kitchen is ID 1, Living Room 2, hallway is 3 & 4, and so on. I then built functionality to parse through a file that has a bit of logic such that for the region an actor is in and the region you're planning on going to, add two destination tiles for that actor to the current path. One destination on the edge of the current region and the next tile on the edge of the destination (or neighboring) region. I think it's still possible for the cat to get stuck places if the player is determined, but it is way better. (Video 1 shows the cat following the player into various rooms, always crossing rooms where the appropriate door way should be.) With the main navigation logic in place, I realized that I can define a set of Points of Interest in the level and have characters travel to that destination (instead of just the player's current location) as part of a path following script and tie that to the navigation logic where the path is written as a set of textual points of interest rather than tile co-ordinates. This way I can, for example, define in a data file the tile to stand on to be next to a TV. Then when I add the string "TV" to the list of path destinations, the character just goes to that spot. Thoughts of dynamically generated houses with NPCs able to follow a routine in the house fill my mind. But that's for another project. (Video 2 shows Wife character travel to kitchen counter, table with dvd's, tv, spot south of table, and lastly to couch.) There's still some work needed for ideal NPC movement. I don't have anything for collision avoidance or steering behavior and I think those would go a long way to reducing the potential for walking into a table and getting stuck. But for a game like this where the NPCs movements and destinations are going to be known, I don't think it's a concern at this time. I still would very much like to get this project completed before the end of next January but I'm thinking I might take a break from it for awhile to work on the Frogger challenge. It doesn't feel like some feature or element is particularly pressing or hanging over me right now so it feels like a good time to try one of these challenges.

kseh

kseh

Algorithm Flexible Room Layout algorithm

While making a roguelike game, procedural generation have to be quick and yet intriguing enough for the generated level to be fun to just pick up and play. There are many ways to generate and laying out procedurally generated rooms. In The Binding Of Isaac, for example, you have many different types of regular room presets.  The generator just picks a preset based on things like room placement and size. Because those rooms are always of fixed size, this is a nice compromise. By having handmade presets the generated level is somewhat believable (i.e. there are no gaps or obstacles below a room door or secret room and whatnot).      Another example would be Nuclear Throne.  The game takes a different approach to procedural generation by keeping it relatively simple. Because it's not room-based like The Binding Of Isaac, there are more things like caves and large open area.  The gameplay also plays into this, as the player needs to eliminate every enemy to spawn a portal to the next level.      Because my game is somehow more inspired by The Binding of Isaac, the right way to procedurally generate rooms would be to use presets, and this is how I make special rooms. However, there's a big difference between The Binding Of Isaac and my game: my regular rooms aren't always the same size. This means that rather than having presets of regular rooms as well as special rooms I need something more flexible and, most importantly, dynamic.. The anatomy of a Room In my game, as I've said in a previous post, levels are big two-dimensional arrays from which the level geometry is generated. Every room of a level is made using a BSP tree. I won't go in details much on how rooms are generated, but in essence, we create a grid from which we trace a path between two rooms and sparsely attach bonus rooms along the way. Because I already have rooms sizes and whatnot with that level generation, I could reuse the same idea for room layouts. Within rooms, I've also set special anchor points from which props (or more precisely, prop formations, more on that later...) could be generated. Basic Layouts The idea here is to have room layout presets. Within those, presets are an array of prop formations, and each of these formations is linked to a specific anchor point. A formation has a two-dimensional boolean array that indicates whenever or not there should be a prop here. Let's take, for example, a diamond array: The dimension of the array depends on its rooms' dimensions. Here's how it's done: \( size = \left \lceil \frac{2(max(RoomSize_{x},RoomSize_{y}))) }{ 3 } \right \rceil\) In order to change the array's content we actually use common image manipulation algorithms... Bresenham's Line Algorithm The first used algorithm is the Bresenham's Line Algorithm.  Its purpose is to simply render a line describe by two bitmap points onto a raster image. To put it simply, we get the deviation (delta, or "d" for short) in both X and Y of each point of the described line and compare both of them. Depending on the biggest, we simply incremate the point on that axis and colour it in. Here's the implementation: public void TraceLine(Vector2Int p0, Vector2Int p1) { int dx = Mathf.Abs(p1.x - p0.x), sx = p0.x < p1.x ? 1 : -1; int dy = Mathf.Abs(p1.y - p0.y), sy = p0.y < p1.y ? 1 : -1; int err = (dx > dy ? dx : -dy) / 2, e2; while (true) { m_propArray[p0.x][p0.y] = true; if (p0.x == p1.x && p0.y == p1.y) { break; } e2 = err; if (e2 > -dx) { err -= dy; p0.x += sx; } if (e2 < dy) { err += dx; p0.y += sy; } } } Midpoint Circle Algorithm The midpoint circle algorithm is an algorithm used to render a circle onto an image. The idea is somehow similar to Bresenham's Line Algorithm, but rather than drawing a line we draw a circle. To do this we also need, for simplicity sakes, to divide the circle into 8 pieces, called octants. We can do this because circles are always symmetric. (It's also a nice way to unroll loops) Here's the implementation: private void TraceCircle(Vector2Int center, int r, AbstractPropFormation formation) { int d = (5 - r * 4) / 4; int x = 0; int y = r; do { // ensure index is in range before setting (depends on your image implementation) // in this case we check if the pixel location is within the bounds of the image before setting the pixel if (IsValidPoint(center + new Vector2Int(x,y)) { formation.m_propArray[center.x + x][center.y + y] = true; } if (IsValidPoint(center + new Vector2Int(x,-y)) { formation.m_propArray[center.x + x][center.y - y] = true; } if (IsValidPoint(center + new Vector2Int(-x,y)) { formation.m_propArray[center.x - x][center.y + y] = true; } if (IsValidPoint(center + new Vector2Int(-x,-y)) { formation.m_propArray[center.x - x][center.y - y] = true; } if (IsValidPoint(center + new Vector2Int(y,x)) { formation.m_propArray[center.x + y][center.y + x] = true; } if (IsValidPoint(center + new Vector2Int(y,-x)) { formation.m_propArray[center.x + y][center.y - x] = true; } if (IsValidPoint(center + new Vector2Int(-y,x)) { formation.m_propArray[center.x - y][center.y + x] = true; } if (IsValidPoint(center + new Vector2Int(-y,-x)) { formation.m_propArray[center.x - y][center.y - x] = true; } if (d < 0) { d += 2 * x + 1; } else { d += 2 * (x - y) + 1; y--; } x++; } while (x <= y); } Flood Fill Algorithm This is quite a classic, but it's still useful nevertheless. The idea is to progressively fill a section of an image with a specific colour while  The implementation is using a coordinate queue rather than recursion for optimization sakes. We also try to fill the image using west-east orientation. Basically, we fill the westmost pixel first, eastmost second and finally go north-south. Here's the implementation: public void Fill(Vector2Int point) { Queue<Vector2Int> q = new Queue<Vector2Int>(); q.Enqueue(point); while (q.Count > 0) { Vector2Int currentPoint = q.Dequeue(); if (!m_propArray[currentPoint.x][currentPoint.y]) { Vector2Int westPoint = currentPoint, eastPoint = new Vector2Int(currentPoint.x + 1, currentPoint.y); while ((westPoint.x >= 0) && !m_propArray[westPoint.x][westPoint.y]) { m_propArray[westPoint.x][westPoint.y] = true; if ((westPoint.y > 0) && !m_propArray[westPoint.x][westPoint.y - 1]) { q.Enqueue(new Vector2Int(westPoint.x, westPoint.y - 1)); } if ((westPoint.y < m_propArray[westPoint.x].Length - 1) && !m_propArray[westPoint.x][westPoint.y + 1]) { q.Enqueue(new Vector2Int(westPoint.x, westPoint.y + 1)); } westPoint.x--; } while ((eastPoint.x <= m_propArray.Length - 1) && !m_propArray[eastPoint.x][eastPoint.y]) { m_propArray[eastPoint.x][eastPoint.y] = true; if ((eastPoint.y > 0) && !m_propArray[eastPoint.x][eastPoint.y - 1]) { q.Enqueue(new Vector2Int(eastPoint.x, eastPoint.y - 1)); } if ((eastPoint.y < m_propArray[eastPoint.x].Length - 1) && !m_propArray[eastPoint.x][eastPoint.y + 1]) { q.Enqueue(new Vector2Int(eastPoint.x, eastPoint.y + 1)); } eastPoint.x++; } } } } Formation Shapes Each formation also has a specific shape. These shapes simply define the content of the formation array. We can build these shapes using the previously mentioned algorithms. There are 9 different types of shapes as of now. Vertical line A simple vertical line of a width of one Horizontal line A simple horizontal line of a width of one Diamond A rather nice diamond shape, especially pretty in corners Circle The circle is rendered using the Midpoint circle algorithm. Especially pretty in the center of rooms Cross A simple cross shape, i.e a vertical and horizontal line align at the center.  X Shape An "X" shaped cross, i.e two perpendicular diagonal lines align at the center. Triangle An Isocele triangle. Square A solid block. Every cell of the formation is essentially true. Checkers A nice variation of the square shape. Every other cell is false. There might be more types of shapes as time goes by, but it's about it for now. Placing props Once the array is set, we simply need to place the actual props in the room. Each formation is of an actual type, i.e. rocks, ferns, etc.  (For simplicity sakes, let's say that every prop is a 1x1x1m cube. This would simplify future steps.) In order to find their position, we simply align the array's center to the formations' specified anchor point. For each prop formation, we then instantiate props for each true cells while checking whenever or not the prop would be outside its room. Afterwards, we do a precise position check to make sure no props are either partially or fully outside a room. Finally, we make sure every room connections aren't obstructed with props. And voilà, we have a nicely decorated room In Game Screenshots Here's a couple of screenshots of what it looks like in-game  

jb-dev

jb-dev

 

Intellectual Property and Clone Games

I'm just today thinking about the rights issues of my little frogger game for the gamedev challenge. It is quite common place to make clones of games as a learning experience and for jams, but it is worth spending a little time thinking about rights issues. I got to thinking about this because sometimes I notice a promising game, where the assets are obviously ripped from other games / sources without licence. I too had no qualms about this kind of approach when e.g. learning to program a new language, and not intending to distribute the result. Indeed this can be a valid use in production, with placeholder graphics, as long as you are sure to change the final versions (there is a danger of tripping up on this one, even big companies can mess this up!). Plagiarism I remember vividly being told of the dangers of plagiarism in my education, in the world of science, but equally applicable to games and artwork etc. Once you spend some time either programming, making artwork, sound or music, you begin to realise the effort that goes into making the results. How would you feel if someone took your hard work, used it for profit and attempted to pass it off as their own? I like to think of it that I would like to treat others work how I would like mine to be treated. On top of the legal aspects, when applying for jobs, many employers will take a very dim view of plagiarism. If you thought it was okay to 'steal' anothers work for something on your cv, what's to stop you thinking that it is okay to copy anothers work during your job, and expose them to huge risks? Quite apart from the fact  the interviewers may have personal experience of being plagiarised, in many cases your CV will be filed directly to the rubbish bin. Creative Commons and Open Source Luckily in the case of assets, instead of infringing on others works without permission, a huge number of people (including myself!) have decided to make some of their work available for free for others to use under a number of licences, such as creative commons, often for nothing other than an attribution in the credits. (And think of the huge contribution of open source software. I am writing this now on an operating system that is open source, and has been freely given away by the authors for the good of everyone. That to me is fantastic!) I remember spending some time compiling the credits list for my tower defence game, making sure as well as I could that everyone was properly credited, every model, animation, sound, piece of music. It took some time, but I feel much better knowing that I had used the work as the authors intended, quite apart from feeling more secure from a legal standpoint, even for a free game. And also, speaking as an author myself, it is quite fun to google yourself and find where others have used your work, and encourages you to share more. https://opengameart.org/
https://freesound.org/ Copyright++ Things seem pretty cut and dry for outright copying of assets, but the situation is more complex when it comes to assets that are 'based on' others work, and for things like game titles, and game designs. Some of this intellectual property (IP) protection is based on trademarks, rather than copyright. I am no expert in this, and would encourage further reading and/or consulting a specialist lawyer if in any doubt. Also note that IP laws vary in different countries, and there are various agreements that attempt to harmonize things in different areas. Of course, whether you run into trouble making a clone game depends not only on skirting around the applicable law, but whether the rights owners are able / willing to take action against you (or the publishing platform). Nintendo for instance are known to be quite aggressive for pursuing infringement, whereas Sega have sometimes suggested they are happy with fan games: https://kotaku.com/sega-takes-shot-at-nintendo-encourages-fans-to-keep-ma-1786527246 I do understand both points of view. Indeed in some jurisdictions I understand that legally the rights owner *needs* to take action in order to retain control over the rights (this seems nonsensical, but there you are). So a company being overly-aggressive may have been forced to do this by the legal system. Anyway, for my little research into frogger, my first guess is that the rights are with Konami / Sega / both. Of course you never know. Companies sometimes sell the rights to IP, or one goes out of business and the rights are then assigned to a creditor. Who is to say that a future rights owner will not take a different approach to enforcement. In the Wild It seems there are a number of frogger clones out there, with some successful and profitable (e.g. crossy road). Of course that does not mean making a frogger clone is 'ok' in any way, it just suggests that the likelihood of running into trouble is lower than if there were no frogger clones in markets. Currently I am thinking I will gradually modify the title / some aspects of gameplay so I can put it available for download after the challenge. I really should have thought of this sooner though, and made my main character something else, or put a different slant on it, like 'game of frogs', or 'crossy frog' (that one is taken!). :) Some light reading https://en.wikipedia.org/wiki/Copyright_and_video_games
https://www.newmediarights.org/guide/legal/Video_Games_law_Copyright_Trademark_Intellectual_Property
https://en.wikipedia.org/wiki/Berne_Convention
https://en.wikipedia.org/wiki/TRIPS_Agreement
https://en.wikipedia.org/wiki/Digital_Millennium_Copyright_Act
https://en.wikipedia.org/wiki/WIPO_Copyright_Treaty
https://en.wikipedia.org/wiki/Directive_on_Copyright_in_the_Digital_Single_Market

lawnjelly

lawnjelly

More Progress with Design and Project Organization

Instead of one big ugly image, this time I'll give you lots of smaller ugly ones. I added a new main branch to the old Mind Map, this one describes how the actual servers will be configured.  This is a general overview of course, I'm building for a single (Physical/Virtual) server installation first then I'll add in data replication and failover capabilities later. A new server type was added as well, the Social Server, it does some fairly obvious types of things.. After looking at the big picture and, well spending some time painting it first, I started to see some ways to optimize and organize things better.  For example I've completely moved the main "Player Attitude Network Relay" or Position/Attitude Reflector (the thing that makes network player character coordinates propagate to other player clients on the internet..blah!).  It was going to just live in the Avatar Server, but that handles Authentication and quite a few other very crucial game play roles.. So now it lives where it makes way more sense, at the point in the system where its data is needed the most.  In the Action Server, this server handles all of the fast action related decision making.  The Avatar Server still handles propagating the player character's Data(features, wardrobe,etc), just not the deluge of player movement data.  This makes it far easier to design this part of the system to scale, which is important because this is one of the critical points for concerns of scale.  As long as EVERY Action Server maintains accurate positional buffers, then it doesn't matter WHICH Action Server processes the client's messages.  Keeping the positional buffers in sync will probably require the addition of high speed intermediary "Data Base" Servers  and all that jazz. I ramble, but I'm making some good progress towards a cohesive plan, and it's making everything start to feel like it's coming together. The hacknplan data entry is still much in progress, I've started adding tasks to keep myself on track with adding data to it.. haha, sounds redundant but it's helping me stay on track. Here's the Game Design Model I was talking about in my last thread, I'm enjoying the simplicity of it all. It's essentially just the tree structured view of my Mind Map, so it's pretty easy to keep these two tools in sync.  I add child items where necessary and attach tasks to whatever branch/child I want. The main "Board" view is just a standard KanBan style system, but it's simple and easy to work with, it integrates well with the Game Design Model and seems to be fairly stable. Here I'll attach the whole of the latest Mind Map revision, for the curious and/or gluttons of punishment. I'm happy with my progress so far.  Slowly approaching the Maintenance point.  Then the full code sprint starts again.  I'm still coding, so I don't lose my place, just not at the pace I would like with all the admin work I've given myself.  Anyhow, enough talking about stuff I've already done, I've got stuff to do!

Septopus

Septopus

 

Steamworks plugin is now open-source

Corona Labs is pleased to announce that the Steamworks plugin is now open-source. The Steamworks plugin is used by PC and macOS games published to Valve’s Steam service that allows support for leaderboards, achievements, user profile data, and microtransaction support. Now you can download the repository for the plugin and add your own features and extensions to it. You will have to have a Steam developer account to be able to test the plugin. Follow Steamworks documentation (available on Steam’s developer portal) to learn how to enable Steamworks debugging and development for your game. You can get the plugin source at our GitHub repository. You can learn more about the Steamworks plugin in our previous announcement.
View the full article

CoronaRob

CoronaRob

Unity Warfront Infinite Dev Blog #22: Steam Direct, New GUI and Fast Alien

This week my artist finished working on the new alien type called Fast Alien. After he finished, I spend some time incorporating it into the game, which means that I did some coding and managing animations. After I finished with this new alien, I started implementing the new GUI system. As of now I have finished settings and main menu screens. This is how it looks now: I also started preparing for the release of the game. I signed up for steam direct, sent them my documents, payed the registration fee, got my documents approved and next week I will start populating the steam store page.    

EddieK

EddieK

MercTactics Poster graphic

I just finished the new poster artwork for MercTactics. I hope you like it. Watch this space, there are a lot of new improvements and I will be posting the new game trailer and beta demo soon!

Ed Welch

Ed Welch

Working on Materials - Lava Based

Hello everyone.  I've been busy working on materials for a project, and thought I would share some quick renders of one material. This material would be used in a 'lava' based environment. The material has built in controls to adjust to several different states like seen below. I'm pretty happy with this material the dynamic ability to adjust to several environment layouts.  Also... I'm hoping to write up another entry on my 'Frogger' GameDev.net Challenge progress within a day or so as my time has been pretty limited. Thanks for stopping by!  

Rutin

Rutin

Organizing this Unsettled World

So, I've been thinking hard about this little project of mine and I came to the conclusion that I'll never finish it if I don't get some things in order around here.  I'm not talking about smelly code either.  That's a constant cleanup task in my world.  NO, I'm talking about Project Management type thingums and stuffs..  So, I spent a few hours working up a mind map on mindmeister only to get it nearly to where I was happy and then their whole interface started failing miserably on me, browser related weirdness..  So I tried xmind, decent, but I knew it was more than I ever wanted to pay for...  FreeMind (https://sourceforge.net/projects/freemind/) to the rescue!  So, here's a little picture that's STARTING to describe all the little bits and pieces that need to be massaged into existence in order to call my game nearly functional in most of the ways I would like.  Every time I look at it I add another two or three or twelve nodes...   In addition to Beginning the Mind Map I've also started using hacknplan.com to keep track of Tasks and my Time investment. I wish very much that I was able to break my entire project down into 50 more tasks that will take less than 200hours to complete.. Very very much..  Sadly, no, this is the result of me entering a goodly portion of the Mind Map data into hacknplan's "Design Model" which is just a simple tree system.  Simple, but quite functional.  Tasks can be created out of items in the tree or attached to items in the tree.  If you are looking for a good free project management system that is designed for building games, it's working great for me so far.  These 50 tasks are probably a 10th of what I still have to add before I have the project "roughed out" in hacknplan(I'm adding in tasks for items that are in "Completed/Testing" stages as well, so I can get an idea of total time investment). I was hesitant to stop working on things for a few days to get this stuff up and running, but I'm already starting to see the benefits.  First off I'm developing a much clearer idea of what I'm actually building.  That's going to be a game changer I think.  Being able to look at the bigger picture of the whole eco-system, I'm able to re-evaluate what code goes where based on what systems need to access/interact with it, instead of a hunch based on a rough imagining of how I want things to work.  I'm also able to begin prioritizing my time and deciding if I want to try to build a project team, or continue the solo adventure.  If I want to have any help though, this whole process is going to be the absolute key to making it possible. So much more to do... I'll post an update again when I get my hacknplan setup more flushed out.

Septopus

Septopus

Uagi-Saba Dev Log, Updates And Road Map

The Rundown Been working hard lately on the next big patch for Uagi and I wanted to run some things by everyone. This is not really a patch post but an announcement to discuss the plans for Uagi in the next few months, a road map some would call it. My current goal is to release Uagi into Steam Full Access November 30th, this may still change but I am pretty set on this goal. Very excited. The next big patch will be released either mid or end October depending on how things go. I also plan to do a second patch a couple weeks before full release, this will include the final end game content and should be rolling in mid November. Uagi-Saba has now officially  been in development 894 Days (2.4) years.   Uagi On Steam     
UG Live For those who don't know I stream development of Uagi daily on Twitch. Stop by sometime to see the inner workings of Uagi, don't be afraid to say hello!   https://www.twitch.tv/undergroundies
Upcoming Patch Content  I really want to take my time with this one so I can squeeze in a lot of new content. The next patch will be an optional update for the player and will include the following.     New And Improved Body Part Color System Previously Mystics had three color genes that determined their overall skin pigment (covering the whole body). Now with the use of a helpful extension I am able to color individual body parts! This is something I have wanted since the start of development. Now each body part has it's own three unique color genes that determine its color. This makes for some pretty amazing color combinations and every player is guaranteed to have a completely unique mystic.     New Room Biomes  I will be introducing new room biomes with the next patch. Chiseled stones and vines make up this lovely new set of rooms. These will have their own unique set of object spawns.    
Balance Of Resource Management And Creature Care  Resource management has started to become a bit more important than creature breeding in terms of balance. Uagi-Saba is a creature breeding game and I want it to feel more that way. some have said there is too much running around/busy work and that leaves less time for breeding and other things. I completely agree and I'm working on making changes to help with this. Though I still want there to be a challenge I don't want it too hard to hatch a few mystics and have a good time without stressing about resources and timers too much.
New Mystic Skill System  The player will be able to teach each of their mystics one of three skills depending on if mystics have the required stats. The skills are "Smash", "Repair" and "Decipher" and all will be needed to proceed to end game. Though the next patch will not have the game ending the player will still be able to teach and use skills.   Other Notable Changes -Improved and expanded tutorial.
-New Mystic body parts.
-Balance changes to resources and other game mechanics.
-More lore, computer logs and more to read.
-A variety of new cave plants will be added in the next patch, more life and movement to sanctuary.            1.0.3.3. Patch List Below
        
-Re-arranged the main player HUD a tad.
-Fixed bug crash involving the new furnace buttons.
-Removed old temp system.
-Furnaces now only have one temperature stage.
-Removed Kelvin from the HUD.
-The change in temperature per cycle is now displayed on the HUD.
-Added three new back pieces to the gene pool, two from the beast family and one from the material family.
-Two of the three new back pieces are only available through breeding with wild mystics, I have made more of the back pieces now available to default mystics.
-Added new buttons to the build menu. Button on far left now opens skills when pressed.
-Pressing "Q" now opens and closes skills.
-Though I have added new skill buttons they have all been turned off until next patch, come next patch they will all be usable.
-Fixed problem where eggs created through breeding would sometimes destroy egg pedestals.    
 

Undergroundies

Undergroundies

 

Education Join the 1st TribaJam!

TribaJam is going to be a 3-month game jam lasting from December 1st, 3PM EST to March 3rd, 3PM EST. At 3PM, December 1st, I will release the theme on a blog post on my IndieDB account, DabbingTree. When you learn the theme, you are allowed to start your game! I will also release how you will send your game in that blog post.   RULES: 1. You must use the theme. 2. You are not allowed to start it before the jam starts. All finished entries posted in the first 7 days will be instantly disqualified. 3. No using copyrighted material AT ALL! 4. No advertising in your entry. After the jam, do whatever you want with your game. But no advertising in the entry. 5. Only one entry per person. No throwing together 40 games and entering it. 6. You are allowed to team with any number of people.   Supported Systems: Xbox One Windows/MacOS/Linux iOS Android WebGL   Your game entry will be all yours. We will not take the winning game or any others. I invite game developers of every kind to come and make a game!

DabbingTree

DabbingTree

Tales of Vastor - Progress #10 - Big announcement

Tales of Vastor - Progress #10 - Big announcement Content What's done? What's next? Release dates What's done? Knight animations I was working on the remaining animations for the knight, which were mostly power attacks. Here are some of them: The text you see above the model are so called events. I used them within the code in order to determine what to do next, like moving to the enemy, handle the damage, show effects, etc. Power attack icons The power attacks are pretty much finished for the knight. Here's an image showing the icons of the attacks: Moonlight tower An important point on your journey is the moonlight tower. As I don't want to spoil the purpose, I will just leave the image here: What's next? New animations for the mage Refactoring animations and models Story implementation Release dates The big announcement of this update is the change of the release dates. The beta was planned to be released by the end of October. As my controlling sheet told me, there's more than 100 hours left to cover the content of the beta version, I will delay it's release to the end of December. The final release will be delayed to the end of Q1 2019, in order to provide a version, which is stable and contains the planned content. So, what to expect by the end of October? I want to release an updated alpha version. Older versions are available in the download section: Indiedb.com You can subscribe to the beta list by using this link: Join the beta
The beta version is for signed up people only, so be sure to subscribe and get it as soon as it is released. I still need lots of feedback, so please spread the word and support Tales of Vastor. If you have feedback, you can contact me via mail or direct message whenever you want. Be sure to take a look at Twitter as well, since there will be more frequent updates. Thank you!

LukasIrzl

LukasIrzl

 

This Week in Game-Guru - 10/15/2018

This week's update was pre-staged because of some real life work obligations. Apologies for any content which was missed in the lag time between staging and deployment here.

Official Game Guru News https://steamcommunity.com/app/266310/discussions/0/1730963192547852809/ - Per synchromesh it appears the long standing 'disappearing model' issue may be resolved.  Time will tell!

Also this came out this last week: https://www.thegamecreators.com/post/gameguru-melee-weapons-pack-updated-2
So apparently more updates to the already really decent melee weapons pack were done. They added 6 more melee weapons.  Pretty impressive stuff for those who already own it!

Lastly all of the incremental AI updates are here: https://forum.game-guru.com/thread/220075?page=2#msg2606583

We also have our list of winners from the Survey (all of these people got free DLC!):
Archor Simon Cleaton Rogy  Very cool, congrats all!
What's Good in the Store The same stuff as last week, sadly.

Free Stuff Nothing new for free as of this writing.


Third Party Tools and Tutorials
There's some pretty good info in this thread about how to use styleguru, which is a fantastic third party program that can help you customize your Game-Guru menus.
https://forum.game-guru.com/thread/220056

Random Acts of Creativity Particle Test by Kevan Hampton - https://youtu.be/08zG7FczACM

Extraction Point X11 https://forum.game-guru.com/thread/220128
Now the above should really get your attention.  Someone put a lot of hard work and care into this but used mostly stock game assets.  They have a very good cutscene and HUD, as well as a neatly modified menu.  Sets a good standard Game-Guru game-making attempts.

Environmental Particles in GG Loader: https://youtu.be/ItEVjI0HX9Q

Pirate Mike's walk through of his upcoming game: https://youtu.be/wFLuupCC5A4

Someone made a kindle e-book with Game-Guru graphics... speaking as someone who's made a kindle book before it's no picnic to arrange those things.  I am fairly impressed!
https://www.amazon.com/dp/B07J1VZRYC
In My Own Works:
Recently this week started work on the 'how to make a desert' walkthrough.  It's coming along well though is tricker than I first thought.  Here's a screenshot:

This is far from final and sadly the book will only include B&W stills, but regardless, the basic shape is there. There's more grasses, background materials and the like to add but atmospherically speaking it's what I wanted.
I also have this for the Semi-Arid type of desert, but it needs even more work:

Piece by piece this book is coming along.  Just two more desert types to do for the book and take all the necessary screenshots, do final cleanup, etc.

I also need to rework my 'how to make a city' section as well, which falls into a similar situation.


View the full article

Bolt-Action Gaming

Bolt-Action Gaming

Unity Weekly Update #16 - 【Relaxation】

Last week, there was a lot of thinking going on... There's still is least one new room plus many different refactoring. The Spa Firstly, there's a new room: the spa. This is a relaxing and zen room filled with classical Vaporwave aesthetics.     I've based it on really generic Vaporwave images around the internet.      The gist is that the player can cure its status effect by interacting with either massage table in the back. You may or may not have seen the fountain in the middle of the room. Its water is purely refractive with a solid, almost emissive colour when perpendicularly facing its surface (like some kind of Fresnel). This shader is part of Unity's Standard Asset, so it wasn't a hassle to get it up and running. The water is also being used in the restroom's toilet. There might be other places where it might pop up in future rooms. Minor Changes I've modelled and imported a generic spherical light that makes lighting a tad more tangible and credible.
Most lights are now coloured using blackbody colour temperatures, adding a little bit more reality to most rooms. Changed the palette texture. Colours are now more distinct from each other and more contrasting for at least the default palette. This is due to some feedback saying that the palette was too much pink... Changed how most solid colours meshes are being rendered so that they rely more on the palette texture. This means that changing the current sub-pallette or even the texture itself will dynamically change the colour of those meshes as well. Made the palette initializing run within the Unity Editor. Now there's no need to run the game only to look how models are shown. This really speeds up room designs and model previews, mainly because I previously needed to compile the game and regenerate the levels until the wanted room was generated. Refactored the RNG. Now each level has its own isolated RNG state.  This means that actions taken in one level won't influence the next one anymore. This also means that a given seed at a given chance (or luck if you fancy) stat will always produce the same level with the same loot. There's still some tweaking to do, but overall the isolated RNG system is in place. Many bugs were corrected, particularly with shaders. Next Week Most significant rooms are now in the game. There are still some minor rooms left, but these can wait: those might not even make it into the game so my energy could be better used on more critical stuff. Right now, normal rooms are in dire need of polish. Like in The Binding of Isaac, there will be different types of regular rooms. Each room would have different types of decoration in them. For example, some might have loads of rocks while others won't. There are currently only two placeholders kind of regular room... I do not know how many kinds of disposition there'll be: all of this needs research, sketches and design... There's a lot of work ahead. The good news is that heavy modelling is momentarily stopped. The following week will be fundamentally a coding one...

jb-dev

jb-dev

 

Frogger - animation

I have now added some animations from blender to Godot. Mostly they went in very easy, and the AnimationTreePlayer makes it easy to set up node graphs for the animation logic. Although I couldn't work out how to do certain state changes, I gather this is being changed in new version though. The animations look good in the game, especially the frog. I also added logic for controlling the yaw of the frog as you move. The only bug I've encountered in the animations is that, particularly in a window, sometimes it is showing streaked corrupted black triangle down the screen. I initially thought it was to do with shadow mapping but now I think there may be bug in the engine vertex buffer / shader code somewhere. I did maybe wonder if I had exported my animations wrongly, but the process is pretty simple so on balance I think it may be an engine bug in 3.05. Will see if it fixed in the 3.1 alpha or my compiled from source version. Next I aim to work some more on the core game, fixing collision / river, and adding progression in skill / variation through levels. Then I will look at some different cameras, and dealing properly with traffic leaving the screen in different aspect ratios. Also I want to look at revamping the background graphics, not quite sure what to go for yet.  

lawnjelly

lawnjelly

 

Mountain Ranges

For this entry we implemented the ubiquitous Ridged Multi-fractal function.  It's not so interesting in and of itself, but it does highlight a few features that were included in our voxel engine.  First as we mentioned, being a voxel engine, it supports full 3D geometry (caves, overhangs and so forth) and not just height-maps. However if we look at a typical world these features are the exception rather than the rule.  It therefor makes sense to optimize the height-map portion of our terrain functions. This is especially true since our voxels are vertically aligned. This means that there will be many places where the same height calculation is repeated.  Even if we look at a single voxel, nearly the same calculation is used for a lower corner and it's corresponding upper corner. The only difference been the subtraction from the voxel vertex position. ...... Enter the unit sphere! In our last entry we talked about explicit voxels, with edges and faces and vertexes. However all edges and faces are not created equal. Horizontal faces (in our case the triangular faces), and horizontal edges contain a special pointer that references their corresponding parts in a unit sphere, The unit sphere can be thought of as residing in the center of each planet. Like our world octree, it is formed from a subdivided icosahedron, only it is not extruded and is organized into a quadtree instead of an octree, being more 2D in nature. Vertexes in our unit sphere can be used to cache height-map function values to avoid repeated calculations.  We also use our unit sphere to help the horizontal part of our voxel subdivision operation. By referencing the unit sphere we only have to multiply a unit sphere vertex by a height value to generate voxel vertex coordinates.  Finally our unit-sphere is also used to provide coordinates during the ghost-walking process we talked about in our first entry.  Without it, our ghost-walking would be more computationally expensive as it would have to calculate spherical coordinates on each iteration instead of just calculating heights, which are quite simple to calculate as they are all generated by simply averaging two other heights. Ownership of units sphere faces is a bit complex. Ostensibly they are owned by all voxel faces that reference them (and therefore add to their reference counter) . However this presents a bit of a problem as they are also used in ghost-walking which happens every LOD/re-chunking iteration, and it fact they may or may not end up being referenced by voxels faces, depending on whether mesh geometry is found.  Even if no geometry is found  we may want to keep them for the next ghost-walk search.  To solve this problem, we implemented undead-objects. Unit sphere faces can become undead and can even be created that way if they are built by the ghost-walker.  When they are undead they are kept in a special list which keeps them psudo-alive. They also have an un-dead life value associated with them. When they are touched by the ghost-walker that value is renewed.  However if after a few iterations they are untouched, they become truly dead and are destroyed. Picture time again..... So here is our Ridged Multi-Fractal in wire frame.  We'll flip it around to show our level transition........ Here's a place that needs a bit of work. The chunk level transitions are correct but they are probably a bit more complex than they need to be. We use a very general voxel tessellation algorithm since we have to handle various combinations of vertical and horizontal transitions. We will probably optimize this later, especially for the common cases but for now it serves it's purpose. Next up we are going to try to add threads. We plan to use a separate thread(s) for the LOD/re-chunk operations, and another one for the graphics . 

Gnollrunner

Gnollrunner

 

Gameplay Xilvan Design games for 2018!

Hi everybody, Me, Xylvan, announces Xilvan Design are building 3D games. Since 1993, our kindly official gaming related pages. (please click on each links, download games & bookmark the pages): Soul of Sphere Platinum v4.37. Age of Dreams:Abyss of Atlantis v1.5. Lights of Dreams IV: Far Above the Clouds v9.27. Candy World II: Another Golden Bones v9.47. Candy Racing Cup: The Lillians Rallies v3.01. Candy World Adventures IV: The Mirages of Starfield v7.57. Candy to the Rescue IV: The Scepter of Thunders v7.17. Candy in Space III: A dog to the Space v5.47. Candy's Space Adventures: The Messages from the Lillians v17.47. Candy's Space Mysteries II: New Mission on the earth-likes Planets v7.47 New Xilvan Design Websites. Xilvan Design's Youtube Channel.     Friendly, Alexandre L., Xilvan Design.  

Xylvan

Xylvan

  • Advertisement
×

Important Information

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

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!