Esempio n. 1
0
        // Find the nearest cardinal direction to a vector (for snapping movement and sprites to 8 frames)
        public static int GetNearestCardinalDir(myVector v)
        {
            int ret = 0;

            for (int i = 1; i < 8; ++i)
            {
                if (v.dot(Geometry.cardinalUnitVectors[i]) > v.dot(Geometry.cardinalUnitVectors[ret]))
                {
                    ret = i;
                }
            }

            return(ret);
        }
Esempio n. 2
0
        // return the squared distanc to the point (remove squareroots)
        public double DistToPoint2(myPoint p)
        {
            // my length squared
            double l2 = (p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y);

            // find the parameterized value of where the nearest point would be
            // (dot product of my vector to the vector from my start to the point)
            myVector toPoint = new myVector(p1, p);
            double   t       = v.dot(toPoint) / l2;

            if (t < 0.0)
            {
                return(p1.distance2(p));
            }
            if (t > 1.0)
            {
                return(p2.distance2(p));
            }

            // it's on the line segment, project to the position
            myPoint projPoint = new myPoint(p1.x + t * v.x, p1.y + t * v.y);

            return(projPoint.distance2(p));
        }
Esempio n. 3
0
        // Check for a Derp's Circle-Cast across the field
        // This will work like a BFS, starting from the initial position
        // then check all 4 corners around the position to build on the bfs
        public bool CheckFieldCollision(Derp d, myVector v, out double t, out myLineSegment col)
        {
            // initial optimistic setup that there will not be a collision
            bool ret = false;

            t   = 1.0;
            col = null;

            // calculate starting point
            int startX = (int)(d.x / BLOCK_WIDTH);
            int startY = (int)(d.y / BLOCK_HEIGHT);

            // Unit Vector in desired direction
            myVector vUnit = new myVector(v.x, v.y);

            vUnit.toUnit();

            // set up the bfs
            Queue <SimpleNode> q = new Queue <SimpleNode>();

            bool[,] vis = new bool[height + 1, width + 1];

            q.Enqueue(new SimpleNode(startX, startY, 0));
            vis[startY, startX] = true;

            // Create the 4 line segments so we don't have to do quiiite as much object creation in this loop
            myLineSegment[] segs = new myLineSegment[4];
            for (int i = 0; i < 4; ++i)
            {
                segs[i] = new myLineSegment(null, null);
            }

            // BFS
            int[] dx       = { 0, 1, 0, -1 };
            int[] dy       = { -1, 0, 1, 0 };
            int   cur_step = 0;

            while (q.Count > 0)
            {
                SimpleNode cur = q.Dequeue();

                // end early if we had a hit already in a previous step
                if (ret && cur_step != cur.step)
                {
                    break;
                }

                // checking 4 nodes around us
                myPoint p1 = new myPoint(cur.x * BLOCK_WIDTH, cur.y * BLOCK_HEIGHT);
                myPoint p2 = new myPoint((cur.x + 1) * BLOCK_WIDTH, cur.y * BLOCK_HEIGHT);
                myPoint p3 = new myPoint((cur.x + 1) * BLOCK_WIDTH, (cur.y + 1) * BLOCK_HEIGHT);
                myPoint p4 = new myPoint(cur.x * BLOCK_WIDTH, (cur.y + 1) * BLOCK_HEIGHT);
                segs[0].Update(p1, p2);
                segs[1].Update(p2, p3);
                segs[2].Update(p4, p3);
                segs[3].Update(p1, p4);

                for (int i = 0; i < 4; ++i)
                {
                    int nx = cur.x + dx[i];
                    int ny = cur.y + dy[i];

                    if (nx < 0 || nx > width || ny < 0 || ny >= height || vis[ny, nx])
                    {
                        continue;
                    }

                    double possible_t;
                    if (Geometry.DerpLineSegmentCast(d, v, segs[i], out possible_t))
                    {
                        // We have a hit! If the next zone is safe to move in, then continue the bfs
                        if (gameGrid[ny, nx] != '0')
                        {
                            q.Enqueue(new SimpleNode(nx, ny, cur.step + 1));
                            vis[ny, nx] = true;
                        }
                        // We hit an unnavigable space. Stop the BFS, this is as far as we go
                        else
                        {
                            ret = true;

                            if (Math.Abs(possible_t - t) < 1e-5 && col != null)
                            {
                                // break ties by taking the furthest behind the direction we wish to go
                                // Calculate the center point on the wall, and get the dot product of the vector to that point.
                                // The most negative value is the furthest behind
                                myPoint  segMidPoint1 = new myPoint((segs[i].p1.x + segs[i].p2.x) / 2.0, (segs[i].p1.y + segs[i].p2.y) / 2.0);
                                myVector toMidPoint1  = new myVector(segMidPoint1.x - d.x, segMidPoint1.y - d.y);

                                myPoint  segMidPoint2 = new myPoint((col.p1.x + col.p2.x) / 2.0, (col.p1.y + col.p2.y) / 2.0);
                                myVector toMidPoint2  = new myVector(segMidPoint2.x - d.x, segMidPoint2.y - d.y);

                                if (vUnit.dot(toMidPoint1) < vUnit.dot(toMidPoint2))
                                {
                                    t   = possible_t;
                                    col = new myLineSegment(segs[i].p1.x, segs[i].p1.y, segs[i].p2.x, segs[i].p2.y); // careful... memory bugs
                                }
                            }
                            else if (possible_t < t)
                            {
                                t   = possible_t;
                                col = new myLineSegment(segs[i].p1.x, segs[i].p1.y, segs[i].p2.x, segs[i].p2.y); // careful... memory bugs
                            }
                        }
                    }
                }

                // if we are a special diagonal case, then check the cross hit as well
                myLineSegment diag = null;

                char c = gameGrid[cur.y, cur.x];
                if (c == '1' || c == '3')
                {
                    diag = new myLineSegment(p2, p4);
                }

                if (c == '2' || c == '4')
                {
                    diag = new myLineSegment(p1, p3);
                }

                if (diag != null)
                {
                    double possible_t;
                    if (Geometry.DerpLineSegmentCast(d, v, diag, out possible_t))
                    {
                        ret = true;

                        if (Math.Abs(possible_t - t) < 1e-5 && col != null)
                        {
                            // break ties by taking the furthest behind the direction we wish to go
                            // Calculate the center point on the wall, and get the dot product of the vector to that point.
                            // The most negative value is the furthest behind
                            myPoint  segMidPoint1 = new myPoint((diag.p1.x + diag.p2.x) / 2.0, (diag.p1.y + diag.p2.y) / 2.0);
                            myVector toMidPoint1  = new myVector(segMidPoint1.x - d.x, segMidPoint1.y - d.y);

                            myPoint  segMidPoint2 = new myPoint((col.p1.x + col.p2.x) / 2.0, (col.p1.y + col.p2.y) / 2.0);
                            myVector toMidPoint2  = new myVector(segMidPoint2.x - d.x, segMidPoint2.y - d.y);

                            if (vUnit.dot(toMidPoint1) < vUnit.dot(toMidPoint2))
                            {
                                t   = possible_t;
                                col = new myLineSegment(diag.p1.x, diag.p1.y, diag.p2.x, diag.p2.y); // careful... memory bugs
                            }
                        }
                        else if (possible_t < t)
                        {
                            t   = possible_t;
                            col = new myLineSegment(diag.p1.x, diag.p1.y, diag.p2.x, diag.p2.y); // careful... memory bugs
                        }
                    }
                }

                cur_step = cur.step;
            }

            return(ret);
        }