commit before I screw up more
This commit is contained in:
parent
a69ed0b0b9
commit
39dce85312
8
core/constants.go
Normal file
8
core/constants.go
Normal file
@ -0,0 +1,8 @@
|
||||
package utils
|
||||
|
||||
const (
|
||||
MapWidth = 100
|
||||
MapHeight = 100
|
||||
TileSize = 32
|
||||
TileHeight = 2.0
|
||||
)
|
1
core/types.go
Normal file
1
core/types.go
Normal file
@ -0,0 +1 @@
|
||||
package utils
|
333
main.go
333
main.go
@ -1,22 +1,37 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
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 {
|
||||
X, Y int
|
||||
Height float32
|
||||
Walkable bool
|
||||
}
|
||||
|
||||
const (
|
||||
MapWidth = 100
|
||||
MapHeight = 100
|
||||
TileSize = 32
|
||||
)
|
||||
type Player struct {
|
||||
PosActual rl.Vector3
|
||||
PosTile Tile
|
||||
TargetPath []Tile
|
||||
Speed float32
|
||||
}
|
||||
|
||||
// Initialize the map with some height data
|
||||
func InitMap() [][]Tile {
|
||||
@ -27,53 +42,241 @@ func InitMap() [][]Tile {
|
||||
mapGrid[x][y] = Tile{
|
||||
X: x,
|
||||
Y: y,
|
||||
Height: float32((x + y) % 10), // Example height
|
||||
Walkable: true, // Set to false for obstacles
|
||||
Height: 1.0 + float32(x%5), //float32((x + y) % 10), // Example height
|
||||
Walkable: true, // Set to false for obstacles
|
||||
}
|
||||
}
|
||||
}
|
||||
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) {
|
||||
for x := 0; x < MapWidth; x++ {
|
||||
for y := 0; y < MapHeight; y++ {
|
||||
tile := mapGrid[x][y]
|
||||
// Simple top-down view: color based on height
|
||||
color := rl.Color{R: uint8(tile.Height * 25), G: 100, B: 100, A: 255}
|
||||
rl.DrawRectangle(int32(tile.X*TileSize), int32(tile.Y*TileSize-int(tile.Height)), TileSize, TileSize, color)
|
||||
// Interpolate height between adjacent tiles for a smoother landscape
|
||||
height := tile.Height
|
||||
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) {
|
||||
// Get current tile height
|
||||
currentTile := mapGrid[player.X][player.Y]
|
||||
// Draw player at PosX, PosY adjusted by height
|
||||
rl.DrawCircle(int32(player.PosX), int32(player.PosY-currentTile.Height), 10, rl.Red)
|
||||
currentTile := mapGrid[player.PosTile.X][player.PosTile.Y]
|
||||
// Draw player cube with height from the map
|
||||
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) {
|
||||
return Tile{}, false
|
||||
}
|
||||
mouseX := rl.GetMouseX()
|
||||
mouseY := rl.GetMouseY()
|
||||
tileX := mouseX / TileSize
|
||||
tileY := (mouseY + int32(mapGrid[tileX][0].Height)) / TileSize
|
||||
mouse := rl.GetMousePosition()
|
||||
|
||||
// Unproject mouse coordinates to 3D ray
|
||||
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 {
|
||||
fmt.Println("Clicked:", tileX, tileY)
|
||||
return mapGrid[tileX][tileY], true
|
||||
}
|
||||
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
|
||||
type Node struct {
|
||||
Tile Tile
|
||||
@ -112,6 +315,7 @@ func FindPath(mapGrid [][]Tile, start, end Tile) []Tile {
|
||||
path = append([]Tile{node.Tile}, path...)
|
||||
node = node.Parent
|
||||
}
|
||||
fmt.Printf("Path found: %v\n", path)
|
||||
return path
|
||||
}
|
||||
|
||||
@ -149,6 +353,7 @@ func FindPath(mapGrid [][]Tile, start, end Tile) []Tile {
|
||||
}
|
||||
|
||||
// No path found
|
||||
fmt.Println("No path found")
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -183,81 +388,3 @@ func abs(x int) int {
|
||||
}
|
||||
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
1
utils/pathfinding.go
Normal file
@ -0,0 +1 @@
|
||||
package utils
|
Loading…
x
Reference in New Issue
Block a user