diff --git a/community/parallax-scrolling-background/README.md b/community/parallax-scrolling-background/README.md new file mode 100644 index 0000000..ceda9ed --- /dev/null +++ b/community/parallax-scrolling-background/README.md @@ -0,0 +1,9 @@ +# Parallax scrolling demo + +Created by [Sergio Vera](https://github.com/svera) + +This example shows how to implement an infinite side scrolling background with a depth effect, using [parallax scrolling](https://en.wikipedia.org/wiki/Parallax_scrolling). Code is based in the [infinite scrolling background](https://github.com/faiface/pixel/tree/master/examples/community/scrolling-background) demo. + +Credits to [Peter Hellberg](https://github.com/peterhellberg) for the improved background images. + +![Parallax scrolling background](result.png) diff --git a/community/parallax-scrolling-background/background.png b/community/parallax-scrolling-background/background.png new file mode 100644 index 0000000..97359fc Binary files /dev/null and b/community/parallax-scrolling-background/background.png differ diff --git a/community/parallax-scrolling-background/foreground.png b/community/parallax-scrolling-background/foreground.png new file mode 100644 index 0000000..7328cd8 Binary files /dev/null and b/community/parallax-scrolling-background/foreground.png differ diff --git a/community/parallax-scrolling-background/main.go b/community/parallax-scrolling-background/main.go new file mode 100644 index 0000000..9add2b9 --- /dev/null +++ b/community/parallax-scrolling-background/main.go @@ -0,0 +1,74 @@ +package main + +import ( + "image" + "os" + "time" + + _ "image/png" + + "github.com/faiface/pixel" + "github.com/faiface/pixel/pixelgl" +) + +func loadPicture(path string) (pixel.Picture, error) { + file, err := os.Open(path) + if err != nil { + return nil, err + } + defer file.Close() + img, _, err := image.Decode(file) + if err != nil { + return nil, err + } + return pixel.PictureDataFromImage(img), nil +} + +const ( + windowWidth = 600 + windowHeight = 450 + foregroundHeight = 149 + // This is the scrolling speed (pixels per second) + // Negative values will make background to scroll to the left, + // positive to the right. + backgroundSpeed = -60 + foregroundSpeed = -120 +) + +func run() { + cfg := pixelgl.WindowConfig{ + Title: "Parallax scrolling demo", + Bounds: pixel.R(0, 0, windowWidth, windowHeight), + VSync: true, + } + win, err := pixelgl.NewWindow(cfg) + if err != nil { + panic(err) + } + + // Pic must have double the width of the window, as it will scroll to the left or right + picBackground, err := loadPicture("background.png") + if err != nil { + panic(err) + } + picForeground, err := loadPicture("foreground.png") + if err != nil { + panic(err) + } + + background := NewScrollingBackground(picBackground, windowWidth, windowHeight, backgroundSpeed) + foreground := NewScrollingBackground(picForeground, windowWidth, foregroundHeight, foregroundSpeed) + + last := time.Now() + for !win.Closed() { + dt := time.Since(last).Seconds() + last = time.Now() + background.Update(win, dt) + foreground.Update(win, dt) + win.Update() + } +} + +func main() { + pixelgl.Run(run) +} diff --git a/community/parallax-scrolling-background/result.png b/community/parallax-scrolling-background/result.png new file mode 100644 index 0000000..3236c67 Binary files /dev/null and b/community/parallax-scrolling-background/result.png differ diff --git a/community/parallax-scrolling-background/scrolling_background.go b/community/parallax-scrolling-background/scrolling_background.go new file mode 100644 index 0000000..87ba83f --- /dev/null +++ b/community/parallax-scrolling-background/scrolling_background.go @@ -0,0 +1,64 @@ +package main + +import ( + "math" + + "github.com/faiface/pixel" + "github.com/faiface/pixel/pixelgl" +) + +// ScrollingBackground stores all needed information to scroll a background +// to the left or right +type ScrollingBackground struct { + width float64 + height float64 + displacement float64 + speed float64 + backgrounds [2]*pixel.Sprite + positions [2]pixel.Vec +} + +// NewScrollingBackground construct and returns a new instance of scrollingBackground, +// positioning the background images according to the speed value +func NewScrollingBackground(pic pixel.Picture, width, height, speed float64) *ScrollingBackground { + sb := &ScrollingBackground{ + width: width, + height: height, + speed: speed, + backgrounds: [2]*pixel.Sprite{ + pixel.NewSprite(pic, pixel.R(0, 0, width, height)), + pixel.NewSprite(pic, pixel.R(width, 0, width*2, height)), + }, + } + + sb.positionImages() + return sb +} + +// If scrolling speed > 0, put second background image ouside the screen, +// at the left side, otherwise put it at the right side. +func (sb *ScrollingBackground) positionImages() { + if sb.speed > 0 { + sb.positions = [2]pixel.Vec{ + pixel.V(sb.width/2, (sb.height/2)+1), + pixel.V((sb.width/2)-sb.width, (sb.height/2)+1), + } + } else { + sb.positions = [2]pixel.Vec{ + pixel.V(sb.width/2, (sb.height/2)+1), + pixel.V(sb.width+(sb.width/2), (sb.height/2)+1), + } + } +} + +// Update will move backgrounds certain pixels, depending of the amount of time passed +func (sb *ScrollingBackground) Update(win *pixelgl.Window, dt float64) { + if math.Abs(sb.displacement) >= sb.width { + sb.displacement = 0 + sb.positions[0], sb.positions[1] = sb.positions[1], sb.positions[0] + } + d := pixel.V(sb.displacement, 0) + sb.backgrounds[0].Draw(win, pixel.IM.Moved(sb.positions[0].Add(d))) + sb.backgrounds[1].Draw(win, pixel.IM.Moved(sb.positions[1].Add(d))) + sb.displacement += sb.speed * dt +}