zllangct / ecs Goto Github PK
View Code? Open in Web Editor NEWA Go-implementation of the ECS (Entity-Component-System), focus on the development of game server.
License: BSD 3-Clause "New" or "Revised" License
A Go-implementation of the ECS (Entity-Component-System), focus on the development of game server.
License: BSD 3-Clause "New" or "Revised" License
Hi,
Trying World.Stop() does not stop the running systems.
您好,最近我也在思考golang如何处理一些破碎内存的问题,想问下这边是准备如何实现处理 连续性 这块的优化?谢谢
func (w *AsyncWorld) Wait(fn func(g SyncWrapper) error) {
w.lock.Lock()
defer w.lock.Unlock()
wait := make(chan struct{})
w.syncQueue = append(w.syncQueue, syncTask{
wait: wait,
fn: fn,
})
<-wait
}
func (w *AsyncWorld) Wait(fn func(g SyncWrapper) error) {
w.lock.Lock()
wait := make(chan struct{})
w.syncQueue = append(w.syncQueue, syncTask{
wait: wait,
fn: fn,
})
w.lock.Unlock()
<-wait
}
Hi,
Is there a way I can use different updates rates for systems ?
For eg, the movement system might need updating every 33 ms, but say the inventory system might only need to be updated on an event like the player firing a gun. Another system - say fuel system - might need updating only every 5 secs.
How do I achieve this?
Thanks
Hi,
I'm creatng an entity in an asyncworld as below.
e = Gaw.NewEntity()
e.Add(p, m, t, r, pr, h, i, d, r)
Entities[id] = e
then deleting the entity by
Entities[id].Destroy()
After Destroying, the entity remains available when doing :-
iterT := ecs.GetComponentAll[components.T](m)
for iter := iterT; !iter.End(); iter.Next() {
ecs.Log.Info(t.id)
}
Please help.
Hi,
I'm adding a weapon entity
game.World.NewEntity().Add(p, m, t, r)
then deleting it after its run
ecs.EntityDestroy(w.World(), data.M.Owner().Entity())
When I want to re-add another weapon entity
game.World.NewEntity().Add(p, m, t, r)
I get an error
panic: runtime error: index out of range [9] with length 9
goroutine 44 [running]:
github.com/zllangct/ecs.(*Collection[...]).Add(0xc000688280, 0xc0000b7000)
/home/chaitanya/workspace/astt/ecs/collection.go:43 +0x2a9
github.com/zllangct/ecs.(*Component[...]).addToCollection(0x20?, {0xd14ee0?, 0xc000688280?})
/home/chaitanya/workspace/astt/ecs/component.go:145 +0x3f
github.com/zllangct/ecs.(*ComponentCollection).getTempTasks.func1()
/home/chaitanya/workspace/astt/ecs/component_collection.go:179 +0x286
github.com/zllangct/ecs.(*systemFlow).run.func4()
/home/chaitanya/workspace/astt/ecs/system_flow.go:197 +0x42
github.com/zllangct/ecs.(*Worker).Start.func1()
/home/chaitanya/workspace/astt/ecs/goroutine_pool.go:28 +0x39
created by github.com/zllangct/ecs.(*Worker).Start
/home/chaitanya/workspace/astt/ecs/goroutine_pool.go:16 +0x56
panic: runtime error: index out of range [9] with length 9```
Am I doing something wrong ?
Thanks
Hi,
Is there a way to use event subscription to call system functions?
Thanks
Hi,
If I move the component and systems into different files, the ecs.GetInterestedComponents[components.Position](m)
function returns nil.
package components
import (
"github.com/zllangct/ecs"
)
type Movement struct {
ecs.Component[Movement]
V int
Dir []int
}
package systems
import (
"github.com/zllangct/ecs"
"astt-ecs/components"
"reflect"
)
type MoveSystemData struct {
P *components.Position
M *components.Movement
}
type MoveSystem struct {
ecs.System[MoveSystem]
logger ecs.IInternalLogger
}
func (m *MoveSystem) Init() {
//m.logger = m.GetWorld().logger
m.SetRequirements(&components.Position{}, &components.Movement{})
}
func (m *MoveSystem) Filter(ls map[reflect.Type][]ecs.ComponentOptResult) {
if len(ls) > 0 {
ecs.Log.Info("new component:", len(ls))
}
}
func (m *MoveSystem) Update(event ecs.Event) {
delta := event.Delta
nc := m.GetInterestedNew()
m.Filter(nc)
//csPosition := m.GetInterested(ecs.GetType[components.Position]()).(*ecs.Collection[components.Position])
csPosition := ecs.GetInterestedComponents[components.Position](m)
if csPosition == nil {
println("here")
return
}
//csMovement := m.GetInterested(ecs.GetType[components.Movement]()).(*ecs.Collection[components.Movement])
csMovement := ecs.GetInterestedComponents[components.Movement](m)
if csMovement == nil {
println("here1")
return
}
d := map[int64]*MoveSystemData{}
for iter := ecs.NewIterator(csPosition); !iter.End(); iter.Next() {
position := iter.Val()
owner := position.Owner()
movement := ecs.CheckComponent[components.Movement](m, owner)
if movement == nil {
continue
}
d[position.Owner().ID()] = &MoveSystemData{P: position, M: movement}
println("here")
}
for e, data := range d {
if data.M == nil || data.P == nil {
//When the aggregated data components are not uniform, skip the processing
continue
}
data.P.X = data.P.X + int(float64(data.M.Dir[0]*data.M.V)*delta.Seconds())
data.P.Y = data.P.Y + int(float64(data.M.Dir[1]*data.M.V)*delta.Seconds())
data.P.Z = data.P.Z + int(float64(data.M.Dir[2]*data.M.V)*delta.Seconds())
ecs.Log.Info("target id:", e, "delta:", delta, " current position:", data.P.X, data.P.Y, data.P.Z)
}
println("here")
}
package main
import (
"astt-ecs/components"
"astt-ecs/systems"
"time"
"github.com/zllangct/ecs"
)
//main function
func Runtime0() {
// Create runtime, runtime unique
rt := ecs.Runtime
rt.Run()
// Create a world, there can be multiple worlds
world := rt.NewWorld(ecs.NewDefaultWorldConfig())
world.Run()
// Registration system
world.Register(&systems.MoveSystem{})
// Create entities and add components
ee1 := world.NewEntity()
ee2 := world.NewEntity()
ee3 := world.NewEntity()
ecs.Log.Info(ee1.ID(), ee2.ID(), ee3.ID())
p1 := &components.Position{
X: 100,
Y: 100,
Z: 100,
}
m1 := &components.Movement{
V: 2000,
Dir: []int{1, 0, 0},
}
world.NewEntity().Add(p1, m1)
p2 := &components.Position{
X: 110,
Y: 110,
Z: 110,
}
m2 := &components.Movement{
V: 2000,
Dir: []int{0, 1, 0},
}
world.NewEntity().Add(p2, m2)
//The example only runs for 10 second
time.Sleep(time.Second * 10)
}
func main() {
Runtime0()
}
What am I not doing correctly ?
Hi,
I want to call the inventory system only when the user wants to see what weapons he has etc.
How can a system be called / component data be accessed based on user interaction?
Thanks
Hi,
I'm converting older code to the new ECS code.
I had a component like so
type Position struct {
ecs.Component[Position]
x float64
y float64
routex []float64
}
func (m *MoveSystem) Init(si ecs.SystemInitConstraint) {
m.SetRequirements(si, &components.Position{})
}
When registering this system like so
ecs.RegisterSystem[systems.MoveSystem](utilities.World)
I'm getting errors like
panic: invalid component type
goroutine 20 [running]:
github.com/zllangct/ecs.(*Component[...]).check(0xc0001e8ea0?, {0xc0003243e0})
/home/cc/ecs/component.go:253 +0xf8
github.com/zllangct/ecs.(*System[...]).setRequirements(0xc0001ba5a0, {0x40f507}, {0xc0000af220?, 0x4?, 0x203001})
/home/cc/ecs/system.go:186 +0xf1
github.com/zllangct/ecs.(*System[...]).SetRequirements(0x17?, {0xc0003243e0?}, {0xc0000af220, 0x2a?, 0xca0e80?})
/home/cc/ecs/system.go:161 +0x2d
ecs-server/systems.(*MoveNpcSystem).Init(0xc0001ba5a0, {0xc000100000?})
/home/cc/ecs-server/systems/moveSystem.go.go:34 +0x112
Seems like there's an issue using slices in components.
Please help.
Hi,
Once an entity's health becomes 0, how can I delete it from a system?
trying
ecs.EntityDestroy(w.World(), data.M.Owner().Entity())
stops the program.
Hi,
I've setup a world and added 3 Entities with movement component.
collection.go:34: collection Add:{"Speed":0.008888888888888889,"Course":145}
collection.go:34: collection Add:{"Speed":0.0033333333333333335,"Course":120}
collection.go:34: collection Add:{"Speed":0.0033333333333333335,"Course":45}
I'm trying to use an Input system similar to your example to get and change speed for an entity.
type MoveChange struct {
ecs.FreeDisposableComponent[MoveChange]
}
import (
"github.com/zllangct/ecs"
"astt-server/components"
)
type MoveChangeSystem struct {
ecs.System[MoveChangeSystem]
}
func (mc *MoveChangeSystem) Init() {
ecs.AddRequireComponent2[components.Movement, components.MoveChange](mc)
}
func (mc *MoveChangeSystem) PreUpdate(event ecs.Event) {
iterMovement := ecs.GetInterestedComponents[components.Movement](mc)
if iterMovement == nil {
return
}
for mov := iterMovement.Begin(); !iterMovement.End(); iterMovement.Next() {
println(mov.Speed, mov.Course)
println(mov.Owner().Entity())
}
}
I get 3 values printed - but they're all the same.
+8.888889e-003 +1.450000e+002
-7673762469411480564
+8.888889e-003 +1.450000e+002
-7673762469411480564
+8.888889e-003 +1.450000e+002
-7673762469411480564
How do I get the data for each separate entity?
Thanks.
Hi,
Given all the changes, what is the best method for the following :-
Thanks
Hi,
I need to stop a running game based on user input.
Then, how can I re-start the game? Or destroy the existing world and create a new world ?
Thanks.
你之前的那个项目还维护吗?怎么又跑来这里搞一个?求解答
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.