Vangard

I’m curious to find out how much you hold entities in your map? From your posts I concluded that you holding many entities, if I am right, here is other questions:

  1. How you updating large number of entities. :stuck_out_tongue:
  2. What is your fps? :smiley:

Destructor, I am targeting 30fps. regarding entities, I posted this previously:

(Quote)
The world is divided into a 100x100 grid, with each cell representing 100m x 100m. During an update an entity can only interact with its own cell and the neighboring cells. This means that logic updates can be done in parallel as long as each cell being updated is separate from other cells being updated concurrently by two intervening cells in all directions.

All entities have a list of behaviors. They get their behavior list from their current career. Each career has exit careers (so a warrior could become a champion or a berserker). When a character satisfies the various entry requirements and enters a new career, their set of behaviors changes.

Behaviors have a planning component and and an execution component. The planning component is more expensive but is run less frequently, while the execution component is executed each logic tick. The execution logic depends on whether the behavior is the current highest priority behavior. for example, if a woodcutter is chopping wood and is attacked by a bear, fighting has a higher priority, while crafting has a lower priority. In the implementation of crafting, no work is done if crafting is not the top priority.

Other behaviors get executed even when they are not top priority. For example, HungryBehavior increments its needToEat counter each logic tick regardless of what the character is doing.

Behaviors communicate with each other by setting shared properties on the character. For example, the woodcutter’s crafting behavior can only be executed when the character is adjacent to a woodpile, so if the character is not near a woodpile, the behavior sets its priority to -1 (cannot execute) but adds the nearest woodpile to entity.movement.desirables map (the other component of the map entry is the priority of the desirable). The GoToBehavior monitors this collection and if it is not empty tries to move to the desirable with the highest priority. (more accurately, in the planning phase, GoToBehavior selects the highest priority desirable as the target, and sets the behavior priority to the desirable priority).

Likewise if a behavior needs an item from the inventory and the item is absent, the item is added to the inventory.wishlist collection. And this collection is monitored by other activities such as PickUpBehavor.

As I’ve learned, debugging this stuff is a nightmare and I am just writing mountains of test code at the moment. :slight_smile:

By the way, some behaviors are not from the career. I am thinking about adding personality behaviors, like GreedyBehavior or LazyBehavior to make the characters more unique.

I think the real figure is around 60k entities now, but there are only 1k humans and a couple of thousand other active entities like animals. The rest are just trees and rocks. Entities can move anywhere; some have an ExploreBehavior that will cause them to visit the entire map (unless they get distracted by a shiny new thing along the way).

I don’t do pathfinding. Entities just move towards their target and have a bit of logic to get unstuck when needed. When entities can go inside buildings, I will need a smarter and more expensive pathfinding solution.
(/Quote)

But you will use pathfinding, right?
If yes, then you should find a way to assign path to each entity without fps drop and do this is not easy then you have ~60k entities, even if you will assign certain number of paths per second with ~60k entities, last entity will need wait for a path too long I think. :persecutioncomplex:

So have you implemented multithreading with your entity logic?

One thread for each entity! ::slight_smile:

I use two threads per CPU core, this seems to be the optimum number for Windows (not optimal for Linux, sorry Linux). There are 10,000 one-hectare cells and these are shared out between the threads in a thread-safe order.

Rergarding A* etc pathfinding, I’m just not very interested in it. It’s expensive and beeline works ok. For indoors movement I will need to have some logic to the movement, as in pathfinding with only a small number of nodes (doorways) to consider. But for outdoors movement I will keep it simple. The complexity in outdoors movement comes from including hazard avoidance, stealthy movement, grouping behavior (so citizens travelling between settlements do not travel dangerous roads alone)…

Most of the objects in the game are small, convex and reasonably spaced, so going in straight lines and sliding to the right around obstacles works for 99% of the cases. For the rarer cases where an entity gets stuck, it simply scatters randomly and tries again. This covers most the remaining cases. It only fails for very large or irregular/concave objects, and for these I will provide local waypoints to guide the entities without the need for global pathfinding.

Render millis were ranging between 24ms (75x zoom) to 60ms (1x zoom) on my new HD530, so I wrote a simple batcher. With partial batching the render millis have improved to the 15-40ms range, with the small side effect that nothing is visible on-screen any more!

This is all unwanted effort as I need to be using LibGDX not Java2D, but I want a quick fix, and the batching may be useful even when I switch graphics frameworks.

I really don’t want to invest in the J2D rendering, but I wanted it at least functional on my PC. So I followed the suggestion of Coldstream24 and added this environment variable:

J2D_D3D_NO_HWCHECK=true

