func (p *Physics) isValidPlace(pt state.Point, size state.Sized, gamestate state.GameState) bool { hasCollision := false powerup := state.Powerup{ Sized: size, Point: pt, } for _, b := range gamestate.Bases { if collision.Collides(powerup, b) { hasCollision = true } } for _, v := range gamestate.Vehicles { if collision.Collides(powerup, v) { hasCollision = true } } for _, b := range gamestate.Shields { if collision.Collides(powerup, b) { hasCollision = true } } for _, s := range gamestate.ShieldGenerators { if collision.Collides(powerup, s) { hasCollision = true } } for _, p := range gamestate.PowerUps { if collision.Collides(powerup, p) { hasCollision = true } } return !hasCollision }
func (p *Physics) MoveRocket(rocket *state.Rocket, duration time.Duration) { t := rocket.Target if t == nil { rocket.ShouldRemove = true return } dx := t.X - rocket.X dy := t.Y - rocket.Y rocket.Angle = math.Atan2(dy, dx) * RadToDeg x, y := p.move2d(rocket.X, rocket.Y, rocket.Angle, rocket.Velocity, duration) rocket.X = x rocket.Y = y if collision.Collides(rocket, t) { rocket.ShouldRemove = true p.damageVehicle(t, p.BulletDamage*20) } }
// Performs next step in the game // Empties g.commandsToProcess and processes them // Also progresses GameState based upon elapsed time // Threadsafe func (g *GameManager) tick() { commandsMutex.Lock() commands := g.commandsToProcess g.commandsToProcess = g.commandsToProcess[:0] commandsMutex.Unlock() stateMutex.Lock() tickDuration := time.Since(g.lastTick) if tickDuration > (50 * time.Millisecond) { log.Println("Lag spike detected") } for _, command := range commands { proc := g.commandFactory.GetCommandProcessor(command) proc.Run(&(g.gameState), *command) } g.physicsManager.ApplyGravity(&g.gameState) if time.Since(g.lastPowerupDespawn) >= g.physicsManager.PowerupRespawn && len(g.gameState.PowerUps) < g.physicsManager.MaxPowerups { g.physicsManager.SpawnPowerup(&g.gameState) g.lastPowerupDespawn = time.Now() } for _, rocket := range g.gameState.Rockets { g.physicsManager.MoveRocket(rocket, tickDuration) } for _, well := range g.gameState.GravityWells { if time.Now().After(well.Expires) { well.ShouldRemove = true } } for _, bullet := range g.gameState.Bullets { g.physicsManager.MoveBullet(bullet, tickDuration) g.physicsManager.BoundBullet(bullet) } for _, bullet := range g.gameState.Bullets { for _, shield := range g.gameState.Shields { if shield.IsEnabled { if collision.Collides(bullet, shield) { bullet.ShouldRemove = true } } } for _, shieldGenerator := range g.gameState.ShieldGenerators { if collision.Collides(shieldGenerator, bullet) { g.physicsManager.DamageShieldGenerator(bullet, shieldGenerator) } } for _, base := range g.gameState.Bases { if collision.Collides(bullet, base) { if g.physicsManager.DamageBase(bullet, base) { g.gameState.GameOver = base.TeamId g.restartTime = time.Now().Add(time.Duration(g.gameRestart) * time.Second) g.gameState.SecToRestart = g.gameRestart } } } } for z, vehicle := range g.gameState.Vehicles { g.physicsManager.RespawnVehicle(vehicle, g.gameState) g.physicsManager.VehicleBounding(vehicle) g.physicsManager.MoveVehicle(vehicle, tickDuration) g.physicsManager.VehicleFrictionSlow(vehicle, tickDuration) for i := z + 1; i < len(g.gameState.Vehicles); i++ { if collision.Collides(vehicle, g.gameState.Vehicles[i]) { g.physicsManager.VehicleCollision(vehicle, g.gameState.Vehicles[i]) } } for _, bullet := range g.gameState.Bullets { if bullet.OwnerId != vehicle.Owner && vehicle.IsAlive { if collision.Collides(vehicle, bullet) { g.physicsManager.DamageVehicle(vehicle, bullet) } } } for _, shield := range g.gameState.Shields { if shield.IsEnabled { if collision.Collides(shield, vehicle) { g.physicsManager.VehicleCollision(vehicle, &state.Vehicle{Angle: vehicle.Angle, IsAlive: true}) } } } for _, shieldGenerator := range g.gameState.ShieldGenerators { if collision.Collides(shieldGenerator, vehicle) { g.physicsManager.VehicleCollision(vehicle, &state.Vehicle{Angle: vehicle.Angle, IsAlive: true}) } } for _, base := range g.gameState.Bases { if collision.Collides(base, vehicle) { g.physicsManager.VehicleCollision(vehicle, &state.Vehicle{Angle: vehicle.Angle, IsAlive: true}) } } for _, powerup := range g.gameState.PowerUps { if collision.Collides(powerup, vehicle) { g.physicsManager.PickupPowerUp(vehicle, powerup) g.lastPowerupDespawn = time.Now() } } } g.gameState.Bullets = processor.CleanupBullets(g.gameState.Bullets) g.gameState.PowerUps = processor.CleanupPowerups(g.gameState.PowerUps) g.gameState.Rockets = processor.CleanupRockets(g.gameState.Rockets) g.gameState.GravityWells = processor.CleanupWells(g.gameState.GravityWells) stateMutex.Unlock() }
func TestCollisions(t *testing.T) { Convey("Basic No Collision", t, func() { v1 := state.Vehicle{ Point: state.NewPoint(10, 10), Sized: state.NewSized(10, 10), Angle: 0} v2 := state.Vehicle{ Point: state.NewPoint(30, 30), Sized: state.NewSized(10, 10), Angle: 0} check := collision.Collides(v1, v2) So(check, ShouldEqual, false) }) Convey("Basic Should Collide", t, func() { v1 := state.Vehicle{ Point: state.NewPoint(10, 10), Sized: state.NewSized(10, 10), Angle: 0} v2 := state.Vehicle{ Point: state.NewPoint(5, 5), Sized: state.NewSized(10, 10), Angle: 0} check := collision.Collides(v1, v2) So(check, ShouldEqual, true) }) Convey("Basic Should Collide", t, func() { v1 := state.Vehicle{ Point: state.NewPoint(10, 10), Sized: state.NewSized(10, 10), Angle: 0} v2 := state.Vehicle{ Point: state.NewPoint(7, 7), Sized: state.NewSized(10, 10), Angle: 0} check := collision.Collides(v1, v2) So(check, ShouldEqual, true) }) Convey("Basic Should Collide with Rotation", t, func() { v1 := state.Vehicle{ Point: state.NewPoint(10, 10), Sized: state.NewSized(10, 10), Angle: 90} v2 := state.Vehicle{ Point: state.NewPoint(7, 7), Sized: state.NewSized(10, 10), Angle: 0} check := collision.Collides(v1, v2) So(check, ShouldEqual, true) }) Convey("Basic Should Collide with Rotation", t, func() { v1 := state.Vehicle{ Point: state.NewPoint(10, 10), Sized: state.NewSized(10, 10), Angle: 90} v2 := state.Vehicle{ Point: state.NewPoint(7, 7), Sized: state.NewSized(10, 10), Angle: 90} check := collision.Collides(v1, v2) So(check, ShouldEqual, true) }) }