Introduce core components for "Escape From Teacher" game: server, client, physics, asset system, and protocol definitions. Add Docker-Compose setup for Redis and NATS infrastructure.
This commit is contained in:
6
pkg/game/assets.go
Normal file
6
pkg/game/assets.go
Normal file
@@ -0,0 +1,6 @@
|
||||
package game
|
||||
|
||||
// Manifest ist die ganze Konfigurationsdatei
|
||||
type Manifest struct {
|
||||
Assets map[string]AssetDefinition `json:"assets"`
|
||||
}
|
||||
86
pkg/game/data.go
Normal file
86
pkg/game/data.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package game
|
||||
|
||||
import "image/color"
|
||||
|
||||
type Vec2 struct {
|
||||
X, Y float64 `json:"x,y"`
|
||||
}
|
||||
type Rect struct {
|
||||
OffsetX, OffsetY, W, H float64
|
||||
Type string
|
||||
} // Type hinzugefügt aus letztem Schritt
|
||||
type HexColor struct {
|
||||
R, G, B, A uint8 `json:"r,g,b,a"`
|
||||
}
|
||||
|
||||
func (h HexColor) ToRGBA() color.RGBA {
|
||||
if h.A == 0 {
|
||||
return color.RGBA{h.R, h.G, h.B, 255}
|
||||
}
|
||||
return color.RGBA{h.R, h.G, h.B, h.A}
|
||||
}
|
||||
|
||||
// --- ASSETS & CHUNKS (Bleiben gleich) ---
|
||||
type AssetDefinition struct {
|
||||
ID, Type, Filename string
|
||||
Scale, ProcWidth, ProcHeight, DrawOffX, DrawOffY float64
|
||||
Color HexColor
|
||||
Hitbox Rect
|
||||
}
|
||||
type AssetManifest struct {
|
||||
Assets map[string]AssetDefinition `json:"assets"`
|
||||
}
|
||||
type LevelObject struct {
|
||||
AssetID string
|
||||
X, Y float64
|
||||
}
|
||||
type Chunk struct {
|
||||
ID string
|
||||
Width int
|
||||
Objects []LevelObject
|
||||
}
|
||||
type ActiveChunk struct {
|
||||
ChunkID string
|
||||
X float64
|
||||
}
|
||||
|
||||
// --- NETZWERK & GAMEPLAY ---
|
||||
|
||||
// Login Request (Client -> Server beim Verbinden)
|
||||
type LoginPayload struct {
|
||||
Action string `json:"action"` // "CREATE" oder "JOIN"
|
||||
RoomID string `json:"room_id"` // Leer bei CREATE, Code bei JOIN
|
||||
Name string `json:"name"` // Spielername
|
||||
}
|
||||
|
||||
// Input vom Spieler während des Spiels
|
||||
type ClientInput struct {
|
||||
Type string `json:"type"` // "JUMP", "START"
|
||||
RoomID string `json:"room_id"`
|
||||
PlayerID string `json:"player_id"`
|
||||
}
|
||||
|
||||
type JoinRequest struct {
|
||||
Name string `json:"name"`
|
||||
RoomID string `json:"room_id"`
|
||||
}
|
||||
|
||||
type PlayerState struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
X float64 `json:"x"`
|
||||
Y float64 `json:"y"`
|
||||
State string `json:"state"`
|
||||
OnGround bool `json:"on_ground"`
|
||||
}
|
||||
|
||||
type GameState struct {
|
||||
RoomID string `json:"room_id"`
|
||||
Players map[string]PlayerState `json:"players"`
|
||||
Status string `json:"status"`
|
||||
TimeLeft int `json:"time_left"`
|
||||
WorldChunks []ActiveChunk `json:"world_chunks"`
|
||||
HostID string `json:"host_id"`
|
||||
|
||||
ScrollX float64 `json:"scroll_x"`
|
||||
}
|
||||
25
pkg/physics/engine.go
Normal file
25
pkg/physics/engine.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package physics
|
||||
|
||||
// Entity repräsentiert alles, was sich bewegt (Spieler, Hindernis)
|
||||
type Entity struct {
|
||||
X, Y float64
|
||||
Width, Height float64
|
||||
VelocityY float64
|
||||
}
|
||||
|
||||
// Config für Konstanten (Schwerkraft etc.)
|
||||
type Config struct {
|
||||
Gravity float64
|
||||
Speed float64
|
||||
}
|
||||
|
||||
// Update simuliert einen Tick (z.B. 1/60 sekunde)
|
||||
func (e *Entity) Update(cfg Config) {
|
||||
e.VelocityY += cfg.Gravity
|
||||
e.Y += e.VelocityY
|
||||
// Einfache Boden-Kollision (Hardcoded für den Anfang)
|
||||
if e.Y > 300 {
|
||||
e.Y = 300
|
||||
e.VelocityY = 0
|
||||
}
|
||||
}
|
||||
20
pkg/protocol/messages.go
Normal file
20
pkg/protocol/messages.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package protocol
|
||||
|
||||
// Input: Was der Spieler drückt
|
||||
type InputMessage struct {
|
||||
PlayerID string `json:"id"`
|
||||
Jump bool `json:"jump"`
|
||||
}
|
||||
|
||||
// State: Wo alles ist (Server -> Client)
|
||||
type GameStateMessage struct {
|
||||
Players map[string]*PlayerState `json:"players"` // Alle Spieler (1 bis 16)
|
||||
Score float64 `json:"score"`
|
||||
Multiplier int `json:"multiplier"`
|
||||
}
|
||||
|
||||
type PlayerState struct {
|
||||
// WICHTIG: Jedes Feld braucht ein eigenes JSON-Tag!
|
||||
X float64 `json:"x"`
|
||||
Y float64 `json:"y"`
|
||||
}
|
||||
32
pkg/stream/adapter.go
Normal file
32
pkg/stream/adapter.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package stream
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/nats-io/nats.go"
|
||||
)
|
||||
|
||||
// Connect verbindet uns mit dem NATS Cluster (oder lokalem Docker Container)
|
||||
func Connect(url string) (*nats.Conn, error) {
|
||||
// Default auf localhost, wenn leer
|
||||
if url == "" {
|
||||
url = nats.DefaultURL
|
||||
}
|
||||
|
||||
nc, err := nats.Connect(url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Printf("🔌 Verbunden mit NATS unter %s", url)
|
||||
return nc, nil
|
||||
}
|
||||
|
||||
// Helper Konstanten für unsere Topic-Struktur
|
||||
const (
|
||||
// Topic: game.<RoomID>.input -> Client sendet Tasten
|
||||
SubjectGameInput = "game.%s.input"
|
||||
|
||||
// Topic: game.<RoomID>.state -> Server sendet Positionen
|
||||
SubjectGameState = "game.%s.state"
|
||||
)
|
||||
Reference in New Issue
Block a user