Artifical Motion Blur > 2D
Contents
Fake Motion Blur
This demonstrates how to create the illusion of motion blur using by drawing a second overlying image with offset and opacity.To complete this example you will need to download the sprite sheet here. Features change in blur fade (opacity) and blur distance. View on Github
Before you start
I am a self taught Go programmer and do it as a hobby, the code below is my own interpretation of how to do something, probably not the only way or the best way. This is intended as a resource to learn some basic Raylib and Go game dev skills. If you want to use any of the code anywhere else, feel free to do so.
Code
package main
import (
"fmt"
"math/rand"
rl "github.com/gen2brain/raylib-go/raylib"
)
/* MORE RAYLIB GO EXAMPLES ARE AVAILABLE HERE:
https://github.com/unklnik/raylib-go-more-examples
*/
var (
imgs rl.Texture2D //TEXTURE TO LOAD IMAGE
cntr rl.Vector2 //SCREEN CENTER
fps = int32(60) //FRAMES PER SECOND OF GAME
blurDistance = float32(2) //OFFSET OF BLUR IMAGE
blurFade = float32(0.2) //BLUR OPACITY (FADE)
scanlines []rl.Vector2 //SLICE OF VECTOR2 FOR SCAN LINES
scanlineson = true //SET SCANLINES ON
scanlinesFade = float32(0.5) //SCANLINES FADE
currentColor int //CURRENT SCANLINE COLOR
scanlineColors = []rl.Color{rl.Black, rl.Green, rl.SkyBlue, rl.LightGray} //SCANLINES COLORS
)
func main() {
rl.InitWindow(0, 0, "fake motion blur - raylib go - https://github.com/unklnik/raylib-go-more-examples")
scrW, scrH := rl.GetScreenWidth(), rl.GetScreenHeight() // GET SCREEN SIZES
rl.SetWindowSize(scrW, scrH) // SET WINDOW SIZE
//rl.SetWindowState(rl.FlagBorderlessWindowedMode) // UNCOMMENT IF YOU HAVE DISPLAY ISSUES
//rl.ToggleFullscreen() // UNCOMMENT IF YOU HAVE DISPLAY ISSUES
cntr = rl.NewVector2(float32(scrW/2), float32(scrH/2)) //CENTER OF SCREEN
imgs = rl.LoadTexture("imgs.png") //LOAD IMAGESc
flagIMG := rl.NewRectangle(0, 0, 16, 16) //FLAG IMAGE RECTANGLE
fireballIMG := rl.NewRectangle(16, 0, 16, 16) //FIREBALL IMAGE RECTANGLE
camera := rl.Camera2D{} // DEFINES THE CAMERA
camera.Zoom = 2.0 //SETS CAMERA ZOOM
camera.Target = cntr //OFFSET CAMERA FROM CENTER AFTER ZOOM CHANGE
camera.Offset.X = float32(scrW / 2)
camera.Offset.Y = float32(scrH / 2)
//CREATE SCANLINE VECTOR2
scanoffset := float32(3) //SPACE BETWEEN SCANLINES
y := float32(-scanoffset) //START FROM ABOVE SCREEN TOP
for y < float32(scrH)+scanoffset { //END BELOW SCREEN HEIGHT
scanlines = append(scanlines, rl.NewVector2(0, y))
y += scanoffset
}
rl.SetTargetFPS(fps) // NUMBER OF FRAMES DRAWN IN A SECOND
for !rl.WindowShouldClose() {
if rl.IsKeyPressed(rl.KeyZ) { //CHANGE FADE
scanlinesFade += 0.1
if scanlinesFade > 1 {
scanlinesFade = 0.2
}
}
if rl.IsKeyPressed(rl.KeyRight) { //CHANGE BLUR
blurFade -= 0.1
if blurFade <= 0.1 {
blurFade = 0.8
}
}
if rl.IsKeyPressed(rl.KeyLeft) { //CHANGE COLOR
currentColor++
if currentColor == len(scanlineColors)-1 {
currentColor = 0
}
}
if rl.IsKeyPressed(rl.KeyDown) { //CHANGE BLUR DISTANCE
blurDistance++
if blurDistance >= 10 {
blurDistance = 1
}
}
if rl.IsKeyPressed(rl.KeyUp) { //CHANGE ZOOM
if camera.Zoom == 1 {
camera.Zoom = 1.5
} else if camera.Zoom == 1.5 {
camera.Zoom = 2
} else if camera.Zoom == 2 {
camera.Zoom = 1
}
//ADJUST CAMERA TO CENTER IMAGE AFTER CHANGE IN ZOOM
camera.Target = cntr
camera.Offset.X = float32(scrW / 2)
camera.Offset.Y = float32(scrH / 2)
}
if rl.IsKeyPressed(rl.KeySpace) { //TURN SCANLINES ON/OFF
scanlineson = !scanlineson
}
for i := 0; i < len(scanlines); i++ { //MOVE SCANLINES DOWN BY OFFEST
scanlines[i].Y += scanoffset
if scanlines[i].Y > float32(scrH) { //RETURN TO ABOVE SCREEN TOP IF REACH SCREEN HEIGHT
scanlines[i].Y = -scanoffset
}
}
rl.BeginDrawing()
rl.ClearBackground(rl.Black)
rl.BeginMode2D(camera)
size := float32(128) //IMAGE SIZE
fireballRec := rl.NewRectangle(cntr.X-size/2, cntr.Y-size, size, size) //FIREBALL DRAW REC
flagRec := rl.NewRectangle(cntr.X-size/2, cntr.Y, size, size) //FLAG DRAW REC
fireballColor := ranOrange() //RANDOM COLOR SEE FUNCTION BELOW
//DRAW ORIGINAL IMAGE
rl.DrawTexturePro(imgs, fireballIMG, fireballRec, rl.Vector2Zero(), 0, fireballColor)
//COPY ORIGINAL IMAGE
blurRec := fireballRec
//MOVE Y RANDOM DISTANCE FUNCTION BELOW
blurRec.Y += rF32(-blurDistance, blurDistance)
//MOVE X RANDOM DISTANCE FUNCTION BELOW
blurRec.X += rF32(-blurDistance, blurDistance)
rl.DrawTexturePro(imgs, fireballIMG, blurRec, rl.Vector2Zero(), 0, rl.Fade(fireballColor, blurFade)) //DRAW OFFEST IMAGE WITH FADE
rl.DrawTexturePro(imgs, flagIMG, flagRec, rl.Vector2Zero(), 0, rl.White)
blurRec = flagRec
blurRec.Y += rF32(-blurDistance, blurDistance)
blurRec.X += rF32(-blurDistance, blurDistance)
rl.DrawTexturePro(imgs, flagIMG, blurRec, rl.Vector2Zero(), 0, rl.Fade(rl.White, blurFade))
rl.EndMode2D()
if scanlineson { //DRAW SCANLINES
for i := 0; i < len(scanlines); i++ {
endV2 := rl.NewVector2(scanlines[i].X+float32(scrW), scanlines[i].Y)
rl.DrawLineV(scanlines[i], endV2, rl.Fade(scanlineColors[currentColor], scanlinesFade))
}
}
rl.DrawText("UP key change zoom / DOWN key change blur distance / RIGHT key change blur fade / LEFT key change scanlines color / Z key change scanlines fade / SPACE key turn scanlines on/off", 10, 10, 10, rl.White)
rl.DrawText("blur distance "+fmt.Sprint(blurDistance)+" blur fade "+fmt.Sprint(blurFade)+" scanlines fade "+fmt.Sprint(scanlinesFade), 10, 20, 10, rl.White)
rl.EndDrawing()
}
rl.UnloadTexture(imgs) //UNLOAD FROM MEMORY
rl.CloseWindow()
}
// RETURNS A RANDOM ORANGE COLOR
func ranOrange() rl.Color {
return rl.NewColor(uint8(255), uint8(rInt(70, 170)), uint8(rInt(0, 50)), 255)
}
// RETURNS A RANDOM INTEGER FOR USE IN RANDOM ORANGE COLOR FUNCTION ABOVE
func rInt(min, max int) int {
return min + rand.Intn(max-min)
}
// RETURNS A RANDOM FLOAT32 VALUE BETWEEN MIN/MAX VALUES
func rF32(min, max float32) float32 {
min2 := float64(min)
max2 := float64(max)
return float32(min2 + rand.Float64()*(max2-min2))
}
Video
Want to give it a Go?
To start making games with Go and Raylib you will need:
- Go - https://go.dev/
- TDM-GCC - https://jmeubank.github.io/tdm-gcc/
- Git - https://git-scm.com/downloads
- Go Bindings for Raylib - https://github.com/gen2brain/raylib-go
- Visual Studio Code - https://code.visualstudio.com/
You can, of course, use other code editors however VS Code is my own personal preference