Code Monkey home page Code Monkey logo

coquette-inspect's Introduction

coquette-inspect Stories in Ready

A Chrome DevTools extension for inspecting games made with the Coquette framework.

The inspector in action in the spinning shapes demo.

Features

  • List entities currently in the game world
  • Inspect the properties of entities as they update
  • Change the properties of entities
  • Play/pause the game loop
  • Step through the game loop

Installing

To install:

git clone [email protected]:thomasboyt/coquette-inspect.git
cd coquette-inspect/
npm install && ./node_modules/.bin/webpack

Then load the chrome-extension folder as an unpacked extension (see this guide).

If it worked, you should see a "Coquette" tab in your developer tools when you next open them.

Usage

There are two modifications you'll need to do to your Coquette apps to make them work.

Exposing Coquette

The most important one is that you expose the Coquette instance in your game as window.__coquette__, e.g.:

var Game = function() {
  window.__coquette__ = this.c = new Coquette(this, "canvas", 500, 150, "#000");
// ...

Without this, the inspector won't be able to find your Coquette instance.

Entity display names

To display your entities with their proper names (i.e. their constructors), one of two of the following need to be true:

If your constructors are defined with the syntax function Foo() {...}, the name will be looked up with entity.constructor.name. This doesn't work if your function is anonymous, e.g. var Foo = function() {...}, because that's just how function.name works. See [MDN] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name) for more detail on this weird quirk.

Otherwise, you can set the displayName property on your entity. You can either set it inside the constructor (e.g. this.displayName = 'Person'), or inside the call to entities.create (e.g. c.entities.create(Person, {displayName: 'Player'})).

coquette-inspect's People

Contributors

thomasboyt avatar waffle-iron 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  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

coquette-inspect's Issues

Better labeling for & handling of hidden objects in properties tree

Labeling

Currently, they all say [[circular reference]] which is actually usually not even true, they're just objects already seen.

There's basically four reasons an object is hidden:

  1. It's not serializable, in which case it should say [object ObjectType]
  2. The object has already been serialized once (either a circular reference, or just a duplicate one). This is tricky, because e.g. [object hidden] may not be clear - may not be obvious where else in the tree it'll be. Right now, this just is [circular reference], so it should be able to stay that way for v0.1.
  3. It's another entity. It would actually be amazing if this could be a link to elsewhere in the tree, using the entity's ID! This could be formatted as e.g. [entity <uuid>]
  4. It's a coquette namespace, in which case it says [coquette namespace]
  1. and 4) should already be working, but 2) and 3) require some way to distinguish between each other so the serializer can set them correctly. I think the solution is to use the value of the entityMap/seen to indicate whether it's a previously serialized object (2), or another entity (3).

Handling

This goes in tandem with the above. One of the tricky bits about this is making sure that these fancy strings with fancy meanings don't end up conflicting with actual set strings, because there's going to be a regex match used against them to ensure that the UI doesn't allow them to be edited.

