GithubHelp home page GithubHelp logo

sedyh / mizu Goto Github PK

View Code? Open in Web Editor NEW
81.0 1.0 3.0 360 KB

Entity Component System framework for Ebitengine

License: Other

Go 100.00%
engine game-engine game-development entity-component-system ecs ebiten go golang gamedev ebitengine

mizu's Issues

System constructor is not checking if component exist

Problem

When adding systems, there is no check for unregistered components.

func makeSystem(world *world, s interface{}) *system {
    ...
    componentId, found := world.componentIds[componentType.Elem()]
    if !found {
        continue // system pointer field is not component bound
    }
    ...
}

Solution

Setting a panic at this point will solve the problem, but may affect the ability to correctly compare entities by mask, as well as the ability to get optional components.
It's also worth noting that fixing issue #1 might fix this issue as well, as before initialization of systems, there will be an initialization of entities in which this check is already present.

How can I use a custom Layout method?

In mizu,struct world implements the method "Layout" from ebiten.Game interface,But I want overwrite the method,or my ebiten app draw text with chinese would be fuzzy。

if I use ebiten directly,use the code below,the text display very clear,

func (g Game) Layout(outsideWidth, outsideHeight int) (screenWidth, screenHeight int) {
	s := ebiten.DeviceScaleFactor()
	return outsideWidth * int(s), outsideHeight * int(s)
}

But if I use mizu, I didnt overwrite the method named Layout, So How do I do?

Help: How can i use imgui with mizu?

I want: run ebiten-imgui 's Usage ( https://github.com/gabstv/ebiten-imgui)

problem: black screen

mod:

module github.com/cdhon/ebiten1

go 1.18

require (
	github.com/gabstv/ebiten-imgui v0.5.0
	github.com/hajimehoshi/ebiten/v2 v2.3.4
	github.com/inkyblackness/imgui-go/v4 v4.4.0
	github.com/sedyh/mizu v1.0.4
)

require (
	github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220320163800-277f93cfa958 // indirect
	github.com/gofrs/flock v0.8.1 // indirect
	github.com/jezek/xgb v1.0.0 // indirect
	golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56 // indirect
	golang.org/x/image v0.0.0-20220321031419-a8550c1d254a // indirect
	golang.org/x/mobile v0.0.0-20220518205345-8578da9835fd // indirect
	golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
	golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f // indirect
)

code:

package main

import (
	"fmt"
	"image/color"
	"log"

	"github.com/gabstv/ebiten-imgui/renderer"
	"github.com/hajimehoshi/ebiten/v2"
	"github.com/hajimehoshi/ebiten/v2/ebitenutil"
	"github.com/inkyblackness/imgui-go/v4"
	"github.com/sedyh/mizu/pkg/engine"
)

type UIComponent struct {
	mgr *renderer.Manager
	// demo members:
	clearColor [3]float32
	floatVal   float32
	counter    int
	name       string
}

type UIEntity struct {
	UIComponent
}

type UISystem struct {
	*UIComponent
}

func (ui *UISystem) Update(w engine.World) {
	ui.mgr.Update(1.0 / 60.0)
	ui.mgr.BeginFrame()
	{
		imgui.Text("ภาษาไทย测试조선말")  // To display these, you'll need to register a compatible font
		imgui.Text("Hello, world!") // Display some text

		imgui.SliderFloat("float", &ui.floatVal, 0.0, 1.0) // Edit 1 float using a slider from 0.0f to 1.0f
		imgui.ColorEdit3("clear color", &ui.clearColor)    // Edit 3 floats representing a color

		if imgui.Button("Button") { // Buttons return true when clicked (most widgets return true when edited/activated)
			ui.counter++
		}
		imgui.SameLine()
		imgui.Text(fmt.Sprintf("counter = %d", ui.counter))

		imgui.InputText("Name", &ui.name)
	}
	ui.mgr.EndFrame()
}

func (ui *UISystem) Draw(screen *ebiten.Image) {
	screen.Fill(color.RGBA{uint8(ui.clearColor[0] * 255), uint8(ui.clearColor[1] * 255), uint8(ui.clearColor[2] * 255), 255})
	ebitenutil.DebugPrint(screen, fmt.Sprintf("TPS: %.2f", ebiten.CurrentTPS()))
	ui.mgr.Draw(screen)
}

type Game struct{}

func (g *Game) Setup(w engine.World) {
	mgr := renderer.New(nil)
	ui :=&UIEntity{UIComponent: UIComponent{mgr: mgr}}
	ui.mgr.SetDisplaySize(float32(800), float32(600))
	w.AddComponents(UIComponent{})
	w.AddEntities(ui)
	w.AddSystems(&UISystem{})
}

