ldtkgo

package module
v0.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 7, 2024 License: MIT Imports: 9 Imported by: 1

README

LDtk-Go

LDtk-Go is a loader for LDtk v0.9.3 projects written in pure Go.

Screenshot

Generally, you first load a project using ldtkgo.Open() or ldtkgo.Read(); afterward, you render the layers out to images, and then draw them onscreen with a rendering or game development framework, like ebiten, Pixel, raylib-go, or raylib-go-plus. An example that uses ebiten for rendering is included.

All of the major elements of LDtk should be supported, including Levels, Layers, Tiles, AutoLayers, IntGrids, Entities, and Properties.

Pkg.go.dev docs

Loading Projects

Using LDtk-Go is simple.

First, you load the LDTK project, either with ldtkgo.Open() or ldtkgo.Read(). After that, you have access to most of the useful parts of the entire LDTK project. You can then render the map using the included renderer if you're using Ebitengine.

package main

import (
	"embed"

	"github.com/solarlune/ldtkgo"
	renderer "github.com/solarlune/ldtkgo/renderer/ebitengine"
)

var ldtkProject *ldtkgo.Project
var ebitenRenderer *renderer.Renderer

//go:embed *.ldtk *.png
var fileSystem embed.FS

func main() {
	// Load the LDtk Project
	ldtkProject, err := ldtkgo.Open("example.ldtk", fileSystem)

	if err != nil {
		panic(err)
	}

	// ldtkProject now contains all data from the file.
	// If you'd like to render it, you could use the included renderer that uses Ebitengine:

	// Choose a level...
	level := ldtkProject.Levels[0]

	// Create a new renderer...
	ebitenRenderer = renderer.New(ldtkProject)

	// ... And render the tiles for the level out to layers, which will be *ebiten.Images. We can then retrieve them to draw in a Draw() loop later.
	ebitenRenderer.Render(level)
}


Running the Example

cd to the example directory, and then call go run . to run the example (as it's self-contained within its directory). The console will give instructions for interacting with the example.

Anything Else?

The core LDtk loader requires the encoding/json and image package. The Ebiten renderer requires Ebitengine as well, of course.

To-do

  • Add map clipping / viewports to Ebitengine renderer

Documentation

Overview

Package ldtkgo is a loader for LDtk projects, written in Golang. The general idea is to load a project using ldtkgo.LoadFile() or ldtkgo.LoadBytes(), and then use the resulting Project. Generally, the smoothest way to use this in game development seems to be to render the layers out to images, and then draw them onscreen with a rendering or game development framework, like Pixel, raylib-go, or ebiten. All of the major elements of LDtk should be supported, including Levels, Layers, Tiles, AutoLayers, IntGrids, Entities, and Properties.

Index

Constants

View Source
const (
	LayerTypeIntGrid  = "IntGrid"
	LayerTypeAutoTile = "AutoLayer"
	LayerTypeTile     = "Tiles"
	LayerTypeEntity   = "Entities"
)

LayerType constants indicating a Layer's type.

View Source
const (
	WorldLayoutHorizontal = "LinearHorizontal"
	WorldLayoutVertical   = "LinearVertical"
	WorldLayoutFree       = "Free"
	WorldLayoutGridVania  = "GridVania"
)

WorldLayout constants indicating direction or layout system for Worlds.

Variables

This section is empty.

Functions

This section is empty.

Types

type BGImage

type BGImage struct {
	Path     string
	ScaleX   float64
	ScaleY   float64
	CropRect []float64
}

BGImage represents a Level's background image as definied withing LDtk (the filepath, the scale, etc).

type Entity

type Entity struct {
	Identifier string      `json:"__identifier"`   // Name of the Entity
	IID        string      `json:"iid"`            // IID of the Entity
	Position   []int       `json:"px"`             // Position of the Entity (x, y)
	Width      int         `json:"width"`          // Width  of the Entity in pixels
	Height     int         `json:"height"`         // Height of the Entity in pixels
	Properties []*Property `json:"fieldInstances"` // The Properties defined on the Entity
	Pivot      []float32   `json:"__pivot"`        // Pivot position of the Entity (a centered Pivot would be 0.5, 0.5)
	Tags       []string    `json:"__tags"`         // Tags (categories) assigned to the Entity
	TileRect   *TileRect   `json:"__tile"`
	Data       interface{} `json:"-"` // Data allows you to attach key custom data to the entity post-parsing
	// contains filtered or unexported fields
}

An Entity represents an Entity as placed in the LDtk level.

func (*Entity) PropertyByIdentifier

func (entity *Entity) PropertyByIdentifier(id string) *Property

PropertyByIdentifier returns a Property by its Identifier string (name).

func (*Entity) WorldX

func (entity *Entity) WorldX() int

WorldX returns the X position of the Entity in world space, adding in the positioning of the Level.

func (*Entity) WorldY

func (entity *Entity) WorldY() int

WorldY returns the Y position of the Entity in world space, adding in the positioning of the Level.

type EntityDefinition

type EntityDefinition struct {
	Identifier string    `json:"identifier"` // Name of the Entity
	UID        int       `json:"uid"`        // IID of the Entity
	Width      int       `json:"width"`      // Width  of the Entity in pixels
	Height     int       `json:"height"`     // Height of the Entity in pixels
	Tags       []string  `json:"tags"`       // Tags (categories) assigned to the Entity
	TileRect   *TileRect `json:"tileRect"`
	PivotX     float32   `json:"pivotX"`
	PivotY     float32   `json:"pivotY"`
}

An Entity represents an Entitydefintion as defined in the entities.

type EnumSet

type EnumSet []string

EnumSet represents a set of Enums applied to tiles; this is just for convenience so you can see if a Tile contains an enum easily.

func (EnumSet) Contains

func (e EnumSet) Contains(enum string) bool

type Integer

type Integer struct {
	Position []int `json:"-"`       // Not actually available from the LDtk file, but added in afterwards as a convenience; the position of the Integer in pixels.
	Value    int   `json:"v"`       // The value of the Integer.
	ID       int   `json:"coordID"` // The ID of the Integer on the IntGrid.
}

Integer indicates the value for an individual "Integer Object" on the IntGrid layer.

type Layer

type Layer struct {
	// The width and height of the layer
	Identifier string   `json:"__identifier"` // Identifier (name) of the Layer
	IID        string   `json:"iid"`          // IID of the layer
	GridSize   int      `json:"__gridsize"`   // Grid size of the Layer
	Opacity    float32  `json:"__opacity"`
	OffsetX    int      `json:"__pxTotalOffsetX"` // The offset of the layer
	OffsetY    int      `json:"__pxTotalOffsetY"`
	CellWidth  int      `json:"__cWid"` // Overall width of the layer in cell count (i.e. a 160x80 level with 16x16 tiles would have a CellWidth and CellHeight of 10x5)
	CellHeight int      `json:"__cHei"` // Overall height of the layer in cell count
	Type       string   `json:"__type"` // Type of Layer. Can be compared using LayerType constants
	Tileset    *Tileset `json:"-"`      // Reference to the Tileset used for this Layer (assuming the path is the same)
	// TilesetPath string     `json:"__tilesetRelPath"` // Relative path to the tileset image; already is normalized using filepath.FromSlash().
	TilesetUID int        `json:"__tilesetDefUid"` // The UID of the used tileset
	IntGrid    []*Integer `json:"-"`
	AutoTiles  []*Tile    `json:"autoLayerTiles"` // Automatically set if IntGrid has values
	Tiles      []*Tile    `json:"gridTiles"`
	Entities   []*Entity  `json:"entityInstances"`
	Visible    bool       `json:"visible"` // Whether the layer is visible in LDtk
	// contains filtered or unexported fields
}

Layer represents a Layer, which can be of multiple types (Entity, AutoTile, Tile, or IntGrid).

func (*Layer) AutoTileAt

func (layer *Layer) AutoTileAt(x, y int) *Tile

AutoTileAt returns the AutoLayer Tile at the specified grid (not world) X and Y position. Note that this doesn't take into account the Layer's local Offset values (so a tile at 3, 4 on a layer with an offset of 64, 64 would still be found at 3, 4).

func (*Layer) EntityByIID

func (layer *Layer) EntityByIID(iid string) *Entity

EntityByIID returns the Entity with the IID specified. If no Entity with the name is found, the function returns nil.

func (*Layer) EntityByIdentifier

func (layer *Layer) EntityByIdentifier(identifier string) *Entity

EntityByIdentifier returns the Entity with the identifier (name) specified. If no Entity with the name is found, the function returns nil.

func (*Layer) ForEachTile

func (layer *Layer) ForEachTile(function func(tile *Tile))

ForEachTile runs a callback for each tile in the Layer. This is to make it simpler to run a render loop regardless of if the Layer is composed of auto tiles or manually placed tiles.

func (*Layer) FromGridPosition

func (layer *Layer) FromGridPosition(x, y int) (int, int)

FromGridPosition converts the specified position from a position on the Layer's grid to world space. For example, if the layer were 128x128 and had 16x16 tiles, FromGridPosition(3, 4) would return (48, 64).

func (*Layer) Index

func (layer *Layer) Index() int

Index returns the index of the layer in the Level's layer stack.

func (*Layer) IntegerAt

func (layer *Layer) IntegerAt(x, y int) *Integer

IntegerAt returns the IntGrid Integer at the specified world X and Y position (rounded down to the Layer's grid). Note that this doesn't take into account the Layer's local Offset values (so a tile at 3, 4 on a layer with an offset of 64, 64 would still be found at 3, 4).

func (*Layer) TileAt

func (layer *Layer) TileAt(x, y int) *Tile

TileAt returns the Tile at the specified grid (not world) X and Y position. Note that this doesn't take into account the Layer's local Offset values (so a tile at 3, 4 on a layer with an offset of 64, 64 would still be found at 3, 4).

func (*Layer) ToGridPosition

func (layer *Layer) ToGridPosition(x, y int) (int, int)

ToGridPosition converts the specified position from a position in world space to a position on the Layer's grid. For example, if the layer were 128x128 and had 16x16 tiles, ToGridPosition(32, 16) would return (2, 1).

type Level

type Level struct {
	Identifier    string // Name of the Level (i.e. "Level0")
	WorldX        int    // Position of the Level in the LDtk Project / world
	WorldY        int
	Width         int         `json:"pxWid"` // Width and height of the level in pixels.
	Height        int         `json:"pxHei"`
	IID           string      `json:"iid"` // IID of the level
	BGColorString string      `json:"__bgColor"`
	BGColor       color.Color `json:"-"`              // Background Color for the Level; will automatically default to the Project's if it is left at default in the LDtk project.
	Layers        []*Layer    `json:"layerInstances"` // The layers in the level in the project. Note that layers here (first is "furthest" / at the bottom, last is on top) is reversed compared to LDtk (first is at the top, bottom is on the bottom).
	Properties    []*Property `json:"fieldInstances"` // The Properties defined on the Entity
	BGImage       *BGImage    `json:"-"`              // Any background image that might be applied to this Level.
	Project       *Project    `json:"-"`
}

Level represents a Level in an LDtk Project.

func (*Level) LayerByIID

func (level *Level) LayerByIID(iid string) *Layer

LayerByIdentifier returns a Layer by its unique identifier. Returns nil if the specified Layer isn't found.

func (*Level) LayerByIdentifier

func (level *Level) LayerByIdentifier(identifier string) *Layer

LayerByIdentifier returns a Layer by its identifier (name). Returns nil if the specified Layer isn't found.

func (*Level) PropertyByIdentifier

func (level *Level) PropertyByIdentifier(id string) *Property

PropertyByIdentifier returns a Property by its Identifier string (name).

type Project

type Project struct {
	WorldLayout       string
	WorldGridWidth    int
	WorldGridHeight   int
	BGColorString     string      `json:"defaultLevelBgColor"`
	BGColor           color.Color `json:"-"`
	JSONVersion       string
	Levels            []*Level
	Tilesets          []*Tileset
	IntGridNames      []string
	EntityDefinitions []*EntityDefinition
}

Project represents a full LDtk Project, allowing you access to the Levels within as well as some project-level properties.

func Open

func Open(filepath string, fileSystem fs.FS) (*Project, error)

Open loads the LDtk project from the filepath specified using the file system provided. Open returns the Project and an error should the loading process fail (unable to find the file, unable to deserialize the JSON, etc).

func Read

func Read(data []byte) (*Project, error)

Read reads the LDtk project using the specified slice of bytes. Returns the Project and an error should there be an error in the loading process (unable to properly deserialize the JSON).

func (*Project) EntityByIID

func (project *Project) EntityByIID(iid string) *Entity

EntityByIID returns the Entity by unique identifier specified, or nil if entity isn't found

func (*Project) EntityDefinitionByIdentifier

func (project *Project) EntityDefinitionByIdentifier(identifier string) *EntityDefinition

EntityDefinitionByIdentifier returns the EntityDefinition by unique identifier specified, or nil if entity isn't found

func (*Project) IntGridConstantByName

func (project *Project) IntGridConstantByName(constantName string) int

IntGridConstantByName returns the IntGrid constant index by a named string. If the string is not found, -1 is returned.

func (*Project) LevelByIID

func (project *Project) LevelByIID(iid string) *Level

LevelByIID returns the level that has the unique identifier specified, or nil if one isn't found.

func (*Project) LevelByIdentifier

func (project *Project) LevelByIdentifier(identifier string) *Level

LevelByIdentifier returns the level that has the identifier specified, or nil if one isn't found.

func (*Project) LevelByPosition

func (project *Project) LevelByPosition(x, y int) *Level

LevelByPosition returns the level that "contains" the point indicated by the X and Y values given, or nil if one isn't found. (Note that the world position is displayed in LDTK at the bottom in the status bar.)

func (*Project) TilesetByIdentifier

func (project *Project) TilesetByIdentifier(identifier string) *Tileset

type Property

type Property struct {
	Identifier string      `json:"__identifier"`
	Type       string      `json:"__type"`  // The Type of the Property.
	Value      interface{} `json:"__value"` // The value contained within the property.
	// contains filtered or unexported fields
}

Property represents custom Properties created and customized on Entities.

func (*Property) AsArray

func (p *Property) AsArray() []interface{}

AsArray returns a property's value as an array of interface{} values. Note that this function doesn't check to ensure the value is the specified type before returning it.

func (*Property) AsBool

func (p *Property) AsBool() bool

AsBool returns a property's value as a boolean value. Note that this function doesn't check to ensure the value is the specified type before returning it.

func (*Property) AsColor

func (p *Property) AsColor() color.Color

AsColor returns a property's value as a color.Color struct. Note that this function doesn't check to ensure the value is the specified type before returning it.

func (*Property) AsEntityRef

func (p *Property) AsEntityRef() *Entity

AsEntityRef returns a proprety's value as an Entity reference. Note that this function doesn't check to ensure the value is the specified type before returning it.

func (*Property) AsFloat64

func (p *Property) AsFloat64() float64

AsFloat64 returns a property's value as a float64. Note that this function doesn't check to ensure the value is the specified type before returning it.

func (*Property) AsInt

func (p *Property) AsInt() int

AsInt returns a property's value as an int. Note that this function doesn't check to ensure the value is the specified type before returning it.

func (*Property) AsMap

func (p *Property) AsMap() map[string]interface{}

AsMap returns a property's value as a map of string to interface{} values. As an aside, the JSON deserialization process turns LDtk Points into Maps, where the key is "cx" or "cy", and the value is the x and y position. Note that this function doesn't check to ensure the value is the specified type before returning it.

func (*Property) AsString

func (p *Property) AsString() string

AsString returns a property's value as a string. Can be used for strings, colors, enums, etc. Note that this function doesn't check to ensure the value is the specified type before returning it.

func (*Property) IsNull

func (p *Property) IsNull() bool

type Tile

type Tile struct {
	Position []int `json:"px"` // Position of the Tile in pixels (x, y)
	Src      []int // The source position on the texture to draw this texture
	Flip     byte  `json:"f"` // Flip bits - first bit is for X-flip, second is for Y. 0 = no flip, 1 = horizontal flip, 2 = vertical flip, 3 = both flipped
	ID       int   `json:"t"` // The ID of the Tile (starting from 0).
}

Tile represents a graphical tile (whether automatic or manually placed).

func (*Tile) FlipX

func (t *Tile) FlipX() bool

FlipX returns if the Tile is flipped horizontally.

func (*Tile) FlipY

func (t *Tile) FlipY() bool

FlipY returns if the Tile is flipped vertically.

type TileRect

type TileRect struct {
	X          int `json:"x`
	Y          int `json:"y`
	W          int `json:"w`
	H          int `json:"h`
	TilesetUID int `json:"tilesetUid"`
	Tileset    *Tileset
}

TileRect represents the rectangle from which an Entity tile is

type Tileset

type Tileset struct {
	Path       string `json:"relPath"` // Relative path to the tileset image; already is normalized using filepath.FromSlash().
	ID         int    `json:"uid"`
	GridSize   int    `json:"tileGridSize"`
	Spacing    int
	Padding    int
	Width      int `json:"pxWid"`
	Height     int `json:"pxHei"`
	Identifier string
	CustomData map[int]string  `json:"-"` // Key: tileID, Value: custom data string
	Enums      map[int]EnumSet `json:"-"` // Key: enumValueID, Value: tileIDs (tile indices)
}

func (*Tileset) CustomDataForTile

func (t *Tileset) CustomDataForTile(tileID int) string

CustomDataForTile returns the custom data defined for the tile of the ID given in the tileset. If no custom data is defined, a blank string is returned.

func (*Tileset) EnumsForTile

func (t *Tileset) EnumsForTile(tileID int) EnumSet

EnumsForTile returns the EnumSet defined for the tile of the ID given in the tileset. If no enums are defined, an empty EnumSet is returned.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL