1. Hey! Guest! The 36th GMC Jam will take place between February 27th, 12:00 UTC - March 2nd, 12:00 UTC. Why not join in! Click here to find out more!
    Dismiss Notice

GM:S 1.4 3D raycasting engine - simplified

Discussion in 'Tutorials' started by slojanko, Jun 20, 2016.

Tags:
  1. slojanko

    slojanko Member

    Joined:
    Jun 20, 2016
    Posts:
    113
    I don't normally post "tutorials" but I'll make an exception and share my work with you.

    GM Version: GMS
    Target Platform: All (with reasonable CPU power)
    Source: download link - Updated
    Precompiled: download link - Updated

    Summary:
    This is a basic tutorial/example of a game using what's called raycasting to generate a 3D view on your environment. This was used in the original Doom and Wolfenstein 3D.

    Tutorial:
    The code used is currently reasonably documented and is organized enough for an intermediate user to figure out what is happening. The project contains 5 scripts which are appropriately named for better recognition.

    [​IMG]
    [​IMG]

    The view on the test room is split into 2, one being the 2D view on the actual position of the objects and a 3D representation using raycasting. This works by firing a set of rays that detect collision in the direction of the camera. These rays go across the room while only being generated in your FOV and return a position of its collision. This is then used to calculate how far/close the pixel a ray has hit should be drawn using a vertical line.

    Because using a ray a few thousand times per frame is very resource intensive I've decided to limit the density of rays and precision of each ray through 2 script variables attached to the camera's Create event.

    Current limitations are:
    - can't draw horizontal planes (floor)
    - no depth checking - massive performance boost when implemented!
    - bad performance!

    I would like to thank Rusky for helping me write the code necessary for drawing lines which are used to show a 3D view on the room. Everything else was written by me following tutorials in javascript.
     
    Last edited: Mar 20, 2017
  2. chance

    chance predictably random Forum Staff Moderator

    Joined:
    Apr 22, 2016
    Posts:
    809
    It's great that you want to share this, but I think it's premature as a tutorial. It has excellent potential, but it's not really suitable as a tutorial yet. As you said yourself, comments are lacking. And many of the comments are in Slovenian. So that probably limits the audience on an international forum such as this.

    Also, you should take special care whenever you "pin" the mouse, as is the case here using display_mouse_set(). For many users, that means they cannot exit or close the example without using the task manager. So if there are other keys that can close the example, you should make that more clear.

    That said, there are some interesting coding techniques here. So it's worth a look for more advanced users. Like I said, excellent potential.
     
    slojanko likes this.
  3. slojanko

    slojanko Member

    Joined:
    Jun 20, 2016
    Posts:
    113
    Thank you for the suggestion,

    I've changed a lot with the presentation of the project along with a better representation of how the engine actually works by drawing 2D rays. If you want to disable this, look for parts marked as "Debug information" and comment them out or simply remove them. They don't in any way affect what the final product of the engine is and are only there to offer some assistance while running. The code is also reasonably commented and should be a lot better to understand what it's doing.

    The mouse controls are now enabled by holding any mouse button down.
     
  4. SweetCelestia

    SweetCelestia Member

    Joined:
    Jun 20, 2016
    Posts:
    10
    nice! i tryed to make self raycasting sys, but it won't work D:
     
    slojanko likes this.
  5. lolslayer

    lolslayer Member

    Joined:
    Jun 23, 2016
    Posts:
    695
    I've done a non raycasting pseudo 3D fps, completely done by math, so no per vertical colomb checking of walls, it was just perfect but also waaaaay to hard to add depth checks :/
     
    slojanko likes this.
  6. PhenomenalDev

    PhenomenalDev Member

    Joined:
    Jan 5, 2017
    Posts:
    121
    How would I go about adding depth checking to the engine?
    Edit: Sorry if this counts as a necro/there are rules about necroposting, new here :I
    Edit2: If possible also doom style enemies?
     
    Last edited: Jan 6, 2017
  7. slojanko

    slojanko Member

    Joined:
    Jun 20, 2016
    Posts:
    113
    I've added depth checking to the current project but I haven't yet uploaded it.
    A problem with how game maker handles collision_lines is that it returns the smallest id of the object you're looking for (when multiple instances of the same instance are in your view.

    You can get around this by getting getting a new id for each iteration of the binary search operation. Basically each time you search for a collision point in a smaller radius you get the instance that was hit in that step. Another problem that occurs now is what if you have instances of different objects. You'll have sort and draw them in an order from furthest to closest. This seems to be the most logical way of rendering objects at the moment.

    To sum up: for each ray you have to scan for all objects added into the engine and get the closest instance of each object. Then sort the instances by distance. If an instance of an object isn't found at the maximum render distance you can abandon it completely within that ray!
     
    Last edited: Jan 7, 2017
  8. Juju

    Juju Member

    Joined:
    Jun 20, 2016
    Posts:
    416
  9. PhenomenalDev

    PhenomenalDev Member

    Joined:
    Jan 5, 2017
    Posts:
    121
    Okay well I'll try Juju's tip of collision_line_first, thanks for the help :D
     
  10. slojanko

    slojanko Member

    Joined:
    Jun 20, 2016
    Posts:
    113
    That is what I described put into a script.
    First it checks if an instance is found at the maximum distance then if it finds one, it'll try to find the closest one by splitting the search area in half each iteration.
     
  11. PhenomenalDev

    PhenomenalDev Member

    Joined:
    Jan 5, 2017
    Posts:
    121
    Sorry but I'm still confused about how you would actually go about doing this, any chance you could give me the r3d_draw_object code for the updated version?
     
  12. Lemth

    Lemth Member

    Joined:
    Oct 7, 2016
    Posts:
    79
    Very nice! If you have any updates please let us know; this is very intriguing stuff.
     
    slojanko likes this.
  13. ras maxim

    ras maxim Member

    Joined:
    Apr 14, 2017
    Posts:
    33
    Very interesting project, slojanko. I did an even simplier implementation of raycasting with GMS, too. Will post it soon.

    It is interesting to know how you are going to map textures. If walls were aligned to the square grid then you could use the coordinates of the intersection point as a texture offset. But your walls are not necessary aligned with the grid, so I have no idea here. Can you please share you thoughts on this?
     
  14. slojanko

    slojanko Member

    Joined:
    Jun 20, 2016
    Posts:
    113
    Because I'm getting the "precise" point of collision of each ray and know the object sprite origin I can get an estimate for which part of the texture should be visible there.
    Imagine having the situation below:
    [​IMG]
    You can get an approx. intersection using the code in my project. The intersection point can then be used to calculate the "part" of the texture (sprite) to be drawn as "intersectionX - object.x" for the image above. Putting in some fancy / and * for getting distance scaling to work and then you're good to go.

    I will port this to GMS2 when the IDE becomes usable for me again.
     
  15. ras maxim

    ras maxim Member

    Joined:
    Apr 14, 2017
    Posts:
    33
    Yes, I understand this. On grid-based map you just choose either x or y coordinate as an offset for drawing a wall column depending on wall being either vertical or horizontal. I just don't get how to test what side of the wall the ray hit if the corners are not 90 degrees.
     
  16. slojanko

    slojanko Member

    Joined:
    Jun 20, 2016
    Posts:
    113
    I am currently porting it to GMS2 and using the path editor for creating "complex" closed shapes. This could be used for the map itself. Regarding smaller objects, I still haven't found a good solution, unless I create a program for making polygons.

    PS: I tried sending you a message but your profile is locked.
     
  17. So, I can make a Doom like game with Game Maker ? that's amazing
     
    slojanko likes this.
  18. PhenomenalDev

    PhenomenalDev Member

    Joined:
    Jan 5, 2017
    Posts:
    121
    Doom was section based not raycasting, think wolfenstein.
     
    slojanko likes this.
  19. slojanko

    slojanko Member

    Joined:
    Jun 20, 2016
    Posts:
    113
    Doom used raycasting but in a more sophisticated way, yes. Look into Binary Space Partitioning if you want to learn more about how Doom achieved way better 3d than what other engines could.
     
  20. jujubs

    jujubs Member

    Joined:
    Aug 4, 2017
    Posts:
    68
    Firstly, thanks for sharing your work with us. It looks amazing, and doesn't look so resource-intensive as you say.

    That being said, how do I change the port size? I'm trying to draw on a low-res, vertical screen (think of the DMG), but the view just looks like a cropped, mashed up version of the window in your project:
     

    Attached Files:

  21. slojanko

    slojanko Member

    Joined:
    Jun 20, 2016
    Posts:
    113
    The version that's uploaded here is quite old, I have an "up-to-date" project on my laptop with better performance and general experience. It might or might not work, but try changing all 3 resolution values in the only existing room (for me it's test_2_room, but I might have renamed it). These are:
    - Room size and View 0 dimensions should match if you want the game to take advantage of the whole window.
    - Port size on screen under View 0 is basically your scale.

    upload_2018-4-8_17-31-22.png

    If you're still having trouble I'll send you my project, which should probably be rewritten anyway and not be taken as bug free.
     
  22. jujubs

    jujubs Member

    Joined:
    Aug 4, 2017
    Posts:
    68
    Like this?
    also disturbing.png

    Those are my current settings, which are the same as my other, 2D rooms (I'm trying to make a bonus level of sorts).

    I'd gladly take a look at it, even if we figure things out with the outdated project. That textured wall looks mighty interesting :D

    EDIT: I tried changing the views on your Project, and got similar results to what turned out on mine
    ohno.png
     
    Last edited: Apr 9, 2018
  23. TheMiningBoyAlpha

    TheMiningBoyAlpha Member

    Joined:
    Feb 17, 2019
    Posts:
    47
    update the link please
     

Share This Page