Update tileset and game log for improved asset management and debugging

- Modified tileset configuration to include multiple tile images with updated dimensions.
- Enhanced game log to provide detailed startup information and entity loading for room1.
- Updated binary file for the game executable.
added climebol laders
This commit is contained in:
2026-04-26 12:13:55 +02:00
parent a6c8044e4a
commit ef550044ad
15 changed files with 2599 additions and 200354 deletions

View File

@@ -4,6 +4,7 @@
"id": 1,
"tiled_id": 1,
"solid": true,
"climbable": false,
"sprites": {
"top": "Tile_31",
"side": "Tile_02"
@@ -13,6 +14,7 @@
"id": 2,
"tiled_id": 2,
"solid": true,
"climbable": false,
"sprites": {
"top": "Tile_12",
"side": "Tile_12"
@@ -28,6 +30,34 @@
},
"target_map": "room2"
},
"ladder_1": {
"id": 4,
"tiled_id": 4,
"solid": false,
"climbable": true,
"sprites": {
"top": "../Ladders/1",
"side": "../Ladders/1"
}
},
"stone_1": {
"id": 5,
"tiled_id": 5,
"solid": true,
"sprites": {
"top": "../Stones/1",
"side": "../Stones/1"
}
},
"tree_1": {
"id": 6,
"tiled_id": 6,
"solid": true,
"sprites": {
"top": "../Trees/1",
"side": "../Trees/1"
}
},
"player": {
"id": 100,
"solid": true,

46
assets/maps/tileset.tsj Normal file
View File

@@ -0,0 +1,46 @@
{
"name": "MainTileset",
"tilecount": 6,
"tileheight": 96,
"tilewidth": 96,
"type": "tileset",
"version": "1.9",
"tiles": [
{
"id": 0,
"image": "../assets/images/1 Tiles/Tile_02.png",
"imageheight": 32,
"imagewidth": 32
},
{
"id": 1,
"image": "../assets/images/1 Tiles/Tile_12.png",
"imageheight": 32,
"imagewidth": 32
},
{
"id": 2,
"image": "../assets/images/1 Tiles/Tile_31.png",
"imageheight": 32,
"imagewidth": 32
},
{
"id": 3,
"image": "../assets/images/Ladders/1.png",
"imageheight": 32,
"imagewidth": 32
},
{
"id": 4,
"image": "../assets/images/Stones/1.png",
"imageheight": 32,
"imagewidth": 32
},
{
"id": 5,
"image": "../assets/images/Trees/1.png",
"imageheight": 96,
"imagewidth": 96
}
]
}

View File

@@ -8,6 +8,7 @@ Pos() mgl64.Vec3
SetPos(pos mgl64.Vec3)
IsBlocking() bool
IsMovable() bool
IsClimbable() bool
Move(dx, dy, dz float64)
Damage(amount int)
Pickup() bool

View File

@@ -8,13 +8,15 @@ import (
type Tile struct {
pos mgl64.Vec3
health int
Climbable bool
SideImg *ebiten.Image
TopImg *ebiten.Image
}
func (t *Tile) Pos() mgl64.Vec3 { return t.pos }
func (t *Tile) SetPos(pos mgl64.Vec3) { t.pos = pos }
func (t *Tile) IsBlocking() bool { return true }
func (t *Tile) IsBlocking() bool { return !t.Climbable }
func (t *Tile) IsClimbable() bool { return t.Climbable }
func (t *Tile) IsMovable() bool { return false }
func (t *Tile) Move(dx, dy, dz float64) {
// Not feasible for soil etc.

View File

@@ -71,25 +71,47 @@ type TiledMap struct {
type Portal struct {
pos mgl64.Vec3
TargetMap string
SideImg *ebiten.Image
TopImg *ebiten.Image
}
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) IsClimbable() 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, tint, alpha float32) {}
func (p *Portal) DrawTop(screen interface{}, x, y float64, tint, alpha float32) {}
func (p *Portal) DrawSide(screen interface{}, x, y float64, tint, alpha float32) {
scr := screen.(*ebiten.Image)
if p.SideImg != nil {
op := &ebiten.DrawImageOptions{}
op.GeoM.Translate(x, y)
op.ColorScale.Scale(tint, tint, tint, alpha)
scr.DrawImage(p.SideImg, op)
}
}
func (p *Portal) DrawTop(screen interface{}, x, y float64, tint, alpha float32) {
scr := screen.(*ebiten.Image)
if p.TopImg != nil {
op := &ebiten.DrawImageOptions{}
op.GeoM.Translate(x, y)
op.ColorScale.Scale(tint, tint, tint, alpha)
scr.DrawImage(p.TopImg, op)
}
}
// 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"`
Climbable bool `json:"climbable,omitempty"`
TargetMap string
SideImg *ebiten.Image
TopImg *ebiten.Image `json:"target_map,omitempty"`
Sprites struct {
Top string `json:"top"`
Side string `json:"side"`
@@ -142,9 +164,14 @@ func LoadWorldFromTiled(tmjPath string) (*World, error) {
if img, ok := loadedImages[name]; ok {
return img
}
img, _, err := ebitenutil.NewImageFromFile("assets/images/1 Tiles/" + name + ".png")
imgPath := "assets/images/1 Tiles/" + name + ".png"
if len(name) > 3 && name[:3] == "../" {
imgPath = "assets/images/" + name[3:] + ".png"
}
img, _, err := ebitenutil.NewImageFromFile(imgPath)
if err != nil {
fmt.Println("Warning, missing image:", name)
fmt.Println("Warning, missing image:", imgPath, err)
}
loadedImages[name] = img
return img
@@ -190,9 +217,9 @@ func LoadWorldFromTiled(tmjPath string) (*World, error) {
sideImg := loadImage(def.Sprites.Side)
if def.TargetMap != "" {
ent = &Portal{TargetMap: def.TargetMap}
ent = &Portal{TargetMap: def.TargetMap, SideImg: sideImg, TopImg: topImg}
} else {
ent = &Tile{SideImg: sideImg, TopImg: topImg}
ent = &Tile{SideImg: sideImg, TopImg: topImg, Climbable: def.Climbable}
}
} else {
// Fallback om def saknas

View File

@@ -30,6 +30,7 @@ type Player struct {
// Sprites
SpriteRun *ebiten.Image
SpriteJump *ebiten.Image
SpriteIdle *ebiten.Image
SpriteTop *ebiten.Image
AnimationFrame int
@@ -61,16 +62,21 @@ func NewPlayScene() *PlayScene {
if pIdle == nil {
pIdle = pRun
}
pJump, _, _ := ebitenutil.NewImageFromFile("assets/images/Warrior_1/Jump.png")
if pJump == nil {
pJump = pRun
}
pTop := ebiten.NewImage(96, 96)
pTop.Fill(color.RGBA{255, 255, 0, 255})
player := &Player{
Pos: mgl64.Vec3{50.0 * entities.TileSize, 6.0 * entities.TileSize, 50.0 * entities.TileSize},
Width: 96,
Height: 96,
Width: 32,
Height: 32,
SpriteRun: pRun,
SpriteIdle: pIdle,
SpriteJump: pJump,
SpriteTop: pTop,
FacingRight: true,
}
@@ -86,26 +92,74 @@ func NewPlayScene() *PlayScene {
func (s *PlayScene) Update() error {
p := s.player
currentMoveSpeed := MoveSpeed
if ebiten.IsKeyPressed(ebiten.KeyControl) {
currentMoveSpeed = MoveSpeed * 1.8 // Lite snabbare när man springer
}
p.Vel[0] = 0
p.Vel[2] = 0
isMoving := false
// Kolla om spelaren är i ett klättringsbart objekt
currentGridX := int((p.Pos[0] + p.Width/2) / entities.TileSize)
currentGridY := int((p.Pos[1] + p.Height/2) / entities.TileSize)
currentGridZ := int((p.Pos[2] + p.Width/2) / entities.TileSize)
entIn := s.world.GetEntityAt(currentGridX, currentGridY, currentGridZ)
isClimbing := false
if entIn != nil && entIn.IsClimbable() && ebiten.IsKeyPressed(ebiten.KeyShift) {
isClimbing = true
}
if isClimbing {
p.Vel[1] = 0 // Ingen gravitation när man klättrar
// W, A, S, D styr X och Y axlar
if ebiten.IsKeyPressed(ebiten.KeyA) {
p.Vel[0] = -currentMoveSpeed
p.FacingRight = false
isMoving = true
}
if ebiten.IsKeyPressed(ebiten.KeyD) {
p.Vel[0] = currentMoveSpeed
p.FacingRight = true
isMoving = true
}
if ebiten.IsKeyPressed(ebiten.KeyW) {
p.Vel[1] = -currentMoveSpeed // Uppåt
isMoving = true
}
if ebiten.IsKeyPressed(ebiten.KeyS) {
p.Vel[1] = currentMoveSpeed // Nedåt
isMoving = true
}
// Upp/ner pilarna styr Z-axeln
if ebiten.IsKeyPressed(ebiten.KeyUp) {
p.Vel[2] = -currentMoveSpeed
isMoving = true
}
if ebiten.IsKeyPressed(ebiten.KeyDown) {
p.Vel[2] = currentMoveSpeed
isMoving = true
}
} else {
if ebiten.IsKeyPressed(ebiten.KeyLeft) || ebiten.IsKeyPressed(ebiten.KeyA) {
p.Vel[0] = -MoveSpeed
p.Vel[0] = -currentMoveSpeed
p.FacingRight = false
isMoving = true
}
if ebiten.IsKeyPressed(ebiten.KeyRight) || ebiten.IsKeyPressed(ebiten.KeyD) {
p.Vel[0] = MoveSpeed
p.Vel[0] = currentMoveSpeed
p.FacingRight = true
isMoving = true
}
if ebiten.IsKeyPressed(ebiten.KeyUp) || ebiten.IsKeyPressed(ebiten.KeyW) {
p.Vel[2] = -MoveSpeed
p.Vel[2] = -currentMoveSpeed
isMoving = true
}
if ebiten.IsKeyPressed(ebiten.KeyDown) || ebiten.IsKeyPressed(ebiten.KeyS) {
p.Vel[2] = MoveSpeed
p.Vel[2] = currentMoveSpeed
isMoving = true
}
@@ -117,6 +171,7 @@ func (s *PlayScene) Update() error {
if !p.IsGrounded {
p.Vel[1] += Gravity
}
}
nextX := p.Pos[0] + p.Vel[0]
nextY := p.Pos[1] + p.Vel[1]
@@ -295,8 +350,8 @@ func (s *PlayScene) drawPlayerSide(screen *ebiten.Image, camX, camY float64) {
op.GeoM.Translate(96, 0)
}
drawX := p.Pos[0] - camX
drawY := p.Pos[1] - camY
drawX := p.Pos[0] - camX - 32
drawY := p.Pos[1] - camY - 64
op.GeoM.Translate(drawX, drawY)
screen.DrawImage(subImg, op)
@@ -306,8 +361,8 @@ func (s *PlayScene) drawPlayerTop(screen *ebiten.Image, camX, camZ float64) {
p := s.player
op := &ebiten.DrawImageOptions{}
drawX := p.Pos[0] - camX
drawZ := p.Pos[2] - camZ
drawX := p.Pos[0] - camX - 32
drawZ := p.Pos[2] - camZ - 64
op.GeoM.Translate(drawX, drawZ)
screen.DrawImage(p.SpriteTop, op)
}

View File

@@ -8,15 +8,15 @@
"scale": 0.135375,
"selectedLayer": 4,
"viewCenter": {
"x": 1676.8236380424748,
"y": 2256.694367497692
"x": 1599.2613111726687,
"y": 1599.2613111726687
}
},
"room2.tmj": {
"scale": 0.135375,
"selectedLayer": 3,
"viewCenter": {
"x": 1602.9547553093257,
"x": 1599.2613111726687,
"y": 1599.2613111726687
}
},

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +1,46 @@
{
"columns": 1,
"name": "MainTileset",
"tilecount": 6,
"tileheight": 96,
"tilewidth": 96,
"type": "tileset",
"version": "1.9",
"tiles": [
{
"id": 0,
"image": "../assets/images/1 Tiles/Tile_02.png",
"imageheight": 32,
"imagewidth": 32
},
{
"id": 1,
"image": "../assets/images/1 Tiles/Tile_12.png",
"imageheight": 32,
"imagewidth": 32,
"name": "MainTileset",
"tilecount": 1,
"tileheight": 32,
"tilewidth": 32,
"type": "tileset",
"version": "1.9"
"imagewidth": 32
},
{
"id": 2,
"image": "../assets/images/1 Tiles/Tile_31.png",
"imageheight": 32,
"imagewidth": 32
},
{
"id": 3,
"image": "../assets/images/Ladders/1.png",
"imageheight": 32,
"imagewidth": 32
},
{
"id": 4,
"image": "../assets/images/Stones/1.png",
"imageheight": 32,
"imagewidth": 32
},
{
"id": 5,
"image": "../assets/images/Trees/1.png",
"imageheight": 96,
"imagewidth": 96
}
]
}

View File

@@ -18,7 +18,7 @@ Spelets arkitektur bygger på att helt separera 3D-spellogiken från 2D-renderin
- **+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.
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. För att springa håller spelaren nere `Ctrl`-knappen. För att klättra i klättringsbara objekt måste spelaren stå inuti objektet och hålla nere `Shift`-knappen; då används `A`, `S`, `D`, `W` för att klättra vänster, ner, höger och upp, och pil upp / pil ner för att klättra inåt eller utåt (Z-axeln).
## Map Pipeline
* **Tiled JSON (`assets/maps/*.tmj`)**: Kartdata.

View File

@@ -4,6 +4,7 @@
"id": 1,
"tiled_id": 1,
"solid": true,
"climbable": false,
"sprites": {
"top": "Tile_31",
"side": "Tile_02"
@@ -13,6 +14,7 @@
"id": 2,
"tiled_id": 2,
"solid": true,
"climbable": false,
"sprites": {
"top": "Tile_12",
"side": "Tile_12"
@@ -28,6 +30,34 @@
},
"target_map": "room2"
},
"ladder_1": {
"id": 4,
"tiled_id": 4,
"solid": false,
"climbable": true,
"sprites": {
"top": "../Ladders/1",
"side": "../Ladders/1"
}
},
"stone_1": {
"id": 5,
"tiled_id": 5,
"solid": true,
"sprites": {
"top": "../Stones/1",
"side": "../Stones/1"
}
},
"tree_1": {
"id": 6,
"tiled_id": 6,
"solid": true,
"sprites": {
"top": "../Trees/1",
"side": "../Trees/1"
}
},
"player": {
"id": 100,
"solid": true,

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +1,46 @@
{
"columns": 1,
"name": "MainTileset",
"tilecount": 6,
"tileheight": 96,
"tilewidth": 96,
"type": "tileset",
"version": "1.9",
"tiles": [
{
"id": 0,
"image": "../assets/images/1 Tiles/Tile_02.png",
"imageheight": 32,
"imagewidth": 32
},
{
"id": 1,
"image": "../assets/images/1 Tiles/Tile_12.png",
"imageheight": 32,
"imagewidth": 32,
"name": "MainTileset",
"tilecount": 1,
"tileheight": 32,
"tilewidth": 32,
"type": "tileset",
"version": "1.9"
"imagewidth": 32
},
{
"id": 2,
"image": "../assets/images/1 Tiles/Tile_31.png",
"imageheight": 32,
"imagewidth": 32
},
{
"id": 3,
"image": "../assets/images/Ladders/1.png",
"imageheight": 32,
"imagewidth": 32
},
{
"id": 4,
"image": "../assets/images/Stones/1.png",
"imageheight": 32,
"imagewidth": 32
},
{
"id": 5,
"image": "../assets/images/Trees/1.png",
"imageheight": 96,
"imagewidth": 96
}
]
}

View File

@@ -31,3 +31,15 @@
2026/04/26 02:35:58 Byter rum till: room2
2026/04/26 02:35:58 Laddar värld från 'assets/maps/room2.tmj'...
2026/04/26 02:35:58 Map parsead med 10 lager.
2026/04/26 11:55:47 --- Spelet startar ---
2026/04/26 11:55:49 Laddar värld från 'assets/maps/room1.tmj'...
2026/04/26 11:55:49 Laddade 7 st entity definitions från JSON.
2026/04/26 11:55:49 Map parsead med 10 lager.
2026/04/26 12:00:56 --- Spelet startar ---
2026/04/26 12:00:57 Laddar värld från 'assets/maps/room1.tmj'...
2026/04/26 12:00:57 Laddade 7 st entity definitions från JSON.
2026/04/26 12:00:57 Map parsead med 10 lager.
2026/04/26 12:09:46 --- Spelet startar ---
2026/04/26 12:09:48 Laddar värld från 'assets/maps/room1.tmj'...
2026/04/26 12:09:48 Laddade 7 st entity definitions från JSON.
2026/04/26 12:09:48 Map parsead med 10 lager.

Binary file not shown.