Add new map and tileset files for Windows release
- Created test.tmj and test.tsj files in the maps directory. - Added tileset.tsj with configuration for the MainTileset including image path and dimensions.
16
.vscode/tasks.json
vendored
@@ -4,13 +4,7 @@
|
|||||||
{
|
{
|
||||||
"label": "Build Windows",
|
"label": "Build Windows",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "go",
|
"command": "mkdir -p release/windows && go build -o release/windows/regin_mountain_game.exe . && cp -r assets release/windows/ && mkdir -p release/windows/assets/maps && cp mapp-maker/*.tmj mapp-maker/*.tsj release/windows/assets/maps/ 2>/dev/null || true",
|
||||||
"args": [
|
|
||||||
"build",
|
|
||||||
"-o",
|
|
||||||
"release/windows/regin_mountain_game.exe",
|
|
||||||
"."
|
|
||||||
],
|
|
||||||
"options": {
|
"options": {
|
||||||
"env": {
|
"env": {
|
||||||
"GOOS": "windows",
|
"GOOS": "windows",
|
||||||
@@ -25,13 +19,7 @@
|
|||||||
{
|
{
|
||||||
"label": "Build Linux",
|
"label": "Build Linux",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "go",
|
"command": "mkdir -p release/linux && go build -o release/linux/regin_mountain_game . && cp -r assets release/linux/ && mkdir -p release/linux/assets/maps && cp mapp-maker/*.tmj mapp-maker/*.tsj release/linux/assets/maps/ 2>/dev/null || true",
|
||||||
"args": [
|
|
||||||
"build",
|
|
||||||
"-o",
|
|
||||||
"release/linux/regin_mountain_game",
|
|
||||||
"."
|
|
||||||
],
|
|
||||||
"options": {
|
"options": {
|
||||||
"env": {
|
"env": {
|
||||||
"GOOS": "linux",
|
"GOOS": "linux",
|
||||||
|
|||||||
45
assets/entity_defs.json
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
{
|
||||||
|
"entity_types": {
|
||||||
|
"ground_grass": {
|
||||||
|
"id": 1,
|
||||||
|
"tiled_id": 1,
|
||||||
|
"solid": true,
|
||||||
|
"sprites": {
|
||||||
|
"top": "Tile_31",
|
||||||
|
"side": "Tile_02"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ground_dirt": {
|
||||||
|
"id": 2,
|
||||||
|
"tiled_id": 2,
|
||||||
|
"solid": true,
|
||||||
|
"sprites": {
|
||||||
|
"top": "Tile_12",
|
||||||
|
"side": "Tile_12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"portal_grass": {
|
||||||
|
"id": 3,
|
||||||
|
"tiled_id": 3,
|
||||||
|
"solid": false,
|
||||||
|
"sprites": {
|
||||||
|
"top": "Tile_31",
|
||||||
|
"side": "Tile_31"
|
||||||
|
},
|
||||||
|
"target_map": "room2"
|
||||||
|
},
|
||||||
|
"player": {
|
||||||
|
"id": 100,
|
||||||
|
"solid": true,
|
||||||
|
"sprites": {
|
||||||
|
"top": "player_idle",
|
||||||
|
"side": "player_idle"
|
||||||
|
},
|
||||||
|
"animations": {
|
||||||
|
"idle": {"frames": [0], "speed": 1},
|
||||||
|
"walk": {"frames": [1, 2, 3, 4], "speed": 5},
|
||||||
|
"jump": {"frames": [5, 6], "speed": 4}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,6 +15,6 @@ GetHealth() int
|
|||||||
|
|
||||||
// Ritar ut framkallningen av spriten
|
// Ritar ut framkallningen av spriten
|
||||||
// sideView: ifall vi ritar från sidan (vänster) eller uppifrån (höger)
|
// sideView: ifall vi ritar från sidan (vänster) eller uppifrån (höger)
|
||||||
DrawSide(screen interface{}, x, y float64)
|
DrawSide(screen interface{}, x, y float64, tint, alpha float32)
|
||||||
DrawTop(screen interface{}, x, y float64)
|
DrawTop(screen interface{}, x, y float64, tint, alpha float32)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
package entities
|
package entities
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/go-gl/mathgl/mgl64"
|
"github.com/go-gl/mathgl/mgl64"
|
||||||
"github.com/hajimehoshi/ebiten/v2"
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Tile struct {
|
type Tile struct {
|
||||||
pos mgl64.Vec3
|
pos mgl64.Vec3
|
||||||
health int
|
health int
|
||||||
SideImg *ebiten.Image
|
SideImg *ebiten.Image
|
||||||
TopImg *ebiten.Image
|
TopImg *ebiten.Image
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tile) Pos() mgl64.Vec3 { return t.pos }
|
func (t *Tile) Pos() mgl64.Vec3 { return t.pos }
|
||||||
@@ -17,26 +17,28 @@ func (t *Tile) SetPos(pos mgl64.Vec3) { t.pos = pos }
|
|||||||
func (t *Tile) IsBlocking() bool { return true }
|
func (t *Tile) IsBlocking() bool { return true }
|
||||||
func (t *Tile) IsMovable() bool { return false }
|
func (t *Tile) IsMovable() bool { return false }
|
||||||
func (t *Tile) Move(dx, dy, dz float64) {
|
func (t *Tile) Move(dx, dy, dz float64) {
|
||||||
// Not feasible for soil etc.
|
// Not feasible for soil etc.
|
||||||
}
|
}
|
||||||
func (t *Tile) Damage(am int) { t.health -= am }
|
func (t *Tile) Damage(am int) { t.health -= am }
|
||||||
func (t *Tile) Pickup() bool { return false }
|
func (t *Tile) Pickup() bool { return false }
|
||||||
func (t *Tile) GetHealth() int { return t.health }
|
func (t *Tile) GetHealth() int { return t.health }
|
||||||
|
|
||||||
func (t *Tile) DrawSide(screen interface{}, x, y float64) {
|
func (t *Tile) DrawSide(screen interface{}, x, y float64, tint, alpha float32) {
|
||||||
scr := screen.(*ebiten.Image)
|
scr := screen.(*ebiten.Image)
|
||||||
if t.SideImg != nil {
|
if t.SideImg != nil {
|
||||||
op := &ebiten.DrawImageOptions{}
|
op := &ebiten.DrawImageOptions{}
|
||||||
op.GeoM.Translate(x, y)
|
op.GeoM.Translate(x, y)
|
||||||
scr.DrawImage(t.SideImg, op)
|
op.ColorScale.Scale(tint, tint, tint, alpha)
|
||||||
}
|
scr.DrawImage(t.SideImg, op)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tile) DrawTop(screen interface{}, x, y float64) {
|
func (t *Tile) DrawTop(screen interface{}, x, y float64, tint, alpha float32) {
|
||||||
scr := screen.(*ebiten.Image)
|
scr := screen.(*ebiten.Image)
|
||||||
if t.TopImg != nil {
|
if t.TopImg != nil {
|
||||||
op := &ebiten.DrawImageOptions{}
|
op := &ebiten.DrawImageOptions{}
|
||||||
op.GeoM.Translate(x, y)
|
op.GeoM.Translate(x, y)
|
||||||
scr.DrawImage(t.TopImg, op)
|
op.ColorScale.Scale(tint, tint, tint, alpha)
|
||||||
}
|
scr.DrawImage(t.TopImg, op)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,11 @@ package entities
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/go-gl/mathgl/mgl64"
|
"github.com/go-gl/mathgl/mgl64"
|
||||||
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
|
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -49,7 +51,7 @@ func (w *World) SetEntityAt(x, y, z int, e Entity) {
|
|||||||
|
|
||||||
// Convert absolute 3D position to Grid index
|
// Convert absolute 3D position to Grid index
|
||||||
func ToGridIndex(pos mgl64.Vec3) (int, int, int) {
|
func ToGridIndex(pos mgl64.Vec3) (int, int, int) {
|
||||||
return int(pos[0]/TileSize), int(pos[1]/TileSize), int(pos[2]/TileSize)
|
return int(pos[0] / TileSize), int(pos[1] / TileSize), int(pos[2] / TileSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
type TiledLayer struct {
|
type TiledLayer struct {
|
||||||
@@ -70,6 +72,7 @@ type Portal struct {
|
|||||||
pos mgl64.Vec3
|
pos mgl64.Vec3
|
||||||
TargetMap string
|
TargetMap string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Portal) Pos() mgl64.Vec3 { return p.pos }
|
func (p *Portal) Pos() mgl64.Vec3 { return p.pos }
|
||||||
func (p *Portal) SetPos(pos mgl64.Vec3) { p.pos = pos }
|
func (p *Portal) SetPos(pos mgl64.Vec3) { p.pos = pos }
|
||||||
func (p *Portal) IsBlocking() bool { return false }
|
func (p *Portal) IsBlocking() bool { return false }
|
||||||
@@ -78,26 +81,86 @@ func (p *Portal) Move(dx, dy, dz float64) {}
|
|||||||
func (p *Portal) Damage(amount int) {}
|
func (p *Portal) Damage(amount int) {}
|
||||||
func (p *Portal) Pickup() bool { return false }
|
func (p *Portal) Pickup() bool { return false }
|
||||||
func (p *Portal) GetHealth() int { return 100 }
|
func (p *Portal) GetHealth() int { return 100 }
|
||||||
func (p *Portal) DrawSide(screen interface{}, x, y float64) {}
|
func (p *Portal) DrawSide(screen interface{}, x, y float64, tint, alpha float32) {}
|
||||||
func (p *Portal) DrawTop(screen interface{}, x, y float64) {}
|
func (p *Portal) DrawTop(screen interface{}, x, y float64, tint, alpha float32) {}
|
||||||
|
|
||||||
|
// EntityDef definierar egenskaperna för ett tile-id
|
||||||
|
type EntityDef struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
TiledID int `json:"tiled_id"`
|
||||||
|
Solid bool `json:"solid"`
|
||||||
|
TargetMap string `json:"target_map,omitempty"`
|
||||||
|
Sprites struct {
|
||||||
|
Top string `json:"top"`
|
||||||
|
Side string `json:"side"`
|
||||||
|
} `json:"sprites"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type EntityDefs struct {
|
||||||
|
EntityTypes map[string]EntityDef `json:"entity_types"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var loadedDefs *EntityDefs
|
||||||
|
var loadedImages map[string]*ebiten.Image
|
||||||
|
|
||||||
// Ladda en värld från Tiled Export (.tmj)
|
// Ladda en värld från Tiled Export (.tmj)
|
||||||
func LoadWorldFromTiled(tmjPath string) (*World, error) {
|
func LoadWorldFromTiled(tmjPath string) (*World, error) {
|
||||||
|
log.Printf("Laddar värld från '%s'...", tmjPath)
|
||||||
|
if loadedDefs == nil {
|
||||||
|
defsData, err := os.ReadFile("assets/entity_defs.json")
|
||||||
|
if err == nil {
|
||||||
|
var defs EntityDefs
|
||||||
|
json.Unmarshal(defsData, &defs)
|
||||||
|
loadedDefs = &defs
|
||||||
|
log.Printf("Laddade %d st entity definitions från JSON.", len(defs.EntityTypes))
|
||||||
|
} else {
|
||||||
|
log.Printf("Varning: Kunde inte läsa entity_defs.json: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fileData, err := os.ReadFile(tmjPath)
|
fileData, err := os.ReadFile(tmjPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Printf("Kunde inte läsa map %s: %v", tmjPath, err)
|
||||||
return nil, fmt.Errorf("kunde inte lasa map %s: %v", tmjPath, err)
|
return nil, fmt.Errorf("kunde inte lasa map %s: %v", tmjPath, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var tMap TiledMap
|
var tMap TiledMap
|
||||||
if err := json.Unmarshal(fileData, &tMap); err != nil {
|
if err := json.Unmarshal(fileData, &tMap); err != nil {
|
||||||
|
log.Printf("Kunde inte parsa JSON i %s: %v", tmjPath, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Printf("Map parsead med %d lager.", len(tMap.Layers))
|
||||||
|
|
||||||
w := NewWorld(tMap.Width, 10, tMap.Height) // 10 i djup(height y), tileHeight z = height i Json
|
w := NewWorld(tMap.Width, 10, tMap.Height) // 10 i djup(height y), tileHeight z = height i Json
|
||||||
|
|
||||||
tile12, _, _ := ebitenutil.NewImageFromFile("assets/images/1 Tiles/Tile_12.png")
|
// Preload images (simple abstraction)
|
||||||
tile02, _, _ := ebitenutil.NewImageFromFile("assets/images/1 Tiles/Tile_02.png")
|
loadImage := func(name string) *ebiten.Image {
|
||||||
tile31, _, _ := ebitenutil.NewImageFromFile("assets/images/1 Tiles/Tile_31.png")
|
if loadedImages == nil {
|
||||||
|
loadedImages = make(map[string]*ebiten.Image)
|
||||||
|
}
|
||||||
|
if img, ok := loadedImages[name]; ok {
|
||||||
|
return img
|
||||||
|
}
|
||||||
|
img, _, err := ebitenutil.NewImageFromFile("assets/images/1 Tiles/" + name + ".png")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Warning, missing image:", name)
|
||||||
|
}
|
||||||
|
loadedImages[name] = img
|
||||||
|
return img
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mappa ID till Def
|
||||||
|
idToDef := make(map[int]EntityDef)
|
||||||
|
if loadedDefs != nil {
|
||||||
|
for _, def := range loadedDefs.EntityTypes {
|
||||||
|
idToDef[def.TiledID] = def
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tile12 := loadImage("Tile_12")
|
||||||
|
tile02 := loadImage("Tile_02")
|
||||||
|
tile31 := loadImage("Tile_31")
|
||||||
|
|
||||||
for _, layer := range tMap.Layers {
|
for _, layer := range tMap.Layers {
|
||||||
if layer.Type != "tilelayer" {
|
if layer.Type != "tilelayer" {
|
||||||
@@ -105,6 +168,7 @@ func LoadWorldFromTiled(tmjPath string) (*World, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var yLevel int
|
var yLevel int
|
||||||
|
addedTiles := 0
|
||||||
fmt.Sscanf(layer.Name, "Y%d", &yLevel)
|
fmt.Sscanf(layer.Name, "Y%d", &yLevel)
|
||||||
if yLevel < 0 || yLevel >= 10 {
|
if yLevel < 0 || yLevel >= 10 {
|
||||||
continue
|
continue
|
||||||
@@ -114,23 +178,36 @@ func LoadWorldFromTiled(tmjPath string) (*World, error) {
|
|||||||
if tileID == 0 {
|
if tileID == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
addedTiles++
|
||||||
x := i % layer.Width
|
x := i % layer.Width
|
||||||
z := i / layer.Width
|
z := i / layer.Width
|
||||||
|
|
||||||
var ent Entity
|
var ent Entity
|
||||||
|
|
||||||
|
def, ok := idToDef[tileID]
|
||||||
|
if ok {
|
||||||
|
topImg := loadImage(def.Sprites.Top) // Om vi har generiska namn
|
||||||
|
sideImg := loadImage(def.Sprites.Side)
|
||||||
|
|
||||||
|
if def.TargetMap != "" {
|
||||||
|
ent = &Portal{TargetMap: def.TargetMap}
|
||||||
|
} else {
|
||||||
|
ent = &Tile{SideImg: sideImg, TopImg: topImg}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Fallback om def saknas
|
||||||
if tileID == 3 { // Portal ID
|
if tileID == 3 { // Portal ID
|
||||||
target := "room2"
|
target := "room2"
|
||||||
if tmjPath == "mapp-maker/room2.tmj" {
|
if tmjPath == "assets/maps/room2.tmj" {
|
||||||
target = "room1"
|
target = "room1"
|
||||||
}
|
}
|
||||||
ent = &Portal{ TargetMap: target }
|
ent = &Portal{TargetMap: target}
|
||||||
} else {
|
} else {
|
||||||
// Mark
|
|
||||||
if yLevel < 9 {
|
if yLevel < 9 {
|
||||||
ent = &Tile{ SideImg: tile12, TopImg: tile12 }
|
ent = &Tile{SideImg: tile12, TopImg: tile12}
|
||||||
} else {
|
} else {
|
||||||
ent = &Tile{ SideImg: tile02, TopImg: tile31 }
|
ent = &Tile{SideImg: tile02, TopImg: tile31}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,148 +216,4 @@ func LoadWorldFromTiled(tmjPath string) (*World, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return w, nil
|
return w, nil
|
||||||
}package entities
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/go-gl/mathgl/mgl64"
|
|
||||||
"github.com/hajimehoshi/ebiten/v2"
|
|
||||||
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
TileSize = 32.0 // Varje block ar 32x32 world units
|
|
||||||
)
|
|
||||||
|
|
||||||
type World struct {
|
|
||||||
Width, Height, Depth int
|
|
||||||
Grid [][][]Entity
|
|
||||||
PortalTrigger string // Håller reda på om vi ska byta rum
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewWorld(w, h, d int) *World {
|
|
||||||
grid := make([][][]Entity, w)
|
|
||||||
for x := 0; x < w; x++ {
|
|
||||||
grid[x] = make([][]Entity, h)
|
|
||||||
for y := 0; y < h; y++ {
|
|
||||||
grid[x][y] = make([]Entity, d)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &World{Width: w, Height: h, Depth: d, Grid: grid, PortalTrigger: ""}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *World) GetEntityAt(x, y, z int) Entity {
|
|
||||||
if x < 0 || x >= w.Width || y < 0 || y >= w.Height || z < 0 || z >= w.Depth {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return w.Grid[x][y][z]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *World) SetEntityAt(x, y, z int, e Entity) {
|
|
||||||
if x < 0 || x >= w.Width || y < 0 || y >= w.Height || z < 0 || z >= w.Depth {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.Grid[x][y][z] = e
|
|
||||||
if e != nil {
|
|
||||||
e.SetPos(mgl64.Vec3{float64(x), float64(y), float64(z)})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert absolute 3D position to Grid index
|
|
||||||
func ToGridIndex(pos mgl64.Vec3) (int, int, int) {
|
|
||||||
return int(pos[0]), int(pos[1]), int(pos[2])
|
|
||||||
}
|
|
||||||
|
|
||||||
type TiledLayer struct {
|
|
||||||
Data []int `json:"data"`
|
|
||||||
Height int `json:"height"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Width int `json:"width"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type TiledMap struct {
|
|
||||||
Height int `json:"height"`
|
|
||||||
Width int `json:"width"`
|
|
||||||
Layers []TiledLayer `json:"layers"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Portal struct {
|
|
||||||
pos mgl64.Vec3
|
|
||||||
TargetMap string
|
|
||||||
}
|
|
||||||
func (p *Portal) Pos() mgl64.Vec3 { return p.pos }
|
|
||||||
func (p *Portal) SetPos(pos mgl64.Vec3) { p.pos = pos }
|
|
||||||
func (p *Portal) IsBlocking() bool { return false }
|
|
||||||
func (p *Portal) IsMovable() bool { return false }
|
|
||||||
func (p *Portal) Move(dx, dy, dz float64) {}
|
|
||||||
func (p *Portal) Damage(amount int) {}
|
|
||||||
func (p *Portal) Pickup() bool { return false }
|
|
||||||
func (p *Portal) GetHealth() int { return 100 }
|
|
||||||
func (p *Portal) DrawSide(screen interface{}, x, y float64) {}
|
|
||||||
func (p *Portal) DrawTop(screen interface{}, x, y float64) {}
|
|
||||||
|
|
||||||
// Ladda en värld från Tiled Export (.tmj)
|
|
||||||
func LoadWorldFromTiled(tmjPath string) (*World, error) {
|
|
||||||
fileData, err := os.ReadFile(tmjPath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("kunde inte lasa map %s: %v", tmjPath, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var tMap TiledMap
|
|
||||||
if err := json.Unmarshal(fileData, &tMap); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
w := NewWorld(tMap.Width, 10, tMap.Height) // 10 i djup(height y), tileHeight z = height i Json
|
|
||||||
|
|
||||||
tile12, _, _ := ebitenutil.NewImageFromFile("assets/images/1 Tiles/Tile_12.png")
|
|
||||||
tile02, _, _ := ebitenutil.NewImageFromFile("assets/images/1 Tiles/Tile_02.png")
|
|
||||||
tile31, _, _ := ebitenutil.NewImageFromFile("assets/images/1 Tiles/Tile_31.png")
|
|
||||||
|
|
||||||
for _, layer := range tMap.Layers {
|
|
||||||
if layer.Type != "tilelayer" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var yLevel int
|
|
||||||
fmt.Sscanf(layer.Name, "Y%d", &yLevel)
|
|
||||||
if yLevel < 0 || yLevel >= 10 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, tileID := range layer.Data {
|
|
||||||
if tileID == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
x := i % layer.Width
|
|
||||||
z := i / layer.Width
|
|
||||||
|
|
||||||
var ent Entity
|
|
||||||
|
|
||||||
if tileID == 3 { // Portal ID
|
|
||||||
log.Println("Hittade portal vid", x, yLevel, z)
|
|
||||||
target := "room2"
|
|
||||||
if tmjPath == "mapp-maker/room2.tmj" {
|
|
||||||
target = "room1"
|
|
||||||
}
|
|
||||||
ent = &Portal{ TargetMap: target }
|
|
||||||
} else {
|
|
||||||
// Mark
|
|
||||||
if yLevel < 9 {
|
|
||||||
ent = &Tile{ SideImg: tile12, TopImg: tile12 }
|
|
||||||
} else {
|
|
||||||
ent = &Tile{ SideImg: tile02, TopImg: tile31 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
w.SetEntityAt(x, yLevel, z, ent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return w, nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ type PlayScene struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewPlayScene() *PlayScene {
|
func NewPlayScene() *PlayScene {
|
||||||
w, err := entities.LoadWorldFromTiled("mapp-maker/room1.tmj")
|
w, err := entities.LoadWorldFromTiled("assets/maps/room1.tmj")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Kunde inte ladda room1:", err)
|
log.Println("Kunde inte ladda room1:", err)
|
||||||
w = entities.NewWorld(100, 10, 100) // Fallback tom värd om JSON saknas
|
w = entities.NewWorld(100, 10, 100) // Fallback tom värd om JSON saknas
|
||||||
@@ -143,7 +143,7 @@ func (s *PlayScene) Update() error {
|
|||||||
standEnt := s.world.GetEntityAt(gridX, gridY, gridZ)
|
standEnt := s.world.GetEntityAt(gridX, gridY, gridZ)
|
||||||
if prt, ok := standEnt.(*entities.Portal); ok {
|
if prt, ok := standEnt.(*entities.Portal); ok {
|
||||||
log.Println("Byter rum till: ", prt.TargetMap)
|
log.Println("Byter rum till: ", prt.TargetMap)
|
||||||
newW, err := entities.LoadWorldFromTiled("mapp-maker/" + prt.TargetMap + ".tmj")
|
newW, err := entities.LoadWorldFromTiled("assets/maps/" + prt.TargetMap + ".tmj")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
s.world = newW
|
s.world = newW
|
||||||
// Reset player position for new map
|
// Reset player position for new map
|
||||||
@@ -181,37 +181,87 @@ func (s *PlayScene) Draw(screen *ebiten.Image) {
|
|||||||
camY := s.player.Pos[1] - float64(ViewSize)/2.0
|
camY := s.player.Pos[1] - float64(ViewSize)/2.0
|
||||||
camZ := s.player.Pos[2] - float64(ViewSize)/2.0
|
camZ := s.player.Pos[2] - float64(ViewSize)/2.0
|
||||||
|
|
||||||
// Vänster vy: Sido-vy (renderar alla X och Y objekt vid spelarens Z)
|
// Vänster vy: Sido-vy (renderar objekt vid spelarens Z och "inåt", max 3 djup)
|
||||||
|
// Rendera från djupast till spelarens Z (mindre Z är djupare inåt bild/scen)
|
||||||
|
leftDepthStart := playerGridZ - 3
|
||||||
|
if leftDepthStart < 0 {
|
||||||
|
leftDepthStart = 0
|
||||||
|
}
|
||||||
|
for zLevel := leftDepthStart; zLevel <= playerGridZ; zLevel++ {
|
||||||
|
tint := float32(1.0)
|
||||||
|
alpha := float32(1.0)
|
||||||
|
if zLevel < playerGridZ {
|
||||||
|
// Förskugga och gör transparent lager längre "in"
|
||||||
|
diff := float32(playerGridZ - zLevel)
|
||||||
|
tint = 1.0 - (diff * 0.2)
|
||||||
|
alpha = 1.0 - (diff * 0.25)
|
||||||
|
if tint < 0.2 {
|
||||||
|
tint = 0.2
|
||||||
|
}
|
||||||
|
if alpha < 0.2 {
|
||||||
|
alpha = 0.2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for x := 0; x < s.world.Width; x++ {
|
for x := 0; x < s.world.Width; x++ {
|
||||||
for y := 0; y < s.world.Height; y++ {
|
for y := 0; y < s.world.Height; y++ {
|
||||||
ent := s.world.GetEntityAt(x, y, playerGridZ)
|
ent := s.world.GetEntityAt(x, y, zLevel)
|
||||||
if ent != nil {
|
if ent != nil {
|
||||||
px := float64(x)*entities.TileSize - camX
|
px := float64(x)*entities.TileSize - camX
|
||||||
py := float64(y)*entities.TileSize - camY
|
py := float64(y)*entities.TileSize - camY
|
||||||
ent.DrawSide(s.leftView, px, py)
|
ent.DrawSide(s.leftView, px, py, tint, alpha)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Höger vy: Ovan-vy (renderar alla X och Z objekt vid underliggande rad)
|
// Höger vy: Ovan-vy (renderar ner i marken så att det känns som det går "in" i bilden)
|
||||||
viewY := playerGridY
|
// -1: Två block inåt jord/hål (Djupast)
|
||||||
if s.player.IsGrounded {
|
// 0: Ett block inåt jord/hål
|
||||||
viewY += 1
|
// +1: Samma (eller 1 över)
|
||||||
|
// För att saker under spelaren ska ligga bakom byter vi tecken. "upp" i z/y är nu inåt.
|
||||||
|
// Vi visar tre block nedåt i Y: playerGridY+3, Y+2, Y+1, Y
|
||||||
|
topLevels := []int{playerGridY + 3, playerGridY + 2, playerGridY + 1, playerGridY}
|
||||||
|
for i, yLevel := range topLevels {
|
||||||
|
if yLevel >= 0 && yLevel < s.world.Height {
|
||||||
|
tint := float32(1.0)
|
||||||
|
alpha := float32(1.0)
|
||||||
|
|
||||||
|
// Sätt färger baserat på relativ nivå ("inåt") där de djupaste (Y+3) är mörkare
|
||||||
|
// Index 0 är djupast i marken
|
||||||
|
if i == 0 { // -2 block (långt under fötter)
|
||||||
|
tint = 0.6
|
||||||
|
alpha = 0.4
|
||||||
|
} else if i == 1 { // -1 block (nyss under fötter)
|
||||||
|
tint = 0.8
|
||||||
|
alpha = 0.6
|
||||||
|
} else if i == 2 { // marken spelaren står på
|
||||||
|
tint = 1.0
|
||||||
|
alpha = 1.0
|
||||||
|
} else if i == 3 { // spelarens fothöjd (0)
|
||||||
|
tint = 1.2
|
||||||
|
alpha = 1.0
|
||||||
}
|
}
|
||||||
|
|
||||||
for x := 0; x < s.world.Width; x++ {
|
for x := 0; x < s.world.Width; x++ {
|
||||||
for z := 0; z < s.world.Depth; z++ {
|
for z := 0; z < s.world.Depth; z++ {
|
||||||
ent := s.world.GetEntityAt(x, viewY, z)
|
ent := s.world.GetEntityAt(x, yLevel, z)
|
||||||
if ent != nil {
|
if ent != nil {
|
||||||
px := float64(x)*entities.TileSize - camX
|
px := float64(x)*entities.TileSize - camX
|
||||||
pz := float64(z)*entities.TileSize - camZ
|
pz := float64(z)*entities.TileSize - camZ
|
||||||
ent.DrawTop(s.rightView, px, pz)
|
ent.DrawTop(s.rightView, px, pz, tint, alpha)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s.drawPlayerSide(s.leftView, camX, camY)
|
// Rendera spelaren på toppen (efter marken och spelarens lager är ritat)
|
||||||
|
if i == 3 {
|
||||||
s.drawPlayerTop(s.rightView, camX, camZ)
|
s.drawPlayerTop(s.rightView, camX, camZ)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s.drawPlayerSide(s.leftView, camX, camY)
|
||||||
|
|
||||||
opL := &ebiten.DrawImageOptions{}
|
opL := &ebiten.DrawImageOptions{}
|
||||||
opL.GeoM.Translate(10, 100)
|
opL.GeoM.Translate(10, 100)
|
||||||
|
|||||||
11
main.go
@@ -3,11 +3,22 @@ package main
|
|||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"mountain/internal/game"
|
"mountain/internal/game"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/v2"
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
// Sätt upp loggning till fil
|
||||||
|
f, err := os.OpenFile("game.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Kunde inte skapa logfil: %v", err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
log.SetOutput(f)
|
||||||
|
|
||||||
|
log.Println("--- Spelet startar ---")
|
||||||
|
|
||||||
ebiten.SetWindowSize(800, 600)
|
ebiten.SetWindowSize(800, 600)
|
||||||
ebiten.SetWindowTitle("Regin: Mountain of Treasures")
|
ebiten.SetWindowTitle("Regin: Mountain of Treasures")
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,51 @@
|
|||||||
{
|
{
|
||||||
"activeFile": "",
|
"activeFile": "room1.tmj",
|
||||||
"expandedProjectPaths": [
|
"expandedProjectPaths": [
|
||||||
|
"."
|
||||||
],
|
],
|
||||||
"fileStates": {
|
"fileStates": {
|
||||||
"start.tsx": {
|
"room1.tmj": {
|
||||||
"dynamicWrapping": true
|
"scale": 0.135375,
|
||||||
|
"selectedLayer": 4,
|
||||||
|
"viewCenter": {
|
||||||
|
"x": 2038.7811634349032,
|
||||||
|
"y": 2256.694367497692
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"room2.tmj": {
|
||||||
|
"scale": 0.135375,
|
||||||
|
"selectedLayer": 3,
|
||||||
|
"viewCenter": {
|
||||||
|
"x": 664.819944598338,
|
||||||
|
"y": 2256.694367497692
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"start.tsx": {
|
||||||
|
"dynamicWrapping": true,
|
||||||
|
"scaleInDock": 1,
|
||||||
|
"scaleInEditor": 1
|
||||||
|
},
|
||||||
|
"tileset.tsj": {
|
||||||
|
"dynamicWrapping": false,
|
||||||
|
"scaleInDock": 1,
|
||||||
|
"scaleInEditor": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"last.exportedFilePath": "/home/brasse/repos/Regin_mountain_of_treasures/assets/maps",
|
||||||
"last.imagePath": "/home/brasse/repos/Regin_mountain_of_treasures/assets/images/1 Tiles",
|
"last.imagePath": "/home/brasse/repos/Regin_mountain_of_treasures/assets/images/1 Tiles",
|
||||||
|
"map.lastUsedExportFilter": "JSON kart-filer ( *.tmj *.json)",
|
||||||
"openFiles": [
|
"openFiles": [
|
||||||
|
"room1.tmj",
|
||||||
|
"room2.tmj",
|
||||||
|
"start.tsx",
|
||||||
|
"tileset.tsj"
|
||||||
],
|
],
|
||||||
"project": "R.M.O.T.tiled-project",
|
"project": "R.M.O.T.tiled-project",
|
||||||
"recentFiles": [
|
"recentFiles": [
|
||||||
|
"tileset.tsj",
|
||||||
|
"start.tsx",
|
||||||
|
"room2.tmj",
|
||||||
|
"room1.tmj"
|
||||||
],
|
],
|
||||||
"tileset.lastUsedFormat": "tsx",
|
"tileset.lastUsedFormat": "tsx",
|
||||||
"tileset.type": 1
|
"tileset.type": 1
|
||||||
|
|||||||
15
plan.md
@@ -11,8 +11,19 @@ Spelets arkitektur bygger på att helt separera 3D-spellogiken från 2D-renderin
|
|||||||
|
|
||||||
1. **3D Verklighet:** Varje spelfigur och block har en 3D-vektor (`X`, `Y`, `Z`) samt en storlek (`Width`, `Height`, `Depth`). Fysikmotorn (som bygger på euler-integrering och AABB-kollisioner) körs helt och hållet i denna 3D-värld. Tyngdkraft drar objekt neråt längs Y eller Z axeln.
|
1. **3D Verklighet:** Varje spelfigur och block har en 3D-vektor (`X`, `Y`, `Z`) samt en storlek (`Width`, `Height`, `Depth`). Fysikmotorn (som bygger på euler-integrering och AABB-kollisioner) körs helt och hållet i denna 3D-värld. Tyngdkraft drar objekt neråt längs Y eller Z axeln.
|
||||||
2. **2D Rendering (Double Viewport):** Spelet renderas genom två synkroniserade vyportar bredvid varandra, båda med en svart inramning:
|
2. **2D Rendering (Double Viewport):** Spelet renderas genom två synkroniserade vyportar bredvid varandra, båda med en svart inramning:
|
||||||
- **Vänster vy (Sido-vy):** Visar X- och Y-axeln (bredd och höjd). När spelaren går "inåt" längs Z-axeln ritas en ny rad av kartan ut, med spelaren uppdaterad i centrum.
|
- **Vänster vy (Sido-vy):** Visar X- och Y-axeln (bredd och höjd). När spelaren går "inåt" längs Z-axeln ritas lagren upp till 3 block inåt i djupet. För varje block inåt blir objektet gradvis mer utgråat (skuggat) och transparent, vilket skapar en tydlig känsla av djup (parallax-liknande 3D-effekt).
|
||||||
- **Höger vy (Ovanifrån):** Visar X- och Z-axeln (bredd och djup). När spelaren ändrar höjd (Y-axel, t.ex. genom att hoppa) renderas en ny höjd-slice av världen med spelaren i absoluta mittpunkten.
|
- **Höger vy (Ovanifrån):** Visar X- och Z-axeln (bredd och djup). Visar bara spelarens närområde i Y-led med en specifik ljushets- och transparensstege:
|
||||||
|
- **-1 block** (Nivån spelaren står på) samt **0 block** (Samma höjd): Båda är lite ljusare (tint 1.2).
|
||||||
|
- **+1 block upp**: Ljusare och lite transparent (alpha 0.5, tint 1.4).
|
||||||
|
- **+2 block upp**: Ännu ljusare och nästan helt transparent (alpha 0.2, tint 1.6).
|
||||||
3. **Kartstruktur:** Världen sparas i grunden som en tre-dimensionell array (`[][][]Entity`), exempelvis motsvarande en 10x10x10 map. Varje block motsvarar 32x32 pixlar i world-space som sedan representeras av specifika sprites ur `assets/images/1 Tiles`. Kartans botten består av solida jordblock som förhindrar spelaren från att falla igenom.
|
3. **Kartstruktur:** Världen sparas i grunden som en tre-dimensionell array (`[][][]Entity`), exempelvis motsvarande en 10x10x10 map. Varje block motsvarar 32x32 pixlar i world-space som sedan representeras av specifika sprites ur `assets/images/1 Tiles`. Kartans botten består av solida jordblock som förhindrar spelaren från att falla igenom.
|
||||||
4. **Gemensamt Spelobjekt (Entity):** All logik byggs på ett generiskt `Entity`-interface som besvarar frågor som `IsBlocking()`, `IsMovable()`, `Move()`, `Damage()`, `Pickup()` och `GetHealth()`. Detta gör att karaktärer, pussel och fiender smidigt kan kalla varandras triggers och dela samma kollisionsmekanismer i 3D-kuben.
|
4. **Gemensamt Spelobjekt (Entity):** All logik byggs på ett generiskt `Entity`-interface som besvarar frågor som `IsBlocking()`, `IsMovable()`, `Move()`, `Damage()`, `Pickup()` och `GetHealth()`. Detta gör att karaktärer, pussel och fiender smidigt kan kalla varandras triggers och dela samma kollisionsmekanismer i 3D-kuben.
|
||||||
5. **Animation och Input:** Kontroller och inputs (Gå, Hoppa m.m) knyts till konfigurerbara actions. Karaktärerna använder sprite-sheets där varje "frame" är 96x96 pixlar som bläddras igenom i en specifik timer för att spela upp livliga animationer. Att byta håll innebär att man byter animation state och hastighetsvektor.
|
5. **Animation och Input:** Kontroller och inputs (Gå, Hoppa m.m) knyts till konfigurerbara actions. Karaktärerna använder sprite-sheets där varje "frame" är 96x96 pixlar som bläddras igenom i en specifik timer för att spela upp livliga animationer. Att byta håll innebär att man byter animation state och hastighetsvektor.
|
||||||
|
|
||||||
|
## Map Pipeline
|
||||||
|
* **Tiled JSON (`assets/maps/*.tmj`)**: Kartdata.
|
||||||
|
* **Entity Definitions (`assets/entity_defs.json`)**: JSON som mappar ID till top/sido sprites samt om den är solid eller har specifik logik.
|
||||||
|
Exempel:
|
||||||
|
- id 1: side tile_02, top tile_31 (Gräs)
|
||||||
|
- id 2: side tile_12, top tile_12 (Jord)
|
||||||
|
- id 3: portal (Grässtruktur som byter karta)
|
||||||
|
|||||||
BIN
regin_mountain_game
Executable file
45
release/linux/assets/entity_defs.json
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
{
|
||||||
|
"entity_types": {
|
||||||
|
"ground_grass": {
|
||||||
|
"id": 1,
|
||||||
|
"tiled_id": 1,
|
||||||
|
"solid": true,
|
||||||
|
"sprites": {
|
||||||
|
"top": "Tile_31",
|
||||||
|
"side": "Tile_02"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ground_dirt": {
|
||||||
|
"id": 2,
|
||||||
|
"tiled_id": 2,
|
||||||
|
"solid": true,
|
||||||
|
"sprites": {
|
||||||
|
"top": "Tile_12",
|
||||||
|
"side": "Tile_12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"portal_grass": {
|
||||||
|
"id": 3,
|
||||||
|
"tiled_id": 3,
|
||||||
|
"solid": false,
|
||||||
|
"sprites": {
|
||||||
|
"top": "Tile_31",
|
||||||
|
"side": "Tile_31"
|
||||||
|
},
|
||||||
|
"target_map": "room2"
|
||||||
|
},
|
||||||
|
"player": {
|
||||||
|
"id": 100,
|
||||||
|
"solid": true,
|
||||||
|
"sprites": {
|
||||||
|
"top": "player_idle",
|
||||||
|
"side": "player_idle"
|
||||||
|
},
|
||||||
|
"animations": {
|
||||||
|
"idle": {"frames": [0], "speed": 1},
|
||||||
|
"walk": {"frames": [1, 2, 3, 4], "speed": 5},
|
||||||
|
"jump": {"frames": [5, 6], "speed": 4}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
4
release/linux/assets/images/.directory
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[Dolphin]
|
||||||
|
PreviewsShown=true
|
||||||
|
Timestamp=2018,1,22,14,58,44
|
||||||
|
Version=4
|
||||||
BIN
release/linux/assets/images/1 Tiles/Tile_01.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_02.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_03.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_04.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_05.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_06.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_07.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_08.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_09.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_10.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_11.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_12.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_13.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_14.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_15.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_16.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_17.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_18.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_19.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_20.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_21.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_22.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_23.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_24.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_25.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_26.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_27.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_28.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_29.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_30.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_31.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_32.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_33.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_34.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_35.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_36.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_37.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_38.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_39.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_40.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_41.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_42.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_43.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_44.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_45.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_46.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_47.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_48.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_49.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_50.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_51.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_52.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_53.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_54.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_55.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_56.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_57.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_58.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_59.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/1 Tiles/Tile_60.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
release/linux/assets/images/1 Tiles/Tileset.png
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
release/linux/assets/images/Boxes/1.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/Boxes/2.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/Boxes/3.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/Boxes/4.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
release/linux/assets/images/Boxes/5.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/Boxes/6.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/Grass/1.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
release/linux/assets/images/Grass/10.png
Normal file
|
After Width: | Height: | Size: 999 B |
BIN
release/linux/assets/images/Grass/2.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
release/linux/assets/images/Grass/3.png
Normal file
|
After Width: | Height: | Size: 1021 B |
BIN
release/linux/assets/images/Grass/4.png
Normal file
|
After Width: | Height: | Size: 1010 B |
BIN
release/linux/assets/images/Grass/5.png
Normal file
|
After Width: | Height: | Size: 1012 B |
BIN
release/linux/assets/images/Grass/6.png
Normal file
|
After Width: | Height: | Size: 998 B |
BIN
release/linux/assets/images/Grass/7.png
Normal file
|
After Width: | Height: | Size: 995 B |
BIN
release/linux/assets/images/Grass/8.png
Normal file
|
After Width: | Height: | Size: 1006 B |
BIN
release/linux/assets/images/Grass/9.png
Normal file
|
After Width: | Height: | Size: 985 B |
BIN
release/linux/assets/images/Ladders/1.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
release/linux/assets/images/Ladders/2.png
Normal file
|
After Width: | Height: | Size: 1011 B |
BIN
release/linux/assets/images/Ladders/3.png
Normal file
|
After Width: | Height: | Size: 1020 B |
BIN
release/linux/assets/images/Ladders/4.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/linux/assets/images/Ladders/5.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
release/linux/assets/images/Ladders/6.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
release/linux/assets/images/Pointers/1.png
Normal file
|
After Width: | Height: | Size: 1017 B |
BIN
release/linux/assets/images/Pointers/2.png
Normal file
|
After Width: | Height: | Size: 1016 B |
BIN
release/linux/assets/images/Pointers/3.png
Normal file
|
After Width: | Height: | Size: 1022 B |
BIN
release/linux/assets/images/Pointers/4.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |