This commit is contained in:
bdnugget 2024-09-30 10:04:38 +02:00
parent ddb02ea56b
commit a69ed0b0b9
3 changed files with 274 additions and 10 deletions

9
go.mod
View File

@ -2,9 +2,10 @@ module goonscape
go 1.23.0 go 1.23.0
require github.com/gen2brain/raylib-go/raylib v0.0.0-20240916050633-6bc3d79c96ad
require ( require (
github.com/ebitengine/purego v0.8.0 // indirect github.com/ebitengine/purego v0.7.1 // indirect
github.com/gen2brain/raylib-go/raylib v0.0.0-20240916050633-6bc3d79c96ad // indirect golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect golang.org/x/sys v0.20.0 // indirect
golang.org/x/sys v0.25.0 // indirect
) )

12
go.sum
View File

@ -1,8 +1,8 @@
github.com/ebitengine/purego v0.8.0 h1:JbqvnEzRvPpxhCJzJJ2y0RbiZ8nyjccVUrSM3q+GvvE= github.com/ebitengine/purego v0.7.1 h1:6/55d26lG3o9VCZX8lping+bZcmShseiqlh2bnUDiPA=
github.com/ebitengine/purego v0.8.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/ebitengine/purego v0.7.1/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ=
github.com/gen2brain/raylib-go/raylib v0.0.0-20240916050633-6bc3d79c96ad h1:kmIjqc2wOOn+MXw/pyuoYhhzfRFsZ+ESfkMWVt+WE7Y= github.com/gen2brain/raylib-go/raylib v0.0.0-20240916050633-6bc3d79c96ad h1:kmIjqc2wOOn+MXw/pyuoYhhzfRFsZ+ESfkMWVt+WE7Y=
github.com/gen2brain/raylib-go/raylib v0.0.0-20240916050633-6bc3d79c96ad/go.mod h1:BaY76bZk7nw1/kVOSQObPY1v1iwVE1KHAGMfvI6oK1Q= github.com/gen2brain/raylib-go/raylib v0.0.0-20240916050633-6bc3d79c96ad/go.mod h1:BaY76bZk7nw1/kVOSQObPY1v1iwVE1KHAGMfvI6oK1Q=
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM=
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=

263
main.go
View File

@ -0,0 +1,263 @@
package main
import (
"math"
rl "github.com/gen2brain/raylib-go/raylib"
)
type Tile struct {
X, Y int
Height float32
Walkable bool
}
const (
MapWidth = 100
MapHeight = 100
TileSize = 32
)
// Initialize the map with some height data
func InitMap() [][]Tile {
mapGrid := make([][]Tile, MapWidth)
for x := 0; x < MapWidth; x++ {
mapGrid[x] = make([]Tile, MapHeight)
for y := 0; y < MapHeight; y++ {
mapGrid[x][y] = Tile{
X: x,
Y: y,
Height: 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)
}
}
}
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)
}
func GetTileAtMouse(mapGrid [][]Tile) (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
if tileX >= 0 && tileX < MapWidth && tileY >= 0 && tileY < MapHeight {
return mapGrid[tileX][tileY], true
}
return Tile{}, false
}
// pathfinding
type Node struct {
Tile Tile
Parent *Node
G, H, F float32
}
func FindPath(mapGrid [][]Tile, start, end Tile) []Tile {
openList := []*Node{}
closedList := make(map[[2]int]bool)
startNode := &Node{Tile: start, G: 0, H: heuristic(start, end)}
startNode.F = startNode.G + startNode.H
openList = append(openList, startNode)
for len(openList) > 0 {
// Find node with lowest F
current := openList[0]
currentIndex := 0
for i, node := range openList {
if node.F < current.F {
current = node
currentIndex = i
}
}
// Move current to closed list
openList = append(openList[:currentIndex], openList[currentIndex+1:]...)
closedList[[2]int{current.Tile.X, current.Tile.Y}] = true
// Check if reached the end
if current.Tile.X == end.X && current.Tile.Y == end.Y {
path := []Tile{}
node := current
for node != nil {
path = append([]Tile{node.Tile}, path...)
node = node.Parent
}
return path
}
// Generate neighbors
neighbors := GetNeighbors(mapGrid, current.Tile)
for _, neighbor := range neighbors {
if !neighbor.Walkable || closedList[[2]int{neighbor.X, neighbor.Y}] {
continue
}
tentativeG := current.G + distance(current.Tile, neighbor)
inOpen := false
var existingNode *Node
for _, node := range openList {
if node.Tile.X == neighbor.X && node.Tile.Y == neighbor.Y {
existingNode = node
inOpen = true
break
}
}
if !inOpen || tentativeG < existingNode.G {
newNode := &Node{
Tile: neighbor,
Parent: current,
G: tentativeG,
H: heuristic(neighbor, end),
}
newNode.F = newNode.G + newNode.H
if !inOpen {
openList = append(openList, newNode)
}
}
}
}
// No path found
return nil
}
func heuristic(a, b Tile) float32 {
return float32(abs(a.X-b.X) + abs(a.Y-b.Y))
}
func distance(a, b Tile) float32 {
_ = a
_ = b
return 1.0 //uniform cost for now
}
func GetNeighbors(mapGrid [][]Tile, tile Tile) []Tile {
directions := [][2]int{
{1, 0}, {-1, 0}, {0, 1}, {0, -1},
{1, 1}, {-1, -1}, {1, -1}, {-1, 1},
}
neighbors := []Tile{}
for _, dir := range directions {
nx, ny := tile.X+dir[0], tile.Y+dir[1]
if nx >= 0 && nx < MapWidth && ny >= 0 && ny < MapHeight {
neighbors = append(neighbors, mapGrid[nx][ny])
}
}
return neighbors
}
func abs(x int) int {
if x < 0 {
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()
}
}