Пример #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,
	}
}
Пример #2
0
func (pd *PathingData) Dir(src, dst linear.Vec2) linear.Vec2 {
	x := int(src.X / pathingDataGrid)
	y := int(src.Y / pathingDataGrid)
	x2 := int(dst.X / pathingDataGrid)
	y2 := int(dst.Y / pathingDataGrid)
	if x < 0 || y < 0 || x >= len(pd.dstData) || y >= len(pd.dstData[x]) {
		return linear.Vec2{0, 0}
	}
	if x2 < 0 || y2 < 0 || x2 >= len(pd.dstData) || y2 >= len(pd.dstData[x2]) {
		return linear.Vec2{0, 0}
	}
	dstData := &pd.dstData[x2][y2]
	dstData.RLock()
	defer dstData.RUnlock()
	if !dstData.complete {
		dstData.once.Do(func() {
			base.Log().Printf("Eval: %2.2v %2.2v", src, dst)
			go func() {
				pd.finishDirectPaths.Wait()
				dstData.Lock()
				defer dstData.Unlock()
				pd.findAllPaths(x2, y2)
				dstData.complete = true
			}()
		})
		return dst.Sub(src).Norm()
	}
	cell := pd.dirs[x2][y2][x][y]
	if !cell.direct {
		return (linear.Vec2{1, 0}).Rotate(cell.angle)
	}
	return dst.Sub(src).Norm()
}
Пример #3
0
func (p *pullProcess) Think(g *game.Game) {
	_player := g.GetEnt(p.Player_id)
	player := _player.(*game.Player)

	base_force := p.Force * p.supplied / p.required
	for _, _target := range g.Ents {
		target, ok := _target.(*game.Player)
		if !ok || target == player {
			continue
		}
		target_pos := linear.Vec2{target.X, target.Y}
		ray := target_pos.Sub(player.Pos())
		target_angle := ray.Angle() - player.Angle
		for target_angle < 0 {
			target_angle += math.Pi * 2
		}
		for target_angle > math.Pi*2 {
			target_angle -= math.Pi * 2
		}
		if target_angle > p.Angle/2 && target_angle < math.Pi*2-p.Angle/2 {
			continue
		}
		ray = player.Pos().Sub(target.Pos())
		// dist := ray.Mag()
		ray = ray.Norm()
		force := base_force // / math.Pow(dist, p.Angle/(2*math.Pi))
		target.ApplyForce(ray.Scale(-force))
		player.ApplyForce(ray.Scale(force))
	}
}
Пример #4
0
// Queries the input system for the direction that this controller is moving in
func getControllerDirection(controller gin.DeviceId) linear.Vec2 {
	v := linear.Vec2{
		axisControl(control.right.CurPressAmt()) - axisControl(control.left.CurPressAmt()),
		axisControl(control.down.CurPressAmt()) - axisControl(control.up.CurPressAmt()),
	}
	if v.Mag2() > 1 {
		v = v.Norm()
	}
	return v
}
Пример #5
0
func (g *Game) RenderLocalEditor(region g2.Region) {
	g.editor.Lock()
	defer g.editor.Unlock()
	g.editor.region = region
	g.editor.camera.regionDims = linear.Vec2{float64(region.Dims.Dx), float64(region.Dims.Dy)}
	levelDims := linear.Vec2{float64(g.Level.Room.Dx), float64(g.Level.Room.Dy)}
	g.editor.camera.StandardRegion(levelDims.Scale(0.5), levelDims)
	g.editor.camera.approachTarget()

	gl.MatrixMode(gl.PROJECTION)
	gl.PushMatrix()
	gl.LoadIdentity()
	defer gl.PopMatrix()

	gl.PushAttrib(gl.VIEWPORT_BIT)
	gl.Viewport(gl.Int(region.X), gl.Int(region.Y), gl.Sizei(region.Dx), gl.Sizei(region.Dy))
	defer gl.PopAttrib()

	current := &g.editor.camera.current
	gl.Ortho(
		gl.Double(current.mid.X-current.dims.X/2),
		gl.Double(current.mid.X+current.dims.X/2),
		gl.Double(current.mid.Y+current.dims.Y/2),
		gl.Double(current.mid.Y-current.dims.Y/2),
		gl.Double(1000),
		gl.Double(-1000),
	)
	defer func() {
		gl.MatrixMode(gl.PROJECTION)
		gl.PopMatrix()
		gl.MatrixMode(gl.MODELVIEW)
	}()
	gl.MatrixMode(gl.MODELVIEW)

	gl.Enable(gl.BLEND)
	gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)

	g.renderWalls()
	g.renderEdges()
	g.renderBases()
	g.renderEntsAndAbilities()
	g.renderProcesses()

	g.editor.renderPathing(&g.Level.Room, g.local.pathingData)

	switch g.editor.action {
	case editorActionNone:
	case editorActionPlaceBlock:
		g.editor.renderPlaceBlock(g)
	default:
		base.Error().Printf("Unexpected editorAction: %v", g.editor.action)
	}
}
Пример #6
0
func (editor *editorData) getPoly(g *Game) linear.Poly {
	pos := editor.cursorPosInGameCoords(&g.Level.Room)
	var offset linear.Vec2
	offset.X = pos.X - editor.placeBlock.offset.X
	offset.X = math.Floor(offset.X/editor.placeBlock.grid+0.5) * editor.placeBlock.grid
	offset.Y = pos.Y - editor.placeBlock.offset.Y
	offset.Y = math.Floor(offset.Y/editor.placeBlock.grid+0.5) * editor.placeBlock.grid
	block := make(linear.Poly, len(editor.placeBlock.block))
	for i := range editor.placeBlock.block {
		block[i] = editor.placeBlock.block[i].Add(offset)
	}
	return block
}
Пример #7
0
func ComplexOperationsSpec(c gospec.Context) {
	c.Specify("Vec2.DistToLine() works.", func() {
		centers := []linear.Vec2{
			linear.Vec2{10, 12},
			linear.Vec2{1, -9},
			linear.Vec2{-100, -42},
			linear.Vec2{0, 1232},
		}
		radiuses := []float64{3, 10.232, 435, 1}
		thetas := []float64{0.001, 0.1, 1, 1.01, 0.034241, 0.789, 90, 179, 180}
		angles := []float64{1.01, 1.0, 1.11111, 930142}
		for _, center := range centers {
			for _, radius := range radiuses {
				for _, angle := range angles {
					for _, theta := range thetas {
						a := linear.Vec2{math.Cos(angle), math.Sin(angle)}
						b := linear.Vec2{math.Cos(angle + theta), math.Sin(angle + theta)}
						seg := linear.Seg2{a.Scale(radius).Add(center), b.Scale(radius).Add(center)}
						dist := center.DistToLine(seg)
						real_dist := radius * math.Cos(theta/2)
						if real_dist < 0 {
							real_dist = -real_dist
						}
						c.Expect(dist, IsWithin(1e-9), real_dist)
					}
				}
			}
		}
	})
}
Пример #8
0
func (g *Game) AddCreeps(pos linear.Vec2, count, side int, params map[string]interface{}) {
	if side < 0 || side >= len(g.Level.Room.SideData) {
		base.Error().Fatalf("Got side %d, but this level only supports sides from 0 to %d.", side, len(g.Level.Room.SideData)-1)
		return
	}
	for i := 0; i < count; i++ {
		var c CreepEnt
		c.StatsInst = stats.Make(stats.Base{
			Health: 100,
			Mass:   250,
			Acc:    50.0,
			Rate:   0.0,
			Size:   8,
			Vision: 400,
		})

		// Evenly space the players on a circle around the starting position.
		randAngle := rand.New(g.Rng).Float64() * math.Pi
		rot := (linear.Vec2{15, 0}).Rotate(randAngle + float64(i)*2*3.1415926535/float64(count))
		c.Position = pos.Add(rot)

		c.Side_ = side
		c.Gid = g.NextGid()

		c.Abilities_ = append(
			c.Abilities_,
			ability_makers["asplode"](map[string]float64{"startRadius": 40, "endRadius": 70, "durationThinks": 50, "dps": 5}))

		// if playerData.gid[0:2] == "Ai" {
		//  c.BindAi("simple", g.local.Engine)
		// }

		g.AddEnt(&c)
		c.BindAi("creep", g.local.Engine)
		for name, value := range params {
			c.ai.SetParam(name, value)
		}
	}
}
Пример #9
0
func (tm *ThunderMenu) Draw(region Region, style StyleStack) {
	// Set clip planes
	gl.PushAttrib(gl.TRANSFORM_BIT)
	defer gl.PopAttrib()
	var eqs [4][4]gl.Double
	eqs[0][0], eqs[0][1], eqs[0][2], eqs[0][3] = 1, 0, 0, -gl.Double(region.X)
	eqs[1][0], eqs[1][1], eqs[1][2], eqs[1][3] = -1, 0, 0, gl.Double(region.X+region.Dx)
	eqs[2][0], eqs[2][1], eqs[2][2], eqs[2][3] = 0, 1, 0, -gl.Double(region.Y)
	eqs[3][0], eqs[3][1], eqs[3][2], eqs[3][3] = 0, -1, 0, gl.Double(region.Y+region.Dy)
	gl.Enable(gl.CLIP_PLANE0)
	gl.Enable(gl.CLIP_PLANE1)
	gl.Enable(gl.CLIP_PLANE2)
	gl.Enable(gl.CLIP_PLANE3)
	gl.ClipPlane(gl.CLIP_PLANE0, &eqs[0][0])
	gl.ClipPlane(gl.CLIP_PLANE1, &eqs[1][0])
	gl.ClipPlane(gl.CLIP_PLANE2, &eqs[2][0])
	gl.ClipPlane(gl.CLIP_PLANE3, &eqs[3][0])

	var start, end int
	if tm.delta <= 0 {
		start = tm.current + int(math.Floor(tm.delta))
		end = tm.current
		region.X += int(float64(region.Dx) * (float64(start-tm.current) - tm.delta))
	} else {
		start = tm.current
		end = tm.current + int(math.Ceil(tm.delta))
		region.X += int(float64(region.Dx) * (float64(end-tm.current) - tm.delta - math.Floor(tm.delta) - 1))
	}
	var offset linear.Vec2
	offset.X = (float64(tm.current) + tm.delta) * float64(region.Dx)
	for i := start; i <= end; i++ {
		style.PushStyle(map[string]interface{}{"offset": offset})
		tm.Subs[tm.menuStack[i]].Draw(region, style)
		style.Pop()
		region.X += region.Dx
	}
}
Пример #10
0
func (editor *editorData) cursorPosInGameCoords(room *Room) linear.Vec2 {
	x, y := editor.sys.GetCursorPos()
	pos := linear.Vec2{float64(x), float64(y)}
	regionPos := linear.Vec2{float64(editor.region.Pos.X), float64(editor.region.Pos.Y)}
	pos = pos.Sub(regionPos)
	pos = pos.Scale(float64(room.Dx) / float64(editor.region.Dims.Dx))
	cameraOffset := linear.Vec2{
		editor.camera.current.dims.X/2 - editor.camera.current.mid.X,
		editor.camera.current.dims.Y/2 - editor.camera.current.mid.Y,
	}
	pos = pos.Sub(cameraOffset)
	return pos
}
Пример #11
0
func (pd *PathingData) findAllDirectPaths(dstx, dsty int, room *Room) {
	defer pd.finishDirectPaths.Done()
	dst := linear.Vec2{(float64(dstx) + 0.5) * pathingDataGrid, (float64(dsty) + 0.5) * pathingDataGrid}
	for x := range pd.dirs[dstx][dsty] {
		for y := range pd.dirs[dstx][dsty][x] {
			src := linear.Vec2{(float64(x) + 0.5) * pathingDataGrid, (float64(y) + 0.5) * pathingDataGrid}
			if dstx == 1 && dsty == 4 {
			}
			if room.ExistsLos(src, dst) {
				if dstx == 1 && dsty == 4 {
				}
				pd.conns[dstx][dsty] = append(pd.conns[dstx][dsty], pathingConnection{
					x:    x,
					y:    y,
					dist: dst.Sub(src).Mag(),
				})
				data := &pd.dirs[dstx][dsty][x][y]
				data.angle = src.Sub(dst).Angle()
				data.direct = true
				// data.filled = true
			}
		}
	}
}
Пример #12
0
func BasicPropertiesSpec(c gospec.Context) {
	a := linear.Vec2{3, 4}
	b := linear.Vec2{5, 6}
	c.Specify("Check that (cross a) dot a == 0.", func() {
		c.Expect(a.Cross().Dot(a), Equals, 0.0)
	})
	c.Specify("Check that a normalize vector's magnitude is 1.", func() {
		c.Expect(a.Norm().Mag(), IsWithin(1e-9), 1.0)
	})
	c.Specify("Check that v.Mag2() == v.Mag()*v.Mag()", func() {
		c.Expect(a.Mag2(), IsWithin(1e-9), a.Mag()*a.Mag())
	})
	c.Specify("Check that a scaled vector's magnitude is appropriately scaled.", func() {
		c.Expect(a.Scale(3.5).Mag(), IsWithin(1e-9), a.Mag()*3.5)
	})
	c.Specify("Check that a-(a-b) == b.", func() {
		VecExpect(c, a.Sub(a.Sub(b)), IsWithin(1e-9), b)
	})
}
Пример #13
0
func (p *Player) ApplyForce(f linear.Vec2) {
	dv := f.Scale(1 / p.Mass())
	p.Vx += dv.X
	p.Vy += dv.Y
}
Пример #14
0
func BasicOperationsSpec(c gospec.Context) {
	a := linear.Vec2{3, 4}
	b := linear.Vec2{5, 6}
	c.Specify("Make sure adding vectors works.", func() {
		VecExpect(c, a.Add(b), Equals, linear.Vec2{8, 10})
	})
	c.Specify("Make sure subtracting vectors works.", func() {
		VecExpect(c, a.Sub(b), Equals, linear.Vec2{-2, -2})
	})
	c.Specify("Make sure dotting vectors works.", func() {
		c.Expect(a.Dot(b), IsWithin(1e-9), 39.0)
	})
	c.Specify("Make sure crossing vectors works.", func() {
		VecExpect(c, a.Cross(), Equals, linear.Vec2{-4, 3})
	})
	c.Specify("Make sure taking the magnitude of vectors works.", func() {
		c.Expect(a.Mag(), IsWithin(1e-9), 5.0)
		c.Expect(a.Mag2(), IsWithin(1e-9), 25.0)
	})
	c.Specify("Make sure scaling vectors works.", func() {
		VecExpect(c, a.Scale(3), Equals, linear.Vec2{9, 12})
	})
}
Пример #15
0
func (camera *cameraInfo) doInvadersFocusRegion(g *Game, side int) {
	min := linear.Vec2{1e9, 1e9}
	max := linear.Vec2{-1e9, -1e9}
	hits := 0
	for _, ent := range g.temp.AllEnts {
		if ent.Side() != side {
			continue
		}
		if player, ok := ent.(*PlayerEnt); ok {
			hits++
			pos := player.Pos()
			if pos.X < min.X {
				min.X = pos.X
			}
			if pos.Y < min.Y {
				min.Y = pos.Y
			}
			if pos.X > max.X {
				max.X = pos.X
			}
			if pos.Y > max.Y {
				max.Y = pos.Y
			}
		}
	}
	if hits == 0 {
		min.X = 0
		min.Y = 0
		max.X = float64(g.Levels[GidInvadersStart].Room.Dx)
		max.Y = float64(g.Levels[GidInvadersStart].Room.Dy)
	} else {
		min.X -= stats.LosPlayerHorizon + 50
		min.Y -= stats.LosPlayerHorizon + 50
		if min.X < 0 {
			min.X = 0
		}
		if min.Y < 0 {
			min.Y = 0
		}
		max.X += stats.LosPlayerHorizon + 50
		max.Y += stats.LosPlayerHorizon + 50
		if max.X > float64(g.Levels[GidInvadersStart].Room.Dx) {
			max.X = float64(g.Levels[GidInvadersStart].Room.Dx)
		}
		if max.Y > float64(g.Levels[GidInvadersStart].Room.Dy) {
			max.Y = float64(g.Levels[GidInvadersStart].Room.Dy)
		}
	}

	mid := min.Add(max).Scale(0.5)
	dims := max.Sub(min)
	if dims.X/dims.Y < camera.regionDims.X/camera.regionDims.Y {
		dims.X = dims.Y * camera.regionDims.X / camera.regionDims.Y
	} else {
		dims.Y = dims.X * camera.regionDims.Y / camera.regionDims.X
	}
	camera.target.dims = dims
	camera.target.mid = mid

	if camera.current.mid.X == 0 && camera.current.mid.Y == 0 {
		// On the very first frame the current midpoint will be (0,0), which should
		// never happen after the game begins.  In this one case we'll immediately
		// set current to target so we don't start off by approaching it from the
		// origin.
		camera.current = camera.target
	} else {
		// speed is in (0, 1), the higher it is, the faster current approaches target.
		speed := 0.1
		camera.current.dims = camera.current.dims.Scale(1 - speed).Add(camera.target.dims.Scale(speed))
		camera.current.mid = camera.current.mid.Scale(1 - speed).Add(camera.target.mid.Scale(speed))
	}
}
Пример #16
0
func (l *LocalData) thinkAbility(g *Game, abs *personalAbilities, gid Gid) {
	if abs.activeAbility == nil {
		return
	}
	var mouse linear.Vec2
	if l.mode == LocalModeArchitect {
		mx, my := l.sys.GetCursorPos()
		mouse.X = float64(mx)
		mouse.Y = float64(my)
		mouse = mouse.Sub(l.architect.camera.regionPos)
		mouse.X /= l.architect.camera.regionDims.X
		mouse.Y /= l.architect.camera.regionDims.Y
		mouse.X *= l.architect.camera.current.dims.X
		mouse.Y *= l.architect.camera.current.dims.Y
		mouse = mouse.Sub(l.architect.camera.current.dims.Scale(0.5))
		mouse = mouse.Add(l.architect.camera.current.mid)
	}
	events, die := abs.activeAbility.Think(gid, g, mouse)
	for _, event := range events {
		l.engine.ApplyEvent(event)
	}
	if die {
		base.Log().Printf("Deactivate on die")
		more_events := abs.activeAbility.Deactivate(gid)
		abs.activeAbility = nil
		for _, event := range more_events {
			l.engine.ApplyEvent(event)
		}
	}
}
Пример #17
0
func (camera *cameraInfo) FocusRegion(g *Game, side int) {
	min := linear.Vec2{1e9, 1e9}
	max := linear.Vec2{-1e9, -1e9}
	player := g.Ents[g.local.Gid]
	if player == nil {
		min.X = 0
		min.Y = 0
		max.X = float64(g.Level.Room.Dx)
		max.Y = float64(g.Level.Room.Dy)
	} else {
		min.X = player.Pos().X - player.Stats().Vision()
		min.Y = player.Pos().Y - player.Stats().Vision()
		if min.X < 0 {
			min.X = 0
		}
		if min.Y < 0 {
			min.Y = 0
		}
		max.X = player.Pos().X + player.Stats().Vision()
		max.Y = player.Pos().Y + player.Stats().Vision()
		if max.X > float64(g.Level.Room.Dx) {
			max.X = float64(g.Level.Room.Dx)
		}
		if max.Y > float64(g.Level.Room.Dy) {
			max.Y = float64(g.Level.Room.Dy)
		}
	}

	mid := min.Add(max).Scale(0.5)
	dims := max.Sub(min)
	if dims.X/dims.Y < camera.regionDims.X/camera.regionDims.Y {
		dims.X = dims.Y * camera.regionDims.X / camera.regionDims.Y
	} else {
		dims.Y = dims.X * camera.regionDims.Y / camera.regionDims.X
	}
	camera.target.dims = dims
	camera.target.mid = mid

	camera.approachTarget()
}
Пример #18
0
func (b *BaseEnt) ApplyForce(f linear.Vec2) {
	b.Velocity = b.Velocity.Add(f.Scale(1 / b.Mass()))
}