169 lines
4.0 KiB
Go
169 lines
4.0 KiB
Go
package game
|
|
|
|
import (
|
|
"gitea.boner.be/bdnugget/goonscape/assets"
|
|
"gitea.boner.be/bdnugget/goonscape/types"
|
|
pb "gitea.boner.be/bdnugget/goonserver/actions"
|
|
rl "github.com/gen2brain/raylib-go/raylib"
|
|
)
|
|
|
|
type Game struct {
|
|
Player *types.Player
|
|
OtherPlayers map[int32]*types.Player
|
|
Camera rl.Camera3D
|
|
Models []types.ModelAsset
|
|
Music rl.Music
|
|
}
|
|
|
|
func New() *Game {
|
|
InitWorld()
|
|
game := &Game{
|
|
Player: &types.Player{
|
|
PosActual: rl.NewVector3(5*types.TileSize, 0, 5*types.TileSize),
|
|
PosTile: GetTile(5, 5),
|
|
Speed: 50.0,
|
|
TargetPath: []types.Tile{},
|
|
},
|
|
OtherPlayers: make(map[int32]*types.Player),
|
|
Camera: rl.Camera3D{
|
|
Position: rl.NewVector3(0, 10, 10),
|
|
Target: rl.NewVector3(0, 0, 0),
|
|
Up: rl.NewVector3(0, 1, 0),
|
|
Fovy: 45.0,
|
|
Projection: rl.CameraPerspective,
|
|
},
|
|
}
|
|
return game
|
|
}
|
|
|
|
func (g *Game) LoadAssets() error {
|
|
var err error
|
|
g.Models, err = assets.LoadModels()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
g.Music, err = assets.LoadMusic("resources/audio/GoonScape2.mp3")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (g *Game) Update(deltaTime float32) {
|
|
g.HandleInput()
|
|
|
|
if len(g.Player.TargetPath) > 0 {
|
|
g.Player.MoveTowards(g.Player.TargetPath[0], deltaTime, GetMapGrid())
|
|
}
|
|
|
|
for _, other := range g.OtherPlayers {
|
|
if len(other.TargetPath) > 0 {
|
|
other.MoveTowards(other.TargetPath[0], deltaTime, GetMapGrid())
|
|
}
|
|
}
|
|
|
|
UpdateCamera(&g.Camera, g.Player.PosActual, deltaTime)
|
|
}
|
|
|
|
func (g *Game) DrawMap() {
|
|
for x := 0; x < types.MapWidth; x++ {
|
|
for y := 0; y < types.MapHeight; y++ {
|
|
height := GetTileHeight(x, y)
|
|
|
|
// Interpolate height for smoother landscape
|
|
if x > 0 {
|
|
height += GetTileHeight(x-1, y)
|
|
}
|
|
if y > 0 {
|
|
height += GetTileHeight(x, y-1)
|
|
}
|
|
if x > 0 && y > 0 {
|
|
height += GetTileHeight(x-1, y-1)
|
|
}
|
|
height /= 4.0
|
|
|
|
tilePos := rl.Vector3{
|
|
X: float32(x * types.TileSize),
|
|
Y: height * types.TileHeight,
|
|
Z: float32(y * types.TileSize),
|
|
}
|
|
color := rl.Color{R: uint8(height * 25), G: 100, B: 100, A: 64}
|
|
rl.DrawCube(tilePos, types.TileSize, types.TileHeight, types.TileSize, color)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (g *Game) DrawPlayer(player *types.Player, model rl.Model) {
|
|
player.Lock()
|
|
defer player.Unlock()
|
|
|
|
grid := GetMapGrid()
|
|
playerPos := rl.Vector3{
|
|
X: player.PosActual.X,
|
|
Y: grid[player.PosTile.X][player.PosTile.Y].Height*types.TileHeight + 16.0,
|
|
Z: player.PosActual.Z,
|
|
}
|
|
|
|
rl.DrawModel(model, playerPos, 16, rl.White)
|
|
|
|
if len(player.TargetPath) > 0 {
|
|
targetTile := player.TargetPath[len(player.TargetPath)-1]
|
|
targetPos := rl.Vector3{
|
|
X: float32(targetTile.X * types.TileSize),
|
|
Y: grid[targetTile.X][targetTile.Y].Height * types.TileHeight,
|
|
Z: float32(targetTile.Y * types.TileSize),
|
|
}
|
|
rl.DrawCubeWires(targetPos, types.TileSize, types.TileHeight, types.TileSize, rl.Green)
|
|
|
|
nextTile := player.TargetPath[0]
|
|
nextPos := rl.Vector3{
|
|
X: float32(nextTile.X * types.TileSize),
|
|
Y: grid[nextTile.X][nextTile.Y].Height * types.TileHeight,
|
|
Z: float32(nextTile.Y * types.TileSize),
|
|
}
|
|
rl.DrawCubeWires(nextPos, types.TileSize, types.TileHeight, types.TileSize, rl.Yellow)
|
|
}
|
|
}
|
|
|
|
func (g *Game) Render() {
|
|
rl.BeginDrawing()
|
|
rl.ClearBackground(rl.RayWhite)
|
|
rl.BeginMode3D(g.Camera)
|
|
|
|
g.DrawMap()
|
|
g.DrawPlayer(g.Player, g.Player.Model)
|
|
|
|
for id, other := range g.OtherPlayers {
|
|
g.DrawPlayer(other, g.Models[int(id)%len(g.Models)].Model)
|
|
}
|
|
|
|
rl.EndMode3D()
|
|
rl.DrawFPS(10, 10)
|
|
rl.EndDrawing()
|
|
}
|
|
|
|
func (g *Game) Cleanup() {
|
|
assets.UnloadModels(g.Models)
|
|
assets.UnloadMusic(g.Music)
|
|
}
|
|
|
|
func (g *Game) HandleInput() {
|
|
clickedTile, clicked := g.GetTileAtMouse()
|
|
if clicked {
|
|
path := FindPath(GetTile(g.Player.PosTile.X, g.Player.PosTile.Y), clickedTile)
|
|
if path != nil && len(path) > 1 {
|
|
g.Player.Lock()
|
|
g.Player.TargetPath = path[1:]
|
|
g.Player.ActionQueue = append(g.Player.ActionQueue, &pb.Action{
|
|
Type: pb.Action_MOVE,
|
|
X: int32(clickedTile.X),
|
|
Y: int32(clickedTile.Y),
|
|
PlayerId: g.Player.ID,
|
|
})
|
|
g.Player.Unlock()
|
|
}
|
|
}
|
|
}
|