Esempio n. 1
0
        public void CollideAxis(PhysicalObject obj, Vector2 startpos, Vector2 move, Axis axis)
        {
            float xcol = 0.05f;

            bool touch_u = false;
            bool touch_r = false;
            bool touch_d = false;
            bool touch_l = false;

            obj.on_ladder[(int)axis] = false;

            Vector2 feet = new Vector2(startpos.X, startpos.Y + obj.hitbox.Y);

            if (axis == Axis.X)
            {
                move = new Vector2(move.X, 0);

                //if the ground is a slope, include the Y-movement
                if (obj.surface_k != 0)
                    if (move.X * -obj.surface_k < 0)
                        move.Y = move.X * -obj.surface_k;
            }
            else
                move = new Vector2(0, move.Y);

            obj.pos += move;

            int index_x = (int)obj.pos.X;
            int index_y = (int)obj.pos.Y;

            //how many tiles can the object potentially collide with
            int width = (int)Math.Ceiling(obj.hitbox.X) + 1;
            int height = (int)Math.Ceiling(obj.hitbox.Y) + 1;
            //get a list of all those
            int[][] check = new int[width * height][];
            int c = 0;
            for (int w = 0; w < width; w++)
                for (int h = 0; h < height; h++)
                {
                    check[c] = new int[] { w + index_x, h + index_y };
                    c++;
                }

            for (int i = 0; i < check.Length; i++)
            {
                Vector4 playerHitBox = new Vector4(obj.pos.X, obj.pos.Y, obj.hitbox.X, obj.hitbox.Y);
                //todo: other blocktypes

                //upper left corner of the tile
                int x = check[i][0];
                int y = check[i][1];

                if (x >= 0 && x < map[0].Length && y >= 0 && y < map.Length)
                {

                    //get the tile from map
                    Tile tile = map[y][x];

                    //reusable variables
                    Vector4 tileHitBox;

                    switch (tile.tileType)
                    {
                        case Tile.TileType.scenery:
                            break;
                        case Tile.TileType.solid:
                            if (tile.GetType() == typeof(Slope))
                            {
                                //SLABS / HALF-BLOCKS
                                Slope slope = tile as Slope;
                                if (slope.side == Slope.Side.floor)
                                    tileHitBox = new Vector4(x, y + (1f - slope.leftY), 1, slope.leftY);
                                else
                                    tileHitBox = new Vector4(x, y, 1, slope.leftY);
                            }
                            else
                                tileHitBox = new Vector4(x, y, 1, 1);//Regular square

                            //Does it collide?
                            if (VectorIntersect(playerHitBox, tileHitBox))
                            {
                                if (axis == Axis.X)
                                {
                                    if (move.X > 0)
                                    {
                                        obj.pos.X = x - obj.hitbox.X;
                                        touch_r = true;

                                        //reset velocity
                                        obj.velocity.X = xcol;
                                    }
                                    else
                                    {
                                        obj.pos.X = x + 1;
                                        touch_l = true;
                                        obj.velocity.X = -xcol;
                                    }

                                }
                                else
                                {
                                    if (playerHitBox.Y < tileHitBox.Y)
                                    {
                                        obj.pos.Y = tileHitBox.Y - obj.hitbox.Y;//tile y pos - player height
                                        touch_d = true;
                                    }
                                    else
                                    {
                                        obj.pos.Y = tileHitBox.Y + tileHitBox.W;//tile y pos + tile height
                                        touch_u = true;
                                    }

                                    //reset velocity
                                    obj.velocity.Y = 0;
                                    obj.surface_k = 0;
                                }
                            }
                            break;
                        case Tile.TileType.platform:
                            if (axis == Axis.Y)
                            {
                                tileHitBox = new Vector4(x, y, 1, 1);//Regular square

                                float slope_m;
                                float slope_k = 0;
                                float slope_x;
                                bool was_above = false;

                                Slope slope = new Slope(Tile.TileType.platform, Slope.Side.floor, 0f, 0f);
                                if (tile.GetType() == typeof(Slope))
                                {
                                    //SLOPES
                                    //y = kx + m
                                    //m -> plat.Y
                                    //k -> plat.right - plat.left
                                    //x -> player.x - plat.x

                                    slope = tile as Slope;
                                    if (slope.leftY == slope.rightY)//slab
                                    {
                                        if (slope.side == Slope.Side.roof)//roof slab
                                            tileHitBox = new Vector4(x, y, 1, slope.leftY);
                                        else//floor slab
                                            tileHitBox = new Vector4(x, (float)y + (1f - slope.leftY), 1, slope.leftY);
                                    }
                                    else
                                    {
                                        if (slope.side == Slope.Side.floor)
                                        {
                                            slope_m = slope.leftY;
                                            slope_k = slope.rightY - slope.leftY;
                                            slope_x = playerHitBox.X + playerHitBox.Z / 2f - (float)x;

                                            float slopeheight = get_slopeheight(slope_k, x, slope_m, slope, obj.pos.X, obj.pos.X + obj.hitbox.X);
                                            float old_slopeheight = get_slopeheight(slope_k, x, slope_m, slope, feet.X, feet.X + obj.hitbox.X);

                                            tileHitBox = new Vector4(x, (float)y + (1f - slopeheight), 1, slopeheight);

                                            was_above = feet.Y <= (float)y + (1f - old_slopeheight) + 0.0001f;
                                        }
                                    }
                                }

                                if (VectorIntersect(playerHitBox, tileHitBox) && (feet.Y <= tileHitBox.Y || was_above))
                                {
                                    //do collision
                                    if (slope.side == Slope.Side.floor)
                                    {
                                        obj.pos.Y = tileHitBox.Y - obj.hitbox.Y;//tile y pos - player height
                                        touch_d = true;
                                    }
                                    else
                                    {
                                        obj.pos.Y = tileHitBox.Y + tileHitBox.W;//tile y pos + tile height
                                        touch_u = true;
                                    }

                                    obj.velocity.Y = 0;
                                    obj.surface_k = slope_k;
                                }
                            }
                            break;
                        case Tile.TileType.ladder:
                            tileHitBox = new Vector4(x + 1f/3, y - 1f/3, 1f/2, 4f/3); //The hitbox is "squeezed" along the x-axis to avoid the ladder being grabbed with minimal overlap.

                            if (VectorIntersect(tileHitBox, playerHitBox))
                            {
                                obj.on_ladder[(int)axis] = true;
                            }
                            break;
                        case Tile.TileType.death:
                            break;
                        case Tile.TileType.win:
                            break;
                    }

                }
            }

            //update the objects intel
            if (axis == Axis.X)
            {
                obj.touch_left.Update(touch_l);
                obj.touch_right.Update(touch_r);
            }
            else
            {
                obj.touch_down.Update(touch_d);
                obj.touch_up.Update(touch_u);
            }
        }
