Raycast at Angle

nathanlink169

Game Dev by Career, no idea what I'm doing
Veteran
Joined
Aug 15, 2013
Messages
72
Reaction score
32
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).
 

gstv87

Veteran
Veteran
Joined
Oct 20, 2015
Messages
2,223
Reaction score
1,199
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:

caethyril

^_^
Veteran
Joined
Feb 21, 2018
Messages
1,940
Reaction score
1,392
First Language
EN
Primarily Uses
RMMZ
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/
 

gstv87

Veteran
Veteran
Joined
Oct 20, 2015
Messages
2,223
Reaction score
1,199
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:

nathanlink169

Game Dev by Career, no idea what I'm doing
Veteran
Joined
Aug 15, 2013
Messages
72
Reaction score
32
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!
 

nathanlink169

Game Dev by Career, no idea what I'm doing
Veteran
Joined
Aug 15, 2013
Messages
72
Reaction score
32
First Language
English
Primarily Uses
RMMV

nathanlink169

Game Dev by Career, no idea what I'm doing
Veteran
Joined
Aug 15, 2013
Messages
72
Reaction score
32
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?
 

gstv87

Veteran
Veteran
Joined
Oct 20, 2015
Messages
2,223
Reaction score
1,199
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.
 

nathanlink169

Game Dev by Career, no idea what I'm doing
Veteran
Joined
Aug 15, 2013
Messages
72
Reaction score
32
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)
 

Users Who Are Viewing This Thread (Users: 0, Guests: 1)

Latest Profile Posts

Trying to create a diagonal sprite, by following through GrandmaDeb's tutorial here.
(Basically, cutting up and resizing parts from the down and left version of the sprite.) :LZScheeze:


I've been reworking some old sketches, there's definitely a change on the artwork :kaopride:


Drawing a character who fight with his dog in battle is an interesting yet difficult affair. :D
Trying to get my good habits back again after this year... I need to go back to the gym, but Brazil is still in a bad situation of Covid-19, so I will try to work out at home! :D
I need to become a better battery.

Forum statistics

Threads
104,426
Messages
1,006,284
Members
135,950
Latest member
FabRG
Top