Devember - Screep Studio

Day 14

Well, a little bit Day 13 and so far Day 14 :smiley:

Did a little more work on the object inspector panel, I added a couple of handy toolbar buttons to it, one to auto expand the JSON tree when an entity is selected (purely based on me being too lazy to expand each node myself all the time)

Very handy for Creeps because they have the largest JSON objects with a couple of levels.

Also added a “Copy” button to copy the JSON in a clean “beautified” format into the clipboard … also turning out to be very handy.

And with the help of the new Object Inspector implemented the progress display for the the “Construction Site” entities. So now they show up as little pie charts/clocks that fill out as the construction site approaches completion (just like the official client)

Today I am planning to have a look at Qts property animator framework to see if it’s something I can use to do the animations for the game entities. As a test I am going to animate the opacity property of the construction site entities so they appear to fade in and out while they are under construction. (Again this seems to be how they work in the official client)

EDIT: Oh, and I forgot to mention, the grid in the room view is now toggle-able via an option in the View menu … need to add a main toolbar too.

Shecks

1 Like

Day 14

Well that was easier than expected :slight_smile:

First time I’ve used Qts Animation Framework and gotta say I like it. The QPropertyAnimation object lets you animated any property exposed to Qts method object frame work. At its most basic you just need to set a start value for the property, an end value and a duration then the animation framework will interpolate between the two values (I think this is called “tweening” in graphicy speak).

There’s a lot more you can do with it like key frames, time lines and ease in/out curves etc but this simple usage was enough for me to add support for the fading/pulsing construction site animations (just animating the “opactiy” property between 1.0 and 0.2 on a loop) and the smoother movement of the Creeps between grid positions (animating the “pos” between current and target position over time)

void RoomGraphicsItemCreep::beginUpdate(const RoomEntity& current, const RoomEntity& updated) {
    if(current.pos() != updated.pos()) {
        _moveAnimation->setStartValue(pos());
        _moveAnimation->setEndValue(QPointF(updated.posX() * cellWidth(), updated.posY() * cellHeight()));
        _moveAnimation->start();
    }
}

Now I have to find something else interesting to do … (putting off fixing the blocky background terrain … anyone want to make some nice 32x32 or 64x64 terrain tiles? :thinking:)

Shecks.

1 Like

Day 15

About half way through #devember2k18 and I’ve reached a milestone. I’ve hit one of the goals I wanted to achieve from the start.

My Screeps Studio client supports “Multi Room” (viewing for the moment at least)

It seems to be working pretty well although my little “carbug” server doesn’t to handle multiple room event subscriptions very well so there’s some lag.

This lag has highlighted an issue with the previous, very basic, code I implemented for Creep movement using QPropertyAnimation, My initial implementation was just really to get something up an running and it was pretty naive. When the server told me there was an update, I checked the position of the Creep and if it had changed I just told the animation to move from the current position to the new position and to do so over a fixed duration (which I arbitrarily choose as 1000ms).

There are two problems with this:-

  1. When there server is not under load things happen quickly so it’s possible for a Creep to move while the previous move animation is still in progress. In this case my code would start a new move animation from the current position (partial move) to the new target. This caused the Creeps to appear to teleport from cell to cell.

  2. When the server is under load there are delays with the move updates and my naive move implementation was skipping moves. So again the Creeps would appear to jump and, even worse, sometimes move through walls instead of going around corners.

So, to solve this I introduced a move queue. Now every time I get a position update for a Creep I first put the new position into the Creeps own move queue, then I call my move method. This method pops a position from the move queue and starts animating to that position. But the important part … when the move animation is complete the move method is automatically called again and the process repeats.

This has the effect of running a catch-up and it seems to work well. The Creeps do tend to look like they speed up from time to time (when running multiple catch up moves) but at least they go around corners now instead of through walls.

