Giter VIP home page Giter VIP logo

engo's People

Contributors

ankithd avatar boombuler avatar countcb avatar dependabot[bot] avatar dsymonds avatar edoardo849 avatar eth0net avatar etiennebruines avatar faide avatar gitter-badger avatar hismito avatar ilyar avatar inkeliz avatar jonbonazza avatar jrmiller82 avatar kunde21 avatar m0re4u avatar matiwinnetou avatar mewmew avatar mrtrustworthy avatar newbrict avatar nikai3d avatar noofbiz avatar otraore avatar paked avatar qiukeren avatar storyfeet avatar theberrybeast avatar umarquez avatar yarbelk 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  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  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  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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

engo's Issues

System New does not have access to system.World

The system.World variable is being set after the system.New() function is being called.

As such, one does not have access to the World from the system.New() function (null-reference). This should be fixed by simply switching two lines: first calling SetWorld, then calling New().

Fix Camera API

The Camera API does not correctly stay within bounds. It does not use the limits correctly (those defined in WorldBounds).

This should be fixed somewhere in assets.go and batch.go.

I have no clue how to handle this (SO).

JavaScript Backend

While we are looking at different platforms to support in #63, I feel it would be good to open up discussion about what to do with the old GopherJS backed JavaScript/HTML backend.

I'm not quite sure how much work it would take to get the GopherJS backend working again. I suspect the hardest thing to do would be fixing up shaders and Font loading/rendering.


Todo list:

(before it even compiles; will be adding more as needed)

  • Loading files:
    • loadImage()
    • loadJSON()
  • Manually creating images
  • CameraSystem (lower-priority)
    • window.GetSize()
    • window.GetCursorPos()
  • AudioSystem (lower-priority)
  • Shaders / graphics - actually seeing some output

DoesExist and Hide

This issue is two-fold:

  • Remove the DoesExist function from the Entitiys;
  • Add a Hidden PriorityLevel to system.go, with a negative value (lower than Background); this will allow objects to not be rendered by RenderSystem. This can be set by the user in the RenderComponent the user adds.

It's open for anyone who wants to do this.

Undraw something

Removing something from the RenderSystem, does not remove it visually.

Asked SO to help - wouldn't know where to begin.

Click handling

How should clicks be handled according to the ECS?

In javascript/html, there's some kind of propagation: the foremost element is clicked, then passed along to any other element that may have been involved ; and each time the element has the ability to stop the propagation.

In ECS, I would assume there is some kind of System that monitors whether or not something gets clicked?