Rendering performance has increased threefold as a result. Which is good enough for now :slight_smile:

What do you mean by animated silhouettes for the people?

Your low-poly tree idea reminded me of a very nice low-poly 3D green forested world in a game called Rain whose graphics style you may find inspiration from

I plan on making people simple monochrome top-down silhouettes to keep the poly count down (and to keep animation simple). A bit like the figure in one of your draft screens you showed on the other thread.

I’m liking the look of Rain!

First update in a while; I’ve been having some nasty health problems involving surgery lately so I have not done anything on Vangard for a while.

Today I added a small feature that lets you put your player-controlled character on “autopilot”. Press “A” and the character’s default AI takes over. For example, a hunter will go hunting, or a healer will gather herbs and craft potions. Press “A” again and you have full human control of the character once more.

I am now working on another feature which is slightly more complex to implement, namely allowing you to switch control to adjacent character. So you can walk your character next to a guard, take control of the guard, and so on.

This may have interesting gameplay possibilities (Demonic Mode anyone?) but for now it is just a debugging tool.

EDIT: Turns out that was a fairly significant update. It meant I had to create an Action class for deferred actions (like modifying the behavior lists of two entities), for which I needed a concurrent queue so that the logic threads can queue up deferred actions like control changes and long-range ownership changes, financial payments, which are then popped off the queue in a (sadly) single thread.

Short range interactions between entities are handled multi-threaded - if entities are closer than approx. 200m then they are in the same thread and I can update them safely. But for longer range interactions I have to defer to a single-threaded cleanup queue.

I’m having fun here, sneaking around the village and taking control of random citizens :slight_smile:

It’s almost as much fun as bumping into trees.

That sounds awesome! It’s a great feeling when hard work pays off and things come together.
And I hope you get better soon, mate.

As a little background info, the player control of a character is just a high-priority behavior added to the character. The player control trumps any other behavior (excluding background always-on behaviors like GetHungry) so the character is “under control of the player”. To allow the character to go on autopilot, I only needed to allow a switch to set the player control behavior priority to -1. It also means that control can be attached to anything that is sortof human-like, so I can for example take control of a deer, and then lure a pack of wolves into the heart of a village. ;D

I hope this remains in the final build. :point:

I must admit I am quite enjoying this game mechanic, I have a vague idea for a demonic mode where you can posess most people (but not everyone), and the game objective is to unlock a portal to hell itself.

Hello, just checking in on the game again. :slight_smile: I wanted to share with you another game from which you might draw inspiration. It’s called Future Unfolding. The genre is completely different, but graphically it is beautiful and the trees of that game reminded me much of the trees here. There are plenty of beautiful animations (such as a bush shaking when the player touches it) and I think you could pull it off with the setup you have for your shrubbery and trees to make your game seem more lively. The animals of that game also touched me and they seemed very 2d apart from the shadows.

Anywho, wishing you well on your game. Take what you will from my ramblings. Good luck!

Hey ags I have just recently started reading this thread and am loving your game so far! My question for you: is the bug where the UI jiggles around occasionally fixed or is that still in progress? :stuck_out_tongue:

I haven’t observed that issue, so I’d have to say it’s not fixed. Thanks for the encouraging feedback :slight_smile:

Sheph, I’ll look into Future Unfolding.

Big coding weekend coming up. Gonna stick an arrow in a deer!

I had a little brainwave on my way home this evening about how to handle the recurring situation of either executing an action in the multithreaded part of the logic or in the single-threaded part of the logic. It involves wrapping the action in an object that decides to execute itself or defer itself to the single-threaded phase.


/**
 * This is an action that can take place over a long distance.
 * If the distance exceeds 100m then the action may be out of bounds of a spatial thread
 * and the action then defers itself to the single-threaded queue.
 * Created by Agslinda on 3/15/2016.
 */
public abstract class LongRangeAction implements WorldAction {

    public void execute(double distance, World world) {
        if (distance > 100) {
            world.putDeferredAction(this);
        } else {
            act();
        }
    }

    public void execute(Entity thiss, Entity other) {
        execute(Collisions.distance(thiss, other), thiss.world);
    }

}


The deer armageddon has been unleashed after months of procrastination. Bloodthirsty hunters have slaughtered whole herds of Bambies, leaving the corpses to rot in the fields (they don’t yet know why they are hunting the deer…).

Now I need to tweak the goto behavior so so day goto objectives aren’t followed up at night. For example, if a hunter sets out toward a herd of deer in the afternoon, they might end up chasing it all night and get no sleep. i.e. HuntingBehavior is scoped to daytime, but it spawns a goto task that is not yet scoped to daytime.