more examples coming, i still have to clean them up though
|
@ -0,0 +1,7 @@
|
||||||
|
# Go Jetpack
|
||||||
|
by [Branson Camp](https://github.com/bcamp1) using [Pixel](https://github.com/faiface/pixel)
|
||||||
|
|
||||||
|
Welcome to Go-Jetpack, where you explore the skies using WASD or Arrow Keys.
|
||||||
|
This example showcases most of the fundamental pixel elements described in the [Pixel Wiki](https://github.com/faiface/pixel/wiki)
|
||||||
|
|
||||||
|

|
After Width: | Height: | Size: 295 B |
After Width: | Height: | Size: 314 B |
|
@ -0,0 +1,306 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"image"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/go-gl/mathgl/mgl32"
|
||||||
|
|
||||||
|
_ "image/png"
|
||||||
|
|
||||||
|
"github.com/faiface/pixel"
|
||||||
|
"github.com/faiface/pixel/pixelgl"
|
||||||
|
"github.com/faiface/pixel/text"
|
||||||
|
"github.com/golang/freetype/truetype"
|
||||||
|
"golang.org/x/image/colornames"
|
||||||
|
)
|
||||||
|
|
||||||
|
// InstallShader ...
|
||||||
|
func InstallShader(w *pixelgl.Window, uAmount *float32, uResolution, uMouse *mgl32.Vec2) {
|
||||||
|
wc := w.GetCanvas()
|
||||||
|
wc.BindUniform("u_resolution", uResolution)
|
||||||
|
wc.BindUniform("u_mouse", uMouse)
|
||||||
|
wc.BindUniform("u_amount", uAmount)
|
||||||
|
wc.SetFragmentShader(pixelateFragShader)
|
||||||
|
wc.UpdateShader()
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadSprite(path string) (pixel.Sprite, error) {
|
||||||
|
pic, err := loadPicture(path)
|
||||||
|
if err != nil {
|
||||||
|
return *pixel.NewSprite(pic, pic.Bounds()), err
|
||||||
|
}
|
||||||
|
sprite := pixel.NewSprite(pic, pic.Bounds())
|
||||||
|
return *sprite, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadTTF(path string, size float64, origin pixel.Vec) *text.Text {
|
||||||
|
file, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
bytes, err := ioutil.ReadAll(file)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
font, err := truetype.Parse(bytes)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
face := truetype.NewFace(font, &truetype.Options{
|
||||||
|
Size: size,
|
||||||
|
GlyphCacheEntries: 1,
|
||||||
|
})
|
||||||
|
|
||||||
|
atlas := text.NewAtlas(face, text.ASCII)
|
||||||
|
|
||||||
|
txt := text.New(origin, atlas)
|
||||||
|
|
||||||
|
return txt
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func run() {
|
||||||
|
// Set up window configs
|
||||||
|
cfg := pixelgl.WindowConfig{ // Default: 1024 x 768
|
||||||
|
Title: "Golang Jetpack!",
|
||||||
|
Bounds: pixel.R(0, 0, 1024, 768),
|
||||||
|
VSync: true,
|
||||||
|
}
|
||||||
|
win, err := pixelgl.NewWindow(cfg)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Importantr variables
|
||||||
|
var jetX, jetY, velX, velY, radians float64
|
||||||
|
flipped := 1.0
|
||||||
|
jetpackOn := false
|
||||||
|
gravity := 0.6 // Default: 0.004
|
||||||
|
jetAcc := 0.9 // Default: 0.008
|
||||||
|
tilt := 0.01 // Default: 0.001
|
||||||
|
whichOn := false
|
||||||
|
onNumber := 0
|
||||||
|
jetpackOffName := "jetpack.png"
|
||||||
|
jetpackOn1Name := "jetpack-on.png"
|
||||||
|
jetpackOn2Name := "jetpack-on2.png"
|
||||||
|
camVector := win.Bounds().Center()
|
||||||
|
|
||||||
|
var uAmount float32
|
||||||
|
var uMouse, uResolution mgl32.Vec2
|
||||||
|
|
||||||
|
InstallShader(win, &uAmount, &uResolution, &uMouse)
|
||||||
|
|
||||||
|
bg, _ := loadSprite("sky.png")
|
||||||
|
|
||||||
|
// Jetpack - Rendering
|
||||||
|
jetpackOff, err := loadSprite(jetpackOffName)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
jetpackOn1, err := loadSprite(jetpackOn1Name)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
jetpackOn2, err := loadSprite(jetpackOn2Name)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tutorial Text
|
||||||
|
txt := loadTTF("intuitive.ttf", 50, pixel.V(win.Bounds().Center().X-450, win.Bounds().Center().Y-200))
|
||||||
|
fmt.Fprintf(txt, "Explore the Skies with WASD or Arrow Keys!")
|
||||||
|
|
||||||
|
currentSprite := jetpackOff
|
||||||
|
|
||||||
|
canvas := pixelgl.NewCanvas(win.Bounds())
|
||||||
|
uResolution[0] = float32(win.Bounds().W())
|
||||||
|
uResolution[1] = float32(win.Bounds().H())
|
||||||
|
uAmount = 300.0
|
||||||
|
// Game Loop
|
||||||
|
for !win.Closed() {
|
||||||
|
|
||||||
|
mpos := win.MousePosition()
|
||||||
|
uMouse[0] = float32(mpos.X)
|
||||||
|
uMouse[1] = float32(mpos.Y)
|
||||||
|
win.SetTitle(fmt.Sprint(uAmount))
|
||||||
|
win.Clear(colornames.Blue)
|
||||||
|
canvas.Clear(colornames.Green)
|
||||||
|
|
||||||
|
// Jetpack - Controls
|
||||||
|
jetpackOn = win.Pressed(pixelgl.KeyUp) || win.Pressed(pixelgl.KeyW)
|
||||||
|
|
||||||
|
if win.Pressed(pixelgl.KeyRight) || win.Pressed(pixelgl.KeyD) {
|
||||||
|
jetpackOn = true
|
||||||
|
flipped = -1
|
||||||
|
radians -= tilt
|
||||||
|
velX += tilt * 30
|
||||||
|
} else if win.Pressed(pixelgl.KeyLeft) || win.Pressed(pixelgl.KeyA) {
|
||||||
|
jetpackOn = true
|
||||||
|
flipped = 1
|
||||||
|
radians += tilt
|
||||||
|
velX -= tilt * 30
|
||||||
|
} else {
|
||||||
|
if velX < 0 {
|
||||||
|
radians -= tilt / 3
|
||||||
|
velX += tilt * 10
|
||||||
|
} else if velX > 0 {
|
||||||
|
radians += tilt / 3
|
||||||
|
velX -= tilt * 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if jetY < 0 {
|
||||||
|
jetY = 0
|
||||||
|
velY = -0.3 * velY
|
||||||
|
}
|
||||||
|
|
||||||
|
if jetpackOn {
|
||||||
|
velY += jetAcc
|
||||||
|
whichOn = !whichOn
|
||||||
|
onNumber++
|
||||||
|
if onNumber == 5 { // every 5 frames, toggle anijetMation
|
||||||
|
onNumber = 0
|
||||||
|
if whichOn {
|
||||||
|
currentSprite = jetpackOn1
|
||||||
|
} else {
|
||||||
|
currentSprite = jetpackOn2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
currentSprite = jetpackOff
|
||||||
|
velY -= gravity
|
||||||
|
}
|
||||||
|
|
||||||
|
if win.Pressed(pixelgl.KeyEqual) {
|
||||||
|
uAmount += 10
|
||||||
|
}
|
||||||
|
if win.Pressed(pixelgl.KeyMinus) {
|
||||||
|
uAmount -= 10
|
||||||
|
}
|
||||||
|
|
||||||
|
positionVector := pixel.V(win.Bounds().Center().X+jetX, win.Bounds().Center().Y+jetY-372)
|
||||||
|
jetMat := pixel.IM
|
||||||
|
jetMat = jetMat.Scaled(pixel.ZV, 4)
|
||||||
|
jetMat = jetMat.Moved(positionVector)
|
||||||
|
jetMat = jetMat.ScaledXY(positionVector, pixel.V(flipped, 1))
|
||||||
|
jetMat = jetMat.Rotated(positionVector, radians)
|
||||||
|
|
||||||
|
jetX += velX
|
||||||
|
jetY += velY
|
||||||
|
|
||||||
|
// Camera
|
||||||
|
camVector.X += (positionVector.X - camVector.X) * 0.2
|
||||||
|
camVector.Y += (positionVector.Y - camVector.Y) * 0.2
|
||||||
|
|
||||||
|
if camVector.X > 25085 {
|
||||||
|
camVector.X = 25085
|
||||||
|
} else if camVector.X < -14843 {
|
||||||
|
camVector.X = -14843
|
||||||
|
}
|
||||||
|
|
||||||
|
if camVector.Y > 22500 {
|
||||||
|
camVector.Y = 22500
|
||||||
|
}
|
||||||
|
|
||||||
|
cam := pixel.IM.Moved(win.Bounds().Center().Sub(camVector))
|
||||||
|
|
||||||
|
canvas.SetMatrix(cam)
|
||||||
|
|
||||||
|
// Drawing to the screen
|
||||||
|
win.SetSmooth(true)
|
||||||
|
bg.Draw(canvas, pixel.IM.Moved(pixel.V(win.Bounds().Center().X, win.Bounds().Center().Y+766)).Scaled(pixel.ZV, 10))
|
||||||
|
txt.Draw(canvas, pixel.IM)
|
||||||
|
win.SetSmooth(false)
|
||||||
|
currentSprite.Draw(canvas, jetMat)
|
||||||
|
canvas.Draw(win, pixel.IM.Moved(win.Bounds().Center()))
|
||||||
|
win.Update()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
pixelgl.Run(run)
|
||||||
|
}
|
||||||
|
|
||||||
|
var pixelateFragShader = `
|
||||||
|
#version 330 core
|
||||||
|
#ifdef GL_ES
|
||||||
|
precision mediump float;
|
||||||
|
precision mediump int;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
in vec4 Color;
|
||||||
|
in vec2 texcoords;
|
||||||
|
in vec2 glpos;
|
||||||
|
|
||||||
|
out vec4 fragColor;
|
||||||
|
|
||||||
|
uniform vec4 u_colormask;
|
||||||
|
uniform vec4 u_texbounds;
|
||||||
|
uniform sampler2D u_texture;
|
||||||
|
uniform float u_amount;
|
||||||
|
uniform vec2 u_mouse;
|
||||||
|
uniform vec2 u_resolution;
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
vec2 t = (texcoords - u_texbounds.xy) / u_texbounds.zw;
|
||||||
|
|
||||||
|
float d = 1.0 / u_amount;
|
||||||
|
float ar = u_resolution.x / u_resolution.y;
|
||||||
|
float u = floor( t.x / d ) * d;
|
||||||
|
d = ar / u_amount;
|
||||||
|
float v = floor( t.y / d ) * d;
|
||||||
|
fragColor = texture( u_texture, vec2( u, v ) );
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
/*
|
||||||
|
//fragColor = vec4(1.0,0.0,0.0,1.0);
|
||||||
|
// float d = 1.0 / u_amount;
|
||||||
|
// float ar = u_resolution.x / u_resolution.y;
|
||||||
|
// float u = floor( texcoords.x / d ) * d;
|
||||||
|
// d = ar / u_amount;
|
||||||
|
// float v = floor( texcoords.y / d ) * d;
|
||||||
|
// fragColor = texture( u_texture, vec2( u, v ) );
|
||||||
|
|
||||||
|
// vec2 p = t.st;
|
||||||
|
// p.x -= mod(t.x / glpos.x, t.x / glpos.x + 0.1);
|
||||||
|
// p.y -= mod(t.y / glpos.y, t.y / glpos.y + 0.1);
|
||||||
|
|
||||||
|
// fragColor = texture(u_texture, p).rgba;
|
||||||
|
*/
|
||||||
|
// varying vec2 vUv;
|
||||||
|
// uniform sampler2D tInput;
|
||||||
|
// uniform vec2 resolution;
|
||||||
|
// uniform float amount;
|
||||||
|
|
||||||
|
// void main() {
|
||||||
|
|
||||||
|
// float d = 1.0 / amount;
|
||||||
|
// float ar = resolution.x / resolution.y;
|
||||||
|
// float u = floor( vUv.x / d ) * d;
|
||||||
|
// d = ar / amount;
|
||||||
|
// float v = floor( vUv.y / d ) * d;
|
||||||
|
// gl_FragColor = texture2D( tInput, vec2( u, v ) );
|
||||||
|
|
||||||
|
// }
|
After Width: | Height: | Size: 243 B |
After Width: | Height: | Size: 106 KiB |
After Width: | Height: | Size: 2.7 MiB |
|
@ -0,0 +1,7 @@
|
||||||
|
# Go Jetpack
|
||||||
|
by [Branson Camp](https://github.com/bcamp1) using [Pixel](https://github.com/faiface/pixel)
|
||||||
|
|
||||||
|
Welcome to Go-Jetpack, where you explore the skies using WASD or Arrow Keys.
|
||||||
|
This example showcases most of the fundamental pixel elements described in the [Pixel Wiki](https://github.com/faiface/pixel/wiki)
|
||||||
|
|
||||||
|

|
After Width: | Height: | Size: 295 B |
After Width: | Height: | Size: 314 B |
|
@ -0,0 +1,451 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"image"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/go-gl/mathgl/mgl32"
|
||||||
|
|
||||||
|
_ "image/png"
|
||||||
|
|
||||||
|
"github.com/faiface/pixel"
|
||||||
|
"github.com/faiface/pixel/pixelgl"
|
||||||
|
"github.com/faiface/pixel/text"
|
||||||
|
"github.com/golang/freetype/truetype"
|
||||||
|
"golang.org/x/image/colornames"
|
||||||
|
)
|
||||||
|
|
||||||
|
// InstallShader ...
|
||||||
|
func InstallShader(w *pixelgl.Window, uAmount *float32, uResolution, uMouse *mgl32.Vec2) {
|
||||||
|
wc := w.GetCanvas()
|
||||||
|
wc.BindUniform("u_resolution", uResolution)
|
||||||
|
wc.BindUniform("u_mouse", uMouse)
|
||||||
|
wc.BindUniform("u_amount", uAmount)
|
||||||
|
wc.SetFragmentShader(toonFragShader)
|
||||||
|
wc.UpdateShader()
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadSprite(path string) (pixel.Sprite, error) {
|
||||||
|
pic, err := loadPicture(path)
|
||||||
|
if err != nil {
|
||||||
|
return *pixel.NewSprite(pic, pic.Bounds()), err
|
||||||
|
}
|
||||||
|
sprite := pixel.NewSprite(pic, pic.Bounds())
|
||||||
|
return *sprite, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadTTF(path string, size float64, origin pixel.Vec) *text.Text {
|
||||||
|
file, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
bytes, err := ioutil.ReadAll(file)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
font, err := truetype.Parse(bytes)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
face := truetype.NewFace(font, &truetype.Options{
|
||||||
|
Size: size,
|
||||||
|
GlyphCacheEntries: 1,
|
||||||
|
})
|
||||||
|
|
||||||
|
atlas := text.NewAtlas(face, text.ASCII)
|
||||||
|
|
||||||
|
txt := text.New(origin, atlas)
|
||||||
|
|
||||||
|
return txt
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func run() {
|
||||||
|
// Set up window configs
|
||||||
|
cfg := pixelgl.WindowConfig{ // Default: 1024 x 768
|
||||||
|
Title: "Golang Jetpack!",
|
||||||
|
Bounds: pixel.R(0, 0, 1024, 768),
|
||||||
|
VSync: true,
|
||||||
|
}
|
||||||
|
win, err := pixelgl.NewWindow(cfg)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Importantr variables
|
||||||
|
var jetX, jetY, velX, velY, radians float64
|
||||||
|
flipped := 1.0
|
||||||
|
jetpackOn := false
|
||||||
|
gravity := 0.6 // Default: 0.004
|
||||||
|
jetAcc := 0.9 // Default: 0.008
|
||||||
|
tilt := 0.01 // Default: 0.001
|
||||||
|
whichOn := false
|
||||||
|
onNumber := 0
|
||||||
|
jetpackOffName := "jetpack.png"
|
||||||
|
jetpackOn1Name := "jetpack-on.png"
|
||||||
|
jetpackOn2Name := "jetpack-on2.png"
|
||||||
|
camVector := win.Bounds().Center()
|
||||||
|
|
||||||
|
var uAmount float32
|
||||||
|
var uMouse, uResolution mgl32.Vec2
|
||||||
|
|
||||||
|
InstallShader(win, &uAmount, &uResolution, &uMouse)
|
||||||
|
|
||||||
|
bg, _ := loadSprite("sky.png")
|
||||||
|
|
||||||
|
// Jetpack - Rendering
|
||||||
|
jetpackOff, err := loadSprite(jetpackOffName)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
jetpackOn1, err := loadSprite(jetpackOn1Name)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
jetpackOn2, err := loadSprite(jetpackOn2Name)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tutorial Text
|
||||||
|
txt := loadTTF("intuitive.ttf", 50, pixel.V(win.Bounds().Center().X-450, win.Bounds().Center().Y-200))
|
||||||
|
fmt.Fprintf(txt, "Explore the Skies with WASD or Arrow Keys!")
|
||||||
|
|
||||||
|
currentSprite := jetpackOff
|
||||||
|
|
||||||
|
canvas := pixelgl.NewCanvas(win.Bounds())
|
||||||
|
uResolution[0] = float32(win.Bounds().W())
|
||||||
|
uResolution[1] = float32(win.Bounds().H())
|
||||||
|
uAmount = 300.0
|
||||||
|
// Game Loop
|
||||||
|
for !win.Closed() {
|
||||||
|
|
||||||
|
mpos := win.MousePosition()
|
||||||
|
uMouse[0] = float32(mpos.X)
|
||||||
|
uMouse[1] = float32(mpos.Y)
|
||||||
|
win.SetTitle(fmt.Sprint(uAmount))
|
||||||
|
win.Clear(colornames.Blue)
|
||||||
|
canvas.Clear(colornames.Green)
|
||||||
|
|
||||||
|
// Jetpack - Controls
|
||||||
|
jetpackOn = win.Pressed(pixelgl.KeyUp) || win.Pressed(pixelgl.KeyW)
|
||||||
|
|
||||||
|
if win.Pressed(pixelgl.KeyRight) || win.Pressed(pixelgl.KeyD) {
|
||||||
|
jetpackOn = true
|
||||||
|
flipped = -1
|
||||||
|
radians -= tilt
|
||||||
|
velX += tilt * 30
|
||||||
|
} else if win.Pressed(pixelgl.KeyLeft) || win.Pressed(pixelgl.KeyA) {
|
||||||
|
jetpackOn = true
|
||||||
|
flipped = 1
|
||||||
|
radians += tilt
|
||||||
|
velX -= tilt * 30
|
||||||
|
} else {
|
||||||
|
if velX < 0 {
|
||||||
|
radians -= tilt / 3
|
||||||
|
velX += tilt * 10
|
||||||
|
} else if velX > 0 {
|
||||||
|
radians += tilt / 3
|
||||||
|
velX -= tilt * 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if jetY < 0 {
|
||||||
|
jetY = 0
|
||||||
|
velY = -0.3 * velY
|
||||||
|
}
|
||||||
|
|
||||||
|
if jetpackOn {
|
||||||
|
velY += jetAcc
|
||||||
|
whichOn = !whichOn
|
||||||
|
onNumber++
|
||||||
|
if onNumber == 5 { // every 5 frames, toggle anijetMation
|
||||||
|
onNumber = 0
|
||||||
|
if whichOn {
|
||||||
|
currentSprite = jetpackOn1
|
||||||
|
} else {
|
||||||
|
currentSprite = jetpackOn2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
currentSprite = jetpackOff
|
||||||
|
velY -= gravity
|
||||||
|
}
|
||||||
|
|
||||||
|
if win.Pressed(pixelgl.KeyEqual) {
|
||||||
|
uAmount += 10
|
||||||
|
}
|
||||||
|
if win.Pressed(pixelgl.KeyMinus) {
|
||||||
|
uAmount -= 10
|
||||||
|
}
|
||||||
|
|
||||||
|
positionVector := pixel.V(win.Bounds().Center().X+jetX, win.Bounds().Center().Y+jetY-372)
|
||||||
|
jetMat := pixel.IM
|
||||||
|
jetMat = jetMat.Scaled(pixel.ZV, 4)
|
||||||
|
jetMat = jetMat.Moved(positionVector)
|
||||||
|
jetMat = jetMat.ScaledXY(positionVector, pixel.V(flipped, 1))
|
||||||
|
jetMat = jetMat.Rotated(positionVector, radians)
|
||||||
|
|
||||||
|
jetX += velX
|
||||||
|
jetY += velY
|
||||||
|
|
||||||
|
// Camera
|
||||||
|
camVector.X += (positionVector.X - camVector.X) * 0.2
|
||||||
|
camVector.Y += (positionVector.Y - camVector.Y) * 0.2
|
||||||
|
|
||||||
|
if camVector.X > 25085 {
|
||||||
|
camVector.X = 25085
|
||||||
|
} else if camVector.X < -14843 {
|
||||||
|
camVector.X = -14843
|
||||||
|
}
|
||||||
|
|
||||||
|
if camVector.Y > 22500 {
|
||||||
|
camVector.Y = 22500
|
||||||
|
}
|
||||||
|
|
||||||
|
cam := pixel.IM.Moved(win.Bounds().Center().Sub(camVector))
|
||||||
|
|
||||||
|
canvas.SetMatrix(cam)
|
||||||
|
|
||||||
|
// Drawing to the screen
|
||||||
|
win.SetSmooth(true)
|
||||||
|
bg.Draw(canvas, pixel.IM.Moved(pixel.V(win.Bounds().Center().X, win.Bounds().Center().Y+766)).Scaled(pixel.ZV, 10))
|
||||||
|
txt.Draw(canvas, pixel.IM)
|
||||||
|
win.SetSmooth(false)
|
||||||
|
currentSprite.Draw(canvas, jetMat)
|
||||||
|
canvas.Draw(win, pixel.IM.Moved(win.Bounds().Center()))
|
||||||
|
win.Update()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
pixelgl.Run(run)
|
||||||
|
}
|
||||||
|
|
||||||
|
var toonFragShader = `
|
||||||
|
#version 330 core
|
||||||
|
|
||||||
|
in vec4 Color;
|
||||||
|
in vec2 texcoords;
|
||||||
|
|
||||||
|
out vec4 fragColor;
|
||||||
|
|
||||||
|
uniform vec4 u_colormask;
|
||||||
|
uniform vec4 u_texbounds;
|
||||||
|
uniform sampler2D u_texture;
|
||||||
|
uniform float u_amount;
|
||||||
|
uniform vec2 u_mouse;
|
||||||
|
uniform vec2 u_resolution;
|
||||||
|
|
||||||
|
#define HueLevCount 6
|
||||||
|
#define SatLevCount 7
|
||||||
|
#define ValLevCount 4
|
||||||
|
|
||||||
|
float HueLevels[HueLevCount];
|
||||||
|
float SatLevels[SatLevCount];
|
||||||
|
float ValLevels[ValLevCount];
|
||||||
|
|
||||||
|
vec3 RGBtoHSV( float r, float g, float b) {
|
||||||
|
float minv, maxv, delta;
|
||||||
|
vec3 res;
|
||||||
|
|
||||||
|
minv = min(min(r, g), b);
|
||||||
|
maxv = max(max(r, g), b);
|
||||||
|
res.z = maxv; // v
|
||||||
|
|
||||||
|
delta = maxv - minv;
|
||||||
|
|
||||||
|
if( maxv != 0.0 )
|
||||||
|
res.y = delta / maxv; // s
|
||||||
|
else {
|
||||||
|
// r = g = b = 0 // s = 0, v is undefined
|
||||||
|
res.y = 0.0;
|
||||||
|
res.x = -1.0;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( r == maxv )
|
||||||
|
res.x = ( g - b ) / delta; // between yellow & magenta
|
||||||
|
else if( g == maxv )
|
||||||
|
res.x = 2.0 + ( b - r ) / delta; // between cyan & yellow
|
||||||
|
else
|
||||||
|
res.x = 4.0 + ( r - g ) / delta; // between magenta & cyan
|
||||||
|
|
||||||
|
res.x = res.x * 60.0; // degrees
|
||||||
|
if( res.x < 0.0 )
|
||||||
|
res.x = res.x + 360.0;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 HSVtoRGB(float h, float s, float v ) {
|
||||||
|
int i;
|
||||||
|
float f, p, q, t;
|
||||||
|
vec3 res;
|
||||||
|
|
||||||
|
if( s == 0.0 ) {
|
||||||
|
// achromatic (grey)
|
||||||
|
res.x = v;
|
||||||
|
res.y = v;
|
||||||
|
res.z = v;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
h /= 60.0; // sector 0 to 5
|
||||||
|
i = int(floor( h ));
|
||||||
|
f = h - float(i); // factorial part of h
|
||||||
|
p = v * ( 1.0 - s );
|
||||||
|
q = v * ( 1.0 - s * f );
|
||||||
|
t = v * ( 1.0 - s * ( 1.0 - f ) );
|
||||||
|
|
||||||
|
if (i==0) {
|
||||||
|
res.x = v;
|
||||||
|
res.y = t;
|
||||||
|
res.z = p;
|
||||||
|
} else if (i==1) {
|
||||||
|
res.x = q;
|
||||||
|
res.y = v;
|
||||||
|
res.z = p;
|
||||||
|
} else if (i==2) {
|
||||||
|
res.x = p;
|
||||||
|
res.y = v;
|
||||||
|
res.z = t;
|
||||||
|
} else if (i==3) {
|
||||||
|
res.x = p;
|
||||||
|
res.y = q;
|
||||||
|
res.z = v;
|
||||||
|
} else if (i==4) {
|
||||||
|
res.x = t;
|
||||||
|
res.y = p;
|
||||||
|
res.z = v;
|
||||||
|
} else if (i==5) {
|
||||||
|
res.x = v;
|
||||||
|
res.y = p;
|
||||||
|
res.z = q;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
float nearestLevel(float col, int mode) {
|
||||||
|
|
||||||
|
if (mode==0) {
|
||||||
|
for (int i =0; i<HueLevCount-1; i++ ) {
|
||||||
|
if (col >= HueLevels[i] && col <= HueLevels[i+1]) {
|
||||||
|
return HueLevels[i+1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode==1) {
|
||||||
|
for (int i =0; i<SatLevCount-1; i++ ) {
|
||||||
|
if (col >= SatLevels[i] && col <= SatLevels[i+1]) {
|
||||||
|
return SatLevels[i+1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (mode==2) {
|
||||||
|
for (int i =0; i<ValLevCount-1; i++ ) {
|
||||||
|
if (col >= ValLevels[i] && col <= ValLevels[i+1]) {
|
||||||
|
return ValLevels[i+1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// averaged pixel intensity from 3 color channels
|
||||||
|
float avg_intensity(vec4 pix) {
|
||||||
|
return (pix.r + pix.g + pix.b)/3.;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 get_pixel(vec2 coords, float dx, float dy) {
|
||||||
|
return texture(u_texture, coords + vec2(dx, dy));
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns pixel color
|
||||||
|
float IsEdge(in vec2 coords){
|
||||||
|
float dxtex = 1.0 / u_resolution.x ;
|
||||||
|
float dytex = 1.0 / u_resolution.y ;
|
||||||
|
|
||||||
|
float pix[9];
|
||||||
|
|
||||||
|
int k = -1;
|
||||||
|
float delta;
|
||||||
|
|
||||||
|
// read neighboring pixel intensities
|
||||||
|
float pix0 = avg_intensity(get_pixel(coords,-1.0*dxtex, -1.0*dytex));
|
||||||
|
float pix1 = avg_intensity(get_pixel(coords,-1.0*dxtex, 0.0*dytex));
|
||||||
|
float pix2 = avg_intensity(get_pixel(coords,-1.0*dxtex, 1.0*dytex));
|
||||||
|
float pix3 = avg_intensity(get_pixel(coords,0.0*dxtex, -1.0*dytex));
|
||||||
|
float pix4 = avg_intensity(get_pixel(coords,0.0*dxtex, 0.0*dytex));
|
||||||
|
float pix5 = avg_intensity(get_pixel(coords,0.0*dxtex, 1.0*dytex));
|
||||||
|
float pix6 = avg_intensity(get_pixel(coords,1.0*dxtex, -1.0*dytex));
|
||||||
|
float pix7 = avg_intensity(get_pixel(coords,1.0*dxtex, 0.0*dytex));
|
||||||
|
float pix8 = avg_intensity(get_pixel(coords,1.0*dxtex, 1.0*dytex));
|
||||||
|
// average color differences around neighboring pixels
|
||||||
|
delta = (abs(pix1-pix7)+
|
||||||
|
abs(pix5-pix3) +
|
||||||
|
abs(pix0-pix8)+
|
||||||
|
abs(pix2-pix6)
|
||||||
|
)/4.;
|
||||||
|
|
||||||
|
return clamp(5.5*delta,0.0,1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
vec2 uv = (texcoords - u_texbounds.xy) / u_texbounds.zw;
|
||||||
|
|
||||||
|
HueLevels[0] = 0.0;
|
||||||
|
HueLevels[1] = 80.0;
|
||||||
|
HueLevels[2] = 160.0;
|
||||||
|
HueLevels[3] = 240.0;
|
||||||
|
HueLevels[4] = 320.0;
|
||||||
|
HueLevels[5] = 360.0;
|
||||||
|
|
||||||
|
SatLevels[0] = 0.0;
|
||||||
|
SatLevels[1] = 0.1;
|
||||||
|
SatLevels[2] = 0.3;
|
||||||
|
SatLevels[3] = 0.5;
|
||||||
|
SatLevels[4] = 0.6;
|
||||||
|
SatLevels[5] = 0.8;
|
||||||
|
SatLevels[6] = 1.0;
|
||||||
|
|
||||||
|
ValLevels[0] = 0.0;
|
||||||
|
ValLevels[1] = 0.3;
|
||||||
|
ValLevels[2] = 0.6;
|
||||||
|
ValLevels[3] = 1.0;
|
||||||
|
|
||||||
|
vec4 colorOrg = texture( u_texture, uv );
|
||||||
|
vec3 vHSV = RGBtoHSV(colorOrg.r,colorOrg.g,colorOrg.b);
|
||||||
|
vHSV.x = nearestLevel(vHSV.x, 0);
|
||||||
|
vHSV.y = nearestLevel(vHSV.y, 1);
|
||||||
|
vHSV.z = nearestLevel(vHSV.z, 2);
|
||||||
|
float edg = IsEdge(uv);
|
||||||
|
vec3 vRGB = (edg >= 0.3)? vec3(0.0,0.0,0.0):HSVtoRGB(vHSV.x,vHSV.y,vHSV.z);
|
||||||
|
fragColor = vec4(vRGB.x,vRGB.y,vRGB.z,1.0);
|
||||||
|
}
|
||||||
|
`
|
After Width: | Height: | Size: 243 B |
After Width: | Height: | Size: 106 KiB |
After Width: | Height: | Size: 2.7 MiB |
|
@ -0,0 +1,13 @@
|
||||||
|
# Isometric view basics
|
||||||
|
|
||||||
|
Created by [Sergio Vera](https://github.com/svera).
|
||||||
|
|
||||||
|
Isometric view is a display method used to create an illusion of 3D for an otherwise 2D game - sometimes referred to as pseudo 3D or 2.5D.
|
||||||
|
|
||||||
|
Implementing an isometric view can be done in many ways, but for the sake of simplicity we'll implement a tile-based approach, which is the most efficient and widely used method.
|
||||||
|
|
||||||
|
In the tile-based approach, each visual element is broken down into smaller pieces, called tiles, of a standard size. These tiles will be arranged to form the game world according to pre-determined level data - usually a 2D array.
|
||||||
|
|
||||||
|
For a detailed explanation about the maths behind this, read [http://clintbellanger.net/articles/isometric_math/](http://clintbellanger.net/articles/isometric_math/).
|
||||||
|
|
||||||
|

|
After Width: | Height: | Size: 26 KiB |
|
@ -0,0 +1,161 @@
|
||||||
|
#version 330-core
|
||||||
|
|
||||||
|
// Using a sobel filter to create a normal map and then applying simple lighting.
|
||||||
|
|
||||||
|
// This makes the darker areas less bumpy but I like it
|
||||||
|
#define USE_LINEAR_FOR_BUMPMAP
|
||||||
|
|
||||||
|
//#define SHOW_NORMAL_MAP
|
||||||
|
//#define SHOW_ALBEDO
|
||||||
|
|
||||||
|
in vec2 texcoords;
|
||||||
|
|
||||||
|
uniform vec4 u_texbounds;
|
||||||
|
uniform sampler2D u_texture;
|
||||||
|
uniform vec2 u_resolution;
|
||||||
|
uniform float u_time;
|
||||||
|
uniform vec4 u_mouse;
|
||||||
|
|
||||||
|
out vec4 fragColor;
|
||||||
|
|
||||||
|
struct C_Sample
|
||||||
|
{
|
||||||
|
vec3 vAlbedo;
|
||||||
|
vec3 vNormal;
|
||||||
|
};
|
||||||
|
|
||||||
|
C_Sample SampleMaterial(const in vec2 uv, sampler2D sampler, const in vec2 vTextureSize, const in float fNormalScale)
|
||||||
|
{
|
||||||
|
C_Sample result;
|
||||||
|
|
||||||
|
vec2 vInvTextureSize = vec2(1.0) / vTextureSize;
|
||||||
|
|
||||||
|
vec3 cSampleNegXNegY = texture(sampler, uv + (vec2(-1.0, -1.0)) * vInvTextureSize.xy).rgb;
|
||||||
|
vec3 cSampleZerXNegY = texture(sampler, uv + (vec2( 0.0, -1.0)) * vInvTextureSize.xy).rgb;
|
||||||
|
vec3 cSamplePosXNegY = texture(sampler, uv + (vec2( 1.0, -1.0)) * vInvTextureSize.xy).rgb;
|
||||||
|
|
||||||
|
vec3 cSampleNegXZerY = texture(sampler, uv + (vec2(-1.0, 0.0)) * vInvTextureSize.xy).rgb;
|
||||||
|
vec3 cSampleZerXZerY = texture(sampler, uv + (vec2( 0.0, 0.0)) * vInvTextureSize.xy).rgb;
|
||||||
|
vec3 cSamplePosXZerY = texture(sampler, uv + (vec2( 1.0, 0.0)) * vInvTextureSize.xy).rgb;
|
||||||
|
|
||||||
|
vec3 cSampleNegXPosY = texture(sampler, uv + (vec2(-1.0, 1.0)) * vInvTextureSize.xy).rgb;
|
||||||
|
vec3 cSampleZerXPosY = texture(sampler, uv + (vec2( 0.0, 1.0)) * vInvTextureSize.xy).rgb;
|
||||||
|
vec3 cSamplePosXPosY = texture(sampler, uv + (vec2( 1.0, 1.0)) * vInvTextureSize.xy).rgb;
|
||||||
|
|
||||||
|
// convert to linear
|
||||||
|
vec3 cLSampleNegXNegY = cSampleNegXNegY * cSampleNegXNegY;
|
||||||
|
vec3 cLSampleZerXNegY = cSampleZerXNegY * cSampleZerXNegY;
|
||||||
|
vec3 cLSamplePosXNegY = cSamplePosXNegY * cSamplePosXNegY;
|
||||||
|
|
||||||
|
vec3 cLSampleNegXZerY = cSampleNegXZerY * cSampleNegXZerY;
|
||||||
|
vec3 cLSampleZerXZerY = cSampleZerXZerY * cSampleZerXZerY;
|
||||||
|
vec3 cLSamplePosXZerY = cSamplePosXZerY * cSamplePosXZerY;
|
||||||
|
|
||||||
|
vec3 cLSampleNegXPosY = cSampleNegXPosY * cSampleNegXPosY;
|
||||||
|
vec3 cLSampleZerXPosY = cSampleZerXPosY * cSampleZerXPosY;
|
||||||
|
vec3 cLSamplePosXPosY = cSamplePosXPosY * cSamplePosXPosY;
|
||||||
|
|
||||||
|
// Average samples to get albdeo colour
|
||||||
|
result.vAlbedo = ( cLSampleNegXNegY + cLSampleZerXNegY + cLSamplePosXNegY
|
||||||
|
+ cLSampleNegXZerY + cLSampleZerXZerY + cLSamplePosXZerY
|
||||||
|
+ cLSampleNegXPosY + cLSampleZerXPosY + cLSamplePosXPosY ) / 9.0;
|
||||||
|
|
||||||
|
vec3 vScale = vec3(0.3333);
|
||||||
|
|
||||||
|
#ifdef USE_LINEAR_FOR_BUMPMAP
|
||||||
|
|
||||||
|
float fSampleNegXNegY = dot(cLSampleNegXNegY, vScale);
|
||||||
|
float fSampleZerXNegY = dot(cLSampleZerXNegY, vScale);
|
||||||
|
float fSamplePosXNegY = dot(cLSamplePosXNegY, vScale);
|
||||||
|
|
||||||
|
float fSampleNegXZerY = dot(cLSampleNegXZerY, vScale);
|
||||||
|
float fSampleZerXZerY = dot(cLSampleZerXZerY, vScale);
|
||||||
|
float fSamplePosXZerY = dot(cLSamplePosXZerY, vScale);
|
||||||
|
|
||||||
|
float fSampleNegXPosY = dot(cLSampleNegXPosY, vScale);
|
||||||
|
float fSampleZerXPosY = dot(cLSampleZerXPosY, vScale);
|
||||||
|
float fSamplePosXPosY = dot(cLSamplePosXPosY, vScale);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
float fSampleNegXNegY = dot(cSampleNegXNegY, vScale);
|
||||||
|
float fSampleZerXNegY = dot(cSampleZerXNegY, vScale);
|
||||||
|
float fSamplePosXNegY = dot(cSamplePosXNegY, vScale);
|
||||||
|
|
||||||
|
float fSampleNegXZerY = dot(cSampleNegXZerY, vScale);
|
||||||
|
float fSampleZerXZerY = dot(cSampleZerXZerY, vScale);
|
||||||
|
float fSamplePosXZerY = dot(cSamplePosXZerY, vScale);
|
||||||
|
|
||||||
|
float fSampleNegXPosY = dot(cSampleNegXPosY, vScale);
|
||||||
|
float fSampleZerXPosY = dot(cSampleZerXPosY, vScale);
|
||||||
|
float fSamplePosXPosY = dot(cSamplePosXPosY, vScale);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Sobel operator - http://en.wikipedia.org/wiki/Sobel_operator
|
||||||
|
|
||||||
|
vec2 vEdge;
|
||||||
|
vEdge.x = (fSampleNegXNegY - fSamplePosXNegY) * 0.25
|
||||||
|
+ (fSampleNegXZerY - fSamplePosXZerY) * 0.5
|
||||||
|
+ (fSampleNegXPosY - fSamplePosXPosY) * 0.25;
|
||||||
|
|
||||||
|
vEdge.y = (fSampleNegXNegY - fSampleNegXPosY) * 0.25
|
||||||
|
+ (fSampleZerXNegY - fSampleZerXPosY) * 0.5
|
||||||
|
+ (fSamplePosXNegY - fSamplePosXPosY) * 0.25;
|
||||||
|
|
||||||
|
result.vNormal = normalize(vec3(vEdge * fNormalScale, 1.0));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
out vec4 fragColor;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec2 uv = fragCoord.xy / u_resolution.xy;
|
||||||
|
|
||||||
|
C_Sample materialSample;
|
||||||
|
|
||||||
|
float fNormalScale = 10.0;
|
||||||
|
materialSample = SampleMaterial( uv, u_texture, u_resolution.xy, fNormalScale );
|
||||||
|
|
||||||
|
// Random Lighting...
|
||||||
|
|
||||||
|
float fLightHeight = 0.2;
|
||||||
|
float fViewHeight = 2.0;
|
||||||
|
|
||||||
|
vec3 vSurfacePos = vec3(uv, 0.0);
|
||||||
|
|
||||||
|
vec3 vViewPos = vec3(0.5, 0.5, fViewHeight);
|
||||||
|
|
||||||
|
vec3 vLightPos = vec3( vec2(sin(u_time),cos(u_time)) * 0.25 + 0.5 , fLightHeight);
|
||||||
|
|
||||||
|
if( u_mouse.z > 0.0 )
|
||||||
|
{
|
||||||
|
vLightPos = vec3(u_mouse.xy / u_resolution.xy, fLightHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 vDirToView = normalize( vViewPos - vSurfacePos );
|
||||||
|
vec3 vDirToLight = normalize( vLightPos - vSurfacePos );
|
||||||
|
|
||||||
|
float fNDotL = clamp( dot(materialSample.vNormal, vDirToLight), 0.0, 1.0);
|
||||||
|
float fDiffuse = fNDotL;
|
||||||
|
|
||||||
|
vec3 vHalf = normalize( vDirToView + vDirToLight );
|
||||||
|
float fNDotH = clamp( dot(materialSample.vNormal, vHalf), 0.0, 1.0);
|
||||||
|
float fSpec = pow(fNDotH, 10.0) * fNDotL * 0.5;
|
||||||
|
|
||||||
|
vec3 vResult = materialSample.vAlbedo * fDiffuse + fSpec;
|
||||||
|
|
||||||
|
vResult = sqrt(vResult);
|
||||||
|
|
||||||
|
#ifdef SHOW_NORMAL_MAP
|
||||||
|
vResult = materialSample.vNormal * 0.5 + 0.5;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SHOW_ALBEDO
|
||||||
|
vResult = sqrt(materialSample.vAlbedo);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fragColor = vec4(vResult,1.0);
|
||||||
|
}
|
|
@ -0,0 +1,309 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-gl/mathgl/mgl32"
|
||||||
|
|
||||||
|
"github.com/faiface/pixel"
|
||||||
|
"github.com/faiface/pixel/pixelgl"
|
||||||
|
|
||||||
|
_ "image/png"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
windowWidth = 800
|
||||||
|
windowHeight = 800
|
||||||
|
// sprite tiles are squared, 64x64 size
|
||||||
|
tileSize = 64
|
||||||
|
f = 0 // floor identifier
|
||||||
|
w = 1 // wall identifier
|
||||||
|
)
|
||||||
|
|
||||||
|
var levelData = [][]uint{
|
||||||
|
{f, f, f, f, f, f}, // This row will be rendered in the lower left part of the screen (closer to the viewer)
|
||||||
|
{w, f, f, f, f, w},
|
||||||
|
{w, f, f, f, f, w},
|
||||||
|
{w, f, f, f, f, w},
|
||||||
|
{w, f, f, f, f, w},
|
||||||
|
{w, w, w, w, w, w}, // And this in the upper right
|
||||||
|
}
|
||||||
|
var win *pixelgl.Window
|
||||||
|
var canvas *pixelgl.Canvas
|
||||||
|
var offset = pixel.V(400, 325)
|
||||||
|
var floorTile, wallTile *pixel.Sprite
|
||||||
|
|
||||||
|
func installshader(c *pixelgl.Canvas, src string, uniformNameAndVar ...interface{}) {
|
||||||
|
c.SetFragmentShader(src)
|
||||||
|
for i := 0; i < len(uniformNameAndVar); i += 2 {
|
||||||
|
c.BindUniform(
|
||||||
|
uniformNameAndVar[i+0].(string),
|
||||||
|
uniformNameAndVar[i+1],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
c.UpdateShader()
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
func run() {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
cfg := pixelgl.WindowConfig{
|
||||||
|
Title: "Isometric demo",
|
||||||
|
Bounds: pixel.R(0, 0, windowWidth, windowHeight),
|
||||||
|
VSync: true,
|
||||||
|
}
|
||||||
|
win, err = pixelgl.NewWindow(cfg)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pic, err := loadPicture("castle.png")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
wallTile = pixel.NewSprite(pic, pixel.R(0, 448, tileSize, 512))
|
||||||
|
floorTile = pixel.NewSprite(pic, pixel.R(0, 128, tileSize, 192))
|
||||||
|
|
||||||
|
uResolution := mgl32.Vec2{float32(win.Bounds().W()), float32(win.Bounds().H())}
|
||||||
|
var uTime float32
|
||||||
|
var uMouse mgl32.Vec4
|
||||||
|
|
||||||
|
canvas = pixelgl.NewCanvas(win.Bounds())
|
||||||
|
wc := win.GetCanvas()
|
||||||
|
|
||||||
|
installshader(wc, embossFragmentShader,
|
||||||
|
"u_resolution", &uResolution,
|
||||||
|
"u_time", &uTime,
|
||||||
|
"u_mouse", &uMouse,
|
||||||
|
)
|
||||||
|
start := time.Now()
|
||||||
|
for !win.Closed() {
|
||||||
|
uTime = float32(time.Since(start).Seconds())
|
||||||
|
|
||||||
|
uMouse[0] = float32(win.MousePosition().X)
|
||||||
|
uMouse[1] = float32(win.MousePosition().Y)
|
||||||
|
if win.Pressed(pixelgl.MouseButton1) {
|
||||||
|
uMouse[2] = 1.0
|
||||||
|
} else {
|
||||||
|
uMouse[2] = 0.0
|
||||||
|
}
|
||||||
|
if win.Pressed(pixelgl.MouseButton2) {
|
||||||
|
uMouse[3] = 1.0
|
||||||
|
} else {
|
||||||
|
uMouse[3] = 0.0
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.Clear(pixel.RGBA{R: 0.09, G: 0.05, B: 0.09, A: 1.0})
|
||||||
|
depthSort()
|
||||||
|
canvas.Draw(win, pixel.IM.Moved(win.Bounds().Center()))
|
||||||
|
|
||||||
|
win.Update()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw level data tiles to window, from farthest to closest.
|
||||||
|
// In order to achieve the depth effect, we need to render tiles up to down, being lower
|
||||||
|
// closer to the viewer (see painter's algorithm). To do that, we need to process levelData in reverse order,
|
||||||
|
// so its first row is rendered last, as OpenGL considers its origin to be in the lower left corner of the display.
|
||||||
|
func depthSort() {
|
||||||
|
for x := len(levelData) - 1; x >= 0; x-- {
|
||||||
|
for y := len(levelData[x]) - 1; y >= 0; y-- {
|
||||||
|
isoCoords := cartesianToIso(pixel.V(float64(x), float64(y)))
|
||||||
|
mat := pixel.IM.Moved(offset.Add(isoCoords))
|
||||||
|
// Not really needed, just put to show bigger blocks
|
||||||
|
mat = mat.ScaledXY(win.Bounds().Center(), pixel.V(2, 2))
|
||||||
|
tileType := levelData[x][y]
|
||||||
|
if tileType == f {
|
||||||
|
floorTile.Draw(canvas, mat)
|
||||||
|
} else {
|
||||||
|
wallTile.Draw(canvas, mat)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cartesianToIso(pt pixel.Vec) pixel.Vec {
|
||||||
|
return pixel.V((pt.X-pt.Y)*(tileSize/2), (pt.X+pt.Y)*(tileSize/4))
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
pixelgl.Run(run)
|
||||||
|
}
|
||||||
|
|
||||||
|
var embossFragmentShader = `
|
||||||
|
#version 330 core
|
||||||
|
|
||||||
|
// Using a sobel filter to create a normal map and then applying simple lighting.
|
||||||
|
|
||||||
|
// This makes the darker areas less bumpy but I like it
|
||||||
|
#define USE_LINEAR_FOR_BUMPMAP
|
||||||
|
|
||||||
|
//#define SHOW_NORMAL_MAP
|
||||||
|
//#define SHOW_ALBEDO
|
||||||
|
|
||||||
|
in vec2 texcoords;
|
||||||
|
|
||||||
|
uniform vec4 u_texbounds;
|
||||||
|
uniform sampler2D u_texture;
|
||||||
|
uniform vec2 u_resolution;
|
||||||
|
uniform float u_time;
|
||||||
|
uniform vec4 u_mouse;
|
||||||
|
|
||||||
|
out vec4 fragColor;
|
||||||
|
|
||||||
|
struct C_Sample
|
||||||
|
{
|
||||||
|
vec3 vAlbedo;
|
||||||
|
vec3 vNormal;
|
||||||
|
};
|
||||||
|
|
||||||
|
C_Sample SampleMaterial(const in vec2 uv, sampler2D sampler, const in vec2 vTextureSize, const in float fNormalScale)
|
||||||
|
{
|
||||||
|
C_Sample result;
|
||||||
|
|
||||||
|
vec2 vInvTextureSize = vec2(1.0) / vTextureSize;
|
||||||
|
|
||||||
|
vec3 cSampleNegXNegY = texture(sampler, uv + (vec2(-1.0, -1.0)) * vInvTextureSize.xy).rgb;
|
||||||
|
vec3 cSampleZerXNegY = texture(sampler, uv + (vec2( 0.0, -1.0)) * vInvTextureSize.xy).rgb;
|
||||||
|
vec3 cSamplePosXNegY = texture(sampler, uv + (vec2( 1.0, -1.0)) * vInvTextureSize.xy).rgb;
|
||||||
|
|
||||||
|
vec3 cSampleNegXZerY = texture(sampler, uv + (vec2(-1.0, 0.0)) * vInvTextureSize.xy).rgb;
|
||||||
|
vec3 cSampleZerXZerY = texture(sampler, uv + (vec2( 0.0, 0.0)) * vInvTextureSize.xy).rgb;
|
||||||
|
vec3 cSamplePosXZerY = texture(sampler, uv + (vec2( 1.0, 0.0)) * vInvTextureSize.xy).rgb;
|
||||||
|
|
||||||
|
vec3 cSampleNegXPosY = texture(sampler, uv + (vec2(-1.0, 1.0)) * vInvTextureSize.xy).rgb;
|
||||||
|
vec3 cSampleZerXPosY = texture(sampler, uv + (vec2( 0.0, 1.0)) * vInvTextureSize.xy).rgb;
|
||||||
|
vec3 cSamplePosXPosY = texture(sampler, uv + (vec2( 1.0, 1.0)) * vInvTextureSize.xy).rgb;
|
||||||
|
|
||||||
|
// convert to linear
|
||||||
|
vec3 cLSampleNegXNegY = cSampleNegXNegY * cSampleNegXNegY;
|
||||||
|
vec3 cLSampleZerXNegY = cSampleZerXNegY * cSampleZerXNegY;
|
||||||
|
vec3 cLSamplePosXNegY = cSamplePosXNegY * cSamplePosXNegY;
|
||||||
|
|
||||||
|
vec3 cLSampleNegXZerY = cSampleNegXZerY * cSampleNegXZerY;
|
||||||
|
vec3 cLSampleZerXZerY = cSampleZerXZerY * cSampleZerXZerY;
|
||||||
|
vec3 cLSamplePosXZerY = cSamplePosXZerY * cSamplePosXZerY;
|
||||||
|
|
||||||
|
vec3 cLSampleNegXPosY = cSampleNegXPosY * cSampleNegXPosY;
|
||||||
|
vec3 cLSampleZerXPosY = cSampleZerXPosY * cSampleZerXPosY;
|
||||||
|
vec3 cLSamplePosXPosY = cSamplePosXPosY * cSamplePosXPosY;
|
||||||
|
|
||||||
|
// Average samples to get albdeo colour
|
||||||
|
result.vAlbedo = ( cLSampleNegXNegY + cLSampleZerXNegY + cLSamplePosXNegY
|
||||||
|
+ cLSampleNegXZerY + cLSampleZerXZerY + cLSamplePosXZerY
|
||||||
|
+ cLSampleNegXPosY + cLSampleZerXPosY + cLSamplePosXPosY ) / 9.0;
|
||||||
|
|
||||||
|
vec3 vScale = vec3(0.3333);
|
||||||
|
|
||||||
|
#ifdef USE_LINEAR_FOR_BUMPMAP
|
||||||
|
|
||||||
|
float fSampleNegXNegY = dot(cLSampleNegXNegY, vScale);
|
||||||
|
float fSampleZerXNegY = dot(cLSampleZerXNegY, vScale);
|
||||||
|
float fSamplePosXNegY = dot(cLSamplePosXNegY, vScale);
|
||||||
|
|
||||||
|
float fSampleNegXZerY = dot(cLSampleNegXZerY, vScale);
|
||||||
|
float fSampleZerXZerY = dot(cLSampleZerXZerY, vScale);
|
||||||
|
float fSamplePosXZerY = dot(cLSamplePosXZerY, vScale);
|
||||||
|
|
||||||
|
float fSampleNegXPosY = dot(cLSampleNegXPosY, vScale);
|
||||||
|
float fSampleZerXPosY = dot(cLSampleZerXPosY, vScale);
|
||||||
|
float fSamplePosXPosY = dot(cLSamplePosXPosY, vScale);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
float fSampleNegXNegY = dot(cSampleNegXNegY, vScale);
|
||||||
|
float fSampleZerXNegY = dot(cSampleZerXNegY, vScale);
|
||||||
|
float fSamplePosXNegY = dot(cSamplePosXNegY, vScale);
|
||||||
|
|
||||||
|
float fSampleNegXZerY = dot(cSampleNegXZerY, vScale);
|
||||||
|
float fSampleZerXZerY = dot(cSampleZerXZerY, vScale);
|
||||||
|
float fSamplePosXZerY = dot(cSamplePosXZerY, vScale);
|
||||||
|
|
||||||
|
float fSampleNegXPosY = dot(cSampleNegXPosY, vScale);
|
||||||
|
float fSampleZerXPosY = dot(cSampleZerXPosY, vScale);
|
||||||
|
float fSamplePosXPosY = dot(cSamplePosXPosY, vScale);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Sobel operator - http://en.wikipedia.org/wiki/Sobel_operator
|
||||||
|
|
||||||
|
vec2 vEdge;
|
||||||
|
vEdge.x = (fSampleNegXNegY - fSamplePosXNegY) * 0.25
|
||||||
|
+ (fSampleNegXZerY - fSamplePosXZerY) * 0.5
|
||||||
|
+ (fSampleNegXPosY - fSamplePosXPosY) * 0.25;
|
||||||
|
|
||||||
|
vEdge.y = (fSampleNegXNegY - fSampleNegXPosY) * 0.25
|
||||||
|
+ (fSampleZerXNegY - fSampleZerXPosY) * 0.5
|
||||||
|
+ (fSamplePosXNegY - fSamplePosXPosY) * 0.25;
|
||||||
|
|
||||||
|
result.vNormal = normalize(vec3(vEdge * fNormalScale, 1.0));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec2 uv = gl_FragCoord.xy / u_resolution.xy;
|
||||||
|
|
||||||
|
C_Sample materialSample;
|
||||||
|
|
||||||
|
float fNormalScale = 5.0;
|
||||||
|
materialSample = SampleMaterial( uv, u_texture, u_resolution.xy, fNormalScale );
|
||||||
|
|
||||||
|
// Random Lighting...
|
||||||
|
|
||||||
|
float fLightHeight = 0.2;
|
||||||
|
float fViewHeight = 1.0;
|
||||||
|
|
||||||
|
vec3 vSurfacePos = vec3(uv, 0.0);
|
||||||
|
|
||||||
|
vec3 vViewPos = vec3(0.5, 0.5, fViewHeight);
|
||||||
|
|
||||||
|
vec3 vLightPos = vec3( vec2(sin(u_time),cos(u_time)) * 0.25 + 0.5 , fLightHeight);
|
||||||
|
|
||||||
|
if( u_mouse.z > 0.0 )
|
||||||
|
{
|
||||||
|
vLightPos = vec3(u_mouse.xy / u_resolution.xy, fLightHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 vDirToView = normalize( vViewPos - vSurfacePos );
|
||||||
|
vec3 vDirToLight = normalize( vLightPos - vSurfacePos );
|
||||||
|
|
||||||
|
float fNDotL = clamp( dot(materialSample.vNormal, vDirToLight), 0.0, 1.0);
|
||||||
|
float fDiffuse = fNDotL;
|
||||||
|
|
||||||
|
vec3 vHalf = normalize( vDirToView + vDirToLight );
|
||||||
|
float fNDotH = clamp( dot(materialSample.vNormal, vHalf), 0.0, 1.0);
|
||||||
|
float fSpec = pow(fNDotH, 10.0) * fNDotL * 0.5;
|
||||||
|
|
||||||
|
vec3 vResult = materialSample.vAlbedo * fDiffuse + fSpec;
|
||||||
|
|
||||||
|
vResult = sqrt(vResult);
|
||||||
|
|
||||||
|
#ifdef SHOW_NORMAL_MAP
|
||||||
|
vResult = materialSample.vNormal * 0.5 + 0.5;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SHOW_ALBEDO
|
||||||
|
vResult = sqrt(materialSample.vAlbedo);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fragColor = vec4(vResult,1.0);
|
||||||
|
}
|
||||||
|
`
|
After Width: | Height: | Size: 126 KiB |
|
@ -0,0 +1,22 @@
|
||||||
|
# raycaster
|
||||||
|
|
||||||
|
A raycaster made by [Peter Hellberg](https://github.com/peterhellberg/) as part of his [pixel-experiments](https://github.com/peterhellberg/pixel-experiments).
|
||||||
|
|
||||||
|
Based on Lode’s article on [raycasting](http://lodev.org/cgtutor/raycasting.html).
|
||||||
|
|
||||||
|
## Controls
|
||||||
|
|
||||||
|
WASD for strafing and arrow keys for rotation.
|
||||||
|
|
||||||
|
Place blocks using the number keys.
|
||||||
|
|
||||||
|
## Screenshots
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
- https://github.com/peterhellberg/pixel-experiments/tree/master/raycaster
|
||||||
|
- https://gist.github.com/peterhellberg/835eccabf95800555120cc8f0c9e16c2
|
|
@ -0,0 +1,63 @@
|
||||||
|
#version 330 core
|
||||||
|
|
||||||
|
in vec2 texcoords;
|
||||||
|
|
||||||
|
uniform vec4 u_texbounds;
|
||||||
|
uniform sampler2D u_texture;
|
||||||
|
uniform vec2 u_resolution;
|
||||||
|
uniform float u_amount;
|
||||||
|
uniform float u_time;
|
||||||
|
uniform vec2 u_mouse;
|
||||||
|
|
||||||
|
out vec4 fragColor;
|
||||||
|
|
||||||
|
#define FXAA_REDUCE_MIN (1.0/128.0)
|
||||||
|
#define FXAA_REDUCE_MUL (1.0/8.0)
|
||||||
|
#define FXAA_SPAN_MAX 8.0
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec2 uv = (texcoords - u_texbounds.xy) / u_texbounds.zw;
|
||||||
|
vec2 res = 1. / u_resolution;
|
||||||
|
|
||||||
|
vec3 rgbNW = texture( u_texture, ( uv.xy + vec2( -1.0, -1.0 ) * res ) ).xyz;
|
||||||
|
vec3 rgbNE = texture( u_texture, ( uv.xy + vec2( 1.0, -1.0 ) * res ) ).xyz;
|
||||||
|
vec3 rgbSW = texture( u_texture, ( uv.xy + vec2( -1.0, 1.0 ) * res ) ).xyz;
|
||||||
|
vec3 rgbSE = texture( u_texture, ( uv.xy + vec2( 1.0, 1.0 ) * res ) ).xyz;
|
||||||
|
vec4 rgbaM = texture( u_texture, uv.xy * res );
|
||||||
|
vec3 rgbM = rgbaM.xyz;
|
||||||
|
vec3 luma = vec3( 0.299, 0.587, 0.114 );
|
||||||
|
|
||||||
|
float lumaNW = dot( rgbNW, luma );
|
||||||
|
float lumaNE = dot( rgbNE, luma );
|
||||||
|
float lumaSW = dot( rgbSW, luma );
|
||||||
|
float lumaSE = dot( rgbSE, luma );
|
||||||
|
float lumaM = dot( rgbM, luma );
|
||||||
|
float lumaMin = min( lumaM, min( min( lumaNW, lumaNE ), min( lumaSW, lumaSE ) ) );
|
||||||
|
float lumaMax = max( lumaM, max( max( lumaNW, lumaNE) , max( lumaSW, lumaSE ) ) );
|
||||||
|
|
||||||
|
vec2 dir;
|
||||||
|
dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
|
||||||
|
dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));
|
||||||
|
|
||||||
|
float dirReduce = max( ( lumaNW + lumaNE + lumaSW + lumaSE ) * ( 0.25 * FXAA_REDUCE_MUL ), FXAA_REDUCE_MIN );
|
||||||
|
|
||||||
|
float rcpDirMin = 1.0 / ( min( abs( dir.x ), abs( dir.y ) ) + dirReduce );
|
||||||
|
dir = min( vec2( FXAA_SPAN_MAX, FXAA_SPAN_MAX),
|
||||||
|
max( vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),
|
||||||
|
dir * rcpDirMin)) * res;
|
||||||
|
vec4 rgbA = (1.0/2.0) * (
|
||||||
|
texture(u_texture, uv.xy + dir * (1.0/3.0 - 0.5)) +
|
||||||
|
texture(u_texture, uv.xy + dir * (2.0/3.0 - 0.5)));
|
||||||
|
vec4 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * (
|
||||||
|
texture(u_texture, uv.xy + dir * (0.0/3.0 - 0.5)) +
|
||||||
|
texture(u_texture, uv.xy + dir * (3.0/3.0 - 0.5)));
|
||||||
|
float lumaB = dot(rgbB, vec4(luma, 0.0));
|
||||||
|
|
||||||
|
if ( ( lumaB < lumaMin ) || ( lumaB > lumaMax ) ) {
|
||||||
|
fragColor = rgbA;
|
||||||
|
} else {
|
||||||
|
fragColor = rgbB;
|
||||||
|
}
|
||||||
|
|
||||||
|
//fragColor = vec4( texture( u_texture,uv ).xyz, 1. );
|
||||||
|
}
|
After Width: | Height: | Size: 47 KiB |
|
@ -116,9 +116,9 @@ in vec2 position;
|
||||||
in vec4 color;
|
in vec4 color;
|
||||||
in vec2 texCoords;
|
in vec2 texCoords;
|
||||||
in float intensity;
|
in float intensity;
|
||||||
|
|
||||||
out vec4 Color;
|
out vec4 Color;
|
||||||
out vec2 texcoords;
|
out vec2 texcoords;
|
||||||
|
out vec2 glpos;
|
||||||
out float Intensity;
|
out float Intensity;
|
||||||
|
|
||||||
uniform mat3 u_transform;
|
uniform mat3 u_transform;
|
||||||
|
@ -131,6 +131,7 @@ void main() {
|
||||||
Color = color;
|
Color = color;
|
||||||
texcoords = texCoords;
|
texcoords = texCoords;
|
||||||
Intensity = intensity;
|
Intensity = intensity;
|
||||||
|
glpos = transPos;
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
|