Private
Public Access
1
0
Files
EscapeFromTeacher/pkg/server/scoring.go
Sebastian Unterschütz 656f279a89
All checks were successful
Dynamic Branch Deploy / build-and-deploy (push) Successful in 6m49s
fix game
2026-03-22 18:18:45 +01:00

207 lines
5.1 KiB
Go

package server
import (
"fmt"
"log"
"time"
"git.zb-server.de/ZB-Server/EscapeFromTeacher/pkg/game"
)
// CheckCoinCollision prüft ob Spieler Coins einsammelt
func (r *Room) CheckCoinCollision(p *ServerPlayer) {
if !p.IsAlive || p.IsSpectator {
return
}
playerHitbox := game.Rect{
OffsetX: p.X + r.pDrawOffX + r.pHitboxOffX,
OffsetY: p.Y + r.pDrawOffY + r.pHitboxOffY,
W: r.pW,
H: r.pH,
}
for _, activeChunk := range r.ActiveChunks {
chunkDef, exists := r.World.ChunkLibrary[activeChunk.ChunkID]
if !exists {
continue
}
for objIdx, obj := range chunkDef.Objects {
assetDef, ok := r.World.Manifest.Assets[obj.AssetID]
if !ok || assetDef.Type != "coin" {
continue
}
coinKey := fmt.Sprintf("%s_%d", activeChunk.ChunkID, objIdx)
if r.CollectedCoins[coinKey] {
continue
}
coinHitbox := game.Rect{
OffsetX: activeChunk.X + obj.X + assetDef.DrawOffX + assetDef.Hitbox.OffsetX,
OffsetY: obj.Y + assetDef.DrawOffY + assetDef.Hitbox.OffsetY,
W: assetDef.Hitbox.W,
H: assetDef.Hitbox.H,
}
if game.CheckRectCollision(playerHitbox, coinHitbox) {
r.CollectedCoins[coinKey] = true
p.BonusScore += 200
p.Score = p.DistanceScore + p.BonusScore
log.Printf("💰 %s hat Coin eingesammelt! Score: %d", p.Name, p.Score)
}
}
}
}
// CheckPowerupCollision prüft ob Spieler Powerups einsammelt
func (r *Room) CheckPowerupCollision(p *ServerPlayer) {
if !p.IsAlive || p.IsSpectator {
return
}
playerHitbox := game.Rect{
OffsetX: p.X + r.pDrawOffX + r.pHitboxOffX,
OffsetY: p.Y + r.pDrawOffY + r.pHitboxOffY,
W: r.pW,
H: r.pH,
}
for _, activeChunk := range r.ActiveChunks {
chunkDef, exists := r.World.ChunkLibrary[activeChunk.ChunkID]
if !exists {
continue
}
for objIdx, obj := range chunkDef.Objects {
assetDef, ok := r.World.Manifest.Assets[obj.AssetID]
if !ok || assetDef.Type != "powerup" {
continue
}
powerupKey := fmt.Sprintf("%s_%d", activeChunk.ChunkID, objIdx)
if r.CollectedPowerups[powerupKey] {
continue
}
powerupHitbox := game.Rect{
OffsetX: activeChunk.X + obj.X + assetDef.DrawOffX + assetDef.Hitbox.OffsetX,
OffsetY: obj.Y + assetDef.DrawOffY + assetDef.Hitbox.OffsetY,
W: assetDef.Hitbox.W,
H: assetDef.Hitbox.H,
}
if game.CheckRectCollision(playerHitbox, powerupHitbox) {
r.CollectedPowerups[powerupKey] = true
switch obj.AssetID {
case "jumpboost":
p.HasDoubleJump = true
p.DoubleJumpUsed = false
p.DoubleJumpEndTime = time.Now().Add(15 * time.Second)
log.Printf("⚡ %s hat Double Jump erhalten! (15 Sekunden)", p.Name)
case "godmode":
p.HasGodMode = true
p.GodModeEndTime = time.Now().Add(10 * time.Second)
log.Printf("🛡️ %s hat Godmode erhalten! (10 Sekunden)", p.Name)
case "magnet":
p.HasMagnet = true
p.MagnetEndTime = time.Now().Add(8 * time.Second)
log.Printf("🧲 %s hat Magnet erhalten! (8 Sekunden)", p.Name)
}
}
}
}
}
// ApplyMagnetEffect sammelt alle Coins im Umkreis von ~300px automatisch ein
func (r *Room) ApplyMagnetEffect(p *ServerPlayer) {
const magnetRadius = 300.0
playerCenterX := p.X + r.pDrawOffX + r.pHitboxOffX + r.pW/2
playerCenterY := p.Y + r.pDrawOffY + r.pHitboxOffY + r.pH/2
for _, activeChunk := range r.ActiveChunks {
chunkDef, exists := r.World.ChunkLibrary[activeChunk.ChunkID]
if !exists {
continue
}
for objIdx, obj := range chunkDef.Objects {
assetDef, ok := r.World.Manifest.Assets[obj.AssetID]
if !ok || assetDef.Type != "coin" {
continue
}
coinKey := fmt.Sprintf("%s_%d", activeChunk.ChunkID, objIdx)
if r.CollectedCoins[coinKey] {
continue
}
coinCenterX := activeChunk.X + obj.X + assetDef.DrawOffX + assetDef.Hitbox.OffsetX + assetDef.Hitbox.W/2
coinCenterY := obj.Y + assetDef.DrawOffY + assetDef.Hitbox.OffsetY + assetDef.Hitbox.H/2
dx := coinCenterX - playerCenterX
dy := coinCenterY - playerCenterY
if dx*dx+dy*dy <= magnetRadius*magnetRadius {
r.CollectedCoins[coinKey] = true
p.BonusScore += 200
p.Score = p.DistanceScore + p.BonusScore
log.Printf("🧲 %s hat Coin per Magnet eingesammelt! Score: %d", p.Name, p.Score)
}
}
}
}
// UpdateDistanceScore aktualisiert Distanz-basierte Punkte
func (r *Room) UpdateDistanceScore() {
if r.Status != "RUNNING" {
return
}
aliveCount := 0
for _, p := range r.Players {
if p.IsAlive && !p.IsSpectator {
aliveCount++
}
}
if aliveCount == 0 {
return
}
for _, p := range r.Players {
if p.IsAlive && !p.IsSpectator {
p.DistanceScore += aliveCount
p.Score = p.DistanceScore + p.BonusScore
}
}
}
// KillPlayer markiert Spieler als tot
func (r *Room) KillPlayer(p *ServerPlayer) {
if !p.IsAlive {
return
}
p.IsAlive = false
p.IsSpectator = true
log.Printf("💀 %s ist gestorben! Final Score: %d", p.Name, p.Score)
aliveCount := 0
for _, pl := range r.Players {
if pl.IsAlive && !pl.IsSpectator {
aliveCount++
}
}
if aliveCount == 0 && r.Status == "RUNNING" {
log.Printf("🏁 Alle Spieler tot - Game Over!")
r.Status = "GAMEOVER"
}
}