Code Monkey home page Code Monkey logo

Comments (5)

0xSMT avatar 0xSMT commented on July 20, 2024 1

Fixed: Looks like the Spin symbol is being parsed as a converter, which newEntityWith from polymorph (at least the version installed via the below command) couldn't understand as a type.

nimble install https://github.com/rlipsc/polymorph.git

The fix to make it work with the version of Polymorph installed with that command is simply to make Spin a more traditional type (float member named rot, and update the constructors and system that uses that component accordingly). Works fine with that fix.

Alternatively, installing polymorph as follows:

nimble install https://github.com/rlipsc/polymorph.git@#master

Makes it such that the fix for Spin is not needed.

In sum, it seems like all the packages simply need to be installed with the @#master suffix (which is frustrating, because installing them in a particular order will cause the incorrect package version to be installed.

from polymers.

0xSMT avatar 0xSMT commented on July 20, 2024

Original error is resolved, partially: installing the glbits library does not work with the following command:

nimble install https://github.com/rlipsc/glbits.git

Had to be installed as follows:

nimble install https://github.com/rlipsc/glbits.git@#master

Not sure why the master branch had to be specified. Regardless, the following error still emerges:

/home/smt/Code/nim/polymorph_tests/test1.nim(190, 29) template/generic instantiation of `newEntityWith` from here
/home/smt/.nimble/pkgs/Polymorph-0.1.0/polymorph/statechanges.nim(37, 11) Error: FindType: adding components needs an object constructor like MyType(field: value) or an ident such as a variable, cannot process a nnkConv
Conv
  Sym "Spin"
  Call
    Sym "degToRad"
    Call
      Sym "rand"
      Infix
        Sym ".."
        FloatLit -1.0
        FloatLit 1.0

from polymers.

rlipsc avatar rlipsc commented on July 20, 2024

Hi @0xSMT, glad you've managed to solve this already, and thanks for writing out the steps you took solve it!

According to https://github.com/nim-lang/nimble#nimble-install

Nimble always fetches and installs the latest version of a package. Note that latest version is defined as the latest tagged version in the Git (or Mercurial) repository

So your solution makes sense. The tagged release of Polymorph is quite old at this point and this library is expected to run with the latest Polymorph commit, so I've pushed an update to the .nimble file to use polymorph#head, instead of defaulting to tagged releases.

I've also pushed a release for glBits so there's a recent tag for nimble to use.

Hopefully these changes mean you don't need to use @#master but let me know if there's still an issue.

from polymers.

0xSMT avatar 0xSMT commented on July 20, 2024

