Compare commits

..

1 Commits

304 changed files with 1480 additions and 10578 deletions

505
.ackrc
View File

@ -1,505 +0,0 @@
--ignore-ack-defaults
# This is the default ackrc for ack version v3.7.0.
# There are four different ways to match
#
# is: Match the filename exactly
#
# ext: Match the extension of the filename exactly
#
# match: Match the filename against a Perl regular expression
#
# firstlinematch: Match the first 250 characters of the first line
# of text against a Perl regular expression. This is only for
# the --type-add option.
### Directories to ignore
# Bazaar
# https://bazaar.canonical.com/
--ignore-directory=is:.bzr
# Codeville
# http://freshmeat.sourceforge.net/projects/codeville
--ignore-directory=is:.cdv
# Interface Builder (Xcode)
# https://en.wikipedia.org/wiki/Interface_Builder
--ignore-directory=is:~.dep
--ignore-directory=is:~.dot
--ignore-directory=is:~.nib
--ignore-directory=is:~.plst
# Git
# https://git-scm.com/
--ignore-directory=is:.git
# When submodules are used, .git is a file.
--ignore-file=is:.git
# Mercurial
# https://www.mercurial-scm.org/
--ignore-directory=is:.hg
# Quilt
# https://directory.fsf.org/wiki/Quilt
--ignore-directory=is:.pc
# Subversion
# https://subversion.apache.org/
--ignore-directory=is:.svn
# Monotone
# https://www.monotone.ca/
--ignore-directory=is:_MTN
# CVS
# https://savannah.nongnu.org/projects/cvs
--ignore-directory=is:CVS
# RCS
# https://www.gnu.org/software/rcs/
--ignore-directory=is:RCS
# SCCS
# https://en.wikipedia.org/wiki/Source_Code_Control_System
--ignore-directory=is:SCCS
# darcs
# http://darcs.net/
--ignore-directory=is:_darcs
# Vault/Fortress
--ignore-directory=is:_sgbak
# autoconf
# https://www.gnu.org/software/autoconf/
--ignore-directory=is:autom4te.cache
# Perl module building
--ignore-directory=is:blib
--ignore-directory=is:_build
# Perl Devel::Cover module's output directory
# https://metacpan.org/release/Devel-Cover
--ignore-directory=is:cover_db
# Node modules created by npm
--ignore-directory=is:node_modules
# CMake cache
# https://www.cmake.org/
--ignore-directory=is:CMakeFiles
# Eclipse workspace folder
# https://eclipse.org/
--ignore-directory=is:.metadata
# Cabal (Haskell) sandboxes
# https://www.haskell.org/cabal/users-guide/installing-packages.html
--ignore-directory=is:.cabal-sandbox
# Python caches
# https://docs.python.org/3/tutorial/modules.html
--ignore-directory=is:__pycache__
--ignore-directory=is:.pytest_cache
# macOS Finder remnants
--ignore-directory=is:__MACOSX
--ignore-file=is:.DS_Store
### Files to ignore
# Backup files
--ignore-file=ext:bak
--ignore-file=match:/~$/
# Emacs swap files
--ignore-file=match:/^#.+#$/
# vi/vim swap files https://www.vim.org/
--ignore-file=match:/[._].*[.]swp$/
# core dumps
--ignore-file=match:/core[.]\d+$/
# minified JavaScript
--ignore-file=match:/[.-]min[.]js$/
--ignore-file=match:/[.]js[.]min$/
# minified CSS
--ignore-file=match:/[.]min[.]css$/
--ignore-file=match:/[.]css[.]min$/
# JS and CSS source maps
--ignore-file=match:/[.]js[.]map$/
--ignore-file=match:/[.]css[.]map$/
# PDFs, because they pass Perl's -T detection
--ignore-file=ext:pdf
# Common graphics, just as an optimization
--ignore-file=ext:gif,jpg,jpeg,png
# Common archives, as an optimization
--ignore-file=ext:gz,tar,tgz,zip
# Python compiled modules
--ignore-file=ext:pyc,pyd,pyo
# Python's pickle serialization format
# https://docs.python.org/2/library/pickle.html#example
# https://docs.python.org/3.7/library/pickle.html#examples
--ignore-file=ext:pkl,pickle
# C extensions
--ignore-file=ext:so
# Compiled gettext files
--ignore-file=ext:mo
# Visual Studio user and workspace settings
# https://code.visualstudio.com/docs/getstarted/settings
--ignore-dir=is:.vscode
### Filetypes defined
# Makefiles
# https://www.gnu.org/s/make/
--type-add=make:ext:mk
--type-add=make:ext:mak
--type-add=make:is:makefile
--type-add=make:is:Makefile
--type-add=make:is:Makefile.Debug
--type-add=make:is:Makefile.Release
--type-add=make:is:GNUmakefile
# Rakefiles
# https://rake.rubyforge.org/
--type-add=rake:is:Rakefile
# CMake
# https://cmake.org/
--type-add=cmake:is:CMakeLists.txt
--type-add=cmake:ext:cmake
# Bazel build tool
# https://docs.bazel.build/versions/master/skylark/bzl-style.html
--type-add=bazel:ext:bzl
# https://docs.bazel.build/versions/master/guide.html#bazelrc-the-bazel-configuration-file
--type-add=bazel:ext:bazelrc
# https://docs.bazel.build/versions/master/build-ref.html#BUILD_files
--type-add=bazel:is:BUILD
# https://docs.bazel.build/versions/master/build-ref.html#workspace
--type-add=bazel:is:WORKSPACE
# Actionscript
--type-add=actionscript:ext:as,mxml
# Ada
# https://www.adaic.org/
--type-add=ada:ext:ada,adb,ads
# ASP
# https://docs.microsoft.com/en-us/previous-versions/office/developer/server-technologies/aa286483(v=msdn.10)
--type-add=asp:ext:asp
# ASP.Net
# https://dotnet.microsoft.com/apps/aspnet
--type-add=aspx:ext:master,ascx,asmx,aspx,svc
# Assembly
--type-add=asm:ext:asm,s
# DOS/Windows batch
--type-add=batch:ext:bat,cmd
# ColdFusion
# https://en.wikipedia.org/wiki/ColdFusion
--type-add=cfmx:ext:cfc,cfm,cfml
# Clojure
# https://clojure.org/
--type-add=clojure:ext:clj,cljs,edn,cljc
# C
# .xs are Perl C files
--type-add=cc:ext:c,h,xs
# C header files
--type-add=hh:ext:h
# CoffeeScript
# https://coffeescript.org/
--type-add=coffeescript:ext:coffee
# C++
--type-add=cpp:ext:cpp,cc,cxx,m,hpp,hh,h,hxx
# C++ header files
--type-add=hpp:ext:hpp,hh,h,hxx
# C#
--type-add=csharp:ext:cs
# Crystal-lang
# https://crystal-lang.org/
--type-add=crystal:ext:cr,ecr
# CSS
# https://www.w3.org/Style/CSS/
--type-add=css:ext:css
# Dart
# https://dart.dev/
--type-add=dart:ext:dart
# Delphi
# https://en.wikipedia.org/wiki/Embarcadero_Delphi
--type-add=delphi:ext:pas,int,dfm,nfm,dof,dpk,dproj,groupproj,bdsgroup,bdsproj
# Elixir
# https://elixir-lang.org/
--type-add=elixir:ext:ex,exs
# Elm
# https://elm-lang.org
--type-add=elm:ext:elm
# Emacs Lisp
# https://www.gnu.org/software/emacs
--type-add=elisp:ext:el
# Erlang
# https://www.erlang.org/
--type-add=erlang:ext:erl,hrl
# Fortran
# https://en.wikipedia.org/wiki/Fortran
--type-add=fortran:ext:f,f77,f90,f95,f03,for,ftn,fpp
# Go
# https://golang.org/
--type-add=go:ext:go
# Groovy
# https://www.groovy-lang.org/
--type-add=groovy:ext:groovy,gtmpl,gpp,grunit,gradle
# GSP
# https://gsp.grails.org/
--type-add=gsp:ext:gsp
# Haskell
# https://www.haskell.org/
--type-add=haskell:ext:hs,lhs
# HTML
--type-add=html:ext:htm,html,xhtml
# Jade
# http://jade-lang.com/
--type-add=jade:ext:jade
# Java
# https://www.oracle.com/technetwork/java/index.html
--type-add=java:ext:java,properties
# JavaScript
--type-add=js:ext:js
# JSP
# https://www.oracle.com/technetwork/java/javaee/jsp/index.html
--type-add=jsp:ext:jsp,jspx,jspf,jhtm,jhtml
# JSON
# https://json.org/
--type-add=json:ext:json
# Kotlin
# https://kotlinlang.org/
--type-add=kotlin:ext:kt,kts
# Less
# http://www.lesscss.org/
--type-add=less:ext:less
# Common Lisp
# https://common-lisp.net/
--type-add=lisp:ext:lisp,lsp
# Lua
# https://www.lua.org/
--type-add=lua:ext:lua
--type-add=lua:firstlinematch:/^#!.*\blua(jit)?/
# Markdown
# https://en.wikipedia.org/wiki/Markdown
--type-add=markdown:ext:md,markdown
# We understand that there are many ad hoc extensions for markdown
# that people use. .md and .markdown are the two that ack recognizes.
# You are free to add your own in your ackrc file.
# Matlab
# https://en.wikipedia.org/wiki/MATLAB
--type-add=matlab:ext:m
# Objective-C
--type-add=objc:ext:m,h
# Objective-C++
--type-add=objcpp:ext:mm,h
# OCaml
# https://ocaml.org/
--type-add=ocaml:ext:ml,mli,mll,mly
# Perl
# https://perl.org/
--type-add=perl:ext:pl,pm,pod,t,psgi
--type-add=perl:firstlinematch:/^#!.*\bperl/
# Perl tests
--type-add=perltest:ext:t
# Perl's Plain Old Documentation format, POD
--type-add=pod:ext:pod
# PHP
# https://www.php.net/
--type-add=php:ext:php,phpt,php3,php4,php5,phtml
--type-add=php:firstlinematch:/^#!.*\bphp/
# Plone
# https://plone.org/
--type-add=plone:ext:pt,cpt,metadata,cpy,py
# PowerShell
# https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_scripts
# https://learn.microsoft.com/en-us/powershell/scripting/developer/module/understanding-a-windows-powershell-module
--type-add=powershell:ext:ps1,psm1
# PureScript
# https://www.purescript.org
--type-add=purescript:ext:purs
# Python
# https://www.python.org/
--type-add=python:ext:py
--type-add=python:firstlinematch:/^#!.*\bpython/
# R
# https://www.r-project.org/
# https://r4ds.had.co.nz/r-markdown.html
--type-add=rr:ext:R,Rmd
# reStructured Text
# https://docutils.sourceforge.io/rst.html
--type-add=rst:ext:rst
# Ruby
# https://www.ruby-lang.org/
--type-add=ruby:ext:rb,rhtml,rjs,rxml,erb,rake,spec
--type-add=ruby:is:Rakefile
--type-add=ruby:firstlinematch:/^#!.*\bruby/
# Rust
# https://www.rust-lang.org/
--type-add=rust:ext:rs
# Sass
# https://sass-lang.com
--type-add=sass:ext:sass,scss
# Scala
# https://www.scala-lang.org/
--type-add=scala:ext:scala,sbt
# Scheme
# https://groups.csail.mit.edu/mac/projects/scheme/
--type-add=scheme:ext:scm,ss
# Shell
--type-add=shell:ext:sh,bash,csh,tcsh,ksh,zsh,fish
--type-add=shell:firstlinematch:/^#!.*\b(?:ba|t?c|k|z|fi)?sh\b/
# Smalltalk
# http://www.smalltalk.org/
--type-add=smalltalk:ext:st
# Smarty
# https://www.smarty.net/
--type-add=smarty:ext:tpl
# SQL
# https://www.iso.org/standard/45498.html
--type-add=sql:ext:sql,ctl
# Stylus
# http://stylus-lang.com/
--type-add=stylus:ext:styl
# SVG
# https://en.wikipedia.org/wiki/Scalable_Vector_Graphics
--type-add=svg:ext:svg
# Swift
# https://developer.apple.com/swift/
--type-add=swift:ext:swift
--type-add=swift:firstlinematch:/^#!.*\bswift/
# Tcl
# https://www.tcl.tk/
--type-add=tcl:ext:tcl,itcl,itk
# TeX & LaTeX
# https://www.latex-project.org/
--type-add=tex:ext:tex,cls,sty
# Template Toolkit (Perl)
# http//template-toolkit.org/
--type-add=ttml:ext:tt,tt2,ttml
# TOML
# https://toml.io/
--type-add=toml:ext:toml
# TypeScript
# https://www.typescriptlang.org/
--type-add=ts:ext:ts,tsx
# Visual Basic
--type-add=vb:ext:bas,cls,frm,ctl,vb,resx
# Verilog
--type-add=verilog:ext:v,vh,sv
# VHDL
# http://www.eda.org/twiki/bin/view.cgi/P1076/WebHome
--type-add=vhdl:ext:vhd,vhdl
# Vim
# https://www.vim.org/
--type-add=vim:ext:vim
# XML
# https://www.w3.org/TR/REC-xml/
--type-add=xml:ext:xml,dtd,xsd,xsl,xslt,ent,wsdl
--type-add=xml:firstlinematch:/<[?]xml/
# YAML
# https://yaml.org/
--type-add=yaml:ext:yaml,yml
# TOM
--ignore-directory=is:src
--ignore-directory=is:tmp
--ignore-directory=is:fonts
--ignore-file=ext:ldtk
--ignore-file=ext:png
--ignore-file=ext:ase
--ignore-file=ext:json
--ignore-file=ext:svg

