func fireDoLine(c *cmwc.Cmwc, pos linear.Vec2, angle, stored float64, speed int, level *game.Level) fireExplosion { rng := rand.New(c) ray := (linear.Vec2{1, 0}) // ray.Scale(math.Abs(rng.NormFloat64()/10) + 50) scale := (stored/5 + 50) * (1 + rng.Float64()*(0.2+stored/2000)) ray = ray.Rotate(angle).Rotate(rng.NormFloat64() * (0.2 + stored/7500)).Scale(scale) seg := linear.Seg2{pos, pos.Add(ray)} base.DoOrdered(level.Room.Walls, func(a, b string) bool { return a < b }, func(_ string, poly linear.Poly) { for i := range poly { if seg.DoesIsect(poly.Seg(i)) { isect := seg.Isect(poly.Seg(i)) seg.Q = isect } } }) p1 := rng.Intn(speed) p2 := rng.Intn(speed) p3 := rng.Intn(speed) return fireExplosion{ Pos: seg.Q, Radius: rng.Float64()*40 + 30, Timer: 0, Start: 1*speed + p1, Peak: 4*speed + p1 + p2, End: 5*speed + p1 + p2 + p3, } }
func (g *Game) DoForLevels(f func(Gid, *Level)) { base.DoOrdered(g.Levels, lessGids, f) }
func (g *Game) Think() { g.GameThinks++ if g.Setup != nil { return } defer base.StackCatcher() // cache wall data if g.temp.AllWalls == nil || g.temp.AllWallsDirty { g.temp.AllWalls = make(map[Gid][]linear.Seg2) g.temp.WallCache = make(map[Gid]*wallCache) g.temp.VisibleWallCache = make(map[Gid]*wallCache) for gid := range g.Levels { var allWalls []linear.Seg2 base.DoOrdered(g.Levels[gid].Room.Walls, func(a, b string) bool { return a < b }, func(_ string, walls linear.Poly) { for i := range walls { allWalls = append(allWalls, walls.Seg(i)) } }) // g.DoForEnts(func(entGid Gid, ent Ent) { // if ent.Level() == gid { // for _, walls := range ent.Walls() { // for i := range walls { // allWalls = append(allWalls, walls.Seg(i)) // } // } // } // }) g.temp.AllWalls[gid] = allWalls g.temp.WallCache[gid] = &wallCache{} g.temp.WallCache[gid].SetWalls(g.Levels[gid].Room.Dx, g.Levels[gid].Room.Dy, allWalls, 100) g.temp.VisibleWallCache[gid] = &wallCache{} g.temp.VisibleWallCache[gid].SetWalls(g.Levels[gid].Room.Dx, g.Levels[gid].Room.Dy, allWalls, stats.LosPlayerHorizon) base.Log().Printf("WallCache: %v", g.temp.WallCache) } g.Moba.losCache.SetWallCache(g.temp.VisibleWallCache[GidInvadersStart]) } // cache ent data for _, ent := range g.temp.AllEnts { if ent.Dead() { if _, ok := ent.(*PlayerEnt); ok { var id int64 _, err := fmt.Sscanf(string(ent.Id()), "Engine:%d", &id) if err != nil { base.Error().Printf("Unable to parse player id '%v'", ent.Id()) } else { if engineData, ok := g.Engines[id]; ok { if !ok { base.Error().Printf("Unable to find engine %d for player %v", id, ent.Id()) } else { engineData.CountdownFrames = 60 * 10 } } } } ent.OnDeath(g) g.RemoveEnt(ent.Id()) } } // Death countdown for engineId, engineData := range g.Engines { if engineData.CountdownFrames > 0 { engineData.CountdownFrames-- if engineData.CountdownFrames == 0 { // TODO: It's a bit janky to do it like this, right? g.AddPlayers([]int64{engineId}, engineData.Side) } } } if g.temp.AllEnts == nil || g.temp.AllEntsDirty { g.temp.AllEnts = g.temp.AllEnts[0:0] g.DoForEnts(func(gid Gid, ent Ent) { g.temp.AllEnts = append(g.temp.AllEnts, ent) }) g.temp.AllEntsDirty = false } for _, proc := range g.Processes { proc.Think(g) } algorithm.Choose(&g.Processes, func(proc Process) bool { return proc.Phase() != PhaseComplete }) // Advance players, check for collisions, add segments for _, ent := range g.temp.AllEnts { ent.Think(g) pos := ent.Pos() eps := 1.0e-3 pos.X = clamp(pos.X, eps, float64(g.Levels[ent.Level()].Room.Dx)-eps) pos.Y = clamp(pos.Y, eps, float64(g.Levels[ent.Level()].Room.Dy)-eps) ent.SetPos(pos) } for i := 0; i < len(g.temp.AllEnts); i++ { for j := i + 1; j < len(g.temp.AllEnts); j++ { outerEnt := g.temp.AllEnts[i] innerEnt := g.temp.AllEnts[j] distSq := outerEnt.Pos().Sub(innerEnt.Pos()).Mag2() colDist := outerEnt.Stats().Size() + innerEnt.Stats().Size() if distSq > colDist*colDist { continue } if distSq < 0.0001 { continue } if distSq <= 0.25 { distSq = 0.25 } dist := math.Sqrt(distSq) force := 50.0 * (colDist - dist) outerEnt.ApplyForce(outerEnt.Pos().Sub(innerEnt.Pos()).Scale(force / dist)) innerEnt.ApplyForce(innerEnt.Pos().Sub(outerEnt.Pos()).Scale(force / dist)) } } switch { case g.Moba != nil: g.ThinkMoba() case g.Standard != nil: panic("Thinkgs aren't implemented, like thinking on mana sources") // Do standard thinking default: panic("Game mode not set") } }
func (g *Game) DoForEnts(f func(Gid, Ent)) { base.DoOrdered(g.Ents, lessGids, f) }