package server import ( "log" v "bitbucket.org/hackerbots/vector" ) // Projectile are the things robots can shoot at eachother. type Projectile struct { Id string `json:"id"` Position v.Point2d `json:"position"` MoveTo v.Point2d `json:"-"` Radius int `json:"-"` Speed float32 `json:"-"` Damage int `json:"-"` Owner *Robot `json:"-"` Delta float32 } // Projectile.Tick is called every game tick and moves projectiles along, // determines when they should blow up, and how damaage is propagated to // players. func (p *Projectile) Tick(g *Game) { vec := p.MoveTo.Sub(p.Position) v_norm := vec.Normalize() v_scaled := v_norm.Scale(p.Speed * p.Delta) newPos := p.Position.Add(v_scaled) hit_player := false for player := range g.players { for _, r := range player.Robots { if r == p.Owner { continue } player_rect := v.AASquareAtPoint(r.Position, 3) collision, _, _ := v.RectIntersection(player_rect, p.Position, v_scaled) if collision { hit_player = true p.Owner.gameStats.Hits++ p.Owner.gameStats.DirectHits++ if r.Health > 0 { // Direct hit causes more damage log.Printf("Direct Hit %v, Dmg:%v", r.Id, p.Damage) r.Health -= p.Damage r.Hit = true if r.Health <= 0 { r.gameStats.Deaths++ p.Owner.gameStats.Kills++ } } } } } // Are we going to intersect the destination zone in this tick? r_dest := v.AASquareAtPoint(p.MoveTo, 3.0) travel := newPos.Sub(p.Position) arrived, _, pos := v.RectIntersection(r_dest, p.Position, travel) if !arrived { for _, obj := range g.obstacles { collision, _, pos := v.RectIntersection(obj.Bounds, p.Position, travel) if collision { arrived = true if pos != nil { p.Position = *pos } obj.Hp -= p.Damage // if obj.Hp < 0 { // delete(g.obstacles, i) // } } } } else { if pos != nil { p.Position = *pos } } if arrived || hit_player { delete(g.projectiles, p) // Spawn a splosion splo := &Splosion{ Id: p.Id, Position: p.Position, Radius: p.Radius, Lifespan: 8, } g.splosions[splo] = true for player := range g.players { for _, r := range player.Robots { dist := v.Distance(r.Position, p.Position) if dist < float32(p.Radius) { if r.Health > 0 { r.Health -= p.Damage r.Hit = true } p.Owner.gameStats.Hits++ if r.Health <= 0 { r.gameStats.Deaths++ if r == p.Owner { p.Owner.gameStats.Suicides++ } else { p.Owner.gameStats.Kills++ } } } } } } else { p.Position.X = newPos.X p.Position.Y = newPos.Y } }