GithubHelp home page GithubHelp logo

renderer's Introduction

@screeps/renderer @screeps/renderer-metadata
npm version npm version

This library is based on PixiJS and contains the renderer engine used in the Screeps game. You can use it to develop your own standalone utilities, or discover the API to create mods for custom graphics on your own private server.

Demo app

The demo folder contains an Electron app which you can use to test the library with real game object samples. You can launch it the following way:

cd demo
npm install
npm run electron

Files in the samples folder can be selected via the "File" menu to render specific game situations.

The demo app is also a good reference of how to integrate the renderer into a web page.

API

See main.d.ts, it contains full TypeScript-style definitions which helps to understand the programmatic API.

If you want to define your own custom graphics on your private server, see mods examples.

Documentation

Pipeline

General pipeline works in the following way:

  1. GameRenderer receives world state applyState method and delegates the logic to the World class.

  2. World passes state to a sequence of preprocessors, which can perform actions with all state. For example, setBadgeUrls preprocessor sets badgeUrls for all users in the state.

  3. Than World brings down states by objects, creates GameObject for each one, if it's not created, and delegates applying state to each GameObject.

  4. GameObject finds metadata according to the object type, and performs actions according to it. Running calculations, actions, processors.

Processor

Processors are core of rendering engine. They are a way to create PIXI objects, to customize them. Actually, a processor is just a function that receives params (see ProcessorParams) and performs some actions with them.

For instance, sprite processor just creates a sprite. But it does it in a smart way. If a texture is not loaded, it creates a container, and initiates resource loading. And only after resource gets loaded it creates a sprite for it.

In general there are 2 kinds of processors:

  1. for creating PIXI-related objects
    • object - implements common infrastructure for creating PIXI objects, the exact class should be passed through payload.Class.
    • container - is a thin wrapper around object for creating PIXI Container objects.
    • draw - is a wrapper around object for creating PIXI Graphics objects, and running methods for drawing. payload.drawings contains array of methods with params to call.
    • sprite - is a wrapper around object for creating PIXI Sprite. payload.texture contains a texture for the sprite.
    • text - is a wrapper around object for creating PIXI Text. It supports 2 params for specifying text attributes: payload.text and payload.style.
  2. and for special purposes above those objects
    • circle - is a wrapper around draw for drawing circles (payload: { color, radius, stroke, strokeWidth})
    • creepActions - parses actionLog of a game object and performs related actions.
    • creepBuildBody - parses body parts of a game object and visualizes them.
    • moveTo - is responsible for moving objects to right coordinates and angle.
    • powerInfluence - renders influence of powerCreep (actionLog.power).
    • resourceCircle - is a wrapper around circle for rendering circle with a radius depending on amount of specified resource.
    • road - draws all roads of the current state.
    • runAction - runs actions on a target object (payload.id), it should be used only in specific cases. Putting actions directly on target object in metadata is preferable.
    • say - visualizes saying of objects
    • siteProgress - draws arc of progress

Calculation

Sometimes we need to perform some calculations that we use in processors. In order to achieve that we use calculations in metadata. They allow us to calculate values if it’s needed and reuse them among several processors, or during several game ticks.

There are 2 major properties of calculations:

  • id - is a name to be used in order to get access to the calculation result
  • func - specifies a way how to calculate the result. It can be a function or an expression.

For example:

{
    id: 'energyTrianglePoints',
    props: ['energy', 'energyCapacity'],
    func: ({ state: { energy, energyCapacity } }) => {
        const { x, y } = resourceTriangle;
        let { width, height } = resourceTriangle;
        const koef = energy / energyCapacity;
        width *= koef;
        height *= koef;
        return [
            x - (width / 2), y,
            x, y - height,
            x + (width / 2), y,
        ];
    },
},

It defines calculation that will be available as { $calc: 'energyTrianglePoints' } in expressions, or as calcs.energyTrianglePoints in code. This calculation will be evaluated every time, when either energy or energyCapacity properties of an object will be updated. And the result is calculated according the func.

Expression

