package scenes import ( "image/color" _ "image/jpeg" _ "image/png" "log" "github.com/go-gl/mathgl/mgl64" "github.com/hajimehoshi/ebiten/v2" "github.com/hajimehoshi/ebiten/v2/ebitenutil" ) const ( Gravity = 0.5 JumpForce = -10.0 MoveSpeed = 4.0 FloorHeight = 500.0 ) type Player struct { Pos mgl64.Vec3 // 3D Kordinater: X (vänster/höger), Y (upp/ner), Z (djup) Vel mgl64.Vec3 // Hastighet Width, Height float64 // För (AABB) Sprite *ebiten.Image } type PlayScene struct { player Player groundImg *ebiten.Image platforms []Platform isGrounded bool } func NewPlayScene() *PlayScene { pImg, _, err := ebitenutil.NewImageFromFile("assets/images/player.jpg") if err != nil { log.Println("Kunde inte ladda spelar-sprite:", err) pImg = ebiten.NewImage(32, 32) } gImg, _, err := ebitenutil.NewImageFromFile("assets/images/ground.jpg") if err != nil { log.Println("Kunde inte ladda mark-sprite:", err) gImg = ebiten.NewImage(800, 100) } wallImg, _, _ := ebitenutil.NewImageFromFile("assets/images/wall.png") stairImg, _, _ := ebitenutil.NewImageFromFile("assets/images/stairs.png") w, h := pImg.Bounds().Dx(), pImg.Bounds().Dy() // Skapa en enkel karta med plattformar för att hoppa på var mapPlatforms []Platform if wallImg != nil { pW := float64(wallImg.Bounds().Dx()) pH := float64(wallImg.Bounds().Dy()) mapPlatforms = append(mapPlatforms, Platform{ Pos: mgl64.Vec3{300.0, 400.0, 0.0}, Width: pW, Height: pH, Sprite: wallImg, Scale: 0.2, // Skala ner väggen eftersom dina bildfiler (125k/325k) förmodligen är stora }) mapPlatforms = append(mapPlatforms, Platform{ Pos: mgl64.Vec3{450.0, 300.0, 0.0}, Width: pW, Height: pH, Sprite: wallImg, Scale: 0.2, }) } if stairImg != nil { sW := float64(stairImg.Bounds().Dx()) sH := float64(stairImg.Bounds().Dy()) mapPlatforms = append(mapPlatforms, Platform{ Pos: mgl64.Vec3{150.0, 480.0, 0.0}, Width: sW, Height: sH, Sprite: stairImg, Scale: 0.5, }) } return &PlayScene{ player: Player{ Pos: mgl64.Vec3{400.0, 100.0, 0.0}, Vel: mgl64.Vec3{0, 0, 0}, Width: float64(w), Height: float64(h), Sprite: pImg, }, groundImg: gImg, platforms: mapPlatforms, } } func (s *PlayScene) Update() error { // === Input (X axis) === s.player.Vel[0] = 0 // Återställ rörelse varje frame if ebiten.IsKeyPressed(ebiten.KeyLeft) || ebiten.IsKeyPressed(ebiten.KeyA) { s.player.Vel[0] = -MoveSpeed } if ebiten.IsKeyPressed(ebiten.KeyRight) || ebiten.IsKeyPressed(ebiten.KeyD) { s.player.Vel[0] = MoveSpeed } // === Hoppa (Y axis) === if (ebiten.IsKeyPressed(ebiten.KeyUp) || ebiten.IsKeyPressed(ebiten.KeySpace)) && s.isGrounded { s.player.Vel[1] = JumpForce s.isGrounded = false } // === Fysik / Euler integrering === // 1. Applicera gravitation if !s.isGrounded { s.player.Vel[1] += Gravity } // 2. Planera Y förflyttning nextY := s.player.Pos[1] + s.player.Vel[1] s.isGrounded = false // Kolla om vi landar på en plattform (endast när vi faller) if s.player.Vel[1] >= 0 { for _, p := range s.platforms { if p.CheckCollisionTop(&s.player, nextY) { nextY = p.Pos[1] - s.player.Height s.player.Vel[1] = 0 s.isGrounded = true break } } } // === "Kollision" med golvet (väldigt simpel 2D-kollision för att simulera ytan på the floor på 2D-skärmen) === if nextY+s.player.Height >= FloorHeight { nextY = FloorHeight - s.player.Height s.player.Vel[1] = 0 s.isGrounded = true } s.player.Pos[0] += s.player.Vel[0] s.player.Pos[1] = nextY return nil } func (s *PlayScene) Draw(screen *ebiten.Image) { // Gör bakgrunden ljusblå (Sky blue) screen.Fill(color.RGBA{135, 206, 235, 255}) // === 3D -> 2D Rendering Pipeline (Side View mode) === // Rita ut marken över hela skärmens bredd (Tiling) if s.groundImg != nil { gWidth := float64(s.groundImg.Bounds().Dx()) if gWidth == 0 { gWidth = 32 // Undvik division med noll ifall bilden är tom } for x := 0.0; x < 800.0; x += gWidth { gOp := &ebiten.DrawImageOptions{} gOp.GeoM.Translate(x, FloorHeight) screen.DrawImage(s.groundImg, gOp) } } // Lägg ut karta/plattformar for _, p := range s.platforms { platOp := &ebiten.DrawImageOptions{} platOp.GeoM.Scale(p.Scale, p.Scale) platOp.GeoM.Translate(p.Pos[0], p.Pos[1]) screen.DrawImage(p.Sprite, platOp) } // Rita Spelaren baserat på dess 3D-kordinater översatta till (X, Y) på 2D-skärmen (vi skippar Z i denna view) pOp := &ebiten.DrawImageOptions{} pOp.GeoM.Translate(s.player.Pos[0], s.player.Pos[1]) screen.DrawImage(s.player.Sprite, pOp) ebitenutil.DebugPrint(screen, "Spelar Scene: SIDOVY. Styr med PILAR och Space.") }