TODO: Still need to fix the blocky terrain … and still putting that off :neutral_face: I’ve been on Open Game Art looking for suitable tiles but I’m still deciding if I want to go down that route or not since the graphics in Screeps has always been pretty basic … but then again, fancy graphics helps the motivation … :thinking:

TODO (instead): Add the code to animate the Creeps transferring energy to structures for building and controller upgrades … LASERS!!!

Shecks

Still Day 15

Does anyone know how I can get YouTube encode my videos in a higher quality? Is is a premium option?

I’ve changed OBS to record reasonably high resolution which look sharp when I watch them locally but when I upload them to YouTube they look like I’ve recorded them on a Mark I Potato :frowning:

Shecks

Day 16

Time to start drawing the Creep entities a little closer to how they are drawn in the official client. From playing the game I know that Creeps are made up of several different body parts based on their function and each Creep is rendered to visually represent this.

While there’s information in the Screeps JavaScript game programming API about the Creep parts and how to build them for your A.I, there’s very little information on how they are visually represented (the player doesn’t have to draw them after all)

Creeps can be constructed in game as follows: -

  1. The main part of a Creeps body is just a circle.

  2. All Creeps have the ability to carry energy so they have an “Energy Store”. This is represented by an inner circle within the Creeps main body, it is a gray colour when empty and is filled with yellow as the Creep harvests energy.

  3. A Creep can have up to 50 “functional parts”. These are represented as different coloured arcs around the outside of the main creep body. Each of these body parts has a hit-points value assigned and the size of the body part (in degrees) is calculated based on the hit-points. The over all size of the arc for a given body part type is the sum of the sizes for all parts of that type. There are 8 different body part type:

    • Move - Allows the Creep to move (this is the only part I’ve found that’s drawn at the back of the Creep)
    • Work - Allows the Creep to perform work like mine energy, upgrade controllers, build structures etc.
    • Carry - Allows the Creep to carry energy (The number of carry parts determines the maximum size of the “Energy Store” component)
    • Attack - The Creep can attack other creeps or enemy defenses in hand to hand combat
    • Ranged Attack - The Creep can attack enemies at range using its laser
    • Heal - The Creep can heal other friendly creeps in battle
    • Claim - The Creep can claim controllers in un-owned rooms (or where the spawn has been destroyed, I think)
    • Tough - This is a special body part. A Creep will only ever visually have 1 or 0 tough parts which is represented as gray circle surrounding the Creeps main body (kind of like a shield). A tough Creep has a higher level of hit-points so can take a lot of damage before being destroyed.

I did some searching and managed to find this graphic to work from:-

screep-bodyparts

Based on the above information and looking at different Creeps in the live game I have written a CreepRenderer class that I can use to drawn any type of Creep with up to 50 parts. To test it I also wrote a small test application. (It was also easier to write the CreepRenderer while rendering 256x256 pixel Creeps rather than 32x32 so I could see what I was doing)

class CreepRenderer {

public:

    enum BodyPart {
        BodyPart_Move,
        BodyPart_Work,
        BodyPart_Carry,
        BodyPart_Attack,
        BodyPart_RangedAttack,
        BodyPart_Heal,
        BodyPart_Claim,
        BodyPart_Tough,

        BodyPart_Count
    };

    CreepRenderer();
    virtual ~CreepRenderer();

    void addBodyPart(BodyPart part, int hitPoints = MAX_PART_HITPOINTS);

    void setEnergy(int energy, int energyCapacity);
    void setTough(bool isTough);

    void reset();

    void draw(QPainter* painter, int size);
};

Here’s an example of my versions of the above Creeps: -

Small worker Creep

Attack Creep

Tough Healing Creep

Attack + Ranged Attack Creep

I am not drawing the Creeps exactly like in the game but they are close enough and as they are going to be drawn 32x32 pixels, I don’t think anyone will notice (or care).