In perfect way the metadata of render engine should be a declarative way to explain how exact objects should be rendered. In this case it will be possible to transfer it via JSON. In order to achieve that we implemented the expression engine.

It introduces some built-in primitive functions that allows to define a way to evaluate expressions. All expressions are “precompiled”, on starting they are transferred to functional calls. It significantly improves performance of evaluation.

Any object key starting with $ is considered an expression.

  • Getting values:
    • $calc - returns value of a calculation (see ‘CalcExpression). For example: { $calc: 'displayName' }`),
    • $rel - returns property value of a target PIXI object (see RelExpression). For example: { $rel: 'scale.x' },
    • $processorParam - returns property value of processor params (see ProcessorParamExpression). For example: { $processorParam: 'tickDuration' },
    • $state - returns property value of a game state (see StateExpression). For example: { $state: 'actionLog.say' }.
  • Conditions and boolean:
    • $if - returns then or else expression, depending on condition provided (see IfExpression). For example: { $if: { $gt: [1, 2] }, then: ‘it cannot be’, else: ‘it can be’ },
    • $and - logical AND (see AndExpression). For example: { $and: [{ $calc: ‘calc1’ }, { $calc: ‘calc2’ }] },
    • $eq - evaluates equal expression. For example: { $eq: [ { $state: ‘x’ }, 10] },
    • $gt - evaluates greater expression (see GtExpression). For example: { $gt: [ { $state: ‘x’ }, 10] },
    • $gte - evaluates greater or equal expression (see GteExpression),
    • $lt - evaluates less expression (see LtExpression),
    • $lte - evaluates less or equal expression (see LteExpression),
    • $not - logical NOT (see NotExpression). For example: { $not: true },
    • $or - logical OR (see OrExpression). For example: { $or: [{ $gt: [ { $state: ‘x’ }, 10] }, { $lt: [ { $state: ‘y’ }, 50] }] },
  • Operations:
    • $add - returns math addition of args (see AddExpression). For example: { $add: [1, 2, 3] },
    • $div - returns math division of 2 args (see DivExpression). For example: { $div: [4, 2] },
    • $max - returns max value of args (see MaxExpression). For example: { $max: [4, 2] },
    • $min - returns min value of args (see MinExpression). For example: { $min: [4, 2] },
    • $mul - returns math multiplication of args (see MulExpression). For example: { $mul: [2, 2] }, random.js
    • $sub - returns math subtraction of args (see SubExpression). For example: { $add: [3, 2, 1] },
    • $concat - returns string concatenation of args. For example: { $concat: ['Hello', ' ', 'World'] },

Actions

Actions are classes that allow to smoothly display transition between different visual states of the object during the time.

There are several ways to create actions in the engine:

  1. On the game object level in metadata (see ProcessorActionMetadata)
  2. On the processor level (see ActionMetadata)

When you define actions on the game object level, their lifecycle is the similar to the lifecycle of the processors. For example:

actions: [
    {
        id: 'resourceScale',
        targetId: 'resourceCircle',
        props: ['resourceScale'],
        actions: [
            {
                action: 'ScaleTo',
                params: [
                    { $calc: 'resourceScale' },
                    { $calc: 'resourceScale' },
                    { $processorParam: 'tickDuration' },
                ],
            },
        ],
    },
],

It defines resourceScale actions that changes scaling of the target object with id resourceCircle, and runs every time the property resourceScale is updated.

When you define actions on the processor level, their lifecycle is completely managed by lifecycle of the parent processor. For example:

{
    type: 'draw',
    once: true,
    payload: {
        ...
    },
    actions: [{
        action: 'Repeat',
        params: [{
            action: 'Sequence',
            params: [
                [
                    {
                        action: 'TintTo',
                        params: [
                            0x0e0c04,
                            4.0,
                        ],
                    },
                    {
                        action: 'TintTo',
                        params: [
                            0x595026,
                            4.0,
                        ],
                    },
                ],
            ],
        }],
    }],
}

The actions run once when processor creates the object.

There are following actions:

  • AlphaBy - changes alpha property of the target object by delta
  • AlphaTo - changes alpha property of the target object to target value
  • Blink - periodically changes visibility of the object
  • CallFunc - runs the function provided during the time
  • DelayTime - just idle for time specified
  • FadeIn - fades in the object, updating its alpha property
  • FadeOut - fades out the object, updating its alpha property
  • FilterTo - updates property value with name specified to the value specified
  • MoveBy - changes x, y properties of the target object by delta
  • MoveTo - changes x, y properties of the target object to target value
  • PivotBy - changes pivot x, y properties of the target object by delta
  • PivotTo - changes pivot x, y properties of the target object to target value
  • Repeat - repeats target action
  • RotateBy - changes rotation property of the target object by delta
  • RotateTo - changes rotation property of the target object to target value
  • RotateBy - changes rotation property of the target object by delta
  • RotateTo - changes rotation property of the target object to target value
  • ScaleBy - changes scale x, y properties of the target object by delta
  • ScaleTo - changes scale x, y properties of the target object to target value
  • Sequence - group target actions to run sequentially after each other
  • SkewBy - changes skew x, y properties of the target object by delta
  • SkewTo - changes skew x, y properties of the target object to target value
  • Spawn - group target actions to run in parallel
  • TintBy - changes tint property of the target object by delta
  • TintTo - changes tint property of the target object to target value

Actions support expressions in the params, it allows you to control actions flexibly.

Lifecycle Metadata

The lifecycle of processors, actions and calculations is managed by RunnableMetadata. It supports the following properties:

  • props - if set, the processor will be re-run when some of the specified properties are changed. It supports own properties of the game object, and its calculations.
  • once - the processor will be run just once, when it meets when condition. When it meets until condition after that, the lifecycle starts from beginning.
  • shouldRun - deprecated, user when instead
  • until - condition when object is destructed
  • when - condition when object is created

Layer

In order to manage z-order of the object the engine has layers implemented. We use pixi-layers for this. It allows to specify z-order separately from parent container.

All layers are specified in layers property of Metadata. The game support the following layers (from bottom to top):

  • terrain - landscape graphics like walls and swamps
  • objects - a default layer for object rendering
  • lighting - lighting effects of the objects, the layer has filters that simplifies that
  • effects - just the most top layer for putting effects

In order to put a processor to specific layer you should specify its name in layer property. For example:

{
  layer: "effects",
}

Viewport

TODO

Resource

TODO

renderer's People

Contributors

artch avatar dmitriyff avatar justjavac avatar o4kapuk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

renderer's Issues

How to render visuals

There are no examples of how to render visuals. Can you provide an example of how to render a visual by converting it to an object that is passed to applyState? Thanks.

[Bug] Reference main.d.ts in @screeps/renderer 1.3.0

Morning!

I am implementing the project in a local tool of mine made in Typescript. When I implemented the latest version of the package, I can't find any reference to the 'main.d.ts' files.

If you need help with this we see it and create a pull request if necessary.

npm P: @screeps/renderer | V: 1.3.0


I solved the typing problem in the project. I have a branch ready to request the Pull Request to add the solution and its later publication via npm. :)

Modularity typings are solved and dist folder is cleaned and ignored.

Provide it via npm pack and an independent project.

I require if possible permissions to upload the branch bug/bug-typings-npm. ;)


PS: Excuse my English!

Display setting for road connections

Currently a cluster of roads display as a sort of knitting pattern with gaps between them:
Gaps

But an alternative display style I've seen requested is where the roads fill for the buffed area, as seen in my terrible MS Paint edit:
Filled

Would be nice to have a setting near Lighting and Swamp Texture for "Roads" and the selector allows for "Filled" and "Tiled" or something.

Cheers!

powerCreep in room example

There is no clear example of a powerCreep in a room using a power. The powerCreep examples JS seems to be missing what it would look like for a client to receive data for actions from a power creep. It would also be good to have an example of powerCreep death/spawn (since powerSpawn spawning is not a thing).

The levels for commander and executer are not defined either. Does this mean that both executor and commander will inherit from operator on in the renderer?

cirlce.svg missing

The circle.svg that is referenced is missing from renderer/metadata/images/.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.