func init() { load_requests = make(chan loadRequest, 10) pipe := make(chan loadRequest, 10) // We want to be able to handle any number of incoming load requests, so // we have one go-routine collect them all and send them along pipe any // time someone is ready to receive one. go func() { defer base.StackCatcher() var rs []loadRequest var send chan loadRequest var hold loadRequest for { select { case r := <-load_requests: rs = append(rs, r) case send <- hold: rs = rs[1:] } if len(rs) > 0 { send = pipe hold = rs[0] } else { // If send is nil then it will effectively be excluded from the select // statement above. This is good since we won't have anything to send // until we get more requests. rs = nil send = nil } } }() for i := 0; i < 4; i++ { go loadTextureRoutine(pipe) } }
func (gw *GameWindow) Draw(region gui.Region, style gui.StyleStack) { defer base.StackCatcher() defer func() { // gl.Translated(gl.Double(gw.region.X), gl.Double(gw.region.Y), 0) gl.Disable(gl.TEXTURE_2D) gl.Color4ub(255, 255, 255, 255) gl.LineWidth(3) gl.Begin(gl.LINES) bx, by := gl.Int(region.X), gl.Int(region.Y) bdx, bdy := gl.Int(region.Dx), gl.Int(region.Dy) gl.Vertex2i(bx, by) gl.Vertex2i(bx, by+bdy) gl.Vertex2i(bx, by+bdy) gl.Vertex2i(bx+bdx, by+bdy) gl.Vertex2i(bx+bdx, by+bdy) gl.Vertex2i(bx+bdx, by) gl.Vertex2i(bx+bdx, by) gl.Vertex2i(bx, by) gl.End() gl.LineWidth(1) }() gw.Engine.Pause() game := gw.Engine.GetState().(*Game) game.RenderLocal(region, gw.Local) gw.Engine.Unpause() }
func main() { defer base.StackCatcher() fmt.Printf("sys.Startup()...") sys.Startup() fmt.Printf("successful.\n") fmt.Printf("gl.Init()...") err := gl.Init() fmt.Printf("successful.\n") if err != nil { base.Error().Fatalf("%v", err) } fmt.Printf("render.Init()...") render.Init() fmt.Printf("successful.\n") render.Queue(func() { fmt.Printf("sys.CreateWindow()...") sys.CreateWindow(10, 10, wdx, wdy) fmt.Printf("successful.\n") sys.EnableVSync(true) }) base.InitShaders() runtime.GOMAXPROCS(10) fmt.Printf("sys.Think()...") sys.Think() fmt.Printf("successful.\n") base.LoadAllDictionaries() if Version() != "standard" { engine, local := debugHookup(Version()) mainLoop(engine, local, "standard") } else { standardHookup() } }
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") } }