As an aside, I also wrote a CreepViewWidget as part of the test application to render Creeps at any size using CreepRenderer, I am planning to re-use this as part of the properties panel in the game client so the user can view their Creeps body parts in detail when selected in the scene.

Shecks

2 Likes

Day 17

Did some work on the rendering for all the entities in the room scene. They now all render in proportion to the grid size of the scene (currently 32x32). I did this because I am thinking about changing the grid to 64x64 for a little higher resolution now that the entities have a little more detail and I wanted them to automatically scale.

I also made some refinements to my CreepRenderer, I found out that the “carry” body part is not rendered by the game, instead each part just increments the creeps total carry capacity by 50.

Finally I added a static method CreepRenderer::fromJson() to my rendering class so that I can construct the appropriate creeps directly from their raw JSON.

Added UI to my test application to make sure it’s working as expected:

I still need to figure out how the Creep parts are rendered in the case where there are two part of exact same size as, with this edge case, one part will completely obscure the other.

TODO: Add the CreepRenderer to the game client.

Shecks

2 Likes

Day 17 - Still

I think I figured out how to upload higher quality videos to YouTube … Looks like it doesn’t like FLVs and MP4s are a better option.

Shecks

1 Like

Day 18

Did some more code clean up. I noticed that I had a few different places where I was declaring game specific values and magic numbers (room dimensions, max creep body part, max hit points etc) so I move them all to a game API specific header ScreepsAPI

I’ve also moved my CreepRenderer code into the main client application and updated my RoomGraphicsItemCreep class to use it. Now the Creeps render with the correct body parts based on the body array defined in their JSON.

Also, now that the Creeps are no longer just circular placeholders I’ve had to implement rotation because they now have a front and back. Currently I rotate the game entity in the direction of travel but I still need to orientate them correctly once they reach their destination (e.g to face the controller, spawn, energy source etc when they arrive)

Here you can see them in action (You can also see their energy stores fill and deplete as they go about their work)

A side effect of the direction rotation code is that I need to re-think my entity selection, as the selection rectangle is also rotated based on the QGraphicsItems transform.

TODO: Implement states and state changes for the creeps so that I can run different animations depending on what they are up to (e.g harvesting from energy source, upgrading the controller, supplying energy to the spawn etc)

Shecks

3 Likes

Day 19

Started working on implementing state handling for the Creeps. I now have them correctly facing the targets harvesting energy from sources and upgrading the room controller by processing the actionLog object in their JSON to determine their current state.

But while testing the state changes I ran into the old issue of my test room getting screwed up again. This time though, I noticed that it seemed to happen when I added more road construction sites to the room. When I removed them the problem resolved itself.

So I decided to dig a little deeper and discovered that it was a problem with my network layer, specifically the processing of the websocket data for the room event streams.

When the server sends data over the websocket it’s in one of two formats:-

A space delimited string for command responses

"[command] [param...0] [param...n]"

Or a JSON array for stream events

[{"<channel>:<stream>", { <JSON Object> } ]"

I’ve been using a regular expression to check for a match on the stream event format and when that match fails I just assume it’s a space delimited command response.

But it turns out that there was am “undocumented feature” in my regular expression for the stream event matching and the capture I was using for the JSON object part which caused it to fail to parse the JSON correctly.

So, I’ve been studying up on PCRE (PHP style) regular expressions. Regular expressions have always been an area I’ve struggled with so I would really appreciate it if there’s anyone reading this with more experience than me who might take a quick look at what I’ve come up with and perhaps give some advice on the correct way to achieve the same results.

For example, the JSON will be in the following formats:

"[{"room:W9N8", { Any valid JSON here }]"

or

"[{"user:02c131b4b35fc35/console", { Any valid JSON here }]"

My goal is to capture 3 different parts:

  1. The channel - “room” or “user”
  2. The stream - “W9N8” or “02c131b4b35fc35/console”
  3. The JSON object -in this case, anything after the “,” and contained in the “{ }” but ending at the closing array bracket “]”

