Compare commits
54 Commits
collidersy
...
rework-ani
| Author | SHA1 | Date | |
|---|---|---|---|
| f23bdaf121 | |||
| 2793710819 | |||
| 940d305c00 | |||
| 2edaccbfda | |||
| 0b0252022e | |||
| 50dd76a268 | |||
| 53bdb7e8ae | |||
| 261f23a5a9 | |||
| 77de9621c9 | |||
| d80a0b99ad | |||
| c76037486d | |||
| cb3ccb323c | |||
| 95469ab3c7 | |||
| f844058bf9 | |||
| 001b67f97a | |||
| 20fa2639c6 | |||
| faf0fd99c2 | |||
| f6f2172f11 | |||
| c6f9557483 | |||
| c7c3859a70 | |||
| 82c67551aa | |||
| dcf31e46ed | |||
| f6d5385d35 | |||
| dc2574643c | |||
| 4c2ecc6f1f | |||
| 5b7c88a1a9 | |||
| f8c09fda76 | |||
| 693293b8c8 | |||
| 51d3776abf | |||
| 19c9a5d502 | |||
| d055c9e913 | |||
| 52c4cb4e66 | |||
| e93c08f81f | |||
| 1d16fcb73f | |||
| ae0e3a0676 | |||
| daa5e41551 | |||
| 35057ec8a6 | |||
| 449a75aa7d | |||
| db228094eb | |||
| 927233aafb | |||
| b9ac1c7995 | |||
| 2084150456 | |||
| 1d9164d140 | |||
| af19ccb833 | |||
| a2ed7782b2 | |||
| ae8058e052 | |||
| 6f85a90b58 | |||
| 1c0f3d19d0 | |||
| ebaeb51f68 | |||
| 707281212a | |||
| 5d2475d525 | |||
| ac88a74bd7 | |||
| 18be0ebe38 | |||
| 451b66a53d |
3
.gitignore
vendored
@@ -1 +1,2 @@
|
||||
openquell
|
||||
openquell*
|
||||
tmp
|
||||
|
||||
24
Makefile
@@ -1,3 +1,12 @@
|
||||
version = $(shell egrep "version string = " config/static.go | cut -d'"' -f 2)
|
||||
BRANCH = $(shell git branch --show-current)
|
||||
COMMIT = $(shell git rev-parse --short=8 HEAD)
|
||||
BUILD = $(shell date +%Y.%m.%d.%H%M%S)
|
||||
#VERSION := $(if $(filter $(BRANCH), development),$(version)-$(BRANCH)-$(COMMIT)-$(BUILD),$(version))
|
||||
VERSION := $(version)-$(BRANCH)-$(COMMIT)-$(BUILD)
|
||||
SHORTVERSION := $(version)-$(BRANCH)-$(COMMIT)
|
||||
LDFLAGS := -ldflags "-X 'openquell/config.VERSION=$(VERSION)'"
|
||||
|
||||
all: clean build
|
||||
@echo ok
|
||||
|
||||
@@ -5,8 +14,19 @@ clean:
|
||||
rm -f openquell
|
||||
|
||||
build:
|
||||
go build
|
||||
go build -ldflags "-X 'openquell/config.VERSION=$(VERSION)'"
|
||||
|
||||
buildwasm:
|
||||
env GOOS=js GOARCH=wasm go build -o openquell.wasm $(LDFLAGS) .
|
||||
|
||||
buildwindows:
|
||||
GOOS=windows GOARCH=amd64 go build $(LDFLAGS) -o openquell.exe
|
||||
|
||||
zipwasm:
|
||||
zip -r openquell-$(SHORTVERSION).zip index.html openquell.wasm wasm_exec.js
|
||||
|
||||
wasm: buildwasm zipwasm
|
||||
@ls -l openquell-$(SHORTVERSION).zip
|
||||
|
||||
test:
|
||||
@echo 1
|
||||
@echo $(VERSION)
|
||||
|
||||
84
TODO.md
@@ -1,32 +1,70 @@
|
||||
## Levels:
|
||||
|
||||
- ignore comments in lvl files
|
||||
|
||||
- check when sphere bounces from one end to the other endlessly w/o
|
||||
any solids in between. this is a game lock and equals game over
|
||||
|
||||
- Start the game end timer and add a score FIXME: put the actual max
|
||||
reachable score into the level definition along with the minimum
|
||||
steps required to reach it, also add a step counter
|
||||
|
||||
- Grid Observer:
|
||||
https://github.com/mlange-42/arche/issues/374
|
||||
|
||||
- Add some final message when the player reaches the last level, start
|
||||
from scratch or a message to buy me some beer, whatever
|
||||
|
||||
- Check player-player collisions!
|
||||
|
||||
- Add player mergers, possibly as an option, so maybe we could have
|
||||
different primary and secondary players: one pair can merge, the
|
||||
other not. Like S + s and M + m or something.
|
||||
|
||||
- Add shaders for animation (player destruction etc)
|
||||
|
||||
- Add player HUD + Stats (as hud_system!)
|
||||
- Start New game starts with last played level, better add a Resume
|
||||
Game menu item for this and use Start New always for level 1.
|
||||
|
||||
- for finding caller:
|
||||
pc := make([]uintptr, 10)
|
||||
n := runtime.Callers(0, pc)
|
||||
pc = pc[:n]
|
||||
fs := runtime.CallersFrames(pc)
|
||||
source, _ := fs.Next()
|
||||
source, _ = fs.Next()
|
||||
source, _ = fs.Next()
|
||||
|
||||
slog.Debug("get observer", "minmoves", observer.LevelScore,
|
||||
"file", source.File, "line", source.Line)
|
||||
|
||||
- Turn menu button in hud_system (events in level_scene!) into ebitenui button
|
||||
|
||||
- Obstacle don't stop at collectibles
|
||||
|
||||
- Player can collect collectible hidden under obstacle (should be
|
||||
fixed when above is fixed)
|
||||
|
||||
- Add player idle animation
|
||||
|
||||
- Add player collision animation
|
||||
|
||||
- Create pixel art ui elements (button, list things) and ui borders/backgrounds
|
||||
|
||||
- Modify font and font color matching the palette
|
||||
|
||||
- Replace HUD with pixel art variant
|
||||
|
||||
- On game start respond to any key (ebitengine-input has an anykey func)
|
||||
|
||||
- Switch to use https://github.com/quasilyte/ebitengine-input
|
||||
|
||||
- Add drag support: point and hold on the player, move cursor in some
|
||||
direction and let the player start moving on release. Respond to
|
||||
mouse and touch pad. See ~/tmp/ebiten/examples/drag/.
|
||||
|
||||
- Add options scene (mouse, player speed, sound options etc)
|
||||
|
||||
- Add save to disk feature including settings and player
|
||||
accomplishements (FIXME: find the lib, asked in Discord)
|
||||
|
||||
- Add coded animated background like in https://github.com/tinne26/bindless/tree/main/src/misc/background
|
||||
|
||||
- Rework sprites (again!) to match stellar background: maybe more
|
||||
technical tiles and items? Like some robotic setup?
|
||||
|
||||
- Fix collision snapin: sometimes, when an entity moves to the right
|
||||
or south (NOT left or north!) it snaps in visibly, so a short wobble
|
||||
can be seen.
|
||||
|
||||
- Rework animation system: since it is impossible to assign multiple
|
||||
animation types to an entity via LDTK, hard code it in Tiles. Keep
|
||||
implementation though. CAUTION: last time I changed this, the
|
||||
collectible detonation didn't work anymore!
|
||||
|
||||
|
||||
## Collider Rework
|
||||
|
||||
|
||||
## Collider Rework [abandoned: see branch collider-system, fails]
|
||||
|
||||
- do not use the map anymore for collision detection
|
||||
- central collision_system
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
Description: test obstacles
|
||||
Background: background-lila
|
||||
|
||||
|
||||
|
||||
#######
|
||||
#o #
|
||||
# t #
|
||||
#> S <#
|
||||
# #
|
||||
# ^ #
|
||||
#######
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
Description: test obstacles
|
||||
Background: background-lila
|
||||
|
||||
|
||||
|
||||
#############
|
||||
# t #
|
||||
#> S # #
|
||||
# ># ^#
|
||||
#< #W#####
|
||||
# o v# o#
|
||||
#############
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
Description: find the fruit
|
||||
Background: background-lila
|
||||
|
||||
|
||||
# ############
|
||||
# #
|
||||
############ #
|
||||
# o S #
|
||||
# ######## ###
|
||||
+ #
|
||||
############ #
|
||||
# o # #
|
||||
# # ######## #
|
||||
# # o
|
||||
# ############
|
||||
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
Description: win
|
||||
Background: background-lila
|
||||
|
||||
|
||||
|
||||
|
||||
########
|
||||
#v o #
|
||||
# S<# #
|
||||
# #### #
|
||||
|
||||
|
||||
# #### #
|
||||
# #
|
||||
#> ^#
|
||||
########
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
Description: use multiple players
|
||||
Background: background-lila
|
||||
|
||||
|
||||
|
||||
|
||||
########W#
|
||||
# v #
|
||||
# #
|
||||
#S s#
|
||||
############
|
||||
# o #
|
||||
######## #
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
Description: space
|
||||
Background: background-lila
|
||||
|
||||
|
||||
|
||||
|
||||
#
|
||||
|
||||
|
||||
S
|
||||
|
||||
|
||||
|
||||
#
|
||||
|
||||
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
#!/bin/bash
|
||||
width=$(grep "width " ../../main.go | awk '{print $4}')
|
||||
height=$(grep "height " ../../main.go | awk '{print $4}')
|
||||
|
||||
read -p " Enter level name: " name
|
||||
read -p " Enter background: " background
|
||||
read -p "Enter description: " des
|
||||
|
||||
if test -z "$name"; then
|
||||
name="newlevel"
|
||||
fi
|
||||
|
||||
if test -z "$bbackground"; then
|
||||
background="background-lila"
|
||||
fi
|
||||
|
||||
w=$(($width/32))
|
||||
h=$(($height/32))
|
||||
|
||||
(
|
||||
echo "Description: $des"
|
||||
echo "Background: $background"
|
||||
|
||||
for x in $(seq 1 $h); do
|
||||
for y in $(seq 1 $w); do
|
||||
echo -n " "
|
||||
done
|
||||
echo
|
||||
done
|
||||
)
|
||||
6425
assets/levels/openquell.ldtk
Normal file
@@ -1,30 +1,35 @@
|
||||
package assets
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
_ "image/png"
|
||||
"io/fs"
|
||||
"log"
|
||||
"log/slog"
|
||||
"openquell/config"
|
||||
"openquell/util"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
"github.com/solarlune/ldtkgo"
|
||||
)
|
||||
|
||||
var Levels = LoadLevels("levels")
|
||||
var Project = LoadLDTK("levels")
|
||||
var Tiles = InitTiles()
|
||||
|
||||
type TileAnimation struct {
|
||||
OnCollision bool // wether to animate a collision
|
||||
OnDestruction bool // wether to animate destruction
|
||||
OnIdle bool // wether to animate during idling
|
||||
|
||||
CollisionSheet AnimationSet // an entry in assets.Animations[name]
|
||||
DestructionSheet AnimationSet
|
||||
IdleSheet AnimationSet
|
||||
}
|
||||
|
||||
// Tile: contains image, identifier (as used in level data) and
|
||||
// additional properties
|
||||
type Tile struct {
|
||||
Id byte
|
||||
Id, Ref string
|
||||
Sprite *ebiten.Image
|
||||
Class string
|
||||
ToggleSprite *ebiten.Image
|
||||
Solid bool // wall brick
|
||||
Player bool // player sphere
|
||||
IsPrimary bool // primary player sphere
|
||||
@@ -33,18 +38,24 @@ type Tile struct {
|
||||
Collectible bool // collectible, vanishes once collected
|
||||
Transient bool // turns into brick wall when traversed
|
||||
Destroyable bool // turns into empty floor when bumped into twice
|
||||
Particle int // -1=unused, 0-3 = show image of slice
|
||||
Tiles []*ebiten.Image // has N sprites
|
||||
TileNames []string // same thing, only the names
|
||||
Obstacle bool // is an obstacle/enemy
|
||||
Direction int // obstacle business end shows into this direction
|
||||
Shader *ebiten.Shader
|
||||
Alpha *ebiten.Image
|
||||
Bond bool // denotes an entity which can have a relation to another
|
||||
Door bool // a door, can be manipulated by a switch
|
||||
Switch bool // opens|closes a door
|
||||
Animation TileAnimation
|
||||
}
|
||||
|
||||
func (tile *Tile) Clone() *Tile {
|
||||
newtile := &Tile{
|
||||
Id: tile.Id,
|
||||
Ref: tile.Ref,
|
||||
Sprite: tile.Sprite,
|
||||
Class: tile.Class,
|
||||
ToggleSprite: tile.ToggleSprite,
|
||||
Solid: tile.Solid,
|
||||
Player: tile.Player,
|
||||
IsPrimary: tile.IsPrimary,
|
||||
@@ -53,11 +64,16 @@ func (tile *Tile) Clone() *Tile {
|
||||
Collectible: tile.Collectible,
|
||||
Transient: tile.Transient,
|
||||
Destroyable: tile.Destroyable,
|
||||
Particle: tile.Particle,
|
||||
Tiles: tile.Tiles,
|
||||
TileNames: tile.TileNames,
|
||||
Obstacle: tile.Obstacle,
|
||||
Direction: tile.Direction,
|
||||
Alpha: tile.Alpha,
|
||||
Shader: tile.Shader,
|
||||
Bond: tile.Bond,
|
||||
Door: tile.Door,
|
||||
Switch: tile.Switch,
|
||||
Animation: tile.Animation,
|
||||
}
|
||||
|
||||
return newtile
|
||||
@@ -68,55 +84,52 @@ const (
|
||||
Secondary bool = false
|
||||
)
|
||||
|
||||
func GetSprites(class []string) []*ebiten.Image {
|
||||
sprites := []*ebiten.Image{}
|
||||
|
||||
for _, sprite := range class {
|
||||
sprites = append(sprites, Assets[sprite])
|
||||
}
|
||||
|
||||
return sprites
|
||||
}
|
||||
|
||||
func NewTilePlayer(isprimary bool) *Tile {
|
||||
tile := &Tile{
|
||||
Id: 'S',
|
||||
Class: "sphere",
|
||||
Renderable: true,
|
||||
Player: true,
|
||||
Velocity: true,
|
||||
IsPrimary: isprimary,
|
||||
}
|
||||
|
||||
switch isprimary {
|
||||
case Primary:
|
||||
tile.Sprite = Assets["sphere-blue"]
|
||||
case Secondary:
|
||||
tile.Sprite = Assets["sphere-blue-secondary"]
|
||||
tile.Id = 's'
|
||||
}
|
||||
|
||||
// primary sprite is always the first one
|
||||
tile.Tiles = []*ebiten.Image{Assets["sphere-blue"], Assets["sphere-blue-secondary"]}
|
||||
tile.Tiles = []*ebiten.Image{Assets["sphere"], Assets["sphere-small"]}
|
||||
return tile
|
||||
}
|
||||
|
||||
func NewTileBlock(class string) *Tile {
|
||||
func NewTileBlock() *Tile {
|
||||
return &Tile{
|
||||
Id: '#',
|
||||
Sprite: Assets[class],
|
||||
Class: class,
|
||||
Solid: true,
|
||||
Renderable: true,
|
||||
}
|
||||
}
|
||||
|
||||
func NewTileCollectible(class string) *Tile {
|
||||
func NewTileCollectible() *Tile {
|
||||
return &Tile{
|
||||
Id: 'o',
|
||||
Sprite: Assets[class],
|
||||
Class: class,
|
||||
Solid: false,
|
||||
Renderable: true,
|
||||
Collectible: true,
|
||||
Animation: TileAnimation{
|
||||
OnDestruction: true,
|
||||
DestructionSheet: Animations["collectible-detonating"],
|
||||
OnIdle: true,
|
||||
IdleSheet: Animations["collectible-idle"],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewTileObstacle(class string, direction int) *Tile {
|
||||
func NewTileObstacle(direction int) *Tile {
|
||||
return &Tile{
|
||||
Id: '+',
|
||||
Sprite: Assets[class],
|
||||
Class: class,
|
||||
Solid: false,
|
||||
Renderable: true,
|
||||
Obstacle: true,
|
||||
@@ -125,184 +138,122 @@ func NewTileObstacle(class string, direction int) *Tile {
|
||||
}
|
||||
}
|
||||
|
||||
func NewTileParticle(class []string) *Tile {
|
||||
sprites := []*ebiten.Image{}
|
||||
|
||||
for _, sprite := range class {
|
||||
sprites = append(sprites, Assets[sprite])
|
||||
}
|
||||
|
||||
func NewTileTranswall() *Tile {
|
||||
return &Tile{
|
||||
Id: '*',
|
||||
Class: "particle",
|
||||
Solid: false,
|
||||
Renderable: false,
|
||||
Particle: 0,
|
||||
Tiles: sprites,
|
||||
}
|
||||
}
|
||||
|
||||
func NewTileTranswall(class []string) *Tile {
|
||||
sprites := []*ebiten.Image{}
|
||||
names := []string{}
|
||||
|
||||
for _, sprite := range class {
|
||||
sprites = append(sprites, Assets[sprite])
|
||||
names = append(names, sprite)
|
||||
}
|
||||
|
||||
return &Tile{
|
||||
Id: 't',
|
||||
Class: "transwall",
|
||||
Solid: false,
|
||||
Renderable: true,
|
||||
Transient: true,
|
||||
Tiles: sprites,
|
||||
Sprite: sprites[0], // initially use the first
|
||||
TileNames: names,
|
||||
}
|
||||
}
|
||||
|
||||
func NewTileHiddenDoor(class []string) *Tile {
|
||||
sprites := []*ebiten.Image{}
|
||||
names := []string{}
|
||||
|
||||
for _, sprite := range class {
|
||||
sprites = append(sprites, Assets[sprite])
|
||||
names = append(names, sprite)
|
||||
}
|
||||
|
||||
func NewTileHiddenDoor(alpha string) *Tile {
|
||||
return &Tile{
|
||||
Id: 'W',
|
||||
Class: "hiddendoor",
|
||||
Solid: false,
|
||||
Renderable: true,
|
||||
Destroyable: true,
|
||||
Tiles: sprites,
|
||||
Sprite: sprites[0], // initially use the first
|
||||
TileNames: names,
|
||||
Alpha: Assets[alpha],
|
||||
Shader: Shaders["destruct"],
|
||||
}
|
||||
}
|
||||
|
||||
func NewTileSwitch() *Tile {
|
||||
return &Tile{
|
||||
Solid: false,
|
||||
Renderable: true,
|
||||
Bond: true,
|
||||
Switch: true,
|
||||
}
|
||||
}
|
||||
|
||||
func NewTileDoor() *Tile {
|
||||
return &Tile{
|
||||
Solid: false,
|
||||
Renderable: true,
|
||||
Bond: true,
|
||||
Door: true,
|
||||
}
|
||||
}
|
||||
|
||||
// used to map level data bytes to actual tiles
|
||||
type TileRegistry map[byte]*Tile
|
||||
|
||||
// holds a raw level spec:
|
||||
//
|
||||
// Name: the name of the level file w/o the .lvl extension
|
||||
// Background: an image name used as game background for this level
|
||||
// Description: text to display on top
|
||||
// Data: a level spec consisting of chars of the above mapping and spaces, e.g.:
|
||||
// ####
|
||||
// # #
|
||||
// ####
|
||||
//
|
||||
// Each level data must be 20 chars wide (= 640 px width) and 15 chars
|
||||
// high (=480 px height).
|
||||
type RawLevel struct {
|
||||
Name string
|
||||
Description string
|
||||
Background *ebiten.Image
|
||||
Data []byte
|
||||
}
|
||||
type TileRegistry map[string]*Tile
|
||||
|
||||
func InitTiles() TileRegistry {
|
||||
return TileRegistry{
|
||||
' ': {Id: ' ', Class: "floor", Renderable: false},
|
||||
//'#': NewTileBlock("block-grey32"),
|
||||
'#': NewTileBlock("block-greycolored"),
|
||||
'B': NewTileBlock("block-orange-32"),
|
||||
'S': NewTilePlayer(Primary),
|
||||
's': NewTilePlayer(Secondary),
|
||||
'o': NewTileCollectible("collectible-orange"),
|
||||
'+': NewTileObstacle("obstacle-star", config.All),
|
||||
'^': NewTileObstacle("obstacle-north", config.North),
|
||||
'v': NewTileObstacle("obstacle-south", config.South),
|
||||
'<': NewTileObstacle("obstacle-west", config.West),
|
||||
'>': NewTileObstacle("obstacle-east", config.East),
|
||||
'*': NewTileParticle([]string{
|
||||
//"particle-ring-1",
|
||||
"particle-ring-2",
|
||||
"particle-ring-3",
|
||||
"particle-ring-4",
|
||||
"particle-ring-5",
|
||||
"particle-ring-6",
|
||||
}),
|
||||
't': NewTileTranswall([]string{"transwall", "block-orange-32"}),
|
||||
'W': NewTileHiddenDoor([]string{"block-greycolored", "block-greycolored-damaged"}),
|
||||
"floor": {Renderable: false},
|
||||
"default": NewTileBlock(),
|
||||
"solidorange": NewTileBlock(),
|
||||
"PlayerPrimary": NewTilePlayer(Primary),
|
||||
"PlayerSecondary": NewTilePlayer(Secondary),
|
||||
"Collectible": NewTileCollectible(),
|
||||
"ObstacleStar": NewTileObstacle(config.All),
|
||||
"ObstacleNorth": NewTileObstacle(config.North),
|
||||
"ObstacleSouth": NewTileObstacle(config.South),
|
||||
"ObstacleWest": NewTileObstacle(config.West),
|
||||
"ObstacleEast": NewTileObstacle(config.East),
|
||||
"Transient": NewTileTranswall(),
|
||||
"HiddenDoor": NewTileHiddenDoor("damage"),
|
||||
"HiddenDoor2": NewTileHiddenDoor("damage"),
|
||||
"HiddenDoor3": NewTileHiddenDoor("damage"),
|
||||
"HiddenDoor4": NewTileHiddenDoor("damage"),
|
||||
"HiddenDoor5": NewTileHiddenDoor("damage"),
|
||||
"HiddenDoor6": NewTileHiddenDoor("damage"),
|
||||
"HiddenDoor7": NewTileHiddenDoor("damage"),
|
||||
"HiddenDoor8": NewTileHiddenDoor("damage"),
|
||||
"HiddenDoor9": NewTileHiddenDoor("damage"),
|
||||
"HiddenDoor10": NewTileHiddenDoor("damage"),
|
||||
"HiddenDoor11": NewTileHiddenDoor("damage"),
|
||||
"HiddenDoor12": NewTileHiddenDoor("damage"),
|
||||
"HiddenDoor13": NewTileHiddenDoor("damage"),
|
||||
"Switch": NewTileSwitch(),
|
||||
"Door": NewTileDoor(),
|
||||
}
|
||||
}
|
||||
|
||||
// load levels at compile time into ram, creates a slice of raw levels
|
||||
func LoadLevels(dir string) []RawLevel {
|
||||
levels := []RawLevel{}
|
||||
|
||||
// we use embed.FS to iterate over all files in ./levels/
|
||||
entries, err := assetfs.ReadDir(dir)
|
||||
// load LDTK project at compile time into ram
|
||||
func LoadLDTK(dir string) *ldtkgo.Project {
|
||||
fd, err := assetfs.Open("levels/openquell.ldtk")
|
||||
if err != nil {
|
||||
log.Fatalf("failed to read level dir %s: %s", dir, err)
|
||||
}
|
||||
|
||||
sort.Slice(entries, func(i, j int) bool {
|
||||
return entries[i].Name() < entries[j].Name()
|
||||
})
|
||||
|
||||
for _, levelfile := range entries {
|
||||
if levelfile.Type().IsRegular() && strings.Contains(levelfile.Name(), ".lvl") {
|
||||
path := filepath.Join("assets", dir)
|
||||
level := ParseRawLevel(path, levelfile)
|
||||
|
||||
levels = append(levels, level)
|
||||
|
||||
slog.Debug("loaded level", "path", path, "file", levelfile)
|
||||
}
|
||||
}
|
||||
|
||||
return levels
|
||||
}
|
||||
|
||||
func ParseRawLevel(dir string, levelfile fs.DirEntry) RawLevel {
|
||||
fd, err := os.Open(filepath.Join(dir, levelfile.Name()))
|
||||
if err != nil {
|
||||
log.Fatalf("failed to read level file %s: %s", levelfile.Name(), err)
|
||||
log.Fatalf("failed to open LDTK file levels/openquell.ldtk: %s", err)
|
||||
}
|
||||
defer fd.Close()
|
||||
|
||||
name := strings.TrimSuffix(levelfile.Name(), ".lvl")
|
||||
des := ""
|
||||
background := &ebiten.Image{}
|
||||
data := []byte{}
|
||||
|
||||
scanner := bufio.NewScanner(fd)
|
||||
for scanner.Scan() {
|
||||
// ignore any whitespace
|
||||
line := scanner.Text()
|
||||
|
||||
// ignore empty lines
|
||||
if len(line) == 0 {
|
||||
continue
|
||||
fileinfo, err := fd.Stat()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to stat() LDTK file levels/openquell.ldtk: %s", err)
|
||||
}
|
||||
|
||||
switch {
|
||||
case strings.Contains(line, "Background:"):
|
||||
haveit := strings.Split(line, ": ")
|
||||
if util.Exists(Assets, haveit[1]) {
|
||||
background = Assets[haveit[1]]
|
||||
filesize := fileinfo.Size()
|
||||
buffer := make([]byte, filesize)
|
||||
|
||||
_, err = fd.Read(buffer)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to read bytes from LDTK file levels/openquell.ldtk: %s", err)
|
||||
}
|
||||
case strings.Contains(line, "Description:"):
|
||||
haveit := strings.Split(line, ": ")
|
||||
des = haveit[1]
|
||||
default:
|
||||
// all other non-empty and non-equalsign lines are
|
||||
// level definition matrix data, merge thes into data
|
||||
data = append(data, line+"\n"...)
|
||||
|
||||
project, err := ldtkgo.Read(buffer)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// do some sanity checks
|
||||
properties := []string{"minmoves", "level", "description"}
|
||||
need := len(properties)
|
||||
|
||||
for idx, level := range project.Levels {
|
||||
have := 0
|
||||
|
||||
for _, property := range level.Properties {
|
||||
if util.Contains(properties, property.Identifier) {
|
||||
have++
|
||||
}
|
||||
}
|
||||
|
||||
return RawLevel{
|
||||
Name: name,
|
||||
Data: data,
|
||||
Background: background,
|
||||
Description: des,
|
||||
if have != need {
|
||||
log.Fatalf("level definition for level %d (%s) invalid: %d missing properties\n required: %s",
|
||||
idx, level.Identifier, need-have, strings.Join(properties, ", "),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return project
|
||||
}
|
||||
|
||||
49
assets/loader-shaders.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package assets
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"log"
|
||||
"log/slog"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
)
|
||||
|
||||
type ShaderRegistry map[string]*ebiten.Shader
|
||||
|
||||
var Shaders = LoadShaders("shaders")
|
||||
|
||||
func LoadShaders(dir string) ShaderRegistry {
|
||||
shaders := ShaderRegistry{}
|
||||
|
||||
entries, err := assetfs.ReadDir(dir)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to read shaders dir %s: %s", dir, err)
|
||||
}
|
||||
|
||||
for _, file := range entries {
|
||||
path := path.Join(dir, file.Name())
|
||||
fd, err := assetfs.Open(path)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to open shader file %s: %s", file.Name(), err)
|
||||
}
|
||||
defer fd.Close()
|
||||
|
||||
name := strings.TrimSuffix(file.Name(), ".kg")
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
buf.ReadFrom(fd)
|
||||
|
||||
shader, err := ebiten.NewShader([]byte(buf.Bytes()))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
shaders[name] = shader
|
||||
|
||||
slog.Debug("loaded shader asset", "path", path)
|
||||
}
|
||||
|
||||
return shaders
|
||||
}
|
||||
@@ -1,14 +1,17 @@
|
||||
package assets
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"embed"
|
||||
"encoding/json"
|
||||
"image"
|
||||
_ "image/png"
|
||||
"io/fs"
|
||||
"log"
|
||||
"log/slog"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
)
|
||||
@@ -16,13 +19,64 @@ import (
|
||||
// Maps image name to image data
|
||||
type AssetRegistry map[string]*ebiten.Image
|
||||
|
||||
//go:embed levels/*.lvl sprites/*.png fonts/*.ttf
|
||||
// A helper to pass the registry easier around
|
||||
type assetData struct {
|
||||
Registry AssetRegistry
|
||||
}
|
||||
|
||||
// to parse asesprite animation json
|
||||
type AnimationGeo struct {
|
||||
X int `json:"x"`
|
||||
Y int `json:"y"`
|
||||
Width int `json:"w"`
|
||||
Height int `json:"h"`
|
||||
}
|
||||
|
||||
type AnimationFrame struct {
|
||||
Position AnimationGeo `json:"frame"`
|
||||
Duration int `json:"duration"`
|
||||
}
|
||||
|
||||
type AnimationMeta struct {
|
||||
Name string `json:"image"`
|
||||
Geo AnimationGeo `json:"size"`
|
||||
}
|
||||
|
||||
// Needed to thaw sprite set written by asesprite
|
||||
type AnimationJSON struct {
|
||||
Meta AnimationMeta `json:"Meta"`
|
||||
Frames []AnimationFrame `json:"frames"`
|
||||
}
|
||||
|
||||
// used to store Animation data
|
||||
type AnimationSprite struct {
|
||||
Sprite *ebiten.Image
|
||||
Duration time.Duration
|
||||
}
|
||||
|
||||
type AnimationSet struct {
|
||||
Width, Height int
|
||||
Sprites []AnimationSprite
|
||||
File string
|
||||
}
|
||||
|
||||
// names in the registry match the sprite set png file name, the JSON
|
||||
// file names are irrelevant as they point to the matching file using
|
||||
// the "image" field.
|
||||
type AnimationRegistry map[string]AnimationSet
|
||||
|
||||
//go:embed sprites/*.png fonts/*.ttf levels/*.ldtk shaders/*.kg sprites/*.json
|
||||
var assetfs embed.FS
|
||||
|
||||
var Assets = LoadImages("sprites")
|
||||
// Called at build time, creates the global asset and animation registries
|
||||
var Assets, Animations = LoadImages()
|
||||
|
||||
func LoadImages(dir string) AssetRegistry {
|
||||
images := AssetRegistry{}
|
||||
// load pngs and json files
|
||||
func LoadImages() (AssetRegistry, AnimationRegistry) {
|
||||
dir := "sprites"
|
||||
imagedata := &assetData{}
|
||||
imagedata.Registry = AssetRegistry{}
|
||||
rawanimations := []AnimationJSON{}
|
||||
|
||||
// we use embed.FS to iterate over all files in ./assets/
|
||||
entries, err := assetfs.ReadDir(dir)
|
||||
@@ -31,13 +85,34 @@ func LoadImages(dir string) AssetRegistry {
|
||||
}
|
||||
|
||||
for _, imagefile := range entries {
|
||||
path := filepath.Join("assets", dir, imagefile.Name())
|
||||
fd, err := os.Open(path)
|
||||
path := path.Join(dir, imagefile.Name())
|
||||
|
||||
fd, err := assetfs.Open(path)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to open image file %s: %s", imagefile.Name(), err)
|
||||
log.Fatalf("failed to open file %s: %s", imagefile.Name(), err)
|
||||
}
|
||||
defer fd.Close()
|
||||
|
||||
switch {
|
||||
case strings.HasSuffix(path, ".png"):
|
||||
name, image := ReadImage(imagefile, fd)
|
||||
imagedata.Registry[name] = image
|
||||
|
||||
case strings.HasSuffix(path, ".json"):
|
||||
animationjson := ReadJson(imagefile, fd)
|
||||
rawanimations = append(rawanimations, animationjson)
|
||||
}
|
||||
|
||||
slog.Debug("loaded asset", "path", path)
|
||||
}
|
||||
|
||||
// preprocess animation sprites
|
||||
animations := ProcessAnimations(rawanimations, imagedata)
|
||||
|
||||
return imagedata.Registry, animations
|
||||
}
|
||||
|
||||
func ReadImage(imagefile fs.DirEntry, fd fs.File) (string, *ebiten.Image) {
|
||||
name := strings.TrimSuffix(imagefile.Name(), ".png")
|
||||
|
||||
img, _, err := image.Decode(fd)
|
||||
@@ -45,10 +120,58 @@ func LoadImages(dir string) AssetRegistry {
|
||||
log.Fatalf("failed to decode image %s: %s", imagefile.Name(), err)
|
||||
}
|
||||
|
||||
images[name] = ebiten.NewImageFromImage(img)
|
||||
image := ebiten.NewImageFromImage(img)
|
||||
|
||||
slog.Debug("loaded asset", "path", path)
|
||||
return name, image
|
||||
}
|
||||
|
||||
return images
|
||||
func ReadJson(imagefile fs.DirEntry, fd fs.File) AnimationJSON {
|
||||
buf := new(bytes.Buffer)
|
||||
buf.ReadFrom(fd)
|
||||
|
||||
animationjson := AnimationJSON{}
|
||||
|
||||
err := json.Unmarshal(buf.Bytes(), &animationjson)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to parse JSON: %s", err)
|
||||
}
|
||||
|
||||
return animationjson
|
||||
}
|
||||
|
||||
// turn a raw JSON from Asesprite into something we can use better
|
||||
// internally we also load all the sprites of an animation by using
|
||||
// image.SubImage() on the spriteset matching the animation name.
|
||||
// so, if the animation JSON is called "player-idle.json", then we
|
||||
// expect to receive the spriteset in a file "player-idle.png", which
|
||||
// has of course already been loaded at this stage. These spritesets
|
||||
// must contain a row of sprites. We get the measurements from the JSON.
|
||||
func ProcessAnimations(rawanimations []AnimationJSON, imagedata *assetData) AnimationRegistry {
|
||||
animations := AnimationRegistry{}
|
||||
|
||||
for _, animation := range rawanimations {
|
||||
animationset := AnimationSet{}
|
||||
|
||||
animationset.File = strings.TrimSuffix(animation.Meta.Name, ".png")
|
||||
|
||||
for _, frame := range animation.Frames {
|
||||
sprite := imagedata.Registry[animationset.File].SubImage(
|
||||
image.Rect(
|
||||
frame.Position.X,
|
||||
frame.Position.Y,
|
||||
frame.Position.X+frame.Position.Width,
|
||||
frame.Position.Y+frame.Position.Height,
|
||||
)).(*ebiten.Image)
|
||||
|
||||
animationset.Sprites = append(animationset.Sprites,
|
||||
AnimationSprite{Sprite: sprite, Duration: time.Duration(frame.Duration)})
|
||||
}
|
||||
|
||||
animationset.Width = animationset.Sprites[0].Sprite.Bounds().Dx()
|
||||
animationset.Height = animationset.Sprites[0].Sprite.Bounds().Dy()
|
||||
|
||||
animations[animationset.File] = animationset
|
||||
}
|
||||
|
||||
return animations
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 145 KiB After Width: | Height: | Size: 145 KiB |
BIN
assets/oldsprites/background-popup-wide.png
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
assets/oldsprites/background-popup.png
Normal file
|
After Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
BIN
assets/oldsprites/collectible-detonating.ase
Normal file
164
assets/oldsprites/collectible-detonating.json
Normal file
@@ -0,0 +1,164 @@
|
||||
{ "frames": [
|
||||
{
|
||||
"filename": "collectible-detonating 0.ase",
|
||||
"frame": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible-detonating 1.ase",
|
||||
"frame": { "x": 64, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible-detonating 2.ase",
|
||||
"frame": { "x": 128, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible-detonating 3.ase",
|
||||
"frame": { "x": 192, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible-detonating 4.ase",
|
||||
"frame": { "x": 256, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible-detonating 5.ase",
|
||||
"frame": { "x": 320, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible-detonating 6.ase",
|
||||
"frame": { "x": 384, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible-detonating 7.ase",
|
||||
"frame": { "x": 448, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible-detonating 8.ase",
|
||||
"frame": { "x": 512, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible-detonating 9.ase",
|
||||
"frame": { "x": 576, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible-detonating 10.ase",
|
||||
"frame": { "x": 640, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible-detonating 11.ase",
|
||||
"frame": { "x": 704, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible-detonating 12.ase",
|
||||
"frame": { "x": 768, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible-detonating 13.ase",
|
||||
"frame": { "x": 832, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible-detonating 14.ase",
|
||||
"frame": { "x": 896, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "http://www.aseprite.org/",
|
||||
"version": "1.x-dev",
|
||||
"image": "collectible-detonating.png",
|
||||
"format": "RGBA8888",
|
||||
"size": { "w": 960, "h": 64 },
|
||||
"scale": "1",
|
||||
"frameTags": [
|
||||
],
|
||||
"layers": [
|
||||
{ "name": "Yellow Sphere", "opacity": 255, "blendMode": "normal" },
|
||||
{ "name": "Layer 8", "opacity": 255, "blendMode": "normal" },
|
||||
{ "name": "Layer 7", "opacity": 255, "blendMode": "normal" },
|
||||
{ "name": "Layer 6", "opacity": 255, "blendMode": "normal" },
|
||||
{ "name": "Layer 5", "opacity": 255, "blendMode": "normal" },
|
||||
{ "name": "Layer 4", "opacity": 255, "blendMode": "normal" },
|
||||
{ "name": "Layer 3", "opacity": 255, "blendMode": "normal" },
|
||||
{ "name": "Layer 2", "opacity": 255, "blendMode": "normal" },
|
||||
{ "name": "Layer 1", "opacity": 255, "blendMode": "normal" },
|
||||
{ "name": "Blitz Outer", "opacity": 70, "blendMode": "normal" },
|
||||
{ "name": "Blitz Middle", "opacity": 84, "blendMode": "normal" },
|
||||
{ "name": "Blitz Inner", "opacity": 97, "blendMode": "normal" }
|
||||
],
|
||||
"slices": [
|
||||
]
|
||||
}
|
||||
}
|
||||
BIN
assets/oldsprites/collectible-detonating.png
Normal file
|
After Width: | Height: | Size: 6.6 KiB |
BIN
assets/oldsprites/collectible-detonating1.png
Normal file
|
After Width: | Height: | Size: 647 B |
BIN
assets/oldsprites/collectible-detonating10.png
Normal file
|
After Width: | Height: | Size: 689 B |
BIN
assets/oldsprites/collectible-detonating11.png
Normal file
|
After Width: | Height: | Size: 472 B |
BIN
assets/oldsprites/collectible-detonating12.png
Normal file
|
After Width: | Height: | Size: 325 B |
BIN
assets/oldsprites/collectible-detonating13.png
Normal file
|
After Width: | Height: | Size: 179 B |
BIN
assets/oldsprites/collectible-detonating14.png
Normal file
|
After Width: | Height: | Size: 179 B |
BIN
assets/oldsprites/collectible-detonating15.png
Normal file
|
After Width: | Height: | Size: 109 B |
BIN
assets/oldsprites/collectible-detonating2.png
Normal file
|
After Width: | Height: | Size: 716 B |
BIN
assets/oldsprites/collectible-detonating3.png
Normal file
|
After Width: | Height: | Size: 783 B |
BIN
assets/oldsprites/collectible-detonating4.png
Normal file
|
After Width: | Height: | Size: 802 B |
BIN
assets/oldsprites/collectible-detonating5.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
assets/oldsprites/collectible-detonating6.png
Normal file
|
After Width: | Height: | Size: 909 B |
BIN
assets/oldsprites/collectible-detonating7.png
Normal file
|
After Width: | Height: | Size: 924 B |
BIN
assets/oldsprites/collectible-detonating8.png
Normal file
|
After Width: | Height: | Size: 937 B |
BIN
assets/oldsprites/collectible-detonating9.png
Normal file
|
After Width: | Height: | Size: 876 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
BIN
assets/oldsprites/collectible.ase
Normal file
BIN
assets/oldsprites/collectible.png
Normal file
|
After Width: | Height: | Size: 577 B |
BIN
assets/oldsprites/damage.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
assets/oldsprites/door.ase
Normal file
BIN
assets/oldsprites/door1.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
assets/oldsprites/door2.png
Normal file
|
After Width: | Height: | Size: 271 B |
BIN
assets/oldsprites/entitymap.png
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
assets/oldsprites/hud.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
2
assets/oldsprites/makemap.sh
Normal file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
montage -tile 4x0 -geometry +0+0 block* collectible-orange.png obstacle-* sphere-blue* transwall.png map.png && okular map.png
|
||||
BIN
assets/oldsprites/map.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
assets/oldsprites/menu.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
assets/oldsprites/obstacle-east.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
assets/oldsprites/obstacle-north.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
assets/oldsprites/obstacle-south.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
assets/oldsprites/obstacle-star.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
assets/oldsprites/obstacle-west.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
assets/oldsprites/primarymap.png
Normal file
|
After Width: | Height: | Size: 132 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.3 KiB |
BIN
assets/oldsprites/switch.ase
Normal file
BIN
assets/oldsprites/switch1.png
Normal file
|
After Width: | Height: | Size: 503 B |
BIN
assets/oldsprites/switch2.png
Normal file
|
After Width: | Height: | Size: 543 B |
BIN
assets/oldsprites/tilemap.png
Normal file
|
After Width: | Height: | Size: 141 KiB |
BIN
assets/oldsprites/transwall.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
assets/oldsprites/woddendoor.ase
Normal file
36
assets/shaders/destruct.kg
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright 2020 The Ebiten Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build ignore
|
||||
|
||||
//kage:unit pixels
|
||||
|
||||
package main
|
||||
|
||||
var Damaged int
|
||||
|
||||
const HP float = 0
|
||||
|
||||
func Fragment(_ vec4, texCoord vec2, _ vec4) vec4 {
|
||||
wallpx := imageSrc0At(texCoord) // A pixel from the wall tile
|
||||
mask := imageSrc1At(texCoord) // A pixel from the damage mask image
|
||||
|
||||
if Damaged == 1 && (wallpx.a != 0.0 && mask.a != 0.0) {
|
||||
alpha := clamp(HP+(1.0-mask.a), 0.0, 1.0)
|
||||
// Create a darker pixel if it's inside a damage mask.
|
||||
return vec4(wallpx.r*alpha, wallpx.g*alpha, wallpx.b*alpha, wallpx.a)
|
||||
}
|
||||
|
||||
return wallpx // Otherwise, leave a pixel color as is
|
||||
}
|
||||
49
assets/sprites/apollo.pal
Normal file
@@ -0,0 +1,49 @@
|
||||
JASC-PAL
|
||||
0100
|
||||
46
|
||||
23 32 56
|
||||
37 58 94
|
||||
60 94 139
|
||||
79 143 186
|
||||
115 190 211
|
||||
164 221 219
|
||||
25 51 45
|
||||
37 86 46
|
||||
70 130 50
|
||||
117 167 67
|
||||
168 202 88
|
||||
208 218 145
|
||||
77 43 50
|
||||
122 72 65
|
||||
173 119 87
|
||||
192 148 115
|
||||
215 181 148
|
||||
231 213 179
|
||||
52 28 39
|
||||
96 44 44
|
||||
136 75 43
|
||||
190 119 43
|
||||
222 158 65
|
||||
232 193 112
|
||||
36 21 39
|
||||
65 29 49
|
||||
117 36 56
|
||||
165 48 48
|
||||
207 87 60
|
||||
218 134 62
|
||||
30 29 57
|
||||
64 39 81
|
||||
122 54 123
|
||||
162 62 140
|
||||
198 81 151
|
||||
223 132 165
|
||||
9 10 20
|
||||
16 20 31
|
||||
21 29 40
|
||||
32 46 55
|
||||
57 74 80
|
||||
87 114 119
|
||||
129 151 150
|
||||
168 181 178
|
||||
199 207 204
|
||||
235 237 233
|
||||
|
Before Width: | Height: | Size: 152 KiB |
BIN
assets/sprites/background-popup-wide.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
BIN
assets/sprites/background1.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
assets/sprites/background2.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
assets/sprites/background3.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
assets/sprites/background4.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
181
assets/sprites/backgroundstars-animated.json
Normal file
@@ -0,0 +1,181 @@
|
||||
{ "frames": [
|
||||
{
|
||||
"filename": "backgroundstars 0.ase",
|
||||
"frame": { "x": 0, "y": 0, "w": 640, "h": 384 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 640, "h": 384 },
|
||||
"sourceSize": { "w": 640, "h": 384 },
|
||||
"duration": 2000
|
||||
},
|
||||
{
|
||||
"filename": "backgroundstars 1.ase",
|
||||
"frame": { "x": 640, "y": 0, "w": 640, "h": 384 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 640, "h": 384 },
|
||||
"sourceSize": { "w": 640, "h": 384 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "backgroundstars 2.ase",
|
||||
"frame": { "x": 1280, "y": 0, "w": 640, "h": 384 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 640, "h": 384 },
|
||||
"sourceSize": { "w": 640, "h": 384 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "backgroundstars 3.ase",
|
||||
"frame": { "x": 1920, "y": 0, "w": 640, "h": 384 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 640, "h": 384 },
|
||||
"sourceSize": { "w": 640, "h": 384 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "backgroundstars 4.ase",
|
||||
"frame": { "x": 2560, "y": 0, "w": 640, "h": 384 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 640, "h": 384 },
|
||||
"sourceSize": { "w": 640, "h": 384 },
|
||||
"duration": 2000
|
||||
},
|
||||
{
|
||||
"filename": "backgroundstars 5.ase",
|
||||
"frame": { "x": 3200, "y": 0, "w": 640, "h": 384 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 640, "h": 384 },
|
||||
"sourceSize": { "w": 640, "h": 384 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "backgroundstars 6.ase",
|
||||
"frame": { "x": 3840, "y": 0, "w": 640, "h": 384 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 640, "h": 384 },
|
||||
"sourceSize": { "w": 640, "h": 384 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "backgroundstars 7.ase",
|
||||
"frame": { "x": 4480, "y": 0, "w": 640, "h": 384 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 640, "h": 384 },
|
||||
"sourceSize": { "w": 640, "h": 384 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "backgroundstars 8.ase",
|
||||
"frame": { "x": 5120, "y": 0, "w": 640, "h": 384 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 640, "h": 384 },
|
||||
"sourceSize": { "w": 640, "h": 384 },
|
||||
"duration": 2000
|
||||
},
|
||||
{
|
||||
"filename": "backgroundstars 9.ase",
|
||||
"frame": { "x": 5760, "y": 0, "w": 640, "h": 384 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 640, "h": 384 },
|
||||
"sourceSize": { "w": 640, "h": 384 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "backgroundstars 10.ase",
|
||||
"frame": { "x": 6400, "y": 0, "w": 640, "h": 384 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 640, "h": 384 },
|
||||
"sourceSize": { "w": 640, "h": 384 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "backgroundstars 11.ase",
|
||||
"frame": { "x": 7040, "y": 0, "w": 640, "h": 384 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 640, "h": 384 },
|
||||
"sourceSize": { "w": 640, "h": 384 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "backgroundstars 12.ase",
|
||||
"frame": { "x": 7680, "y": 0, "w": 640, "h": 384 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 640, "h": 384 },
|
||||
"sourceSize": { "w": 640, "h": 384 },
|
||||
"duration": 2000
|
||||
},
|
||||
{
|
||||
"filename": "backgroundstars 13.ase",
|
||||
"frame": { "x": 8320, "y": 0, "w": 640, "h": 384 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 640, "h": 384 },
|
||||
"sourceSize": { "w": 640, "h": 384 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "backgroundstars 14.ase",
|
||||
"frame": { "x": 8960, "y": 0, "w": 640, "h": 384 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 640, "h": 384 },
|
||||
"sourceSize": { "w": 640, "h": 384 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "backgroundstars 15.ase",
|
||||
"frame": { "x": 9600, "y": 0, "w": 640, "h": 384 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 640, "h": 384 },
|
||||
"sourceSize": { "w": 640, "h": 384 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "backgroundstars 16.ase",
|
||||
"frame": { "x": 10240, "y": 0, "w": 640, "h": 384 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 640, "h": 384 },
|
||||
"sourceSize": { "w": 640, "h": 384 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "backgroundstars 17.ase",
|
||||
"frame": { "x": 10880, "y": 0, "w": 640, "h": 384 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 640, "h": 384 },
|
||||
"sourceSize": { "w": 640, "h": 384 },
|
||||
"duration": 2000
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "http://www.aseprite.org/",
|
||||
"version": "1.x-dev",
|
||||
"image": "backgroundstars-animated.png",
|
||||
"format": "RGBA8888",
|
||||
"size": { "w": 11520, "h": 384 },
|
||||
"scale": "1",
|
||||
"frameTags": [
|
||||
],
|
||||
"layers": [
|
||||
{ "name": "background", "opacity": 255, "blendMode": "normal" },
|
||||
{ "name": "stars", "opacity": 124, "blendMode": "normal" }
|
||||
],
|
||||
"slices": [
|
||||
]
|
||||
}
|
||||
}
|
||||
BIN
assets/sprites/backgroundstars-animated.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
assets/sprites/backgroundstars.ase
Normal file
BIN
assets/sprites/backgroundstars.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 584 B |
156
assets/sprites/collectible-detonating.json
Normal file
@@ -0,0 +1,156 @@
|
||||
{ "frames": [
|
||||
{
|
||||
"filename": "collectible #Detonation 0.ase",
|
||||
"frame": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 20
|
||||
},
|
||||
{
|
||||
"filename": "collectible #Detonation 1.ase",
|
||||
"frame": { "x": 64, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 20
|
||||
},
|
||||
{
|
||||
"filename": "collectible #Detonation 2.ase",
|
||||
"frame": { "x": 128, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 20
|
||||
},
|
||||
{
|
||||
"filename": "collectible #Detonation 3.ase",
|
||||
"frame": { "x": 192, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 20
|
||||
},
|
||||
{
|
||||
"filename": "collectible #Detonation 4.ase",
|
||||
"frame": { "x": 256, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible #Detonation 5.ase",
|
||||
"frame": { "x": 320, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible #Detonation 6.ase",
|
||||
"frame": { "x": 384, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible #Detonation 7.ase",
|
||||
"frame": { "x": 448, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible #Detonation 8.ase",
|
||||
"frame": { "x": 512, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible #Detonation 9.ase",
|
||||
"frame": { "x": 576, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible #Detonation 10.ase",
|
||||
"frame": { "x": 640, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible #Detonation 11.ase",
|
||||
"frame": { "x": 704, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible #Detonation 12.ase",
|
||||
"frame": { "x": 768, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible #Detonation 13.ase",
|
||||
"frame": { "x": 832, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "http://www.aseprite.org/",
|
||||
"version": "1.x-dev",
|
||||
"image": "collectible-detonating.png",
|
||||
"format": "I8",
|
||||
"size": { "w": 896, "h": 64 },
|
||||
"scale": "1",
|
||||
"frameTags": [
|
||||
{ "name": "Detonation", "from": 1, "to": 14, "direction": "forward" }
|
||||
],
|
||||
"layers": [
|
||||
{ "name": "Yellow Sphere", "opacity": 255, "blendMode": "normal" },
|
||||
{ "name": "Layer 8", "opacity": 255, "blendMode": "normal" },
|
||||
{ "name": "Layer 7", "opacity": 255, "blendMode": "normal" },
|
||||
{ "name": "Layer 6", "opacity": 255, "blendMode": "normal" },
|
||||
{ "name": "Layer 5", "opacity": 255, "blendMode": "normal" },
|
||||
{ "name": "Layer 4", "opacity": 255, "blendMode": "normal" },
|
||||
{ "name": "Layer 3", "opacity": 255, "blendMode": "normal" },
|
||||
{ "name": "Layer 2", "opacity": 255, "blendMode": "normal" },
|
||||
{ "name": "Layer 1", "opacity": 255, "blendMode": "normal" },
|
||||
{ "name": "Blitz Outer", "opacity": 70, "blendMode": "normal" },
|
||||
{ "name": "Blitz Middle", "opacity": 84, "blendMode": "normal" },
|
||||
{ "name": "Blitz Inner", "opacity": 97, "blendMode": "normal" }
|
||||
],
|
||||
"slices": [
|
||||
]
|
||||
}
|
||||
}
|
||||
BIN
assets/sprites/collectible-detonating.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
assets/sprites/collectible-idle.ase
Normal file
54
assets/sprites/collectible-idle.json
Normal file
@@ -0,0 +1,54 @@
|
||||
{ "frames": [
|
||||
{
|
||||
"filename": "collectible-idle 0.ase",
|
||||
"frame": { "x": 0, "y": 0, "w": 32, "h": 32 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
|
||||
"sourceSize": { "w": 32, "h": 32 },
|
||||
"duration": 200
|
||||
},
|
||||
{
|
||||
"filename": "collectible-idle 1.ase",
|
||||
"frame": { "x": 32, "y": 0, "w": 32, "h": 32 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
|
||||
"sourceSize": { "w": 32, "h": 32 },
|
||||
"duration": 200
|
||||
},
|
||||
{
|
||||
"filename": "collectible-idle 2.ase",
|
||||
"frame": { "x": 64, "y": 0, "w": 32, "h": 32 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
|
||||
"sourceSize": { "w": 32, "h": 32 },
|
||||
"duration": 200
|
||||
},
|
||||
{
|
||||
"filename": "collectible-idle 3.ase",
|
||||
"frame": { "x": 96, "y": 0, "w": 32, "h": 32 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
|
||||
"sourceSize": { "w": 32, "h": 32 },
|
||||
"duration": 200
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "http://www.aseprite.org/",
|
||||
"version": "1.x-dev",
|
||||
"image": "collectible-idle.png",
|
||||
"format": "RGBA8888",
|
||||
"size": { "w": 128, "h": 32 },
|
||||
"scale": "1",
|
||||
"frameTags": [
|
||||
],
|
||||
"layers": [
|
||||
{ "name": "Layer 1", "opacity": 255, "blendMode": "normal" }
|
||||
],
|
||||
"slices": [
|
||||
]
|
||||
}
|
||||
}
|
||||
BIN
assets/sprites/collectible-idle.png
Normal file
|
After Width: | Height: | Size: 931 B |
BIN
assets/sprites/collectible.ase
Normal file
BIN
assets/sprites/collectible.png
Normal file
|
After Width: | Height: | Size: 448 B |
BIN
assets/sprites/door.ase
Normal file
BIN
assets/sprites/door1.png
Normal file
|
After Width: | Height: | Size: 615 B |
BIN
assets/sprites/door2.png
Normal file
|
After Width: | Height: | Size: 357 B |
BIN
assets/sprites/entitymap.png
Normal file
|
After Width: | Height: | Size: 7.0 KiB |
BIN
assets/sprites/entitymap.xcf
Normal file
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.4 KiB |
BIN
assets/sprites/menu.png
Normal file
|
After Width: | Height: | Size: 712 B |
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 967 B |
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 935 B |
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 950 B |
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 1023 B |
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 963 B |
|
Before Width: | Height: | Size: 5.8 KiB |