//go:build example // +build example package system import ( "math" "time" "code.rocketnine.space/tslocum/gohan" "code.rocketnine.space/tslocum/gohan/examples/twinstick/component" "code.rocketnine.space/tslocum/gohan/examples/twinstick/entity" "github.com/hajimehoshi/ebiten/v2" ) func angle(x1, y1, x2, y2 float64) float64 { return math.Atan2(y1-y2, x1-x2) } type fireInputSystem struct { player gohan.Entity } func NewFireInputSystem(player gohan.Entity) *fireInputSystem { return &fireInputSystem{ player: player, } } func (_ *fireInputSystem) Components() []gohan.ComponentID { return []gohan.ComponentID{ component.PositionComponentID, component.WeaponComponentID, } } func (s *fireInputSystem) fire(weapon *component.WeaponComponent, position *component.PositionComponent, fireAngle float64) { if time.Since(weapon.LastFire) < weapon.FireRate { return } weapon.Ammo-- weapon.LastFire = time.Now() speedX := math.Cos(fireAngle) * -weapon.BulletSpeed speedY := math.Sin(fireAngle) * -weapon.BulletSpeed bullet := entity.NewBullet(position.X, position.Y, speedX, speedY) _ = bullet } func (s *fireInputSystem) Update(ctx *gohan.Context) error { position := component.Position(ctx) weapon := component.Weapon(ctx) if weapon.Ammo <= 0 { return nil } if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) { cursorX, cursorY := ebiten.CursorPosition() fireAngle := angle(position.X, position.Y, float64(cursorX), float64(cursorY)) s.fire(weapon, position, fireAngle) } if ebiten.IsMouseButtonPressed(ebiten.MouseButtonRight) { cursorX, cursorY := ebiten.CursorPosition() fireAngle := angle(position.X, position.Y, float64(cursorX), float64(cursorY)) const div = 5 weapon.BulletSpeed /= div for i := 0.0; i < 24; i++ { s.fire(weapon, position, fireAngle+i*(math.Pi/12)) weapon.LastFire = time.Time{} } weapon.BulletSpeed *= div } switch { case ebiten.IsKeyPressed(ebiten.KeyLeft) && ebiten.IsKeyPressed(ebiten.KeyUp): s.fire(weapon, position, math.Pi/4) case ebiten.IsKeyPressed(ebiten.KeyLeft) && ebiten.IsKeyPressed(ebiten.KeyDown): s.fire(weapon, position, -math.Pi/4) case ebiten.IsKeyPressed(ebiten.KeyRight) && ebiten.IsKeyPressed(ebiten.KeyUp): s.fire(weapon, position, math.Pi*.75) case ebiten.IsKeyPressed(ebiten.KeyRight) && ebiten.IsKeyPressed(ebiten.KeyDown): s.fire(weapon, position, -math.Pi*.75) case ebiten.IsKeyPressed(ebiten.KeyLeft): s.fire(weapon, position, 0) case ebiten.IsKeyPressed(ebiten.KeyRight): s.fire(weapon, position, math.Pi) case ebiten.IsKeyPressed(ebiten.KeyUp): s.fire(weapon, position, math.Pi/2) case ebiten.IsKeyPressed(ebiten.KeyDown): s.fire(weapon, position, -math.Pi/2) } return nil } func (_ *fireInputSystem) Draw(ctx *gohan.Context, _ *ebiten.Image) error { return gohan.ErrSystemWithoutDraw }