diff --git a/game.go b/game.go index a4be255..4c84274 100644 --- a/game.go +++ b/game.go @@ -117,7 +117,7 @@ func (g *game) tick(payload *Boardstate) int { for _, r := range p.Robots { if r.Health > 0 { living_robots++ - p.Tick(g) + r.Tick(g) } if len(r.Message) > 0 { @@ -180,7 +180,7 @@ func (g *game) send_update(payload *Boardstate) { player_payload.Turn = payload.Turn player_payload.Reset = payload.Reset for _, r := range p.Robots { - player_payload.MyRobots = append(player_payload.MyRobots, r) + player_payload.MyRobots = append(player_payload.MyRobots, *r) player_payload.OtherRobots = append( player_payload.OtherRobots, r.GetTruncatedDetails()) @@ -209,7 +209,7 @@ func (g *game) send_update(payload *Boardstate) { // Filter projectiles for proj := range g.projectiles { - if proj.Owner == &r { + if proj.Owner == r { player_payload.Projectiles = append( player_payload.Projectiles, *proj) diff --git a/player.go b/player.go index 1acebdf..8174ead 100644 --- a/player.go +++ b/player.go @@ -10,7 +10,7 @@ import ( type player struct { ws *websocket.Conn - Robots []Robot + Robots []*Robot send chan *Boardstate Instruction Instruction } @@ -31,8 +31,9 @@ func (p *player) recv() { for { // XXX: need to mark myself as having received something, also binding // such action to a particular game turn ID - var msgs PlayerInstructions + var msgs map[string]Instruction err := websocket.JSON.Receive(p.ws, &msgs) + if err != nil { // TODO: perhaps we could be a bit more precise in the handling of // this 'error' by selecting on some kill signal channel and this @@ -43,11 +44,14 @@ func (p *player) recv() { for _, r := range p.Robots { - msg, ok := msgs.RobotInstructions[r.Id] + msg, ok := msgs[r.Id] + if !ok { continue } + // log.Printf("%v", msg.FireAt) + if msg.Repair != nil && *msg.Repair == true { r.TargetSpeed = 0 r.FireAt = nil @@ -116,7 +120,7 @@ func (r *Robot) checkCollisions(g *game, move_vector v.Vector2d) (bool, v.Point2 player_rect := v.RectFromPoint(bot.Position, 3) collision, _, pos := v.RectIntersection(player_rect, r.Position, move_vector) if collision { - return collision, pos, &bot + return collision, pos, bot } } } @@ -132,116 +136,113 @@ func (r *Robot) checkCollisions(g *game, move_vector v.Vector2d) (bool, v.Point2 return collision, intersection_point, nil } -func (p *player) Tick(g *game) { - for _, r := range p.Robots { +func (r *Robot) Tick(g *game) { + r.Collision = false + r.Hit = false + r.scan(g) - r.Collision = false - r.Hit = false - r.scan(g) - - // Adjust Speed - if r.Speed < r.TargetSpeed { - r.Speed += (r.Stats.Acceleration * delta) - if r.Speed > r.TargetSpeed { - r.Speed = r.TargetSpeed - } - - } else if float32(math.Abs(float64(r.Speed-r.TargetSpeed))) > v.Epsilon { - r.Speed -= (r.Stats.Acceleration * delta) - } else { + // Adjust Speed + if r.Speed < r.TargetSpeed { + r.Speed += (r.Stats.Acceleration * delta) + if r.Speed > r.TargetSpeed { r.Speed = r.TargetSpeed } - // Adjust Heading - current_heading := r.Heading - if current_heading.Mag() == 0 && r.MoveTo != nil { - // We may have been stopped before this and had no heading - current_heading = r.MoveTo.Sub(r.Position).Normalize() + } else if float32(math.Abs(float64(r.Speed-r.TargetSpeed))) > v.Epsilon { + r.Speed -= (r.Stats.Acceleration * delta) + } else { + r.Speed = r.TargetSpeed + } + + // Adjust Heading + current_heading := r.Heading + if current_heading.Mag() == 0 && r.MoveTo != nil { + // We may have been stopped before this and had no heading + current_heading = r.MoveTo.Sub(r.Position).Normalize() + } + + new_heading := current_heading + if r.MoveTo != nil { + // Where do we WANT to be heading? + new_heading = r.MoveTo.Sub(r.Position).Normalize() + } + + if new_heading.Mag() > 0 { + // Is our direction change too much? Hard coding to 5 degrees/s for now + angle := v.Angle(current_heading, new_heading) * v.Rad2deg + + dir := 1.0 + if angle < 0 { + dir = -1.0 } - new_heading := current_heading - if r.MoveTo != nil { - // Where do we WANT to be heading? - new_heading = r.MoveTo.Sub(r.Position).Normalize() + // Max turn radius in this case is in degrees per second + if float32(math.Abs(float64(angle))) > (float32(r.Stats.TurnSpeed) * delta) { + // New heading should be a little less, take current heading and + // rotate by the max turn radius per frame. + rot := (float32(r.Stats.TurnSpeed) * delta) * v.Deg2rad + + new_heading = current_heading.Rotate(rot * float32(dir)) } - if new_heading.Mag() > 0 { - // Is our direction change too much? Hard coding to 5 degrees/s for now - angle := v.Angle(current_heading, new_heading) * v.Rad2deg - - dir := 1.0 - if angle < 0 { - dir = -1.0 + move_vector := new_heading.Scale(r.Speed * delta) + collision, intersection_point, hit_robot := r.checkCollisions(g, move_vector) + if collision { + r.Collision = true + if hit_robot != nil { + hit_robot.Health -= int(r.Speed / 10.0) + hit_robot.Speed = (hit_robot.Speed * 0.1) + hit_robot.Heading = r.Heading } + move_by := intersection_point.Sub(r.Position) + move_dist := move_by.Scale(float32(math.Floor(float64(move_by.Mag()-3.0))) / move_by.Mag()) - // Max turn radius in this case is in degrees per second - if float32(math.Abs(float64(angle))) > (float32(r.Stats.TurnSpeed) * delta) { - // New heading should be a little less, take current heading and - // rotate by the max turn radius per frame. - rot := (float32(r.Stats.TurnSpeed) * delta) * v.Deg2rad - - new_heading = current_heading.Rotate(rot * float32(dir)) - } - - move_vector := new_heading.Scale(r.Speed * delta) - collision, intersection_point, hit_robot := r.checkCollisions(g, move_vector) - if collision { - r.Collision = true - if hit_robot != nil { - hit_robot.Health -= int(r.Speed / 10.0) - hit_robot.Speed = (hit_robot.Speed * 0.1) - hit_robot.Heading = r.Heading - } - move_by := intersection_point.Sub(r.Position) - move_dist := move_by.Scale(float32(math.Floor(float64(move_by.Mag()-3.0))) / move_by.Mag()) - - r.Position = r.Position.Add(move_dist) - r.Health -= int(r.Speed / 10.0) - r.MoveTo = &r.Position - r.Speed = (r.Speed * 0.1) - r.Heading = r.Heading.Scale(-1.0) + r.Position = r.Position.Add(move_dist) + r.Health -= int(r.Speed / 10.0) + r.MoveTo = &r.Position + r.Speed = (r.Speed * 0.1) + r.Heading = r.Heading.Scale(-1.0) + } else { + r.Position = r.Position.Add(move_vector) + if new_heading.Mag() > 0 { + r.Heading = new_heading } else { - r.Position = r.Position.Add(move_vector) - if new_heading.Mag() > 0 { - r.Heading = new_heading - } else { - log.Printf("Zero Heading %v", new_heading) - } + log.Printf("Zero Heading %v", new_heading) } } + } - // We only self repair when we're stopped - if math.Abs(float64(r.Speed)) < v.Epsilon && r.RepairCounter > 0 { - r.RepairCounter -= delta - if r.RepairCounter < 0 { - r.Health += g.repair_hp - r.RepairCounter = g.repair_rate - } + // We only self repair when we're stopped + if math.Abs(float64(r.Speed)) < v.Epsilon && r.RepairCounter > 0 { + r.RepairCounter -= delta + if r.RepairCounter < 0 { + r.Health += g.repair_hp + r.RepairCounter = g.repair_rate } + } - // We only self repair when we're stopped - if math.Abs(float64(r.Speed)) < v.Epsilon && r.ActiveScan { - r.ScanCounter += delta * float32(r.Stats.ScannerRadius) * 0.1 - } else if r.ScanCounter > 0 { - r.ScanCounter -= delta * float32(r.Stats.ScannerRadius) * 0.05 - if r.ScanCounter <= 0 { - r.ScanCounter = 0 - } + // We only self repair when we're stopped + if math.Abs(float64(r.Speed)) < v.Epsilon && r.ActiveScan { + r.ScanCounter += delta * float32(r.Stats.ScannerRadius) * 0.1 + } else if r.ScanCounter > 0 { + r.ScanCounter -= delta * float32(r.Stats.ScannerRadius) * 0.05 + if r.ScanCounter <= 0 { + r.ScanCounter = 0 } + } - if r.FireAt != nil { - proj := r.fire(g.projectiles, g.turn) - if proj != nil { - g.projectiles[proj] = true - } + if r.FireAt != nil { + proj := r.fire(g.projectiles, g.turn) + if proj != nil { + g.projectiles[proj] = true } + } - if r.Probe != nil && r.ProbeResult == nil { - probe_vector := r.Probe.Sub(r.Position) - coll, pos, _ := r.checkCollisions(g, probe_vector) - if coll { - r.ProbeResult = &pos - } + if r.Probe != nil && r.ProbeResult == nil { + probe_vector := r.Probe.Sub(r.Position) + coll, pos, _ := r.checkCollisions(g, probe_vector) + if coll { + r.ProbeResult = &pos } } } @@ -311,6 +312,8 @@ func (r *Robot) reset(g *game) { r.Position = start_pos r.Health = r.Stats.Hp + log.Printf("Reset %v", r) + // Check Obstacles retry := false for _, obj := range g.obstacles { diff --git a/projectile.go b/projectile.go index 0aa0ad6..1f65cb6 100644 --- a/projectile.go +++ b/projectile.go @@ -24,7 +24,7 @@ func (p *Projectile) Tick(g *game) { hit_player := false for player := range g.players { for _, r := range player.Robots { - if &r == p.Owner { + if r == p.Owner { continue } diff --git a/protocol.go b/protocol.go index d1a115d..0f7a0cd 100644 --- a/protocol.go +++ b/protocol.go @@ -192,7 +192,7 @@ func addPlayer(ws *websocket.Conn) { } p := &player{ - Robots: []Robot{}, + Robots: []*Robot{}, send: make(chan *Boardstate), ws: ws, } @@ -200,14 +200,14 @@ func addPlayer(ws *websocket.Conn) { for _, stats := range conf.Stats { r := Robot{ Stats: DeriveStats(stats), - Id: player_id, + Id: idg.Hash(), Name: clientid.Name, Health: 10, Scanners: make([]Scanner, 0)} r.Health = r.Stats.Hp log.Printf("Adding Robot: %v", r) - p.Robots = append(p.Robots, r) r.reset(game) + p.Robots = append(p.Robots, &r) } game.register <- p diff --git a/robot.go b/robot.go index 344e966..9c5c54c 100644 --- a/robot.go +++ b/robot.go @@ -157,9 +157,4 @@ type Instruction struct { TargetSpeed *float32 `json:"target_speed,omitempty"` Repair *bool `json:"repair,omitempty"` Scan *bool `json:"scan,omitempty"` - Stats Stats `json:"stats"` -} - -type PlayerInstructions struct { - RobotInstructions map[string]Instruction `json:"instructions"` }