Any best-practices here? Anything I misunderstood? (I imagine the "buttons" in the "main menu" I'm creating, to be some kind of clickable)


Current status

  • Rightclick-handling

Demo count

As @matiwinnetou also mentioned at IRC: it looks like we're going to have a huge amount of demos, if we keep going like this.


What are we going to do about the huge amount of demos?

  • Categorize them? (i.e.: audio-related, camera-related, etc.)
  • Remove them? (i.e.: only take those most important)
  • Merge them? (like in games as pong)
  • Better document them in the "main" README.md file in the demos/ directory?
  • ...?

We can use this issue to keep track of what we want to do about this (upcoming) problem.

HUDGround ratio

The current HUDGround PriorityLevel does not have a correct perception of pixels.

If you draw something with width 800, and have a 1600px monitor, you will see that the Entity covers the entire screen, not half.

Even though it's not hard to just do /2 in the users' code, this should be fixed.

Consistency between Type and Name

Some interfaces require implementation of the Name() string function, while others require the Type() string function.

Both are implemented in exactly the same way (which could also be done by reflect, but that's another story). We should create some consistency and use either one of those.

Thoughts on which one?

Fix performance issues

I don't know exactly why (yet), but this code runs (after selecting "New Game", and adding 100 entities on-screen), at a mere 17 FPS.

I'm not saying I want to reach 1,8 million fps again (which we'll never reach with rendering), but looking at the things I'm doing, I feel like this should be fixed.

The go profiler says it's mostly external code ๐Ÿ˜ž .


  • The problem definitely has something to do with engi.RenderSystem.
  • More precisely, this function call (line 119 in batch.go):
Gl.BufferSubData(Gl.ARRAY_BUFFER, 0, b.vertices)
  • b.vertices is of length 200.000 (maximum length) every time. Not sure why that is the case, but it sure is related to the problem.
  • I am rendering 100 different entities; that might be related (a lot of calls to that function)
  • That function is called about 30 times per frame; which could be worse, but as it requires 0.1ms to run, that's too much to handle.

Messaging System is clunky

Currently when subscribing to an event you pass in the system and the event name. This is clunky and leads to too much message confirmation logic in the default System.Receive(msg Message) handler.

My proposal is to pass a type func(msg Message) when subscribing to an event instead.

Any objections?

Docs in README

Docs section at README.md could use some work.

I'd say we keep those "thoughts" in separate issues, so they can be addressed / discussed in an orderly manner? Some of them are vague (issues would clarify them).

Rendering of sprites

Having spend like hours looking at the code I seem to understand why I cannot render a tile from a tile map or a sprite from a sprite map.

func (r *Region) Render(b *Batch, render *RenderComponent, space *SpaceComponent) {
    r.texture.Render(b, render, space)
}

This function simply renders texture, but that is not what I want. When I, however, want to render a sprite it doesn't work with a ECS system. It looks like it's render method has been only implemented for *Batch.

I don't get these batches but even if I did I think this is some legacy from the old forked engine, which does not seem to be ECS based.

Would it make sense to make Sprite "Renderable" so that it satisfies the contract from Renderable type? For me this is the most natural progression but I don't get of this if it has not been implemented due to lack of time or I am missing something fundamental here.

Can you open a Gitter channel please? Have you heard of gitter? It is perfect for OpenSource project, not Slack (IMHO).

FPS Limit

When using the example given at the README, I'm getting a FPS of about 30-40k.

It would be nice if we could limit this, since this wastes quite some CPU resources. The programmer could pass/set options somewhere, to set the limit to 30/60/90/120/unlimited whenever he wants. Preferably at runtime (because it'll reside in the game Settings).

Looking at the code here, it's obvious why the FPS is getting this high.

What about something like this?

    Wo.New()
    ticker := time.NewTicker(time.Duration(int(time.Second) / fpsLimit))

Outer:
    for {
        select {
        case <-ticker.C:
            responder.Update(Time.Delta())
            window.SwapBuffers()
            glfw.PollEvents()
            keysUpdate()
            Time.Tick()
            if window.ShouldClose() {
                break Outer
            }
        }
    }
    ticker.Stop()

Not sure what the best practice would be if someone were to change the fpsLimit - we'd have to re-create the ticker.

Multiple entities forming one entity

Imagine one having an Entity, with a RenderComponent - let's say this is a character in-game.
Now, let's say that this character has a health-bar, a bar that's more/less green, right above his head.

The health-bar is associated with the character, and therefore would be the same Entity. But as there's only room for one RenderComponent for that Entity, it should become another Entity.

What's the best way to handle this? Two Entitys that are linked together? (i.e. a ReferenceComponent, which references to the other Entity), or is there a way we can say that that Entity has two RenderComponents? What's the best-practice here?

@paked @matiwinnetou ?

Mobile (+ tablet) support

We'd like to support engi on Android and iOS.

List of thoughts:

  • We would need OpenGL / GLFW available on the mobile device; or refactor a lot
  • We would want to support both phones and tablets
  • Mobile support should improve in Go 1.6.

Any additional information can be posted in this issue.

Todo list

(will be added upon when needed)

Dependencies Debian

As mentioned at their GitHub page, glfw has some dependencies.

For example, on Debian/Ubuntu, you need to:

sudo apt-get install mesa-common-dev xorg-dev libgl1-mesa-dev

These are the only dependencies I've found (so far). I'll leave it up to you if you want to document this, and how you want to document this.

Restructure Animation Component/System

In the ECS paradigm components are designed to only store data, systems are supposed to manipulate this data. The current animation implementation has logic spread between the component and its related system.

Renaming

Some things in engi don't have idiomatic names.

Examples are:

  • engi.GetComponent -> engi.Component
  • engi.Keys.KEY_SPACE -> engi.Keys.SPACE

Also: we might want to think about removing engi.Keys.SPACE (and such) all-together? Since we have engi.Keys.Get(engi.Space) - which works for every key, and not just a few of them?

code.google.com shutting down

warning: code.google.com is shutting down; import path code.google.com/p/freetype-go/freetype will stop working
warning: code.google.com is shutting down; import path code.google.com/p/freetype-go/freetype/raster will stop working
warning: code.google.com is shutting down; import path code.google.com/p/freetype-go/freetype/truetype will stop working

These are referenced at font.go, and should be replaced with the new import path (github.com/golang/freetype).

Scenes in ECS

With the term Scene, I mean something that fills the screen. Such as "level 1 in pacman", or "main menu", or "settings", or "high scores".

How should one handle this / switch between them, in ECS / engi?

My original thought was to add / remove Systems on-the-fly, indicating which would be active and which would not. I am not sure if this is the best/correct way to go, or if there's another (more idiomatic) approach?

RemoveEntity at System level

@matiwinnetou and I talked about this a few days ago; RemoveEntity is now implemented at World, which removes it from the global list of Entitys, but it also needs to be removed from the specific Systems that update the Entity.

Fix examples

It seems like the examples are broken from when better font support was added.

  • Pong
  • botmark.go
  • game.go
  • hello.go
  • tilemap.go

Multithreading

As Go is such a nice language to do multithreading in, and most games lack multithreading, it'd be nice if we supported it.

Currently, each frame, we are iterating over all Systems, and iterating over all Entitys "in" those Systems.

I'm not sure if we can safely multithread multiple Systems at once, but we could easily multithread the iteration over Entitys?

Current implementation

    for _, system := range w.Systems() {
        if headless && system.SkipOnHeadless() {
            continue // so skip it
        }

        system.Pre()
        for _, entity := range system.Entities() {
            if w.paused {
                ok := entity.GetComponent(&unp)
                if !ok {
                    continue // so skip it
                }
            }
            if entity.Exists {
                system.Update(entity, dt)
            }
        }
        system.Post()
    }

Proposed implementation

    for _, system := range w.Systems() {
        if headless && system.SkipOnHeadless() {
            continue // so skip it
        }

        entities := system.Entities()

        system.Pre()

        // It's not always faster to multithread; so in this case we're not going to
        if len(entities) < 2*runtime.NumCPU() {
            for _, ent := range entities {
                system.Update(ent, dt)
            }
            system.Post()
            continue // with other Systems
        }

        entityChannel := make(chan *Entity)
        wg := sync.WaitGroup{}

        // Launch workers
        for i := 0; i < runtime.NumCPU(); i++ {
            go func() {
                for ent := range entityChannel {
                    system.Update(ent, dt)
                    wg.Done()
                }
            }()
        }

        // Give them something to do
        for _, entity := range entities {
            if w.paused {
                ok := entity.GetComponent(&unp)
                if !ok {
                    continue // so skip it
                }
            }
            if entity.Exists {
                wg.Add(1)
                entityChannel <- entity
            }
        }

        // Wait until they're done, before continuing to other Systems
        wg.Wait()
        close(entityChannel)

        system.Post()
    }

I know it's a bit more code than the original implementation, but it sure is efficient.

Automatically add Systems

In the README.md file, it reads:

  • Automatically detect which systems should be added to based off component depends on

It's a nice idea, and I would like to use this issue to talk about it - possibly 'accepting' or 'rejecting' it as an idea.


Pros

  • Easier to for the user, no need to manually add those Systems.

Cons

  • We possibly don't know the System - if it's RenderSystem, we know it. But if it's some kind of MyCustomSystem, then we wouldn't be able to add it;
  • It's slower, if we have to check "did we add System this already?" whenever an Entity is added.

Cleanup: engi has both responder and Wo - global

In engi.go, two variables are globally defined:

var (
    responder   Responder
    Wo          Responder
)

They have exactly the same value, and are used for exactly the same. Which one are we keeping?

Side-node, if it's a Responder (and not a World), should we even call it Wo? It took me a while before I noticed why Wo didn't have the functions / variables available that World has.

Remove Legacy Code

Throughout the codebase there are various pieces of legacy code. These need to be removed.

  • Sprite
  • Drawable (or Renderable)

Pause also hides items

The current implementation of the PauseSystem also makes sure that everything that is paused, isn't rendered.

This is because it skips all Entitys that do not have an UnpauseComponent - and thus these Entitys are not passed along to the RenderSystem. This only showed once #57 was fixed.

The question here is: do we want this behavior? Don't we want this behavior? Do we want to make this behavior optional / default?

AudioSystem - Weird sound at start

Whenever the background music starts, I hear some kind of weird 'popping' sound. Not sure what it is, or how to fix it. Sounds almost like the speakers turning on.

Anyone else hear that sometimes?

Pong sample broken.

With the recent API changes regarding collision messaging, the pong sample found in demos/pong/ is broken.

Benchmarking / Non-GLFW solution

What

Would be nice to have a way to "disable" GLFW renderings, and just test the "logic" behind it all. In other words: I want to be able to benchmark engi, using go test.

Why

This makes automated tests easier, as well as benchmarking a certain solution (i.e. Message-usage) - in order to improve its performance.


Tasks (and possibly more to add):

  • allow to remove FPS limit (only then, can we actually benchmark)
  • fix termination/crash of GLFW when within go test operations

Animation: default

The idea is that something has a user-defined default animation (i.e. standing still).

Whenever someone wants to do something (i.e. animate a "grab", "jump", "kick", "nod", etc.), he calls a function and duration:

something.Animate(ACTION_JUMP, time.Second * 0.5)

It animates as it normally would, but instead of repeating it, it would go back to animating the default behavior.

Thoughts? @paked @matiwinnetou

Use different Shader for HUD

HUDGround is defined in system.go, to indicate some kind of HUD. This is good.

This is given a PriorityLevel, to indicate it must be drawn on top. (i.e. Background is all at the bottom).

However, the HUD is no affected by the camera (shouldn't move / change size). Since the camera behavior is defined in the Shader (assets.go, lines 248 and up), we should use other definitions for the HUD.

Related is also batch.go, line 44.

Feature Request: Menu

It'd be nice if someone pressed something like ESC (or something else), it'd pop-up some kind of menu. We all know it; it asks us if we want to continue, change settings, exit, save, load, etc.

But it also stops everything else in the game -- depending on which game you're playing.

Proposition:

width := 600
height := 800
pauseWorld := true

menuEntity := engi.CreateMenu(width, height, pauseWorld)

And this Entity, would then contain a SpaceComponent of given size, and one could add some additional components (i.e. RenderComponent) to do the markup themselves. The pauseWorld part is why I'd love to see this implemented (by me or someone else).

Additional proposition (which you don't have to like):

pauseWorld := true
items := map[string]func() {
    "Continue" : func() { /* do nothing */},
    "Save" : func() { /* save the game */},
    "Exit" : func() { /* exit the game */},
}

menuEntity := engi.CreateMenu(pauseWorld, items)

Then engi would just create a menu with these options, possibly with some styling options for the user.

Not sure how this fits in the whole ECS-paradigm, but it'd be a nice feature to have. And this issue would be a great place to discuss (or summarize discussions).

Project's Todo List / Chat

I'm currently working on a game prototype using this engine, but there's a lot of things missing on it for now. So I'm currently committing only to my fork of this project.

Can we have a Trello's to-do list or at least any chat to sync this project's information?
Are you on Gopher's Slack? or IRC?

GetComponent - performance w.r.t. reflect

The GetComponent function we use, is quite nice. The current usage being:

var comp *SpaceComponent
if !ent.GetComponent(&comp) {
    return // not found
}

However, reflect is quite slow.

An alternative:

var comp *SpaceComponent
interf := ent.GetComponent(comp)
if comp, ok = interf.(*SpaceComponent); !ok {
    return // not found
}

But ... This does not feel right, but rewriting it as this isn't perfect either:

var comp *SpaceComponent
var ok bool
comp, ok = ent.GetComponent(comp).(*SpaceComponent)
if !ok {
    return // not found
} 

Or this:

var comp *SpaceComponent
if comp, ok = ent.GetComponent(comp).(*SpaceComponent); !ok {
    return // not found
}

Ignoring the reflect package and try to manipulate it with the unsafe package also didn't quite work.

The fastest solution I've come up so far, is this one:

// SPACE_COMPONENT is a uint32 or something, thats generated 
// on build-time by the user; the same would be needed for AddComponent, etc.
// or on boot-time, when calling some kind of Register function
comp, ok :=  ent.GetComponent(SPACE_COMPONENT).(*SpaceComponent)
if !ok {
    return // not found
}

I'm not sure what we should do here; if we should do anything at all. All I know for now, is that 20% of the runtime, Go is occupied with the reflect part of the GetComponent function (i.e.: that's about 95% of the GetComponent function duration).

I'm putting it here, because perhaps someone has a nice suggestion as to how to improve this.

GC creates strange results

The Go Garbage Collector does some strange stuff, as we all know. It even made some benchmarks look quite weird.

I had a point where benchmarking the same function, 5 times, would increase in performance over time (1st benchmark 100%, 5th benchmark 87% of the runtime).

Perhaps we should use runtime.MemStats.EnableGC = false, to disable GC completely, and then call runtime.GC() just before we wait for the buffer synchronization (which usually blocks anyway, waiting for the monitor/GPU)?

Thoughts @paked @matiwinnetou ?

Resizing window

We should handle the resizing of the window.

The user should be able to say: I want my things to stretch / shrink as needed (useful for i.e. pong), or to leave the HUD as-is, and just provide a larger/smaller view of "the world" (useful for i.e. Prison Architect, Roller Coaster Tycoon (1+2), etc.)

Currently, the first is implemented. But there's no way to listen for a "ResizeMessage" or something like that.

Changing PriorityLevel

Right now, when changing the Priority in a RenderComponent, it doesn't get rendered correctly.

The current workaround is to add the Entity to the world again, to ensure the RenderSystem categorizes things correctly.

Note that this is because of the rendersystem.changed variable, which makes sure the per-PriorityLevel list doesn't have to get rebuild on each frame.

WorldBounds.Max default before Setup

Before calling the Setup() function, we should have set the WorldBounds.Max value.

Currently, this happens when World is created, which is after calling Setup(). If we do so before, users can actually use those default values (or override them if they want to).

Suggested fixes for botmark.go example

Hi,

Nice work, I have been exploring the library and I found that botmark.go need these changes

type Game struct {
    engi.World
}

func (game *Game) Preload() {
    engi.Files.Add(engi.NewResource("bot", "data/icon.png"))
}

All Entitys in one map/slice

In order to reduce Garbage Collection, we could keep track of all our Entitys, and keep them all in the same map or slice.

Everything within a []Entity is ignored for GC, but []*Entity is being tracked by GC. We could keep one list of all Entitys.

Not sure if it would increase performance, but it's worth the benchmark.

Colors within engi

We currently use:

  • engi.Color
  • color.RGBA
  • uint32

All of these represent colors. We should refactor and use only color.Color. This allows use of color.RGBA, and possibly others (it's an interface in the standard library image/color).

It's open for anyone who wants to do this.

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.