a
This commit is contained in:
commit
9a3bc05131
5
go.mod
Normal file
5
go.mod
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
module kisekinopureya.com.tr/go-raycasting
|
||||||
|
|
||||||
|
go 1.24.1
|
||||||
|
|
||||||
|
require github.com/veandco/go-sdl2 v0.4.40
|
||||||
2
go.sum
Normal file
2
go.sum
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
github.com/veandco/go-sdl2 v0.4.40 h1:fZv6wC3zz1Xt167P09gazawnpa0KY5LM7JAvKpX9d/U=
|
||||||
|
github.com/veandco/go-sdl2 v0.4.40/go.mod h1:OROqMhHD43nT4/i9crJukyVecjPNYYuCofep6SNiAjY=
|
||||||
259
main.go
Normal file
259
main.go
Normal file
@ -0,0 +1,259 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
|
||||||
|
"github.com/veandco/go-sdl2/sdl"
|
||||||
|
worldMap "kisekinopureya.com.tr/go-raycasting/worldMap"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
screenWidth = 640
|
||||||
|
screenHeight = 480
|
||||||
|
fontPath = "assets/test.ttf"
|
||||||
|
fontSize = 16
|
||||||
|
debug = true
|
||||||
|
texWidth = 64
|
||||||
|
texHeight = 64
|
||||||
|
)
|
||||||
|
|
||||||
|
func verLine(x int32, drawStart int32, drawEnd int32, color sdl.Color, window *sdl.Window) {
|
||||||
|
surface, err := window.GetSurface()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
for y := drawStart; y < drawEnd; y++ {
|
||||||
|
pixel := sdl.MapRGBA(surface.Format, color.R, color.G, color.B, color.A)
|
||||||
|
surface.FillRect(&sdl.Rect{X: x, Y: y, W: 1, H: 1}, pixel)
|
||||||
|
}
|
||||||
|
window.UpdateSurface()
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
level := worldMap.GetMap()
|
||||||
|
|
||||||
|
var buffer [screenHeight][screenWidth]uint32
|
||||||
|
texture := worldMap.GetTextures()
|
||||||
|
var renderer *sdl.Renderer
|
||||||
|
|
||||||
|
if err := sdl.Init(sdl.INIT_EVERYTHING); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer sdl.Quit()
|
||||||
|
|
||||||
|
window, err := sdl.CreateWindow("go raycasting", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED, screenWidth, screenHeight, sdl.WINDOW_SHOWN)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer window.Destroy()
|
||||||
|
|
||||||
|
renderer, err = sdl.CreateRenderer(window, -1, sdl.RENDERER_ACCELERATED)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var posX float64 = 3 //22 //x and y start position
|
||||||
|
var posY float64 = 4 //12
|
||||||
|
|
||||||
|
var dirX float64 = -1
|
||||||
|
var dirY float64 = 0 //initial direction vector
|
||||||
|
|
||||||
|
var planeX float64 = 0
|
||||||
|
var planeY float64 = 0.66 //the 2d raycaster version of camera plane
|
||||||
|
|
||||||
|
var time float64 = 0 //time of current frame
|
||||||
|
var oldTime float64 = 0 //time of previous frame
|
||||||
|
|
||||||
|
running := true
|
||||||
|
for running {
|
||||||
|
for x := range screenWidth {
|
||||||
|
var cameraX float64 = (float64)(2*x/screenWidth - 1)
|
||||||
|
var rayDirX = dirX + planeX*cameraX
|
||||||
|
var rayDirY = dirY + planeY*cameraX
|
||||||
|
var mapX int = int(posX)
|
||||||
|
var mapY int = int(posY)
|
||||||
|
|
||||||
|
var sideDistX float64
|
||||||
|
var sideDistY float64
|
||||||
|
|
||||||
|
var deltaDistX float64
|
||||||
|
if rayDirX == 0 {
|
||||||
|
deltaDistX = 1e30
|
||||||
|
} else {
|
||||||
|
deltaDistX = math.Abs(1 / rayDirX)
|
||||||
|
}
|
||||||
|
|
||||||
|
var deltaDistY float64
|
||||||
|
if rayDirY == 0 {
|
||||||
|
deltaDistY = 1e30
|
||||||
|
} else {
|
||||||
|
deltaDistY = math.Abs(1 / rayDirY)
|
||||||
|
}
|
||||||
|
|
||||||
|
var perpWallDist float64
|
||||||
|
|
||||||
|
var stepX int
|
||||||
|
var stepY int
|
||||||
|
|
||||||
|
var hit int = 0 //was there a wall hit?
|
||||||
|
var side int //was a NS or a EW wall hit?
|
||||||
|
//calculate step and initial sideDist
|
||||||
|
if rayDirX < 0 {
|
||||||
|
stepX = -1
|
||||||
|
sideDistX = (posX - float64(mapX)) * deltaDistX
|
||||||
|
} else {
|
||||||
|
stepX = 1
|
||||||
|
sideDistX = (float64(mapX) + 1.0 - posX) * deltaDistX
|
||||||
|
}
|
||||||
|
|
||||||
|
if rayDirY < 0 {
|
||||||
|
stepY = -1
|
||||||
|
sideDistY = (posY - float64(mapY)) * deltaDistY
|
||||||
|
} else {
|
||||||
|
stepY = 1
|
||||||
|
sideDistY = (float64(mapY) + 1.0 - posY) * deltaDistY
|
||||||
|
}
|
||||||
|
//perform DDA
|
||||||
|
for hit == 0 {
|
||||||
|
//jump to next map square, either in x-direction, or in y-direction
|
||||||
|
if sideDistX < sideDistY {
|
||||||
|
sideDistX += deltaDistX
|
||||||
|
mapX += stepX
|
||||||
|
side = 0
|
||||||
|
} else {
|
||||||
|
sideDistY += deltaDistY
|
||||||
|
mapY += stepY
|
||||||
|
side = 1
|
||||||
|
}
|
||||||
|
//Check if ray has hit a wall
|
||||||
|
if level[mapX][mapY] > 0 {
|
||||||
|
hit = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if side == 0 {
|
||||||
|
perpWallDist = (sideDistX - deltaDistX)
|
||||||
|
} else {
|
||||||
|
perpWallDist = (sideDistY - deltaDistY)
|
||||||
|
}
|
||||||
|
|
||||||
|
var lineHeight int = (int)(screenHeight / perpWallDist)
|
||||||
|
|
||||||
|
var pitch int = 100
|
||||||
|
|
||||||
|
//calculate lowest and highest pixel to fill in current stripe
|
||||||
|
var drawStart int = -lineHeight/2 + screenHeight/2 + pitch
|
||||||
|
if drawStart < 0 {
|
||||||
|
drawStart = 0
|
||||||
|
}
|
||||||
|
var drawEnd int = lineHeight/2 + screenHeight/2 + pitch
|
||||||
|
if drawEnd >= screenHeight {
|
||||||
|
drawEnd = screenHeight - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
var texNum int = level[mapX][mapY] - 1
|
||||||
|
|
||||||
|
var wallX float64 //where exactly the wall was hit
|
||||||
|
if side == 0 {
|
||||||
|
wallX = posY + perpWallDist*rayDirY
|
||||||
|
} else {
|
||||||
|
wallX = posX + perpWallDist*rayDirX
|
||||||
|
}
|
||||||
|
wallX -= math.Floor((wallX))
|
||||||
|
|
||||||
|
var texX int = int(wallX * float64(texWidth))
|
||||||
|
if side == 0 && rayDirX > 0 {
|
||||||
|
texX = texWidth - texX - 1
|
||||||
|
}
|
||||||
|
if side == 1 && rayDirY < 0 {
|
||||||
|
texX = texWidth - texX - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
step := 1.0 * float64(texHeight) / float64(lineHeight)
|
||||||
|
// Starting texture coordinate
|
||||||
|
texPos := (float64(drawStart) - float64(pitch) - float64(screenHeight)/2 + float64(lineHeight)/2) * step
|
||||||
|
for y := drawStart; y < drawEnd; y++ {
|
||||||
|
// Cast the texture coordinate to integer, and mask with (texHeight - 1) in case of overflow
|
||||||
|
texY := int(texPos) & (texHeight - 1)
|
||||||
|
texPos += step
|
||||||
|
color := texture[texNum][texHeight*texY+texX]
|
||||||
|
//make color darker for y-sides: R, G and B byte each divided through two with a "shift" and an "and"
|
||||||
|
if side == 1 {
|
||||||
|
color = (color >> 1) & 8355711
|
||||||
|
}
|
||||||
|
buffer[y][x] = color
|
||||||
|
}
|
||||||
|
|
||||||
|
//draw the pixels of the stripe as a vertical line
|
||||||
|
for y := range screenHeight {
|
||||||
|
for x := range screenWidth {
|
||||||
|
renderer.SetDrawColor((uint8(buffer[y][x]>>16) & 255), uint8((buffer[y][x]>>8)&255), uint8(buffer[y][x]&255), uint8((buffer[y][x]>>24)&255))
|
||||||
|
renderer.DrawPoint(int32(x), int32(y))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
renderer.Present()
|
||||||
|
|
||||||
|
oldTime = time
|
||||||
|
time = float64(sdl.GetTicks64())
|
||||||
|
var frameTime = (time - oldTime) / 1000.0
|
||||||
|
var moveSpeed float64 = frameTime * 5.0 //the constant value is in squares/second
|
||||||
|
var rotSpeed float64 = frameTime * 3.0
|
||||||
|
fmt.Println(1.0 / frameTime)
|
||||||
|
|
||||||
|
window.UpdateSurface()
|
||||||
|
|
||||||
|
for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *sdl.QuitEvent: // NOTE: Please use `*sdl.QuitEvent` for `v0.4.x` (current version).
|
||||||
|
println("Quit")
|
||||||
|
running = false
|
||||||
|
break
|
||||||
|
case *sdl.KeyboardEvent:
|
||||||
|
switch e.Keysym.Sym {
|
||||||
|
case sdl.K_w:
|
||||||
|
if level[int(posX+dirX*moveSpeed)][int(posY)] == 0 {
|
||||||
|
posX += dirX * moveSpeed
|
||||||
|
}
|
||||||
|
if level[int(posX)][int(posY+dirY*moveSpeed)] == 0 {
|
||||||
|
posY += dirY * moveSpeed
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case sdl.K_s:
|
||||||
|
if level[int(posX-dirX*moveSpeed)][int(posY)] == 0 {
|
||||||
|
posX -= dirX * moveSpeed
|
||||||
|
}
|
||||||
|
if level[int(posX)][int(posY-dirY*moveSpeed)] == 0 {
|
||||||
|
posY -= dirY * moveSpeed
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case sdl.K_d:
|
||||||
|
var oldDirX float64 = dirX
|
||||||
|
dirX = dirX*math.Cos(-rotSpeed) - dirY*math.Sin(-rotSpeed)
|
||||||
|
dirY = oldDirX*math.Sin(-rotSpeed) + dirY*math.Cos(-rotSpeed)
|
||||||
|
var oldPlaneX float64 = planeX
|
||||||
|
planeX = planeX*math.Cos(-rotSpeed) - planeY*math.Sin(-rotSpeed)
|
||||||
|
planeY = oldPlaneX*math.Sin(-rotSpeed) + planeY*math.Cos(-rotSpeed)
|
||||||
|
fmt.Println("rotating right")
|
||||||
|
break
|
||||||
|
case sdl.K_a:
|
||||||
|
var oldDirX float64 = dirX
|
||||||
|
dirX = dirX*math.Cos(rotSpeed) - dirY*math.Sin(rotSpeed)
|
||||||
|
dirY = oldDirX*math.Sin(rotSpeed) + dirY*math.Cos(rotSpeed)
|
||||||
|
var oldPlaneX float64 = planeX
|
||||||
|
planeX = planeX*math.Cos(rotSpeed) - planeY*math.Sin(rotSpeed)
|
||||||
|
planeY = oldPlaneX*math.Sin(rotSpeed) + planeY*math.Cos(rotSpeed)
|
||||||
|
fmt.Println("rotating left")
|
||||||
|
break
|
||||||
|
case sdl.K_ESCAPE:
|
||||||
|
running = false
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
72
worldMap/worldMap.go
Normal file
72
worldMap/worldMap.go
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package worldMap
|
||||||
|
|
||||||
|
const (
|
||||||
|
mapWidth = 24
|
||||||
|
mapHeight = 24
|
||||||
|
texWidth = 64
|
||||||
|
texHeight = 64
|
||||||
|
)
|
||||||
|
|
||||||
|
var level = [mapWidth][mapHeight]int{
|
||||||
|
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
|
||||||
|
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||||
|
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||||
|
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||||
|
{1, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 3, 0, 3, 0, 3, 0, 0, 0, 1},
|
||||||
|
{1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||||
|
{1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 1},
|
||||||
|
{1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||||
|
{1, 0, 0, 0, 0, 0, 2, 2, 0, 2, 2, 0, 0, 0, 0, 3, 0, 3, 0, 3, 0, 0, 0, 1},
|
||||||
|
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||||
|
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||||
|
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||||
|
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||||
|
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||||
|
{1, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||||
|
{1, 4, 0, 4, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||||
|
{1, 4, 0, 0, 0, 0, 5, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||||
|
{1, 4, 0, 4, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||||
|
{1, 4, 0, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||||
|
{1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||||
|
{1, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||||
|
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetMap() [24][24]int {
|
||||||
|
return level
|
||||||
|
}
|
||||||
|
|
||||||
|
var texture = make([][]uint32, 8)
|
||||||
|
|
||||||
|
func GetTextures() [][]uint32 {
|
||||||
|
for i := range texture {
|
||||||
|
texture[i] = make([]uint32, texWidth*texHeight)
|
||||||
|
}
|
||||||
|
var tex0, tex5 int
|
||||||
|
for x := range texWidth {
|
||||||
|
for y := range texHeight {
|
||||||
|
xorcolor := (x * 256 / texWidth) ^ (y * 256 / texHeight)
|
||||||
|
ycolor := y * 256 / texHeight
|
||||||
|
xycolor := y*128/texHeight + x*128/texWidth
|
||||||
|
if x != y && x != texWidth-y {
|
||||||
|
tex0 = 1
|
||||||
|
} else {
|
||||||
|
tex0 = 0
|
||||||
|
}
|
||||||
|
texture[0][texWidth*y+x] = uint32(65536 * 254 * tex0) //flat red texture with black cross
|
||||||
|
texture[1][texWidth*y+x] = uint32(xycolor + 256*xycolor + 65536*xycolor) //sloped greyscale
|
||||||
|
texture[2][texWidth*y+x] = uint32(256*xycolor + 65536*xycolor) //sloped yellow gradient
|
||||||
|
texture[3][texWidth*y+x] = uint32(xorcolor + 256*xorcolor + 65536*xorcolor) //xor greyscale
|
||||||
|
texture[4][texWidth*y+x] = uint32(256 * xorcolor)
|
||||||
|
if x%16 != 0 && y%16 != 0 {
|
||||||
|
tex5 = 1
|
||||||
|
} else {
|
||||||
|
tex5 = 0
|
||||||
|
} //xor green
|
||||||
|
texture[5][texWidth*y+x] = uint32(65536 * 192 * tex5) //red bricks
|
||||||
|
texture[6][texWidth*y+x] = uint32(65536 * ycolor) //red gradient
|
||||||
|
texture[7][texWidth*y+x] = uint32(128 + 256*128 + 65536*128) //flat grey texture
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return texture
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user