add offline moving platform logic: implement dynamic platform detection and movement handling in offline mode
All checks were successful
Dynamic Branch Deploy / build-and-deploy (push) Successful in 1m49s
All checks were successful
Dynamic Branch Deploy / build-and-deploy (push) Successful in 1m49s
This commit is contained in:
@@ -202,21 +202,26 @@ func (g *Game) spawnOfflineChunk(atX float64) {
|
|||||||
chunkDef := g.world.ChunkLibrary[randomID]
|
chunkDef := g.world.ChunkLibrary[randomID]
|
||||||
for i, obj := range chunkDef.Objects {
|
for i, obj := range chunkDef.Objects {
|
||||||
asset, ok := g.world.Manifest.Assets[obj.AssetID]
|
asset, ok := g.world.Manifest.Assets[obj.AssetID]
|
||||||
// In Solo gibt es keine MovingPlatformData, Plattformen sind statisch
|
if !ok {
|
||||||
if ok && asset.Type == "moving_platform" {
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check ob es eine bewegende Plattform ist (entweder Typ oder explizite Daten)
|
||||||
|
if obj.MovingPlatform != nil {
|
||||||
|
mpData := obj.MovingPlatform
|
||||||
p := &MovingPlatform{
|
p := &MovingPlatform{
|
||||||
ChunkID: randomID,
|
ChunkID: randomID,
|
||||||
ObjectIdx: i,
|
ObjectIdx: i,
|
||||||
AssetID: obj.AssetID,
|
AssetID: obj.AssetID,
|
||||||
StartX: atX + obj.X,
|
StartX: atX + mpData.StartX,
|
||||||
StartY: obj.Y,
|
StartY: mpData.StartY,
|
||||||
EndX: atX + obj.X,
|
EndX: atX + mpData.EndX,
|
||||||
EndY: obj.Y,
|
EndY: mpData.EndY,
|
||||||
Speed: 0,
|
Speed: mpData.Speed,
|
||||||
Direction: 1.0,
|
Direction: 1.0,
|
||||||
IsActive: false,
|
IsActive: true,
|
||||||
CurrentX: atX + obj.X,
|
CurrentX: atX + mpData.StartX,
|
||||||
CurrentY: obj.Y,
|
CurrentY: mpData.StartY,
|
||||||
HitboxW: asset.Hitbox.W,
|
HitboxW: asset.Hitbox.W,
|
||||||
HitboxH: asset.Hitbox.H,
|
HitboxH: asset.Hitbox.H,
|
||||||
DrawOffX: asset.DrawOffX,
|
DrawOffX: asset.DrawOffX,
|
||||||
@@ -225,6 +230,11 @@ func (g *Game) spawnOfflineChunk(atX float64) {
|
|||||||
HitboxOffY: asset.Hitbox.OffsetY,
|
HitboxOffY: asset.Hitbox.OffsetY,
|
||||||
}
|
}
|
||||||
g.offlineMovingPlatforms = append(g.offlineMovingPlatforms, p)
|
g.offlineMovingPlatforms = append(g.offlineMovingPlatforms, p)
|
||||||
|
} else if asset.Type == "moving_platform" || asset.Type == "platform" {
|
||||||
|
// Statische Plattform (oder Fallback)
|
||||||
|
// Wir fügen sie NICHT zu offlineMovingPlatforms hinzu, da sie über
|
||||||
|
// den statischen World-Collider Check in physics.go bereits erfasst wird.
|
||||||
|
// (Vorausgesetzt der Typ ist "platform")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
"math"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.zb-server.de/ZB-Server/EscapeFromTeacher/pkg/config"
|
"git.zb-server.de/ZB-Server/EscapeFromTeacher/pkg/config"
|
||||||
@@ -9,6 +10,26 @@ import (
|
|||||||
"git.zb-server.de/ZB-Server/EscapeFromTeacher/pkg/physics"
|
"git.zb-server.de/ZB-Server/EscapeFromTeacher/pkg/physics"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// CheckMovingPlatformLanding prüft ob der Spieler auf einer bewegenden Plattform steht
|
||||||
|
func (g *Game) CheckMovingPlatformLanding(x, y, w, h float64) *MovingPlatform {
|
||||||
|
playerRect := game.Rect{OffsetX: x, OffsetY: y, W: w, H: h}
|
||||||
|
|
||||||
|
for _, mp := range g.offlineMovingPlatforms {
|
||||||
|
mpRect := game.Rect{
|
||||||
|
OffsetX: mp.CurrentX + mp.DrawOffX + mp.HitboxOffX,
|
||||||
|
OffsetY: mp.CurrentY + mp.DrawOffY + mp.HitboxOffY,
|
||||||
|
W: mp.HitboxW,
|
||||||
|
H: mp.HitboxH,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Etwas großzügigerer Check nach oben
|
||||||
|
if game.CheckRectCollision(playerRect, mpRect) {
|
||||||
|
return mp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// ApplyInput wendet einen Input auf den vorhergesagten Zustand an
|
// ApplyInput wendet einen Input auf den vorhergesagten Zustand an
|
||||||
// Nutzt die gemeinsame Physik-Engine aus pkg/physics
|
// Nutzt die gemeinsame Physik-Engine aus pkg/physics
|
||||||
func (g *Game) ApplyInput(input InputState) {
|
func (g *Game) ApplyInput(input InputState) {
|
||||||
@@ -20,6 +41,29 @@ func (g *Game) ApplyInput(input InputState) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- OFFLINE: Mit Plattform mitbewegen ---
|
||||||
|
if g.isOffline && g.predictedGround {
|
||||||
|
pConst := physics.DefaultPlayerConstants()
|
||||||
|
mp := g.CheckMovingPlatformLanding(
|
||||||
|
g.predictedX+pConst.DrawOffX+pConst.HitboxOffX,
|
||||||
|
g.predictedY+pConst.DrawOffY+pConst.HitboxOffY,
|
||||||
|
pConst.Width,
|
||||||
|
pConst.Height,
|
||||||
|
)
|
||||||
|
if mp != nil {
|
||||||
|
// Berechne Plattform-Geschwindigkeit
|
||||||
|
dx := mp.EndX - mp.StartX
|
||||||
|
dy := mp.EndY - mp.StartY
|
||||||
|
dist := math.Sqrt(dx*dx + dy*dy)
|
||||||
|
if dist > 0.1 {
|
||||||
|
vx := (dx / dist) * (mp.Speed / 20.0) * mp.Direction
|
||||||
|
vy := (dy / dist) * (mp.Speed / 20.0) * mp.Direction
|
||||||
|
g.predictedX += vx
|
||||||
|
g.predictedY += vy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Horizontale Bewegung mit analogem Joystick
|
// Horizontale Bewegung mit analogem Joystick
|
||||||
moveX := 0.0
|
moveX := 0.0
|
||||||
if input.Left {
|
if input.Left {
|
||||||
|
|||||||
@@ -77,6 +77,10 @@ func (w *World) GenerateColliders(activeChunks []ActiveChunk) []Collider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, obj := range chunk.Objects {
|
for _, obj := range chunk.Objects {
|
||||||
|
if obj.MovingPlatform != nil {
|
||||||
|
continue // Überspringe bewegende Plattformen, werden dynamisch geprüft
|
||||||
|
}
|
||||||
|
|
||||||
def, ok := w.Manifest.Assets[obj.AssetID]
|
def, ok := w.Manifest.Assets[obj.AssetID]
|
||||||
if !ok {
|
if !ok {
|
||||||
fmt.Printf("⚠️ Asset '%s' nicht in Manifest!\n", obj.AssetID)
|
fmt.Printf("⚠️ Asset '%s' nicht in Manifest!\n", obj.AssetID)
|
||||||
|
|||||||
@@ -218,6 +218,10 @@ func (c *ClientCollisionChecker) CheckCollision(x, y, w, h float64) (bool, strin
|
|||||||
for _, activeChunk := range c.ActiveChunks {
|
for _, activeChunk := range c.ActiveChunks {
|
||||||
if chunk, ok := c.World.ChunkLibrary[activeChunk.ChunkID]; ok {
|
if chunk, ok := c.World.ChunkLibrary[activeChunk.ChunkID]; ok {
|
||||||
for _, obj := range chunk.Objects {
|
for _, obj := range chunk.Objects {
|
||||||
|
if obj.MovingPlatform != nil {
|
||||||
|
continue // Wird separat als MovingPlatform geprüft
|
||||||
|
}
|
||||||
|
|
||||||
if assetDef, ok := c.World.Manifest.Assets[obj.AssetID]; ok {
|
if assetDef, ok := c.World.Manifest.Assets[obj.AssetID]; ok {
|
||||||
if assetDef.Hitbox.W > 0 && assetDef.Hitbox.H > 0 {
|
if assetDef.Hitbox.W > 0 && assetDef.Hitbox.H > 0 {
|
||||||
colliderRect := game.Rect{
|
colliderRect := game.Rect{
|
||||||
@@ -228,7 +232,11 @@ func (c *ClientCollisionChecker) CheckCollision(x, y, w, h float64) (bool, strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
if game.CheckRectCollision(playerRect, colliderRect) {
|
if game.CheckRectCollision(playerRect, colliderRect) {
|
||||||
return true, assetDef.Hitbox.Type
|
colType := assetDef.Hitbox.Type
|
||||||
|
if colType == "" {
|
||||||
|
colType = assetDef.Type
|
||||||
|
}
|
||||||
|
return true, colType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user