doodle/pkg/sprites/sprites.go
Noah Petherbridge 672ee9641a Savegame and High Scores
* Adds pkg/savegame to store user progress thru Level Packs.
* The savegame.json is mildly tamper resistant by including a checksum
  along with the JSON body.
* The checksum combines the JSON string + an app secret (in savegame.go)
  + user specific entropy (stored in their settings.json). If the user
  modifies their save file and the checksum becomes invalid the game
  will not load the save file, acting like it didn't exist, resetting
  all their high scores.

Updates to the Story Mode window:

* On the LevelPacks list: shows e.g. "[completed 0 of 3 levels]" showing
  a user's progress thru the level pack.
* Below the levels on the Detail screen:
  * Shows an indicator whether the level is completed or not.
  * Shows high scores (fastest times beating the level)
  * Shows a padlock icon if levels are locked and the player hasn't
    reached them yet. Pops up an Alert modal if a locked level is
    clicked on.

Scoring is based around your fastest time elapsed to finish the level.

* Perfect Time (gold coin): player has not died during the level.
* Best Time (silver coin): player has continued from a checkpoint.

In-game an elapsed timer is shown in the top left corner along with the
gold or silver coin indicating if your run has been Perfect.

If the user enters any Cheat Codes during gameplay they are not eligible
to win a high score, but the level will still be marked as completed.
The icon next to the in-game timer disappears when a cheat code has been
entered.
2022-01-02 16:28:43 -08:00

87 lines
1.8 KiB
Go

/*
Package sprites manages miscellaneous in-game sprites.
The sprites are relatively few for UI purposes. Their textures are
loaded ONE time and cached in this package for performance.
*/
package sprites
import (
"bytes"
"errors"
"image/png"
"io/ioutil"
"os"
"runtime"
"git.kirsle.net/apps/doodle/assets"
"git.kirsle.net/apps/doodle/pkg/log"
"git.kirsle.net/apps/doodle/pkg/wasm"
"git.kirsle.net/go/render"
"git.kirsle.net/go/ui"
)
// Cache of loaded sprites.
var cache = map[string]*ui.Image{}
// FlushCache clears the sprites cache.
func FlushCache() {
panic("TODO: free textures")
}
// LoadImage loads a sprite as a ui.Image object. It checks Doodle's embedded
// bindata, then the filesystem before erroring out.
//
// NOTE: only .png images supported as of now. TODO
func LoadImage(e render.Engine, filename string) (*ui.Image, error) {
if cached, ok := cache[filename]; ok {
return cached, nil
}
// Try the bindata first.
if data, err := assets.Asset(filename); err == nil {
log.Debug("sprites.LoadImage: %s from bindata", filename)
img, err := png.Decode(bytes.NewBuffer(data))
if err != nil {
return nil, err
}
return ui.ImageFromImage(img)
}
// WASM: try the file over HTTP ajax request.
if runtime.GOOS == "js" {
data, err := wasm.HTTPGet(filename)
if err != nil {
return nil, err
}
img, err := png.Decode(bytes.NewBuffer(data))
if err != nil {
return nil, err
}
return ui.ImageFromImage(img)
}
// Then try the file system.
if _, err := os.Stat(filename); !os.IsNotExist(err) {
log.Debug("sprites.LoadImage: %s from filesystem", filename)
data, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
img, err := png.Decode(bytes.NewBuffer(data))
if err != nil {
return nil, err
}
return ui.ImageFromImage(img)
}
return nil, errors.New("no such sprite found")
}