3
.gitignore vendored
View File

@ -1,2 +1 @@
openquell*
tmp
openquell

View File

@ -1,12 +1,3 @@
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
@ -14,22 +5,8 @@ clean:
rm -f openquell
build:
go build -ldflags "-X 'openquell/config.VERSION=$(VERSION)'"
go build
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 $(VERSION)
nixshell:
nix-shell -p xorg.libX11 xorg.libXrandr libGL xorg.libXcursor xorg.libXinerama xorg.libXi xorg.libXxf86vm xorg_sys_opengl
@echo 1

62
TODO.md
View File

@ -1,46 +1,32 @@
## Levels:
- 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.
- ignore comments in lvl files
- Turn menu button in hud_system (events in level_scene!) into ebitenui button
- 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
- Obstacle don't stop at collectibles
- 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
- Player can collect collectible hidden under obstacle (should be
fixed when above is fixed)
- Add player idle animation
- Grid Observer:
https://github.com/mlange-42/arche/issues/374
- Add player collision animation
- Add some final message when the player reaches the last level, start
from scratch or a message to buy me some beer, whatever
- Create pixel art ui elements (button, list things) and ui borders/backgrounds
Replace HUD with pixel art variant
- Check player-player collisions!
- Modify font and font color matching the palette
- 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.
- On game start respond to any key (ebitengine-input has an anykey func)
- Add shaders for animation (player destruction etc)
- Switch to use https://github.com/quasilyte/ebitengine-input
- Add player HUD + Stats (as hud_system!)
- 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)
- Rework sprites (again!) to match stellar background: maybe more
technical tiles and items? Like some robotic setup?
## Collider Rework [abandoned: see branch collider-system, fails]
## Collider Rework
- do not use the map anymore for collision detection
- central collision_system
@ -58,17 +44,3 @@
Collider.IntersectResolve => func(newpos) {player.pos = newpos; player.vel = stop}
- in the end it must be possible to add new entities without the need
to write a collision check for them, but have collision detection anyway!
## Just in case stuff
- 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)