Works great now! Only caveat is installing Polymorph first directly (without @#master) will still seem to install an older version, so if you install Polymorph first and then Polymers you'll have two versions of Polymorph installed, but otherwise everything works out of the box!

Also would just like to thank you for the amazing work on these projects -- Polymorph has such amazing potential and it's very well-designed, I've been playing with it all weekend. Its use of the macro system for compile-time ECS generation is inspiring, and sets a gold-standard for Nim libraries (especially since so many of them anymore seem to be unmaintained...) The best of luck on this project in the future, I'll continue keeping an eye on it! :)

from polymers.

rlipsc avatar rlipsc commented on July 20, 2024

Only caveat is installing Polymorph first directly (without @#master) will still seem to install an older version

Nimble is downloading from the tag, which is super old. I'm currently working on better documentation for a new tagged release and will push that when the docs are decent, then I'll submit it to nimble so you can do nimble install polymorph and hopefully it will all work (I'll have a deeper dive into nimble when that happens).

Really cool to hear things work out of the box, though. I'm developing on a Windows machine so it's great to hear graphics and physics works on Linux!

Also would just like to thank you for the amazing work on these projects -- Polymorph has such amazing potential and it's very well-designed, I've been playing with it all weekend. Its use of the macro system for compile-time ECS generation is inspiring, and sets a gold-standard for Nim libraries (especially since so many of them anymore seem to be unmaintained...)

Thank you for the kind words! It's great to hear, and it's nice to hear the design resonates, too! I'm a big believer that ECS is just another way to organise code in the same vein as OOD, and Polymorph is developed with that in mind rather than specifically for game development (though I'm also using it for gamedev).

There's definitely a lot of potential with a code generation approach to ECS. Since there's no run time to speculate on potential features it's truly "pay for what you use", and as data structures are configurable without changing any code, it's extremely adaptable.

Essentially, Polymorph is translating declarative dispatch - "run this code when this data exists" - into simple imperative loops and statically compiled list updates. All the code runs predictably from top to bottom as it's written, and combined with being able to allocate everything on the stack to fixed sizes (pending a few seq being configurable as array behind the scenes), it's amenable to embedded and resource constrained devices where stack overflows from complex callbacks are an occupational hazard.

Inline events also let you build imperative code whilst writing in an event driven style, as they're directly included into the generated code output for relevant operations. For example, code added to an event like SomeComponent.onAdd is output by entity.add SomeComponent(), and multiple code blocks can be added to individual events. This lets you create libraries with events which can be extended by users whilst maintaining the open/closed principle and linear code flow. System events even let you add and remove components within the event (of course, with great power comes great responsibility)!

Using macros is one of Nim's killer features and I'm really looking forward to seeing what's possible going forward. I feel we're at the beginning of the potential curve of Nim's macros being used in earnest. Even with Polymorph, there's little things like registerComponentsFromFile which is just three lines of code, but potentially allows fetching the file from a network source, perhaps even as part of the build process, so you can maintain compile time type checking with a remote source.

Of course, the caveat to extensive metaprogramming is that it does add to build times. Thankfully Nim is pretty fast already, but the push for incremental compilation right now shows things could be faster still.

The best of luck on this project in the future, I'll continue keeping an eye on it! :)

Cheers!

As a taste of future work, check out automated threading. This will take advantage of the static analysis Polymorph currently does to determine which components are being written to and read from within systems (you can see this info when compiling with -d:ecsPerformanceHints) to automatically handle threading for you. As systems are expected to be run in order, there are 'paths' of systems which don't interact with others based on the components they use, so these can be spawned as threads and the appropriate synchronisation primitives can be inserted for you at the points where these 'paths' interact with other systems.

As for Polymers, aside from working demonstrations of how to use Polymorph the goal is to be able to use it as a kind of standard library for data oriented programming.

In that vein many of the components in Polymers are unrelated to game development directly and focus on the kinds of things that programmers need to do as self contained composable components, such as database and console input/output. Originally this was a challenge to see how the ECS pattern fares on these kind of tasks, but as I've written more of these components and systems, I've found that ECS often has advantages over traditional object oriented designs with non-gamedev tasks as well.

For instance the functional isolation of components and systems means you can combine, say, a 3D model rendering component with a component that reads a network stream, add a system that sets the colour of the model based on data in the stream, and you've got the basics of a graphical monitoring tool for remote machines. This could be extended with database components, file access components, or console output components, and so on. As everything is isolated and composable at run time, dramatically pivoting these kind of designs is often just a case of writing a system to bridge component functionality.

Regarding networking, I have a stack of networking components I'm preparing to release for Polymers, including:

  • TCP read/write components using IO completion ports.
  • HTTP processing and responses.
  • JSON RPC.
  • Web fetching and RSS feed extraction.

Many languages, Nim included, use async or coroutines for networking code. My hope is that networking with ECS will offer a reduction in run time complexity (and mental complexity), increased operational transparency, and less/no callback context switching.

One of the pros of async is latency, as once you await something, immediately something else might be processed (although you might not know what). With the ECS networking components, this advantage is captured by using events to begin networking operations. So, entity.add TcpSend(data: "Hello") will start the operation and then return immediately, much as async does. A dedicated system reads packet completion events and adds 'completion components' (such as TcpSendComplete and TcpRecvComplete) so you can create asynchronous systems that build upon one another.

This provides a lot of control and flexibility; systems can be run as batches or stream their operations over time, the order of processing is explicit, operations can be cancelled by removing components or deleting entities (events ensure resources are collected), and statuses can be checked by simply reading the data in the appropriate components.

The other side is that it's a pretty different way of working compared to async, and currently it's missing SSL/TLS support (this will be implemented with OpenSSL).

At the risk of making this reply excessively long, here's how a basic web server looks with these components:

    import polymorph, polymers

    const
      maxEnts   = 10_000  # Maximum concurrent connections.
      entOpts   = fixedSizeEntities(maxEnts)
      compOpts  = fixedSizeComponents(maxEnts)
      sysOpts   = fixedSizeSystem(maxEnts)

    defineTCPNetworking(compOpts, sysOpts, tllEvents)
    defineHttp(compOpts, sysOpts)

    registerComponents(compOpts):
      type RootPage* = object

    makeSystemOpts("servePage", [RootPage], sysOpts):
      # Send the response for the root page.
      added: item.entity.add HttpResponse(
        code: Http200,
        body: "Hello!"
      )

    makeSystemOpts("finishServePage", [RootPage, HttpResponseSent], sysOpts):
      # Clean up the connection.
      finish: removeEntities()

    makeEcs(entOpts)
    commitSystems("poll")

    let
      server =
        newEntityWith(
          TCPListen(
            port: Port(5555),
            # When a connection is accepted, the following components are added:
            onAccept: cl(
              ProcessHttp(),
              HttpRouteEntity(
                patterns: @[
                  ("/", cl RootPage())
                ]
              )
            )
          )
        )

    while true: poll()

However, unfortunately several of the components in Polymers are Windows only.

I really want to include the Linux equivalent for completion ports for the TCP components, and ecs_renderchar needs to support Linux too. I need to set up a Linux subsystem or VM and start testing stuff out!

from polymers.

Related Issues (1)

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.