1st commit

This commit is contained in:
2024-02-06 15:26:20 +01:00
commit 014209898f
33 changed files with 984 additions and 0 deletions

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

@@ -0,0 +1,29 @@
#!/bin/sh
width=$(grep "width int" ../main.go | awk '{print $4}')
height=$(grep "height int" ../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
(
echo "Description: $des"
echo "Background: $background"
w=$(($width / 32))
h=$(($height / 32))
for x in $(seq 1 $h); do
for y in $(seq 1 $w); do
echo -n " "
done
echo
done
)

17
assets/levels/gurke.lvl Normal file
View File

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

17
assets/levels/intro.lvl Normal file
View File

@@ -0,0 +1,17 @@
Description: Introduction: collect the goods by moving the ball onto them
Background: background-lila
####################
# #
# #
# #
# #
# #
# #
# ######
#
#
#
#
#
#
####################

150
assets/loader-levels.go Normal file
View File

@@ -0,0 +1,150 @@
package assets
import (
"bufio"
"fmt"
_ "image/png"
"io/fs"
"log"
"openquell/util"
"os"
"path/filepath"
"strings"
"github.com/hajimehoshi/ebiten/v2"
)
var Levels = LoadLevels("levels")
var Tiles = InitTiles()
// Tile: contains image, identifier (as used in level data) and
// additional properties
type Tile struct {
Id byte
Sprite *ebiten.Image
Class string
Solid bool
Player bool
Renderable bool
Velocity bool
}
func NewTilePlayer() *Tile {
return &Tile{
Id: 'S',
Sprite: Assets["sphere-blue"],
Class: "sphere",
Renderable: true,
Player: true,
Velocity: true,
}
}
func NewTileBlock(class string) *Tile {
return &Tile{
Id: '#',
Sprite: Assets[class],
Class: class,
Solid: true,
Renderable: 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
}
func InitTiles() TileRegistry {
return TileRegistry{
' ': {Id: ' ', Class: "floor", Renderable: false},
'#': NewTileBlock("block-grey32"),
'S': NewTilePlayer(),
}
}
// 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 read level dir %s: %s", dir, err)
}
for _, levelfile := range entries {
if levelfile.Type().IsRegular() && strings.Contains(levelfile.Name(), ".lvl") {
path := filepath.Join("assets", dir)
fmt.Printf("LOADING level %s/%s ... ", path, levelfile)
level := ParseRawLevel(path, levelfile)
fmt.Printf("done\n")
levels = append(levels, level)
}
}
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()
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
}
switch {
case strings.Contains(line, "Background:"):
haveit := strings.Split(line, ": ")
if util.Exists(Assets, haveit[1]) {
background = Assets[haveit[1]]
}
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 RawLevel{
Name: name,
Data: data,
Background: background,
Description: des,
}
}

58
assets/loader-sprites.go Normal file
View File

@@ -0,0 +1,58 @@
package assets
import (
"embed"
"fmt"
"image"
_ "image/png"
"log"
"os"
"path/filepath"
"strings"
"github.com/hajimehoshi/ebiten/v2"
)
// Maps image name to image data
type AssetRegistry map[string]*ebiten.Image
//go:embed levels/*.lvl sprites/*.png
var assetfs embed.FS
var Assets = LoadImages("sprites")
func LoadImages(dir string) AssetRegistry {
images := AssetRegistry{}
// we use embed.FS to iterate over all files in ./assets/
entries, err := assetfs.ReadDir(dir)
if err != nil {
log.Fatalf("failed to read assets dir %s: %s", dir, err)
}
for _, entry := range entries {
fmt.Println(entry.Name())
}
for _, imagefile := range entries {
path := filepath.Join("assets", dir, imagefile.Name())
fmt.Printf("LOADING %s ... ", path)
fd, err := os.Open(path)
if err != nil {
log.Fatalf("failed to open image file %s: %s", imagefile.Name(), err)
}
defer fd.Close()
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)
}
images[name] = ebiten.NewImageFromImage(img)
fmt.Printf("done\n")
}
return images
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 584 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB