lints, loading fix
This commit is contained in:
parent
f2f9b9dd6f
commit
1ff0694049
17 changed files with 92 additions and 46 deletions
|
@ -52,6 +52,7 @@ type DebugToast struct {
|
||||||
Text string
|
Text string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw uses DebugPrintAt to draw d.Text at the position d.Pos.
|
||||||
func (d *DebugToast) Draw(screen *ebiten.Image, _ *ebiten.DrawImageOptions) {
|
func (d *DebugToast) Draw(screen *ebiten.Image, _ *ebiten.DrawImageOptions) {
|
||||||
ebitenutil.DebugPrintAt(screen, d.Text, d.Pos.X, d.Pos.Y)
|
ebitenutil.DebugPrintAt(screen, d.Text, d.Pos.X, d.Pos.Y)
|
||||||
}
|
}
|
||||||
|
@ -60,12 +61,14 @@ func (d *DebugToast) String() string {
|
||||||
return fmt.Sprintf("DebugToast@%v", d.Pos)
|
return fmt.Sprintf("DebugToast@%v", d.Pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Toast sets the text to appear for 2 seconds.
|
||||||
func (d *DebugToast) Toast(text string) {
|
func (d *DebugToast) Toast(text string) {
|
||||||
d.Text = text
|
d.Text = text
|
||||||
d.Timer = 120
|
d.Timer = 120
|
||||||
d.Hides = false
|
d.Hides = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update hides the toast text once the timer is exhausted.
|
||||||
func (d *DebugToast) Update() error {
|
func (d *DebugToast) Update() error {
|
||||||
if d.Hides = d.Timer <= 0; !d.Hides {
|
if d.Hides = d.Timer <= 0; !d.Hides {
|
||||||
d.Timer--
|
d.Timer--
|
||||||
|
@ -78,6 +81,7 @@ type PerfDisplay struct {
|
||||||
Hides
|
Hides
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw uses DebugPrint to print the TPS and FPS in the top-left.
|
||||||
func (p PerfDisplay) Draw(screen *ebiten.Image, _ *ebiten.DrawImageOptions) {
|
func (p PerfDisplay) Draw(screen *ebiten.Image, _ *ebiten.DrawImageOptions) {
|
||||||
ebitenutil.DebugPrint(screen, fmt.Sprintf("TPS: %0.2f FPS: %0.2f", ebiten.CurrentTPS(), ebiten.CurrentFPS()))
|
ebitenutil.DebugPrint(screen, fmt.Sprintf("TPS: %0.2f FPS: %0.2f", ebiten.CurrentTPS(), ebiten.CurrentFPS()))
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,8 @@ type DrawDFS struct {
|
||||||
game *Game
|
game *Game
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw draws all descendant components (that are not managed by some other
|
||||||
|
// DrawManager) in a pre-order traversal.
|
||||||
func (d *DrawDFS) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
|
func (d *DrawDFS) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
|
||||||
stack := []ebiten.DrawImageOptions{*opts}
|
stack := []ebiten.DrawImageOptions{*opts}
|
||||||
d.game.Query(d, DrawerType,
|
d.game.Query(d, DrawerType,
|
||||||
|
@ -81,6 +83,7 @@ func (d *DrawDFS) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
|
||||||
// DrawManager.
|
// DrawManager.
|
||||||
func (DrawDFS) ManagesDrawingSubcomponents() {}
|
func (DrawDFS) ManagesDrawingSubcomponents() {}
|
||||||
|
|
||||||
|
// Prepare saves a reference to g.
|
||||||
func (d *DrawDFS) Prepare(g *Game) error {
|
func (d *DrawDFS) Prepare(g *Game) error {
|
||||||
d.game = g
|
d.game = g
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -39,12 +39,13 @@ func init() {
|
||||||
// Fill fills the screen with a colour.
|
// Fill fills the screen with a colour.
|
||||||
type Fill struct {
|
type Fill struct {
|
||||||
ID
|
ID
|
||||||
Color color.Color
|
Colour color.Color
|
||||||
Hides
|
Hides
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw fills the screen with the colour.
|
||||||
func (f *Fill) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
|
func (f *Fill) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
|
||||||
screen.Fill(opts.ColorM.Apply(f.Color))
|
screen.Fill(opts.ColorM.Apply(f.Colour))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Fill) String() string { return "Fill" }
|
func (f *Fill) String() string { return "Fill" }
|
||||||
|
|
|
@ -22,19 +22,25 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// LoadingSwitch switches between two subcomponents. While After is being
|
||||||
|
// loaded asynchronously, During is shown. Once loading is complete, During
|
||||||
|
// is hidden and After is shown.
|
||||||
type LoadingSwitch struct {
|
type LoadingSwitch struct {
|
||||||
During Hider
|
During, After interface {
|
||||||
After Hider
|
Disabler
|
||||||
|
Hider
|
||||||
|
}
|
||||||
|
|
||||||
assets fs.FS
|
assets fs.FS
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan only scans s.During, thus, only s.During is loaded by Game directly.
|
// Scan only scans s.During. Only s.During is loaded automatically - s.After is
|
||||||
|
// loaded asynchronously from Prepare below.
|
||||||
func (s *LoadingSwitch) Scan(visit VisitFunc) error {
|
func (s *LoadingSwitch) Scan(visit VisitFunc) error {
|
||||||
return visit(s.During)
|
return visit(s.During)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load stores a copy of assets to use later.
|
// Load stores a copy of assets to pass to s.After.Load later.
|
||||||
func (s *LoadingSwitch) Load(assets fs.FS) error {
|
func (s *LoadingSwitch) Load(assets fs.FS) error {
|
||||||
s.assets = assets
|
s.assets = assets
|
||||||
return nil
|
return nil
|
||||||
|
@ -43,7 +49,11 @@ func (s *LoadingSwitch) Load(assets fs.FS) error {
|
||||||
// Prepare loads, registers, and prepares.After in a separate goroutine. Once
|
// Prepare loads, registers, and prepares.After in a separate goroutine. Once
|
||||||
// ready, LoadingSwitch hides s.During and shows s.After.
|
// ready, LoadingSwitch hides s.During and shows s.After.
|
||||||
func (s *LoadingSwitch) Prepare(game *Game) error {
|
func (s *LoadingSwitch) Prepare(game *Game) error {
|
||||||
go func() {
|
go s.loadAfter(game)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LoadingSwitch) loadAfter(game *Game) {
|
||||||
startLoad := time.Now()
|
startLoad := time.Now()
|
||||||
if err := game.Load(s.After, s.assets); err != nil {
|
if err := game.Load(s.After, s.assets); err != nil {
|
||||||
log.Printf("Couldn't load: %v", err)
|
log.Printf("Couldn't load: %v", err)
|
||||||
|
@ -51,6 +61,9 @@ func (s *LoadingSwitch) Prepare(game *Game) error {
|
||||||
}
|
}
|
||||||
log.Printf("LoadingSwitch: finished loading in %v", time.Since(startLoad))
|
log.Printf("LoadingSwitch: finished loading in %v", time.Since(startLoad))
|
||||||
|
|
||||||
|
s.After.Disable()
|
||||||
|
s.After.Hide()
|
||||||
|
|
||||||
startBuild := time.Now()
|
startBuild := time.Now()
|
||||||
if err := game.Register(s.After, s); err != nil {
|
if err := game.Register(s.After, s); err != nil {
|
||||||
log.Printf("Couldn't register: %v", err)
|
log.Printf("Couldn't register: %v", err)
|
||||||
|
@ -65,8 +78,8 @@ func (s *LoadingSwitch) Prepare(game *Game) error {
|
||||||
log.Printf("LoadingSwitch: finished preparing in %v", time.Since(startPrep))
|
log.Printf("LoadingSwitch: finished preparing in %v", time.Since(startPrep))
|
||||||
|
|
||||||
// TODO: better scene transitions
|
// TODO: better scene transitions
|
||||||
|
s.During.Disable()
|
||||||
s.During.Hide()
|
s.During.Hide()
|
||||||
|
s.After.Enable()
|
||||||
s.After.Show()
|
s.After.Show()
|
||||||
}()
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,11 +28,13 @@ func init() {
|
||||||
gob.Register(&SolidRect{})
|
gob.Register(&SolidRect{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SolidRect is a minimal implementation of a Collider defined by a single Box.
|
||||||
type SolidRect struct {
|
type SolidRect struct {
|
||||||
ID
|
ID
|
||||||
geom.Box
|
geom.Box
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CollidesWith reports if r overlaps with s.Box.
|
||||||
func (s SolidRect) CollidesWith(r geom.Box) bool {
|
func (s SolidRect) CollidesWith(r geom.Box) bool {
|
||||||
return s.Box.Overlaps(r)
|
return s.Box.Overlaps(r)
|
||||||
}
|
}
|
||||||
|
|
|
@ -159,6 +159,7 @@ type Tile interface {
|
||||||
// StaticTile returns a fixed tile index.
|
// StaticTile returns a fixed tile index.
|
||||||
type StaticTile int
|
type StaticTile int
|
||||||
|
|
||||||
|
// Cell returns s as an int.
|
||||||
func (s StaticTile) Cell() int { return int(s) }
|
func (s StaticTile) Cell() int { return int(s) }
|
||||||
|
|
||||||
// AnimatedTile uses an Anim to choose a tile index.
|
// AnimatedTile uses an Anim to choose a tile index.
|
||||||
|
@ -168,6 +169,7 @@ type AnimatedTile struct {
|
||||||
anim *Anim
|
anim *Anim
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cell returns the value of Cell provided by the animation.
|
||||||
func (a *AnimatedTile) Cell() int { return a.anim.Cell() }
|
func (a *AnimatedTile) Cell() int { return a.anim.Cell() }
|
||||||
|
|
||||||
// Scan visits a.anim.
|
// Scan visits a.anim.
|
||||||
|
|
|
@ -126,6 +126,7 @@ func (u *WallUnit) Scan(visit VisitFunc) error {
|
||||||
return visit(u.Tile)
|
return visit(u.Tile)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Transform returns a translation by the position and offset.
|
||||||
func (u *WallUnit) Transform() (opts ebiten.DrawImageOptions) {
|
func (u *WallUnit) Transform() (opts ebiten.DrawImageOptions) {
|
||||||
opts.GeoM.Translate(geom.CFloat(
|
opts.GeoM.Translate(geom.CFloat(
|
||||||
geom.CMul(u.pos, u.wall.UnitSize).Add(u.wall.UnitOffset),
|
geom.CMul(u.pos, u.wall.UnitSize).Add(u.wall.UnitOffset),
|
||||||
|
|
12
example.go
12
example.go
|
@ -81,21 +81,21 @@ func main() {
|
||||||
Projection: geom.SimpleProjection{},
|
Projection: geom.SimpleProjection{},
|
||||||
VoxelScale: geom.Float3{
|
VoxelScale: geom.Float3{
|
||||||
// Each voxel counts for this much (Euclidean) space.
|
// Each voxel counts for this much (Euclidean) space.
|
||||||
X: 1,
|
X: 1, Y: 1, Z: math.Sqrt(3),
|
||||||
Y: 1,
|
|
||||||
Z: math.Sqrt(3),
|
|
||||||
},
|
},
|
||||||
Root: &engine.DrawDFS{
|
Root: &engine.DrawDFS{
|
||||||
Child: engine.MakeContainer(
|
Child: engine.MakeContainer(
|
||||||
&engine.Fill{
|
&engine.Fill{
|
||||||
ID: "bg_fill",
|
ID: "bg_fill",
|
||||||
Color: color.Gray{100},
|
Colour: color.Gray{100},
|
||||||
},
|
},
|
||||||
&engine.LoadingSwitch{
|
&engine.LoadingSwitch{
|
||||||
During: &engine.Billboard{
|
During: &engine.Scene{
|
||||||
ID: "loading_screen",
|
ID: "loading_scene",
|
||||||
|
Child: &engine.Billboard{
|
||||||
Src: engine.ImageRef{Path: "assets/loading.png"},
|
Src: engine.ImageRef{Path: "assets/loading.png"},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
After: &engine.Camera{
|
After: &engine.Camera{
|
||||||
ID: "game_camera",
|
ID: "game_camera",
|
||||||
Child: lev1,
|
Child: lev1,
|
||||||
|
|
|
@ -20,5 +20,6 @@ package example
|
||||||
|
|
||||||
import "embed"
|
import "embed"
|
||||||
|
|
||||||
|
// Assets is the embedded assets FS.
|
||||||
//go:embed assets
|
//go:embed assets
|
||||||
var Assets embed.FS
|
var Assets embed.FS
|
||||||
|
|
|
@ -65,6 +65,8 @@ type Awakeman struct {
|
||||||
// Ident returns "awakeman". There should be only one!
|
// Ident returns "awakeman". There should be only one!
|
||||||
func (aw *Awakeman) Ident() string { return "awakeman" }
|
func (aw *Awakeman) Ident() string { return "awakeman" }
|
||||||
|
|
||||||
|
// Update updates Awakeman, including capturing input, applying gravity and
|
||||||
|
// movement, and repositioning the camera.
|
||||||
func (aw *Awakeman) Update() error {
|
func (aw *Awakeman) Update() error {
|
||||||
// TODO: better cheat for noclip
|
// TODO: better cheat for noclip
|
||||||
if inpututil.IsKeyJustPressed(ebiten.KeyN) {
|
if inpututil.IsKeyJustPressed(ebiten.KeyN) {
|
||||||
|
@ -257,6 +259,7 @@ func (aw *Awakeman) realUpdate() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prepare captures necessary references to other game components.
|
||||||
func (aw *Awakeman) Prepare(game *engine.Game) error {
|
func (aw *Awakeman) Prepare(game *engine.Game) error {
|
||||||
aw.game = game
|
aw.game = game
|
||||||
cam, ok := game.Component(aw.CameraID).(*engine.Camera)
|
cam, ok := game.Component(aw.CameraID).(*engine.Camera)
|
||||||
|
@ -275,6 +278,7 @@ func (aw *Awakeman) Prepare(game *engine.Game) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scan visits &aw.Sprite.
|
||||||
func (aw *Awakeman) Scan(visit engine.VisitFunc) error {
|
func (aw *Awakeman) Scan(visit engine.VisitFunc) error {
|
||||||
return visit(&aw.Sprite)
|
return visit(&aw.Sprite)
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ var _ interface {
|
||||||
engine.Updater
|
engine.Updater
|
||||||
} = &Bubble{}
|
} = &Bubble{}
|
||||||
|
|
||||||
|
// Bubble implements a single bubble within a simple particle system.
|
||||||
type Bubble struct {
|
type Bubble struct {
|
||||||
Life int
|
Life int
|
||||||
Sprite engine.Sprite
|
Sprite engine.Sprite
|
||||||
|
@ -38,6 +39,8 @@ type Bubble struct {
|
||||||
game *engine.Game
|
game *engine.Game
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewBubble creates a bubble. Before it can be used, the return value needs to
|
||||||
|
// be loaded, registered, and prepared.
|
||||||
func NewBubble(pos geom.Int3) *Bubble {
|
func NewBubble(pos geom.Int3) *Bubble {
|
||||||
return &Bubble{
|
return &Bubble{
|
||||||
Life: 60,
|
Life: 60,
|
||||||
|
@ -72,6 +75,7 @@ func NewBubble(pos geom.Int3) *Bubble {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scan visits &b.sprite.
|
||||||
func (b *Bubble) Scan(visit engine.VisitFunc) error {
|
func (b *Bubble) Scan(visit engine.VisitFunc) error {
|
||||||
return visit(&b.Sprite)
|
return visit(&b.Sprite)
|
||||||
}
|
}
|
||||||
|
@ -80,11 +84,14 @@ func (b *Bubble) String() string {
|
||||||
return fmt.Sprintf("Bubble@%v", b.Sprite.Actor.Pos)
|
return fmt.Sprintf("Bubble@%v", b.Sprite.Actor.Pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prepare saves a reference to g.
|
||||||
func (b *Bubble) Prepare(g *engine.Game) error {
|
func (b *Bubble) Prepare(g *engine.Game) error {
|
||||||
b.game = g
|
b.game = g
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update moves the bubble randomly, and handles unregistering the bubble when
|
||||||
|
// it has "popped".
|
||||||
func (b *Bubble) Update() error {
|
func (b *Bubble) Update() error {
|
||||||
b.Life--
|
b.Life--
|
||||||
if b.Life <= 0 {
|
if b.Life <= 0 {
|
||||||
|
|
|
@ -26,7 +26,7 @@ type Int3 struct {
|
||||||
X, Y, Z int
|
X, Y, Z int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pt3(x, y, z) is shorthand for Int3{x, y, z}.
|
// Pt3 returns Int3{x, y, z}.
|
||||||
func Pt3(x, y, z int) Int3 {
|
func Pt3(x, y, z int) Int3 {
|
||||||
return Int3{x, y, z}
|
return Int3{x, y, z}
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,7 +98,7 @@ func (a IntMatrix2x3) Apply(v Int3) image.Point {
|
||||||
// RatMatrix3 implements a 3x3 matrix with rational number entries.
|
// RatMatrix3 implements a 3x3 matrix with rational number entries.
|
||||||
type RatMatrix3 [3][3]Rat
|
type RatMatrix3 [3][3]Rat
|
||||||
|
|
||||||
// IdentityRatMatrix3x4 is the identity matrix for RatMatrix3x4.
|
// IdentityRatMatrix3 is the identity matrix for RatMatrix3.
|
||||||
var IdentityRatMatrix3 = RatMatrix3{
|
var IdentityRatMatrix3 = RatMatrix3{
|
||||||
0: [3]Rat{0: {1, 1}},
|
0: [3]Rat{0: {1, 1}},
|
||||||
1: [3]Rat{1: {1, 1}},
|
1: [3]Rat{1: {1, 1}},
|
||||||
|
|
|
@ -40,6 +40,11 @@ func Dot(p, q image.Point) int {
|
||||||
return p.X*q.X + p.Y*q.Y
|
return p.X*q.X + p.Y*q.Y
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CSign applies Sign componentwise to the Point.
|
||||||
|
func CSign(p image.Point) image.Point {
|
||||||
|
return image.Point{X: Sign(p.X), Y: Sign(p.Y)}
|
||||||
|
}
|
||||||
|
|
||||||
// ---------- Some other helpers ----------
|
// ---------- Some other helpers ----------
|
||||||
|
|
||||||
// FSign returns the sign of the float64 (-1, 0, or 1).
|
// FSign returns the sign of the float64 (-1, 0, or 1).
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"math"
|
"math"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Cardinal directions, as used in the return from PolygonExtrema.
|
||||||
const (
|
const (
|
||||||
East = iota
|
East = iota
|
||||||
North
|
North
|
||||||
|
|
|
@ -54,6 +54,7 @@ func (SimpleProjection) Project(z int) image.Point { return image.Pt(0, z) }
|
||||||
// Projection uses two floats to define a custom projection.
|
// Projection uses two floats to define a custom projection.
|
||||||
type Projection struct{ X, Y float64 }
|
type Projection struct{ X, Y float64 }
|
||||||
|
|
||||||
|
// Sign returns the componentwise sign of π.
|
||||||
func (π Projection) Sign() image.Point {
|
func (π Projection) Sign() image.Point {
|
||||||
return image.Pt(int(FSign(π.X)), int(FSign(π.Y)))
|
return image.Pt(int(FSign(π.X)), int(FSign(π.Y)))
|
||||||
}
|
}
|
||||||
|
@ -71,7 +72,8 @@ func (π Projection) Project(z int) image.Point {
|
||||||
// be used in e.g. a diametric projection (IntProjection{X:0, Y:2}).
|
// be used in e.g. a diametric projection (IntProjection{X:0, Y:2}).
|
||||||
type IntProjection image.Point
|
type IntProjection image.Point
|
||||||
|
|
||||||
func (π IntProjection) Sign() image.Point { return image.Point(π) }
|
// Sign returns CSign(π).
|
||||||
|
func (π IntProjection) Sign() image.Point { return CSign(image.Point(π)) }
|
||||||
|
|
||||||
// Project returns (z/π.X, z/π.Y), unless π.X or π.Y are 0, in which case that
|
// Project returns (z/π.X, z/π.Y), unless π.X or π.Y are 0, in which case that
|
||||||
// component is zero
|
// component is zero
|
||||||
|
|
|
@ -51,7 +51,7 @@ func (s *LinearSpline) Prepare() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interpolate, given x, returns y where (x,y) is a point on the spline.
|
// Interpolate returns y where (x,y) is a point on the spline.
|
||||||
// If x is outside the spline, it extrapolates from either the first or
|
// If x is outside the spline, it extrapolates from either the first or
|
||||||
// last segments of the spline.
|
// last segments of the spline.
|
||||||
func (s *LinearSpline) Interpolate(x float64) float64 {
|
func (s *LinearSpline) Interpolate(x float64) float64 {
|
||||||
|
@ -236,9 +236,9 @@ func (s *CubicSpline) Prepare() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interpolate, given x, returns y where (x,y) is a point on the spline.
|
// Interpolate returns y where (x,y) is a point on the spline.
|
||||||
// If x is outside the spline, it extrapolates from either the first or
|
// If x is outside the spline, it extrapolates from the first or last point
|
||||||
// last segments of the spline.
|
// together with s.Preslope or s.Postslope.
|
||||||
func (s *CubicSpline) Interpolate(x float64) float64 {
|
func (s *CubicSpline) Interpolate(x float64) float64 {
|
||||||
N := len(s.Points)
|
N := len(s.Points)
|
||||||
if x < s.Points[0].X {
|
if x < s.Points[0].X {
|
||||||
|
|
Loading…
Reference in a new issue