Esempio n. 2
0
        public bool Collides(PhysicalObject obj)
        {
            Vector4 rec1 = new Vector4(pos.X, pos.Y, hitbox.X, hitbox.Y);
            Vector4 rec2 = new Vector4(obj.pos.X, obj.pos.Y, obj.hitbox.X, obj.hitbox.Y);

            Vector2 pos1 = new Vector2(rec1.X + rec1.Z / 2f, rec1.Y + rec1.W / 2f);
            Vector2 pos2 = new Vector2(rec2.X + rec2.Z / 2f, rec2.Y + rec2.W / 2f);
            return (Math.Abs(pos1.X - pos2.X) < (rec1.Z + rec2.Z) / 2   //if ΔX < medelvärdet av width
                &&
                Math.Abs(pos1.Y - pos2.Y) < (rec1.W + rec2.W) / 2);  //if ΔY < medelvärdet av height
        }
Esempio n. 3
0
        public void UpdatePhysicalObject(PhysicalObject obj)
        {
            //store start position and velocity
            Vector2 pos = obj.pos;
            Vector2 vel = obj.velocity;

            //move on the X-axis
            CollideAxis(obj, pos, obj.velocity, Axis.X);

            //since the slope-movement (int the Y axis) is already included in the X-step if the ground is sloped,
            //remove the slopes' Y movement
            float correction = 0f;
            if (obj.surface_k != 0)
                if (vel.X * -obj.surface_k < 0)
                    correction = vel.X * obj.surface_k;
                else
                    correction += 0.1f;//make sure the character gets pushed down to the ground

            //reset surface
            obj.surface_k = 0;
            //move on the Y-axis
            CollideAxis(obj, pos, obj.velocity + new Vector2(0, correction), Axis.Y);
        }