func (o *ship) HandleEvent(ev tcell.Event) bool { if o.dead { return false } switch ev := ev.(type) { case *EventSpriteAccelerate: if ev.s != o.ship { return false } vx, _ := o.ship.Velocity() if vx >= 1.0 { o.ship.SetFrame("RIGHT") } else if vx <= -1.0 { o.ship.SetFrame("LEFT") } else { o.ship.SetFrame("FWD") } case *EventSpriteMove: // We don't let ship leave the map x, y := o.ship.Position() ox, oy := x, y vx, vy := o.ship.Velocity() w, h := o.level.Size() if x < 0 { x = 0 if vx < 0 { vx = 0 } } else if x >= w { x = w - 1 if vx > 0 { vx = 0 } } if y < 0 { y = 0 if vy < 0 { vy = 0 } } else if y >= h { y = h - 1 if vy > 0 { vy = 0 } } if ox != x || oy != y { o.ship.SetPosition(x, y) o.ship.SetVelocity(vx, vy) } if y == 0 { o.dead = true o.level.HandleEvent(&EventLevelComplete{}) } o.adjustView() case *EventGravity: now := ev.When() if !o.lastgrav.IsZero() { vx, vy := o.ship.Velocity() frac := float64(now.Sub(o.lastgrav)) frac /= float64(time.Second) vy += ev.Accel() * frac o.ship.SetVelocity(vx, vy) } o.lastgrav = now case *EventCollision: switch ev.Collider().Layer() { case LayerTerrain, LayerHazard, LayerShot: o.destroy() case LayerPad: // if we're on the pad, and not too // fast, then stay on the pad. // TODO: probably the max velocity (4.0) // should be tunable. vx, vy := o.ship.Velocity() x, y := o.ship.Position() if vx == 0 && vy > 0 && vy < 4.0 { y-- vy = 0 o.ship.SetPosition(x, y) o.ship.SetVelocity(vx, vy) o.launched = false } else { o.destroy() } } case *EventTimesUp: o.destroy() case *tcell.EventKey: switch ev.Key() { case tcell.KeyLeft: o.thrustLeft() return true case tcell.KeyRight: o.thrustRight() return true case tcell.KeyUp: o.thrustUp() return true case tcell.KeyDown: o.thrustDown() return true case tcell.KeyRune: switch ev.Rune() { case ' ': o.shoot() return true case 'j', 'J': o.thrustLeft() return true case 'k', 'K': o.thrustRight() return true case 'i', 'I': o.thrustUp() return true case 'm', 'M': o.thrustDown() return true } } case *tcell.EventResize: x, y := o.ship.Position() o.level.Center(x, y) o.adjustView() } return false }