Here's a decent example of a Doom style 3D setup. I had a hard time finding one myself that I could understand. This is a combination of what I found. I'm posting it here to help anyone else trying to find something similar or couldn't understand what the other ones were doing. The code here is pretty bare bones so it should make it easier to follow. Let me know if you have any questions.
Neat - with none of the 'classic' artifacts like holes and fisheye!
The FPS counter is a bit dubious - even when cpu>1.0, it says 63fps :/
Note: you got 1 line missing at the top and 2 lines missing at the bottom though...
That's not the game FPS, that's the number of times per second that PICO-8 is rendering to its window.
This should be printing stat(7), not stat(9).
This seems to be a great example of something (raycasting) that I've always been curious about.
Thank you for taking the time to put this together :D
This is nicely done. I'd never looked at how these kind of engines work before and your code is very easy to understand.
I've just had a bit of a play around with it and made a quick modification to the draw function to add texture mapping to the walls. Here's the code for anyone interested:
texturesize = 16 function draw() --draw the ceiling and floor cls(5) rectfill(0,64,128,128,4) --set black to opaque palt(0,false) for x=0, width do --calculate ray position and direction camerax = 2 * x / width - 1 --x-coordinate in camera space raydirx = dirx + planex * camerax raydiry = diry + planey * camerax --which box of the map we're in mapx = flr(posx) mapy = flr(posy) --length of ray from current position to next x or y-side sidedistx = 0 sidedisty = 0 --length of ray from one x or y-side to next x or y-side deltadistx = abs(1 / raydirx) deltadisty = abs(1 / raydiry) perpwalldist = 0 --what direction to step in x or y-direction (either +1 or -1) stepx = 0 stepy = 0 hit = 0 --was there a wall hit? side = 0 --was a ns or a ew wall hit? --calculate step and initial sidedist if raydirx < 0 then stepx = -1 sidedistx = (posx - mapx) * deltadistx else stepx = 1 sidedistx = (mapx + 1.0 - posx) * deltadistx end if raydiry < 0 then stepy = -1 sidedisty = (posy - mapy) * deltadisty else stepy = 1 sidedisty = (mapy + 1.0 - posy) * deltadisty end --perform dda while hit == 0 do --jump to next map square, or in x-direction, or in y-direction if sidedistx < sidedisty then sidedistx += deltadistx mapx += stepx side = 0 else sidedisty += deltadisty mapy += stepy side = 1 end --check if ray has hit a wall if map[mapx][mapy] > 0 then hit = 1 end end --calculate distance projected on camera direction (euclidean distance will give fisheye effect!) if side == 0 then perpwalldist = (mapx - posx + (1 - stepx) / 2) / raydirx sproffsetx = posy + perpwalldist * raydiry else perpwalldist = (mapy - posy + (1 - stepy) / 2) / raydiry sproffsetx = posx + perpwalldist * raydirx end if perpwalldist < drawdistance then --calculate height of line to draw on screen lineheight = height / perpwalldist --calculate lowest and highest pixel to fill in current stripe drawstart = -lineheight / 2 + height / 2 --calculate which line of the texture to draw sproffsetx = flr((sproffsetx - flr(sproffsetx)) * texturesize) sspr((map[mapx][mapy] - 1) * texturesize + sproffsetx, 0, 1, texturesize, x, drawstart - 1, 1, lineheight - lineheight % 2) end end print('mem:'..stat(0), 0, 0, 7) print('cpu:'..stat(1), 0, 8, 7) print('fps:'..stat(9).."/"..stat(8), 0, 16, 7) end |
...and some textures to try it out with (which I just ripped from a game I made previously)
__gfx__ 666666366666663166666666663666355dddddd5ddddd351666666316666666511111111111111110000000000000000d50dd351dddd335133dd35555555d555 3666335333333dd13663333335533d311dd355503315555136633dd1363333d115dd5510111110010dd5001000005100550d5551d35553515ddddd51dd51dddd 53663555533553d15633355555153d5113351110511115505d5555d1535555d11511110011ddd510051100000000110011135511d55555510000000000015100 5d335555553555d153d3555555155d511551111051111150151555d15d55553105111100105511100111051001100000001351111111555100000000000d1000 5ddd5515555555d15dd555555511111115511110111111505d1555315d5515110111110000511110000001100110000055151110d35155110017801000135000 11551113555555315dd555555553dd5115511110155511505d1555315d551d310111110000511110001100000000011051111000d55111111518801111165110 3333dd33555555315dd5555555555d51155111101511115055155551555515510000000010111110001101000000011011d3551155515511555101511d165151 5d333555555555515dd5555555555d1115111110111111501111111111111111100000001000000000000000000000000055111111111111155555111656d1d0 5ddd5555551111115d55555555555d11010000001111115066666665666366651110111115511111000000000055100011511111dddd551100000000155d5110 5ddd5555551d3dd115111111555553111335511000000010366333d1363133d115d501111511110100000000001110001111dd51d55111115100000011110001 55dd5555551355d155dd5331555553111351111010015530563555d15d5135d1151101011111dd5000011000001110001111355151111111d610000015dd5511 555d5555551355d153355531555555111511100000011150535555d15d51553101110550110151100001100000000000d5115551111111113d61000011000001 555d1555551555d155315531555ddd5111111011100111105d555531531111110000051005101110000000000000000055111111dd5111115ddd10000566d510 55551155551555d155511551555d551101000011000511105d511511531dd55100110000011000000000001000001100511d5511551155115ddd51001d111151 51ddd515d31155515155d3515d13551100000010000100101551dd51551511110011000000000000000000000000110011155511511151115d35351011551111 11d55111111115111151111115111111000000000000000011115111111111110000000000000000000000000000000011111111111111115511111115551111 |
this is really cool, still kinda new to pico-8, im aware that the console can give the x and y cords of the mouse pos, (stat(32) and stat(33)) but can the console set the mouse position so you could have a fps like this but with mouse control aswell?
[Please log in to post a comment]