You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
122 lines
2.6 KiB
122 lines
2.6 KiB
package server |
|
|
|
import ( |
|
"log" |
|
|
|
v "hackerbots.us/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 float64 `json:"-"` |
|
Damage int `json:"-"` |
|
Owner *Robot `json:"-"` |
|
Delta float64 |
|
} |
|
|
|
// 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 < float64(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 |
|
} |
|
}
|
|
|