func (cs *CollisionSystem) Update(entity *ecs.Entity, dt float32) { var ( space *SpaceComponent collision *CollisionComponent ok bool ) if space, ok = entity.ComponentFast(space).(*SpaceComponent); !ok { return } if collision, ok = entity.ComponentFast(collision).(*CollisionComponent); !ok { return } if !collision.Main { return } var ( otherSpace *SpaceComponent otherCollision *CollisionComponent ) for _, other := range cs.Entities() { if other.ID() != entity.ID() { if otherSpace, ok = other.ComponentFast(otherSpace).(*SpaceComponent); !ok { return } if otherCollision, ok = other.ComponentFast(otherCollision).(*CollisionComponent); !ok { return } entityAABB := space.AABB() offset := Point{collision.Extra.X / 2, collision.Extra.Y / 2} entityAABB.Min.X -= offset.X entityAABB.Min.Y -= offset.Y entityAABB.Max.X += offset.X entityAABB.Max.Y += offset.Y otherAABB := otherSpace.AABB() offset = Point{otherCollision.Extra.X / 2, otherCollision.Extra.Y / 2} otherAABB.Min.X -= offset.X otherAABB.Min.Y -= offset.Y otherAABB.Max.X += offset.X otherAABB.Max.Y += offset.Y if IsIntersecting(entityAABB, otherAABB) { if otherCollision.Solid && collision.Solid { mtd := MinimumTranslation(entityAABB, otherAABB) space.Position.X += mtd.X space.Position.Y += mtd.Y } Mailbox.Dispatch(CollisionMessage{Entity: entity, To: other}) } } } }
func (as *AudioSystem) Update(entity *ecs.Entity, dt float32) { var ac *AudioComponent var ok bool if ac, ok = entity.ComponentFast(ac).(*AudioComponent); !ok { return } if ac.player == nil { f := Files.Sound(ac.File) if f == nil { return } var err error ac.player, err = NewPlayer(f, 0, 0) if err != nil { log.Println("Error initializing AudioSystem:", err) return } } if ac.player.State() != Playing { if ac.player.State() == Stopped { if !ac.Repeat { al.RewindSources(ac.player.source) al.StopSources(ac.player.source) entity.RemoveComponent(ac) return } } // Prepares if the track hasn't been buffered before. if err := ac.player.prepare(ac.Background, 0, false); err != nil { log.Println("Error initializing AudioSystem:", err) return } al.PlaySources(ac.player.source) if !ac.Background { var space *SpaceComponent var ok bool if space, ok = entity.ComponentFast(space).(*SpaceComponent); !ok { return } ac.player.source.SetPosition(al.Vector{ (space.Position.X + space.Width/2) / Width(), (space.Position.Y + space.Height/2) / Height(), 0}) } } }
func (rs *RenderSystem) Update(entity *ecs.Entity, dt float32) { if !rs.changed { return } var render *RenderComponent var ok bool if render, ok = entity.ComponentFast(render).(*RenderComponent); !ok { return } rs.renders[render.priority] = append(rs.renders[render.priority], entity) }
func (c *Calibrate) Update(entity *ecs.Entity, dt float32) { if c.frameIndex != 0 { return } var ( cal *CalibrateComponent ok bool ) if cal, ok = entity.ComponentFast(cal).(*CalibrateComponent); !ok { return } // Render the image again plt, err := plot.New() if err != nil { log.Fatal(err) } plotutil.AddLinePoints(plt, "CH"+strconv.Itoa(int(cal.ChannelIndex)), plotter.XYer(c.channels[cal.ChannelIndex])) img := image.NewRGBA(image.Rect(0, 0, 3*dpi, 3*dpi)) canv := vgimg.NewWith(vgimg.UseImage(img)) plt.Draw(draw.New(canv)) bgTexture := engi.NewImageRGBA(img) // Give it to engi erender := &engi.RenderComponent{ Display: engi.NewRegion(engi.NewTexture(bgTexture), 0, 0, 3*dpi, 3*dpi), Scale: engi.Point{1, 1}, Transparency: 1, Color: color.RGBA{255, 255, 255, 255}, } erender.SetPriority(engi.HUDGround) entity.AddComponent(erender) }
func (m *Maze) Update(entity *ecs.Entity, dt float32) { if entity.ID() != m.playerEntity.ID() { return } var ( move *MovementComponent ok bool ) if move, ok = entity.ComponentFast(move).(*MovementComponent); ok { return // because we're still moving! } if m.currentLevel.Width == 0 || m.currentLevel.Height == 0 { return // because there's no maze } oldX, oldY := m.currentLevel.PlayerX, m.currentLevel.PlayerY if m.currentLevel.Grid[oldY][oldX] == TileGoal { // Goal achieved! if strings.HasPrefix(m.currentLevel.Name, "Random ") { engi.Mailbox.Dispatch(MazeMessage{}) return } if m.sequence != SequenceNone { m.cleanup() m.initialize("") return } } switch m.Controller.Action(m.currentLevel) { case ActionUp: m.currentLevel.PlayerY-- case ActionDown: m.currentLevel.PlayerY++ case ActionLeft: m.currentLevel.PlayerX-- case ActionRight: m.currentLevel.PlayerX++ case ActionStop: return // so don't move } if !m.currentLevel.IsAvailable(m.currentLevel.PlayerX, m.currentLevel.PlayerY) { m.currentLevel.PlayerX, m.currentLevel.PlayerY = oldX, oldY return // because it's an invalid move } entity.AddComponent(&MovementComponent{ From: engi.Point{float32(oldX) * tileWidth, float32(oldY) * tileHeight}, To: engi.Point{float32(m.currentLevel.PlayerX) * tileWidth, float32(m.currentLevel.PlayerY) * tileHeight}, In: time.Second / moveSpeed, Callback: func() { if m.currentLevel.Grid[m.currentLevel.PlayerY][m.currentLevel.PlayerX] == TileRoute { m.currentLevel.Grid[m.currentLevel.PlayerY][m.currentLevel.PlayerX] = TileBlank m.currentLevel.GridEntities[m.currentLevel.PlayerY][m.currentLevel.PlayerX].AddComponent(tileBlank) } else if m.currentLevel.Grid[oldY][oldX] == TileError || m.currentLevel.Grid[oldY][oldX] == TileBlank { m.currentLevel.Grid[oldY][oldX] = TileRoute if m.currentLevel.Grid[m.currentLevel.PlayerY][m.currentLevel.PlayerX] == TileHiddenError { m.currentLevel.Grid[m.currentLevel.PlayerY][m.currentLevel.PlayerX] = TileError } } }, }) }
// Update sets the MouseComponent values for each Entity func (m *MouseSystem) Update(entity *ecs.Entity, dt float32) { var ( mc *MouseComponent space *SpaceComponent render *RenderComponent ok bool ) // We need MouseComponent to save our findings if mc, ok = entity.ComponentFast(mc).(*MouseComponent); !ok { return } // We need SpaceComponent for the location if space, ok = entity.ComponentFast(space).(*SpaceComponent); !ok { return } // We need RenderComponent for the Priority if render, ok = entity.ComponentFast(render).(*RenderComponent); !ok { return } // Reset some values mc.Leave = false mx := m.mouseX my := m.mouseY // Special case: HUD if render.priority >= HUDGround { mx = Mouse.X my = Mouse.Y } // if the Mouse component is a tracker we always update it // Check if the X-value is within range // and if the Y-value is within range if mc.Track || mx > space.Position.X && mx < (space.Position.X+space.Width) && my > space.Position.Y && my < (space.Position.Y+space.Height) { mc.Enter = !mc.Hovered mc.Hovered = true mc.Released = false // track mouse position so that systems that need to stay on the mouse // position can do it (think an RTS when placing a new building and // you get a ghost building following your mouse until you click to // place it somewhere in your world. mc.MouseX = mx mc.MouseY = my switch Mouse.Action { case PRESS: switch Mouse.Button { case MouseButtonLeft: mc.Clicked = true case MouseButtonRight: mc.RightClicked = true } m.mouseDown = true case RELEASE: switch Mouse.Button { case MouseButtonLeft: mc.Released = true case MouseButtonRight: mc.RightReleased = true } // dragging stops as soon as one of the currently pressed buttons // is released mc.Dragged = false // mouseDown goes false as soon as one of the pressed buttons is // released. Effectively ending any dragging m.mouseDown = false case MOVE: if m.mouseDown { mc.Dragged = true } } } else { if mc.Hovered { mc.Leave = true } mc.Hovered = false } }