Raycast at Angle

Discussion in 'Learning Javascript' started by nathanlink169, Aug 11, 2019.

  1. nathanlink169

    nathanlink169 Veteran Veteran

    Messages:
    49
    Likes Received:
    16
    Location:
    Ottawa
    First Language:
    English
    Primarily Uses:
    RMMV
    Hi all!

    I'm making a stealth script because there wasn't any that fit my particular needs. The "does the NPC detect the player" part is all taking place in common events because I'm too lazy to make an actual script.

    As is usual with game development, vision is three checks: a distance check, an angle check, and a raycast check (in that order, due to how expensive each operation is). If one doesn't pass, you cancel out. If it does, you move onto the next step.

    I've got the first two implemented, but it's the last one that I'm struggling with a little. This is my current thinking: the raycast will go from the npc event to the player event. Picture a line drawn through every single square between the two. If any of those squares are "not walkable", the raycast check fails.

    upload_2019-8-11_1-0-25.png

    What do people think of this? Fortunately it won't be too many squares due to the distance check previously. I still need to think of the math of "getting every square in a line between two squares", as well as actually learn how to get the collision details from a map through JavaScript. If anyone has any knowledge of these, I would love to hear it! (I come from a Unity background, so my knowledge of interacting with RPG Maker's internals is still very fuzzy).
     
    #1
  2. gstv87

    gstv87 Veteran Veteran

    Messages:
    1,794
    Likes Received:
    822
    First Language:
    Spanish
    Primarily Uses:
    RMVXA
    I seem to remember a function involving basic Pythagorean math, some angle calculations, and intersections of sets of tiles.
    I used it for a projectile function, but wasn't my code originally.... I think it was Victor Sant's, or GubiD's... I have it somewhere.
    it shouldn't be that hard to process when implemented, it's basic math 2000 years old.

    too tired to really look for it right now, so here's another suggestion, as I think about it:
    you propose a line, but given that the engine always counts tiles from the left, how about tracking the center of each tile within the area marked by the extremes of the tiles conforming the end points? (the center can always be written based on the coordinate and the tile size, both of which are known)

    nuevo-2.JPG

    if the center of the tile is out of the rectangle, then the direct line is also missing the tile entirely.
    I came up with this because I couldn't write it as a function of angles (brain.exe not working).
    but it should be doable directly with angles and proportions.
     
    Last edited: Aug 11, 2019
    #2
  3. caethyril

    caethyril ^_^ Veteran

    Messages:
    1,275
    Likes Received:
    796
    Location:
    UK
    First Language:
    English
    Primarily Uses:
    RMMV
    Should be possible, yes. I think I encountered a couple of problems when I tried this (gave up on it after a while)...
    • Check tile-by-tile: careful of rounding errors, special cases for flat lines, etc.
      Could check pixel-by-pixel, but that'd be very inefficient.
      For the line-to-tiles thing (discretisation) you may want to look at anti-aliasing algorithms.

    • Left-handed coordinate system! (I'm used to right-handed, careful with the angles etc...)
    Here's my failed attempt in case you're interested (I think it's an angle-to-direction issue, but couldn't nail down the cause):
    view Cae_LineOfSight (Google Drive).

    More recently I discovered Galv's Event Detectors plugin, which says it has line-of-sight...haven't investigated it yet:
    https://galvs-scripts.com/2016/08/01/mv-event-detectors/
     
    #3
  4. gstv87

    gstv87 Veteran Veteran

    Messages:
    1,794
    Likes Received:
    822
    First Language:
    Spanish
    Primarily Uses:
    RMVXA
    here's *kind of* what I had in mind initially:

    nuevo-1.jpg

    if one could define the area swept under the vectors |ae and |gc as defined by points aegc, and use those vectors as reference for the angles alpha and epsilon, and gamma, kappa and pi, then, IF, point p2 could be written in function of pi and alpha, then p2 would be outside of the area aegc, by being it's angle pi greater than kappa, but it's angle alpha lesser than epsilon.
    likewise, since point p1 could be defined by angle gamma being lesser than kappa, then that point would be within the area swept of |ae, but outside the area swept by |gc

    see each point as it's Cartesian components, and from there, it all turns into triangles.

    grabbing the area to be swept, is not hard either.... a simple radius check of distance (this square's position - that other square's position), for both end points, and then intersect both sets.
    *to those resulting tiles*, you apply this process, and find which is within the area seen by both end points.
     
    Last edited: Aug 12, 2019
    #4
    caethyril likes this.
  5. nathanlink169

    nathanlink169 Veteran Veteran

    Messages:
    49
    Likes Received:
    16
    Location:
    Ottawa
    First Language:
    English
    Primarily Uses:
    RMMV
    Thank you both! This is good food for thought. I'm going to bring up the idea with my coworkers on Monday and see what they say. I'll keep you updated!
     
    #5
  6. Jonforum

    Jonforum Veteran Veteran

    Messages:
    1,586
    Likes Received:
    1,365
    Location:
    Canada / Québec
    First Language:
    French
    Primarily Uses:
    RMMV
    #6
  7. Jonforum

    Jonforum Veteran Veteran

    Messages:
    1,586
    Likes Received:
    1,365
    Location:
    Canada / Québec
    First Language:
    French
    Primarily Uses:
    RMMV
    Last edited: Aug 15, 2019
    #7
  8. nathanlink169

    nathanlink169 Veteran Veteran

    Messages:
    49
    Likes Received:
    16
    Location:
    Ottawa
    First Language:
    English
    Primarily Uses:
    RMMV
    Thanks for the links Jon. I will turn to that first one if my current attempt doesn't go well. As for distance and angle calculations, I already have those working.
     
    #8
  9. gstv87

    gstv87 Veteran Veteran

    Messages:
    1,794
    Likes Received:
    822
    First Language:
    Spanish
    Primarily Uses:
    RMVXA
    > M A T H ! <

    you can't fail, with math.
     
    #9
  10. nathanlink169

    nathanlink169 Veteran Veteran

    Messages:
    49
    Likes Received:
    16
    Location:
    Ottawa
    First Language:
    English
    Primarily Uses:
    RMMV
    Alright, I have it all mostly working! Slightly basic question - if I have the coordinates for a tile I want to check, can I check if the tile has collision or not?
     
    #10
  11. gstv87

    gstv87 Veteran Veteran

    Messages:
    1,794
    Likes Received:
    822
    First Language:
    Spanish
    Primarily Uses:
    RMVXA
    Code:
    Game_Map.prototype.isPassable = function(x, y, d) {
        return this.checkPassage(x, y, (1 << (d / 2 - 1)) & 0x0f);
    };
    
    be mindful, that any B-E tiles on top of the A map tile can override the passability.
     
    #11
  12. nathanlink169

    nathanlink169 Veteran Veteran

    Messages:
    49
    Likes Received:
    16
    Location:
    Ottawa
    First Language:
    English
    Primarily Uses:
    RMMV
    I got it working! Thanks to everyone who helped out!

    For those wanting to take a look, here is a link to the Json Map: https://www.mediafire.com/file/s8h23abtbsp6c47/Map001.json/file

    I did it all through events, all the code is contained in there too. I'm sure there's a better way to do it, and lots of optimizations and more proper ways to do things, but this is not bad for a first pass. I'm planning on making it into a common event with better labeling of variables and the like.

    EDIT: for those who happen to stumble upon this post and want to take a look, you want to place Map001.json in the file path: YOUR_GAME_NAME/data/ - make sure that there is no Map001.json there already otherwise it will overwrite that map. If there is one, replace the 001 with a number that isn't taken (i.e. Map005.json)
     
    #12
    caethyril likes this.

Share This Page