package internal import ( "context" "fmt" "log" "math/rand" "git.wisellama.rocks/Project-Ely/project-ely/internal/animation" "git.wisellama.rocks/Project-Ely/project-ely/internal/channels" "git.wisellama.rocks/Project-Ely/project-ely/internal/entity" "git.wisellama.rocks/Project-Ely/project-ely/internal/player" "git.wisellama.rocks/Project-Ely/project-ely/internal/sprite" "git.wisellama.rocks/Wisellama/gosimpleconf" rl "github.com/gen2brain/raylib-go/raylib" ) // Drawables can be rendered with OpenGL. See the 'entity' and 'animation' packages. type Drawable interface { Draw() error } // Objects can have physical interactions. See the 'entity' and 'physics' packages. type Object interface { Update() error } // Run is the main function to start the game. func Run(ctx context.Context, configMap gosimpleconf.ConfigMap) error { var err error ctx, cancel := context.WithCancel(ctx) defer cancel() framerate64 := gosimpleconf.Int64(configMap["game.framerate"]) framerate := int32(framerate64) // Initialize the RayLib window channels.RL.Do(func() { rl.InitWindow(800, 600, configMap["game.title"]) rl.SetTargetFPS(framerate) }) defer func() { channels.RL.Do(func() { rl.CloseWindow() }) }() // Initialize our sprites and animations sprite.InitSpriteCache() animation.DefineAnimations() drawables := make([]Drawable, 0) objects := make([]Object, 0) center := rl.Vector2{X: float32(rl.GetScreenWidth()) / 2, Y: float32(rl.GetScreenHeight()) / 2 * -1} player1 := player.NewPlayer(ctx) player1Penguin := entity.NewPenguin() player1Penguin.SetColor(rl.Gold) player1Penguin.GetObject().SetPosition(center) player1.SetControlledObject(player1Penguin.GetObject()) drawables = append(drawables, player1Penguin) objects = append(objects, player1Penguin) for i := 0; i < 10; i++ { p := entity.NewPenguin() p.GetObject().SetPosition(rl.Vector2{ X: rand.Float32() * float32(rl.GetScreenWidth()), Y: rand.Float32() * float32(rl.GetScreenHeight()*-1), }) p.GetAnimationTracker().SetAnimation(animation.RandomPenguinAnimation()) p.ToggleStaticAnimation() drawables = append(drawables, p) objects = append(objects, p) } // And now starting the main loop running := true for running { channels.RL.Do(func() { if rl.WindowShouldClose() { cancel() } }) // Allow us to exit early if the context is done select { case <-ctx.Done(): running = false default: // Keep running } if !running { break } player1.Update() // Update physics // TODO probably move out to something else to handle collisions. for _, o := range objects { err = o.Update() if err != nil { log.Printf("error updating physics: %v", err) } } channels.RL.Do(func() { rl.BeginDrawing() }) // Draw stuff for _, d := range drawables { err = d.Draw() if err != nil { log.Printf("error drawing: %v", err) } } channels.RL.Do(func() { rl.ClearBackground(rl.Black) rl.DrawText("Some Text!", 190, 200, 20, rl.Blue) rl.DrawText(fmt.Sprintf("%v FPS", rl.GetFPS()), 190, 250, 20, rl.Blue) }) channels.RL.Do(func() { rl.EndDrawing() }) } sprite.CleanupSpriteCache() return nil }