From the above, I could think of a few regexes to match:

  1. ^\[object\s[^\s]*]$ - matches [object Object], not [object], not [object object object]
  2. ^[circular reference]$
  3. ^[entity \s[^\s]*$ - similar to 1
  4. ^[coquette namespace]$

These should probably be in the docs somewhere, as a way of saying "make sure your strings don't match things!"

Inspect entity at cursor

This one's pretty out there, but I think it's doable, if prone to breaking in intense ways:

Any entity in Coquette's collision detection framework should have this.size{x,y} and this.center{x,y} properties that could be used to determine whether two x,y coordinates lie within an entity. In fact, Coquette even has a super awesome method built in for this, used like this in the spinning shapes demo.

The debugger could have an "inspect at cursor" toggle, almost exactly like the inspect element button in the DOM inspector, that would allow you to click an entity and open its particular tree.

Create embeddable inspector

this would be super, super cool, and make it easy to create "playground" demos with coquette.

seems like the main thing to do here is to have an "adapter" abstraction for the communication between the Agent and the UI, like how Ember Inspector does, that could replaced with just pure window.postMessage() or whatever weird shit you have to do to make iframe communication go (if that's how it's embedded)

Real bad performance on Box2D demo

This is specifically related to the (non-)performance of serializing entities. This demo creates lots of tiny particles, each represented as an entity. Serializing all of them is mad expensive. It's unclear whether the cost is due to the number of entities, or if some very complex object is getting serialized.

Add delta-time step ability

So, there's a "step" button now, but it's a bit weird because there's no delta time in the frame (it's set to 0 for the first frame after start(), see https://github.com/maryrosecook/coquette/blob/master/src/ticker.js#L13-L17). This means that no update code is going to go that depends on a delta time (e.g. moving things).

Easiest way to do this would be to set a "perfect" delta time for 60fps, which would be 1000/60 ms (~16.67). Easiest way to do that would probably be to monkey patch start() to accept an initial prev time. Unfortunately, any monkey patch wouldn't have access to the gameLoop variable that's in the closure, so likely the entire Ticker constructor needs to be patched to store that in its context :(

Attach a unique ID to each entity

When entities are listed, their position in the entities array is currently used as the React key. However, this means that an entity being moved in position (i.e. if a prior entity is removed) will require the DOM for that entity to be entirely recomputed, which is a big overhead. It also makes it extremely hard to subscribe to the state of a specific entity.

So, there are two changes that need to happen:

  • Each entity needs to have a unique UUID
  • A method needs to exist for the agent to look up an entity by UUID

There's a couple options to implement UUIDs -

  • Monkey-patch entities.create to generate a UUID and store it in the entity, then iterate over the current entities list and backfill any that don't have UUIDs
  • Actually patch entities.create

entities.create is pretty simple; the easiest way to monkey-patch would be to simply wrap the original function:

var orig = this.__coquette__.entities.create;
this.__coquette__.entities.create = function(Constructor, settings) {
  var entity = orig.apply(this, Constructor, settings);
  entity._uuid = generateUUID();
  return entity;
};

Backfilling's also easy, e.g. this.__coquette__.entities.all().map((entity) => { entity._uuid = generateUUID() })

For looking up an entity by UUID, a filter should be good enough to start. Could cache a map of {uuid: entityObject}, but would have to make sure that the map entry is removed if the entity is deleted, which would require a monkey-patch around entities.remove

Arrays totally destroy perf? what the hell :<

I'm pretty sure that #14 was actually caused by this, which means that I did all of this for little gain, but they're kind of nice to have anyways, I guess :(

reproduce: 33rpm -> game object -> musicConfig -> intros -> watch as dev tools freezes entirely

UI freezes when streaming "large/complex" objects

Great test case: the game object in 33rpm.

Displays fine when paused, of course. Seems likely that there's an O(n^2) algo doing dumb things somewhere. Should experiment with different object shapes in a testbed - should test objects, arrays, number of properties, depth, etc.

FPS counter

this seems like a relatively easy piece of work - simply report the current time on each entities tick, and have the UI calculate the average FPS over time.

Modifying entity properties

UI thoughts:

  • Primitives need to be turned into inputs
    • Number: <input type="number" />
    • String: <input type="text" />
    • Bool: <select><option value="true">True</option><option value="false">False</option></select>
    • null: This is super tricky because it's totally unknown what they're supposed to be. I'm thinking they could just be an <input type="text" /> and autocast based on whether it's a number or string? Obviously that's not great but seems better than not letting you change it at all.
  • It should be possible to set a property to undefined or null, no matter the type.

Agent thoughts:

  • Message should be some sort of path. I'm thinking:
{
  name: "modify",
  data: {
    entityId: "<uuid>",
    path: "foo.bar.baz",
    value: "<value>"
  }
}

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.