func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
	return 800, 600
}

func main() {
	ebiten.SetWindowSize(800, 600)
	if err := ebiten.RunGame(engine.NewGame(&Game{})); err != nil {
		log.Fatal(err)
	}
}

error:

level=error msg="[linters context] typechecking error: c:\\PF\\go\\ebiten\\ebiten1\\main.go:5:2: could not import image/color (-: could not load export data: cannot import \"image/color\" (unknown iexport format version 2), export data is newer version - update tool)"
level=error msg="[linters context] typechecking error: c:\\PF\\go\\ebiten\\ebiten1\\main.go:56:34: undeclared name: ebiten"
level=error msg="[linters context] typechecking error: c:\\PF\\go\\ebiten\\ebiten1\\main.go:39:3: undeclared name: imgui"
level=error msg="[linters context] typechecking error: c:\\PF\\go\\ebiten\\ebiten1\\main.go:40:3: undeclared name: imgui"
level=error msg="[linters context] typechecking error: c:\\PF\\go\\ebiten\\ebiten1\\main.go:42:3: undeclared name: imgui"
level=error msg="[linters context] typechecking error: c:\\PF\\go\\ebiten\\ebiten1\\main.go:43:3: undeclared name: imgui"
level=error msg="[linters context] typechecking error: c:\\PF\\go\\ebiten\\ebiten1\\main.go:45:6: undeclared name: imgui"
level=error msg="[linters context] typechecking error: c:\\PF\\go\\ebiten\\ebiten1\\main.go:48:3: undeclared name: imgui"
level=error msg="[linters context] typechecking error: c:\\PF\\go\\ebiten\\ebiten1\\main.go:49:3: undeclared name: imgui"
level=error msg="[linters context] typechecking error: c:\\PF\\go\\ebiten\\ebiten1\\main.go:51:3: undeclared name: imgui"
level=error msg="[linters context] typechecking error: c:\\PF\\go\\ebiten\\ebiten1\\main.go:58:57: undeclared name: ebiten"
level=error msg="[linters context] typechecking error: c:\\PF\\go\\ebiten\\ebiten1\\main.go:80:2: undeclared name: ebiten"
level=error msg="[linters context] typechecking error: c:\\PF\\go\\ebiten\\ebiten1\\main.go:81:12: undeclared name: ebiten"
level=error msg="[linters context] typechecking error: c:\\PF\\go\\ebiten\\ebiten1\\main.go:9:2: \"github.com/hajimehoshi/ebiten/v2\" imported but not used"
level=error msg="[linters context] typechecking error: c:\\PF\\go\\ebiten\\ebiten1\\main.go:11:2: \"github.com/inkyblackness/imgui-go/v4\" imported but not used"
level=warning msg="[runner] Can't run linter goanalysis_metalinter: buildir: failed to load package goarch: could not load export data: cannot import \"internal/goarch\" (unknown iexport format version 2), export data is newer version - update tool"

Enable runtime component modification

Problem

The library code now contains methods for modifying components at runtime, but they are not yet tested and turned off.

Solution

It is necessary to enable and test their work, and it will also be determined whether it is worth creating all entities at runtime or limited to only modifying components.

The scene must be initialized in a certain order

Problem

At the moment, scene initialization should always go in the order: components > systems > entities. Otherwise, they will not find each other.

type Game struct{}

func (g *Game) Setup(w engine.World) {
    w.AddComponents()
    w.AddSystems()
    w.AddEntities()
}

Solution

It is necessary to correct this behavior by replacing the functions of adding all parts with a builder that will automatically initialize at the very end of the scene creation.

func (w *world) AddComponents(components ...interface{}) {
	w.futureComponents = append(w.futureComponents, components...)
}
func (w *world) AddSystems(systems ...interface{}) {
	w.futureSystems = append(w.futureSystems, components...)
}
func (w *world) AddEntities(entities ...interface{}) {
	w.futureEntities = append(w.futureEntities, components...)
}
func (w *world) ChangeScene(next Scene) {
	next.Setup(w)
        w.buildScene()
}

Filtering entities with external slice reuse

Problem

We need an alternative to Filter, which will allow you to use your own list (for example, for sorting), but at the same time, it will not do the allocation once again.

Solution

You can make an analogue of append, but for entities.

func (v *view) AppendEntities(entities []Entity) {
    for _, en := range v.w.entities {
        if en.mask.contains(v.mask) {
            entities = append(entities, en)
        }
    }
}

type System struct {
    entities []Entity
    balls engine.View
}

func (s *System) Update(w engine.World) {
    // Clear balls
    s.entities = s.entities[:0]
    ...
    // Add balls
    balls.AppendEntities(s.entities)
}

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.