View File

@ -0,0 +1,17 @@
Description: test obstacles
Background: background-lila
#######
#o #
# t #
#> S <#
# #
# ^ #
#######

View File

@ -0,0 +1,17 @@
Description: test obstacles
Background: background-lila
#############
# t #
#> S # #
# ># ^#
#< #W#####
# o v# o#
#############

View File

@ -0,0 +1,17 @@
Description: find the fruit
Background: background-lila
# ############
# #
############ #
# o S #
# ######## ###
+ #
############ #
# o # #
# # ######## #
# # o
# ############

17
assets/levels/03-own.lvl Normal file
View File

@ -0,0 +1,17 @@
Description: win
Background: background-lila
########
#v o #
# S<# #
# #### #
# #### #
# #
#> ^#
########

View File

@ -0,0 +1,17 @@
Description: use multiple players
Background: background-lila
########W#
# v #
# #
#S s#
############
# o #
######## #

View File

@ -0,0 +1,17 @@
Description: space
Background: background-lila
#
S
#

30
assets/levels/gen.sh Executable file
View File

@ -0,0 +1,30 @@
#!/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
)

File diff suppressed because it is too large Load Diff

View File

@ -1,80 +1,63 @@
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 Project = LoadLDTK("levels")
var Levels = LoadLevels("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
OnMoving bool // wether to animate during moving
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, Ref string
Sprite *ebiten.Image
ToggleSprite *ebiten.Image
Solid bool // wall brick
Player bool // player sphere
IsPrimary bool // primary player sphere
Renderable bool // visible, has sprite
Velocity bool // movable
Collectible bool // collectible, vanishes once collected
Transient bool // turns into brick wall when traversed
Destroyable bool // turns into empty floor when bumped into twice
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
Id byte
Sprite *ebiten.Image
Class string
Solid bool // wall brick
Player bool // player sphere
IsPrimary bool // primary player sphere
Renderable bool // visible, has sprite
Velocity bool // movable
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
}
func (tile *Tile) Clone() *Tile {
newtile := &Tile{
Id: tile.Id,
Ref: tile.Ref,
Sprite: tile.Sprite,
ToggleSprite: tile.ToggleSprite,
Solid: tile.Solid,
Player: tile.Player,
IsPrimary: tile.IsPrimary,
Renderable: tile.Renderable,
Velocity: tile.Velocity,
Collectible: tile.Collectible,
Transient: tile.Transient,
Destroyable: tile.Destroyable,
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,
Id: tile.Id,
Sprite: tile.Sprite,
Class: tile.Class,
Solid: tile.Solid,
Player: tile.Player,
IsPrimary: tile.IsPrimary,
Renderable: tile.Renderable,
Velocity: tile.Velocity,
Collectible: tile.Collectible,
Transient: tile.Transient,
Destroyable: tile.Destroyable,
Particle: tile.Particle,
Tiles: tile.Tiles,
TileNames: tile.TileNames,
Obstacle: tile.Obstacle,
Direction: tile.Direction,
}
return newtile
@ -85,52 +68,55 @@ 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"], Assets["sphere-small"]}
tile.Tiles = []*ebiten.Image{Assets["sphere-blue"], Assets["sphere-blue-secondary"]}
return tile
}
func NewTileBlock() *Tile {
func NewTileBlock(class string) *Tile {
return &Tile{
Id: '#',
Sprite: Assets[class],
Class: class,
Solid: true,
Renderable: true,
}
}
func NewTileCollectible() *Tile {
func NewTileCollectible(class string) *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(direction int) *Tile {
func NewTileObstacle(class string, direction int) *Tile {
return &Tile{
Id: '+',
Sprite: Assets[class],
Class: class,
Solid: false,
Renderable: true,
Obstacle: true,
@ -139,122 +125,184 @@ func NewTileObstacle(direction int) *Tile {
}
}
func NewTileTranswall() *Tile {
func NewTileParticle(class []string) *Tile {
sprites := []*ebiten.Image{}
for _, sprite := range class {
sprites = append(sprites, Assets[sprite])
}
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(alpha string) *Tile {
func NewTileHiddenDoor(class []string) *Tile {
sprites := []*ebiten.Image{}
names := []string{}
for _, sprite := range class {
sprites = append(sprites, Assets[sprite])
names = append(names, sprite)
}
return &Tile{
Id: 'W',
Class: "hiddendoor",
Solid: false,
Renderable: true,
Destroyable: true,
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,
Tiles: sprites,
Sprite: sprites[0], // initially use the first
TileNames: names,
}
}
// used to map level data bytes to actual tiles
type TileRegistry map[string]*Tile
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
}
func InitTiles() TileRegistry {
return TileRegistry{
"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(),
' ': {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"}),
}
}
// load LDTK project at compile time into ram
func LoadLDTK(dir string) *ldtkgo.Project {
fd, err := assetfs.Open("levels/openquell.ldtk")
// 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)
if err != nil {
log.Fatalf("failed to open LDTK file levels/openquell.ldtk: %s", err)
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)
}
defer fd.Close()
fileinfo, err := fd.Stat()
if err != nil {
log.Fatalf("failed to stat() LDTK file levels/openquell.ldtk: %s", err)
}
name := strings.TrimSuffix(levelfile.Name(), ".lvl")
des := ""
background := &ebiten.Image{}
data := []byte{}
filesize := fileinfo.Size()
buffer := make([]byte, filesize)
scanner := bufio.NewScanner(fd)
for scanner.Scan() {
// ignore any whitespace
line := scanner.Text()
_, err = fd.Read(buffer)
if err != nil {
log.Fatalf("failed to read bytes from LDTK file levels/openquell.ldtk: %s", err)
}
// ignore empty lines
if len(line) == 0 {
continue
}
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++
switch {
case strings.Contains(line, "Background:"):
haveit := strings.Split(line, ": ")
if util.Exists(Assets, haveit[1]) {
background = Assets[haveit[1]]
}
}
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, ", "),
)
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"...)
}
}
return project
return RawLevel{
Name: name,
Data: data,
Background: background,
Description: des,
}
}

View File

@ -1,49 +0,0 @@
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
}

View File

@ -1,17 +1,14 @@
package assets
import (
"bytes"
"embed"
"encoding/json"
"image"
_ "image/png"
"io/fs"
"log"
"log/slog"
"path"
"os"
"path/filepath"
"strings"
"time"
"github.com/hajimehoshi/ebiten/v2"
)
@ -19,64 +16,13 @@ import (
// Maps image name to image data
type AssetRegistry map[string]*ebiten.Image
// 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
//go:embed levels/*.lvl sprites/*.png fonts/*.ttf
var assetfs embed.FS
// Called at build time, creates the global asset and animation registries
var Assets, Animations = LoadImages()
var Assets = LoadImages("sprites")
// load pngs and json files
func LoadImages() (AssetRegistry, AnimationRegistry) {
dir := "sprites"
imagedata := &assetData{}
imagedata.Registry = AssetRegistry{}
rawanimations := []AnimationJSON{}
func LoadImages(dir string) AssetRegistry {
images := AssetRegistry{}
// we use embed.FS to iterate over all files in ./assets/
entries, err := assetfs.ReadDir(dir)
@ -85,93 +31,24 @@ func LoadImages() (AssetRegistry, AnimationRegistry) {
}
for _, imagefile := range entries {
path := path.Join(dir, imagefile.Name())
fd, err := assetfs.Open(path)
path := filepath.Join("assets", dir, imagefile.Name())
fd, err := os.Open(path)
if err != nil {
log.Fatalf("failed to open file %s: %s", imagefile.Name(), err)
log.Fatalf("failed to open image file %s: %s", imagefile.Name(), err)
}
defer fd.Close()
switch {
case strings.HasSuffix(path, ".png"):
name, image := ReadImage(imagefile, fd)
imagedata.Registry[name] = image
name := strings.TrimSuffix(imagefile.Name(), ".png")
case strings.HasSuffix(path, ".json"):
animationjson := ReadJson(imagefile, fd)
rawanimations = append(rawanimations, animationjson)
img, _, err := image.Decode(fd)
if err != nil {
log.Fatalf("failed to decode image %s: %s", imagefile.Name(), err)
}
images[name] = ebiten.NewImageFromImage(img)
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)
if err != nil {
log.Fatalf("failed to decode image %s: %s", imagefile.Name(), err)
}
image := ebiten.NewImageFromImage(img)
return name, image
}
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
return images
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

View File

@ -1,164 +0,0 @@
{ "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": [
]
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 647 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 689 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 472 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 325 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 179 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 179 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 716 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 783 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 802 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 909 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 924 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 937 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 876 B

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 577 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 271 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -1,2 +0,0 @@
#!/bin/sh
montage -tile 4x0 -geometry +0+0 block* collectible-orange.png obstacle-* sphere-blue* transwall.png map.png && okular map.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 503 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 543 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

View File

@ -1,36 +0,0 @@
// 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
}

View File

@ -1,45 +0,0 @@
JASC-PAL
0100
42
0 0 0
0 0 0
14 14 14
29 29 29
51 51 51
80 80 80
99 99 99
122 122 122
167 167 167
192 192 192
228 228 228
251 245 239
242 211 171
255 227 160
255 216 117
255 202 60
255 168 36
255 141 0
73 77 126
63 69 136
54 61 145
44 52 155
35 44 164
26 36 173
39 39 68
31 31 76
27 27 80
22 22 85
17 17 90
14 14 93
139 109 156
142 98 167
145 86 179
150 68 197
154 52 213
158 36 229
198 159 165
204 153 161
212 145 155
221 136 149
230 127 143
241 116 135

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,33 +0,0 @@
JASC-PAL
0100
30
242 211 171
236 199 134
230 193 96
224 176 50
205 142 32
198 159 165
186 140 144
180 129 129
172 115 115
147 87 98
139 109 156
118 93 138
97 80 118
82 68 100
62 51 75
73 77 126
61 61 106
51 48 83
37 33 56
27 21 37
39 39 68
39 39 68
39 39 68
39 39 68
39 39 68
251 245 239
223 207 198
194 178 174
171 157 155
146 134 130

Binary file not shown.

Binary file not shown.

View File

@ -1,42 +0,0 @@
JASC-PAL
0100
39
32 0 59
63 0 83
108 0 108
146 0 124
187 0 151
236 0 178
255 19 186
255 64 190
255 113 213
255 147 231
255 186 253
245 220 255
255 255 255
0 0 0
12 12 12
26 26 26
39 39 39
54 54 54
71 71 71
86 86 86
99 99 99
118 118 118
133 133 133
153 153 153
177 177 177
205 205 205
42 2 0
52 9 0
71 24 0
94 46 0
131 71 0
165 96 0
201 106 0
243 119 0
255 165 41
255 186 82
255 239 169
255 250 211
255 255 247

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@ -1,49 +0,0 @@
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

View File

Before

Width:  |  Height:  |  Size: 145 KiB

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1,181 +0,0 @@
{ "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": [
]
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 584 B

View File

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1,156 +0,0 @@
{ "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": [
]
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

View File

@ -1,54 +0,0 @@
{ "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": [
]
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 931 B

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 448 B

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 615 B

Some files were not shown because too many files have changed in this diff Show More