commit before I screw up more

This commit is contained in:
bdnugget 2024-09-30 15:34:16 +02:00
parent a69ed0b0b9
commit 39dce85312
4 changed files with 240 additions and 103 deletions

8
core/constants.go Normal file
View File

@ -0,0 +1,8 @@
package utils
const (
MapWidth = 100
MapHeight = 100
TileSize = 32
TileHeight = 2.0
)

1
core/types.go Normal file
View File

@ -0,0 +1 @@
package utils

331
main.go
View File

@ -1,22 +1,37 @@
package main package main
import ( import (
"fmt"
"math" "math"
rl "github.com/gen2brain/raylib-go/raylib" rl "github.com/gen2brain/raylib-go/raylib"
) )
const (
MapWidth = 100
MapHeight = 100
TileSize = 32
TileHeight = 2.0
)
var (
cameraDistance = float32(64.0)
cameraYaw = float32(45.0)
cameraPitch = float32(30.0)
)
type Tile struct { type Tile struct {
X, Y int X, Y int
Height float32 Height float32
Walkable bool Walkable bool
} }
const ( type Player struct {
MapWidth = 100 PosActual rl.Vector3
MapHeight = 100 PosTile Tile
TileSize = 32 TargetPath []Tile
) Speed float32
}
// Initialize the map with some height data // Initialize the map with some height data
func InitMap() [][]Tile { func InitMap() [][]Tile {
@ -27,7 +42,7 @@ func InitMap() [][]Tile {
mapGrid[x][y] = Tile{ mapGrid[x][y] = Tile{
X: x, X: x,
Y: y, Y: y,
Height: float32((x + y) % 10), // Example height Height: 1.0 + float32(x%5), //float32((x + y) % 10), // Example height
Walkable: true, // Set to false for obstacles Walkable: true, // Set to false for obstacles
} }
} }
@ -35,45 +50,233 @@ func InitMap() [][]Tile {
return mapGrid return mapGrid
} }
type Player struct {
X, Y int // Current tile position
PosX, PosY float32 // Actual position for smooth movement
TargetPath []Tile
Speed float32
}
func DrawMap(mapGrid [][]Tile) { func DrawMap(mapGrid [][]Tile) {
for x := 0; x < MapWidth; x++ { for x := 0; x < MapWidth; x++ {
for y := 0; y < MapHeight; y++ { for y := 0; y < MapHeight; y++ {
tile := mapGrid[x][y] tile := mapGrid[x][y]
// Simple top-down view: color based on height // Interpolate height between adjacent tiles for a smoother landscape
color := rl.Color{R: uint8(tile.Height * 25), G: 100, B: 100, A: 255} height := tile.Height
rl.DrawRectangle(int32(tile.X*TileSize), int32(tile.Y*TileSize-int(tile.Height)), TileSize, TileSize, color) if x > 0 {
height += mapGrid[x-1][y].Height
}
if y > 0 {
height += mapGrid[x][y-1].Height
}
if x > 0 && y > 0 {
height += mapGrid[x-1][y-1].Height
}
height /= 4.0
// Draw each tile as a 3D cube based on its height
tilePos := rl.Vector3{
X: float32(x * TileSize), // X-axis for horizontal position
Y: height * TileHeight, // Y-axis for height (Z in 3D is Y here)
Z: float32(y * TileSize), // Z-axis for depth (Y in 3D is Z here)
}
color := rl.Color{R: uint8(height * 25), G: 100, B: 100, A: 64}
rl.DrawCube(tilePos, TileSize, TileHeight, TileSize, color) // Draw a cube representing the tile
} }
} }
} }
func DrawPlayer(player Player, mapGrid [][]Tile) { func DrawPlayer(player Player, mapGrid [][]Tile) {
// Get current tile height // Get current tile height
currentTile := mapGrid[player.X][player.Y] currentTile := mapGrid[player.PosTile.X][player.PosTile.Y]
// Draw player at PosX, PosY adjusted by height // Draw player cube with height from the map
rl.DrawCircle(int32(player.PosX), int32(player.PosY-currentTile.Height), 10, rl.Red) playerPos := rl.Vector3{
X: float32(player.PosTile.X * TileSize),
Y: currentTile.Height * TileHeight,
Z: float32(player.PosTile.Y * TileSize),
}
rl.DrawCube(playerPos, 16, 16, 16, rl.Green) // Draw player cube
} }
func GetTileAtMouse(mapGrid [][]Tile) (Tile, bool) { func GetTileAtMouse(mapGrid [][]Tile, camera *rl.Camera3D) (Tile, bool) {
if !rl.IsMouseButtonPressed(rl.MouseLeftButton) { if !rl.IsMouseButtonPressed(rl.MouseLeftButton) {
return Tile{}, false return Tile{}, false
} }
mouseX := rl.GetMouseX() mouse := rl.GetMousePosition()
mouseY := rl.GetMouseY()
tileX := mouseX / TileSize // Unproject mouse coordinates to 3D ray
tileY := (mouseY + int32(mapGrid[tileX][0].Height)) / TileSize var ray rl.Ray = rl.GetMouseRay(mouse, *camera)
// Calculate the distance from the camera to the ray's intersection with the ground plane (Y=0)
dist := -ray.Position.Y / ray.Direction.Y
// Calculate the intersection point
intersection := rl.NewVector3(
ray.Position.X+ray.Direction.X*dist,
ray.Position.Y+ray.Direction.Y*dist,
ray.Position.Z+ray.Direction.Z*dist,
)
// Convert the intersection point to tile coordinates
tileX := int(intersection.X / float32(TileSize))
tileY := int(intersection.Z / float32(TileSize))
if tileX >= 0 && tileX < MapWidth && tileY >= 0 && tileY < MapHeight { if tileX >= 0 && tileX < MapWidth && tileY >= 0 && tileY < MapHeight {
fmt.Println("Clicked:", tileX, tileY)
return mapGrid[tileX][tileY], true return mapGrid[tileX][tileY], true
} }
return Tile{}, false return Tile{}, false
} }
func UpdatePlayer(player *Player, deltaTime float32, mapGrid [][]Tile, camera *rl.Camera) {
if len(player.TargetPath) > 0 {
targetTile := player.TargetPath[0]
// Calculate the direction vector to the target
direction := rl.Vector3{
X: float32(targetTile.X*TileSize) - player.PosActual.X,
Y: float32(targetTile.Y*TileSize) - player.PosActual.Y,
}
// Normalize the direction vector to get smooth movement
dist := float32(math.Sqrt(float64(direction.X*direction.X + direction.Y*direction.Y)))
if dist > 0 {
direction.X /= dist
direction.Y /= dist
}
// Move towards the target
newPosX := player.PosActual.X + direction.X*player.Speed*deltaTime
newPosY := player.PosActual.Y + direction.Y*player.Speed*deltaTime
// Check if the player is moving into a non-walkable tile
if !mapGrid[int(newPosX)/TileSize][int(newPosY)/TileSize].Walkable {
return
}
// Update player's position
player.PosActual.X = newPosX
player.PosActual.Y = newPosY
// Check if the player reached the target tile
if dist < 1.0 {
player.PosActual.X = float32(targetTile.X * TileSize)
player.PosActual.Y = float32(targetTile.Y * TileSize)
player.PosTile = targetTile // Update the player's tile position
player.TargetPath = player.TargetPath[1:] // Move to the next tile in the path
}
// Update camera target and position
camera.Target = player.PosActual
camera.Position.X = player.PosActual.X
camera.Position.Y = player.PosActual.Y
camera.Position.Z = player.PosActual.Z + cameraDistance
}
}
func HandleInput(player *Player, mapGrid [][]Tile, camera *rl.Camera) {
clickedTile, clicked := GetTileAtMouse(mapGrid, camera)
if clicked {
path := FindPath(mapGrid, mapGrid[player.PosTile.X][player.PosTile.Y], clickedTile)
if path != nil {
// Exclude the first tile (current position)
if len(path) > 1 {
player.TargetPath = path[1:]
}
}
}
}
func main() {
rl.InitWindow(800, 600, "RuneScape-like Game")
defer rl.CloseWindow()
frameCnt := 0
mapGrid := InitMap()
player := Player{
PosTile: Tile{X: 10, Y: 10},
PosActual: rl.Vector3{X: float32(10 * TileSize), Y: float32(10 * TileSize), Z: float32(mapGrid[10][10].Height /* * TileHeight */)},
Speed: 100.0, // pixels per second
}
// Initialize 3D camera
cameraDistance := float32(64.0)
cameraYaw := float32(45.0)
cameraPitch := float32(30.0)
camera := rl.Camera3D{
Position: rl.NewVector3(player.PosActual.X, player.PosActual.Y, player.PosActual.Z+cameraDistance), // Updated camera position
Target: player.PosActual, // The point the camera looks at (player)
Up: rl.NewVector3(0, 1, 0), // Camera up vector (y-axis is up)
Fovy: 45.0, // Field of view
Projection: rl.CameraPerspective, // Perspective camera mode
}
rl.SetTargetFPS(60)
for !rl.WindowShouldClose() {
deltaTime := rl.GetFrameTime()
frameCnt++
frameCnt %= 60
HandleInput(&player, mapGrid, &camera)
UpdatePlayer(&player, deltaTime, mapGrid, &camera)
// Update camera based on mouse wheel
wheelMove := rl.GetMouseWheelMove()
if wheelMove != 0 {
cameraDistance += wheelMove * 5
if cameraDistance < 10 {
cameraDistance = 10
} else if cameraDistance > 100 {
cameraDistance = 100
}
}
// Update camera position directly above the player
camera.Target = player.PosActual // Ensure the camera always looks at the player
// Update camera based on arrow keys (camera orbits player)
if rl.IsKeyDown(rl.KeyRight) {
cameraYaw -= 60 * deltaTime // Rotate right
}
if rl.IsKeyDown(rl.KeyLeft) {
cameraYaw += 60 * deltaTime // Rotate left
}
if rl.IsKeyDown(rl.KeyUp) {
cameraPitch += 60 * deltaTime // Tilt up
}
if rl.IsKeyDown(rl.KeyDown) {
cameraPitch -= 60 * deltaTime // Tilt down
}
// Constrain camera pitch to avoid flipping
if cameraPitch > 85.0 {
cameraPitch = 85.0
} else if cameraPitch < -10.0 {
cameraPitch = -10.0
}
// Convert spherical coordinates to cartesian to calculate the camera's position
camera.Position.X = player.PosActual.X + cameraDistance*float32(math.Cos(float64(cameraPitch)*math.Pi/180.0))*float32(math.Sin(float64(cameraYaw)*math.Pi/180.0))
camera.Position.Y = player.PosActual.Y + cameraDistance*float32(math.Sin(float64(cameraPitch)*math.Pi/180.0))
camera.Position.Z = player.PosActual.Z + cameraDistance*float32(math.Cos(float64(cameraPitch)*math.Pi/180.0))*float32(math.Cos(float64(cameraYaw)*math.Pi/180.0))
// Begin rendering
rl.BeginDrawing()
rl.ClearBackground(rl.RayWhite)
rl.BeginMode3D(camera)
// Draw map and player
DrawMap(mapGrid)
DrawPlayer(player, mapGrid)
rl.EndMode3D()
rl.EndDrawing()
if frameCnt == 0 {
fmt.Printf("Player Pos: %v, Camera Pos: %v\n", player.PosActual, camera.Position)
}
}
}
// pathfinding // pathfinding
type Node struct { type Node struct {
Tile Tile Tile Tile
@ -112,6 +315,7 @@ func FindPath(mapGrid [][]Tile, start, end Tile) []Tile {
path = append([]Tile{node.Tile}, path...) path = append([]Tile{node.Tile}, path...)
node = node.Parent node = node.Parent
} }
fmt.Printf("Path found: %v\n", path)
return path return path
} }
@ -149,6 +353,7 @@ func FindPath(mapGrid [][]Tile, start, end Tile) []Tile {
} }
// No path found // No path found
fmt.Println("No path found")
return nil return nil
} }
@ -183,81 +388,3 @@ func abs(x int) int {
} }
return x return x
} }
// end pathfinding
func UpdatePlayer(player *Player, deltaTime float32, mapGrid [][]Tile) {
if len(player.TargetPath) > 0 {
targetTile := player.TargetPath[0]
targetX := float32(targetTile.X * TileSize)
targetY := float32(targetTile.Y*TileSize - int(targetTile.Height))
// Calculate direction
dirX := targetX - player.PosX
dirY := targetY - player.PosY
distance := float32(math.Sqrt(float64(dirX*dirX + dirY*dirY)))
if distance < player.Speed*deltaTime {
// Snap to target tile
player.PosX = targetX
player.PosY = targetY
player.X = targetTile.X
player.Y = targetTile.Y
// Remove the reached tile from the path
player.TargetPath = player.TargetPath[1:]
} else {
// Move towards target
player.PosX += (dirX / distance) * player.Speed * deltaTime
player.PosY += (dirY / distance) * player.Speed * deltaTime
}
}
}
func HandleInput(player *Player, mapGrid [][]Tile) {
clickedTile, clicked := GetTileAtMouse(mapGrid)
if clicked {
path := FindPath(mapGrid, mapGrid[player.X][player.Y], clickedTile)
if path != nil {
// Exclude the first tile (current position)
if len(path) > 1 {
player.TargetPath = path[1:]
}
}
}
}
func main() {
rl.InitWindow(800, 600, "RuneScape-like Game")
defer rl.CloseWindow()
mapGrid := InitMap()
player := Player{
X: 10,
Y: 10,
PosX: float32(10 * TileSize),
PosY: float32(10*TileSize - int(mapGrid[10][10].Height)),
Speed: 100.0, // pixels per second
}
rl.SetTargetFPS(60)
for !rl.WindowShouldClose() {
deltaTime := rl.GetFrameTime()
// Handle input
HandleInput(&player, mapGrid)
// Update player position
UpdatePlayer(&player, deltaTime, mapGrid)
// Draw everything
rl.BeginDrawing()
rl.ClearBackground(rl.RayWhite)
DrawMap(mapGrid)
DrawPlayer(player, mapGrid)
rl.EndDrawing()
}
}

1
utils/pathfinding.go Normal file
View File

@ -0,0 +1 @@
package utils