Example #1
0
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,
	}
}
Example #2
0
func (g *Game) DoForLevels(f func(Gid, *Level)) {
	base.DoOrdered(g.Levels, lessGids, f)
}
Example #3
0
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")
	}
}
Example #4
0
func (g *Game) DoForEnts(f func(Gid, Ent)) {
	base.DoOrdered(g.Ents, lessGids, f)
}