I’ve come up with the following RegExp

^\["(\w+):([\w\/]+)"({.+})\]$

Which seems to work but I am not 100% sure that the last capture group “({.+})” will capture the entire JSON object and not get confused because the JSON object can have internal arrays [] and objects {} so I am concerned that the parser might stop when it hits the first “]” or “}” instead of capturing the entire object. The entire string is delimited by “[” and “]”

Anyway, if any regular expression experts are interested in taking a look I have some test data and my regex here and would really appreciate your input.

Cheers,

Shecks

3 Likes

Day 20

Some things have been fixed: -

  1. Event stream from the websocket is being parsed correctly and it’s a little more robust now
  2. Creep rotation is now independent of the seleciton rectangle so it doesn’t rotate with the creep.
  1. Creeps are now correctly facing their targets while harvesting from sources and upgrading the room controller.

Shecks

1 Like

Day 20-ish

Was looking for inspiration/motivation and thought I found some cool free tiles to make the rooms look a little nicer … they almost fit, except for the case where there’s a wall that’s only 1 cell wide.

I really wish I could draw … maybe next #devember I’ll take a drawing course :frowning:

Shecks

1 Like

Day 21 - I really should go sleep

Space themed Screeps?

I really like these tiles, but the thoughts of having to figure out which tile goes where just by looking at the tile neighbours hurts my brain … especially with all the shadowed tiles.

Shecks

Day 21

CunningPlan

But first I need to finish my Christmas shopping :neutral_face:

Shecks

Day 21

Phase 1 of my cunning plan is complete.

I’ve decided instead of using nice fancy tiles for the room I’m just going to put some different coloured hexadecimal numbers on them instead for that sci-fi tech/hacker theme :wink:

Shecks

2 Likes

So much DEADBEEF C0FEFE

1 Like

Day 22

Today I will be mostly “painting by numbers”

I implemented 8-bit bit-mapping for the room tiles (each tile is assigned a bitmap based on its neighbours) so I can determine which tiles go next to each other logically.

That was the easy part … now I need to do the hard “artistic” part and figure out which tiles work visually for each bitmap … and then create a blob tileset for each type of terrain (I’ve got 3 1/2 terrains so far)

He’re where I am with the wall terrain tileset so far.

wall_tileset

Just imagine there are no gaps :smile:

It’s gonna be a long day (I mean hour)

Shecks

Day 22

Auto tiling for the rooms fixed walls is almost done … just a few more tiles to find and maybe fix some of those internal walls, I am not sure I am using the correct tiles from the tileset I found.

Shecks

2 Likes

Day 23

Not a whole lot done today, did a bit more work on the auto tiling and started work on the tileset for the internal tiles (Screeps calls these the “plains” and they are the tiles with no movement penalty for the Creeps)

The tiles with the shadows cast from their neighbouring walls look kind of cool.

But there are some issues I need to work out because there are two tiles that really should cast different shadows but my auto mapping algorithm is assigning them the same tile flags :thinking:

Anyway, I am not sure how much more work I am going to do on this. Maybe it’s the tiling, I might go back to just basic graphics like the original Screeps client at some point but it means drawing my own tilesets and I just don’t have the motivation anymore.

Anyway, I’m off to waste more hours playing some SWTOR because it’s double rewards week.

Shecks

1 Like

I have not been following this project, but kudos on still surviving devember, keep at it!

1 Like

Day 24

Back to basics, I’ve decided to just use some simple tiles for the the moment and go back to concentrating on the functionality. I’d like to get the roads and constructed walls working then have a look at adding a tool palette so the player mark out construction sites for the Creeps to build.

I’ve done the fixed wall tiles (When I figure out how to do it I will try to make them a bit darker with GIMP) then I need to create a simple tileset for the ground and the swamp areas

After that I plan to go back to working on the game functionality and leave the graphics until a later date.

Shecks

1 Like