Log In  

Cart #53524 | 2018-06-13 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
23

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.

P#53503 2018-06-12 14:27 ( Edited 2018-06-16 00:31)

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...

P#53506 2018-06-12 16:03 ( Edited 2018-06-12 20:03)

Updated. The FPS is the same as if you hit ctrl + 1.

P#53510 2018-06-12 16:55 ( Edited 2018-06-12 20:55)

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).

P#53517 2018-06-12 23:12 ( Edited 2018-06-13 03:15)

Good to know. Updated.

P#53525 2018-06-13 09:56 ( Edited 2018-06-13 13:56)

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

P#53536 2018-06-14 02:20 ( Edited 2018-06-14 06:20)
3

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
P#53537 2018-06-14 03:59 ( Edited 2018-06-14 07:59)

Super fast and smooth! Nice work.

P#53591 2018-06-15 20:31 ( Edited 2018-06-16 00:31)

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?

P#81632 2020-09-09 22:58 ( Edited 2020-09-10 01:04)

[Please log in to post a comment]

Follow Lexaloffle:          
Generated 2024-03-29 05:31:05 | 0.014s | Q:27