New scene examples added.
This commit is contained in:
254
examples/splashmenu/scenes/parallax.go
Normal file
254
examples/splashmenu/scenes/parallax.go
Normal file
@@ -0,0 +1,254 @@
|
||||
package splashmenu
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"cosmos/diego/groovy"
|
||||
"image"
|
||||
"image/color"
|
||||
"log"
|
||||
"math"
|
||||
"math/rand"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
"github.com/hajimehoshi/ebiten/v2/vector"
|
||||
|
||||
_ "embed"
|
||||
)
|
||||
|
||||
const (
|
||||
GALAXY_SCALE_DIST = 50
|
||||
DEBRIS_SCALE_DIST = 10
|
||||
FLOAT_SCALE = 8
|
||||
ASTEROID_COUNT = 14
|
||||
MAX_ROTATION_SPEED = 3
|
||||
MIN_ROTATION_SPEED = 1
|
||||
OFF_SCREEN_SCALE = 2 // number of parallax dimension screens for the logical game display area
|
||||
)
|
||||
|
||||
var (
|
||||
//go:embed assets/galaxy4.jpg
|
||||
galaxyImg_jpg []byte
|
||||
|
||||
//go:embed assets/debris_00.png
|
||||
debrisImg_png []byte
|
||||
|
||||
//go:embed assets/roid1.png
|
||||
roid1Img_png []byte
|
||||
|
||||
//go:embed assets/roid2.png
|
||||
roid2Img_png []byte
|
||||
|
||||
//go:embed assets/blend.png
|
||||
blendImg_png []byte
|
||||
|
||||
galaxyBackground *ebiten.Image
|
||||
debrisImage *ebiten.Image
|
||||
blendImage *ebiten.Image
|
||||
blendTmp *ebiten.Image
|
||||
roids []*ebiten.Image
|
||||
)
|
||||
|
||||
type Asteroid struct {
|
||||
cX int
|
||||
cY int
|
||||
rotationSpeed float64
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Load up images
|
||||
img, _, err := image.Decode(bytes.NewReader(galaxyImg_jpg))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
galaxyBackground = ebiten.NewImageFromImage(img)
|
||||
|
||||
img, _, err = image.Decode(bytes.NewReader(debrisImg_png))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
debrisImage = ebiten.NewImageFromImage(img)
|
||||
|
||||
//asteroids!
|
||||
img, _, err = image.Decode(bytes.NewReader(roid1Img_png))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
roids = append(roids, ebiten.NewImageFromImage(img))
|
||||
|
||||
img, _, err = image.Decode(bytes.NewReader(roid2Img_png))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
roids = append(roids, ebiten.NewImageFromImage(img))
|
||||
|
||||
img, _, err = image.Decode(bytes.NewReader(blendImg_png))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
blendImage = ebiten.NewImageFromImage(img)
|
||||
blendTmp = ebiten.NewImageFromImage(blendImage)
|
||||
}
|
||||
|
||||
type Parallax struct {
|
||||
events map[groovy.SceneEvent]func()
|
||||
Dimensions groovy.Area
|
||||
increment int
|
||||
asteroids []Asteroid
|
||||
}
|
||||
|
||||
func NewParallax() Parallax {
|
||||
return Parallax{
|
||||
events: make(map[groovy.SceneEvent]func()),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Parallax) Update() error {
|
||||
p.increment++
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parallax) Draw(screen *ebiten.Image) {
|
||||
|
||||
p.DrawDynamicBackground(screen)
|
||||
p.DrawObstacles(screen)
|
||||
//p.DrawObstaclesWithShamLighting(screen)
|
||||
|
||||
p.RepositionTest(screen)
|
||||
|
||||
}
|
||||
|
||||
func (p *Parallax) SetDimensions(a groovy.Area) {
|
||||
p.Dimensions = a
|
||||
}
|
||||
|
||||
func (p *Parallax) SetEventHandler(event groovy.SceneEvent, f func()) {
|
||||
p.events[event] = f
|
||||
}
|
||||
|
||||
func (p *Parallax) InitializeParallax() {
|
||||
|
||||
if p.Dimensions.Area() <= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
for i := 0; i < ASTEROID_COUNT; i++ {
|
||||
newX := rand.Intn(p.Dimensions.Width) * OFF_SCREEN_SCALE
|
||||
newY := rand.Intn(p.Dimensions.Height) * OFF_SCREEN_SCALE
|
||||
rS := rand.Float64()*MAX_ROTATION_SPEED + MIN_ROTATION_SPEED
|
||||
p.asteroids = append(p.asteroids, Asteroid{cX: newX, cY: newY, rotationSpeed: rS})
|
||||
}
|
||||
|
||||
whiteImage.Fill(color.White)
|
||||
}
|
||||
|
||||
func (p *Parallax) DrawDynamicBackground(screen *ebiten.Image) {
|
||||
x, y := ebiten.CursorPosition()
|
||||
|
||||
op := &ebiten.DrawImageOptions{}
|
||||
op.GeoM.Translate(float64(-x-p.Dimensions.Width)/GALAXY_SCALE_DIST, float64(-y-p.Dimensions.Height)/GALAXY_SCALE_DIST)
|
||||
screen.DrawImage(galaxyBackground, op)
|
||||
|
||||
//debris layers
|
||||
const DEBRIS_QTY = 3
|
||||
const DEBRIS_WIDTH = 640 / 3 * 2
|
||||
const DEBRIS_HEIGHT = 480 / 3 * 2
|
||||
const TOTAL_LAYERS = 2
|
||||
for k := 0; k < TOTAL_LAYERS; k++ {
|
||||
for i := 0; i < DEBRIS_QTY; i++ {
|
||||
for j := 0; j < DEBRIS_QTY; j++ {
|
||||
//compute object origins (pre-shifts)
|
||||
x0 := float64(j*DEBRIS_WIDTH) + float64(p.increment/640)
|
||||
y0 := float64(i*DEBRIS_HEIGHT) + float64(p.increment/480)
|
||||
//now compute delta with parallax effect
|
||||
xd := (x0-float64(x))/DEBRIS_SCALE_DIST*float64(k+1) + x0 - float64(p.increment*k)/FLOAT_SCALE
|
||||
yd := (y0-float64(y))/DEBRIS_SCALE_DIST*float64(k+1) + y0 - float64(p.increment*k)/FLOAT_SCALE
|
||||
|
||||
op = &ebiten.DrawImageOptions{}
|
||||
op.GeoM.Translate(xd, yd)
|
||||
//op.GeoM.Rotate(math.Pi / 180 * float64(p.increment))
|
||||
|
||||
op.Blend = ebiten.BlendSourceOver
|
||||
screen.DrawImage(debrisImage, op)
|
||||
//log.Printf("%d, %d", xoffset, yoffset)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Parallax) DrawObstacles(screen *ebiten.Image) {
|
||||
|
||||
x, y := ebiten.CursorPosition()
|
||||
|
||||
for _, a := range p.asteroids {
|
||||
cx := float64(a.cX)
|
||||
cy := float64(a.cY)
|
||||
|
||||
op := &ebiten.DrawImageOptions{}
|
||||
op.GeoM.Translate(-100, -66)
|
||||
op.GeoM.Rotate(-float64(p.increment) * a.rotationSpeed / (math.Pi * 120))
|
||||
op.GeoM.Translate(cx-float64(x), cy-float64(y))
|
||||
screen.DrawImage(roids[0], op)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Parallax) DrawObstaclesWithShamLighting(screen *ebiten.Image) {
|
||||
|
||||
x, y := ebiten.CursorPosition()
|
||||
|
||||
for _, a := range p.asteroids {
|
||||
cx := float64(a.cX)
|
||||
cy := float64(a.cY)
|
||||
|
||||
op := &ebiten.DrawImageOptions{}
|
||||
op.GeoM.Translate(-100, -66)
|
||||
op.GeoM.Rotate(-float64(p.increment) * a.rotationSpeed / (math.Pi * 120))
|
||||
op.GeoM.Translate(100, 66)
|
||||
|
||||
//draw roid to temporary location
|
||||
blendTmp.DrawImage(roids[0], op)
|
||||
|
||||
op = &ebiten.DrawImageOptions{}
|
||||
op.Blend = ebiten.BlendSourceAtop
|
||||
blendTmp.DrawImage(blendImage, op)
|
||||
|
||||
op = &ebiten.DrawImageOptions{}
|
||||
op.GeoM.Translate(cx-float64(x), cy-float64(y))
|
||||
screen.DrawImage(blendTmp, op)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Parallax) RepositionTest(screen *ebiten.Image) {
|
||||
|
||||
var path vector.Path
|
||||
|
||||
//set up origin and boundaries
|
||||
x0 := float32(p.Dimensions.Width / 2)
|
||||
y0 := float32(p.Dimensions.Height / 2)
|
||||
|
||||
xd := float32(100.0)
|
||||
yd := float32(100.0)
|
||||
|
||||
//connect the dots
|
||||
path.MoveTo(x0-xd, y0-yd)
|
||||
path.LineTo(x0+xd, y0-yd)
|
||||
path.LineTo(x0+xd, y0+yd)
|
||||
path.LineTo(x0-xd, y0+yd)
|
||||
path.LineTo(x0-xd, y0+yd)
|
||||
path.Close()
|
||||
|
||||
var vs []ebiten.Vertex
|
||||
var is []uint16
|
||||
|
||||
vs, is = path.AppendVerticesAndIndicesForFilling(nil, nil)
|
||||
for i := range vs {
|
||||
vs[i].SrcX = 1
|
||||
vs[i].SrcY = 1
|
||||
vs[i].ColorR = float32(0xff) / 0xFF
|
||||
vs[i].ColorG = float32(0x00) / 0xFF
|
||||
vs[i].ColorB = float32(0x00) / 0xFF
|
||||
vs[i].ColorA = 1
|
||||
}
|
||||
screen.DrawTriangles(vs, is, whiteSubImage, nil)
|
||||
}
|
||||
Reference in New Issue
Block a user