Exemplo n.º 1
0
 /// <summary>
 /// Constructor of the Tile
 /// </summary>
 /// <param name="ID">ID of the tile</param>
 /// <param name="data">If there is custom data pass it here</param>
 public Tile(int ID, CustomTileData data, TileGameObject assosiateWithThis, Chunk chunk)
 {
     tileID = ID;
     customTileData.Add(data);
     associatesWithThisGameObject = assosiateWithThis;
     isInChunk = chunk;
 }
        public override void Initialize()
        {
            this.didInit = true;
            if (Level.current is Editor)
            {
                return;
            }
            this.backgroundColor          = new Color(25, 38, 41);
            Level.current.backgroundColor = this.backgroundColor;
            CustomTileData data = Custom.GetData(0, CustomType.Parallax);

            if (data != null && data.texture != null)
            {
                this._parallax = new ParallaxBackground(data.texture);
                for (int yPos = 0; yPos < 40; ++yPos)
                {
                    this._parallax.AddZone(yPos, 0.0f, 0.0f, true);
                }
                Level.Add((Thing)this._parallax);
            }
            else
            {
                this._parallax = new ParallaxBackground("background/office", 0.0f, 0.0f, 3);
                Level.Add((Thing)this._parallax);
            }
        }
    /// <summary>
    /// Checks if x axis movement causes collision with anything, and stops movement if it does
    /// </summary>
    private void CheckCollisionHorizontal()
    {
        if (char_stats.velocity.x == 0.0f)
        {
            return;
        }

        Vector2 collision_box_size, collision_box_center, direction;

        SetupHorizontalCollision(out collision_box_center, out collision_box_size, out direction);
        float distance = Mathf.Abs(char_stats.velocity.x) * Time.deltaTime * Time.timeScale + ONE_PIXEL_BUFFER;

        char_stats.touched_vault_obstacle = null;

        RaycastHit2D hit = Physics2D.BoxCast(collision_box_center, collision_box_size, 0.0f, direction, distance, CollisionMasks.upwards_collision_mask);

        if (hit.collider == null)
        {
            return;
        }

        float hit_distance = hit.distance - ONE_PIXEL_BUFFER;

        if (hit_distance <= Mathf.Abs(char_stats.velocity.x * Time.deltaTime * Time.timeScale))
        {
            CustomTileData tile_data      = Utils.GetCustomTileData(hit.collider);
            CollisionType  collision_type = null;
            if (tile_data != null)
            {
                collision_type = tile_data.collision_type;
            }

            if (collision_type != null)
            {
                if (collision_type.CanVaultOver == true && char_stats.IsGrounded)
                {
                    char_stats.touched_vault_obstacle = tile_data.gameObject.GetComponent <Collider2D>();
                }
                //if ( ! collision_type.IsBlocking ) { return; }  // non-blocking objects now are on their own layer so they are ignored by this boxcast
            }
            // we touched a wall
            Vector3 gap;
            if (char_stats.velocity.x > 0.0f)
            {
                gap = new Vector3(hit_distance, 0.0f, 0.0f);
            }
            else
            {
                gap = new Vector3(-hit_distance, 0.0f, 0.0f);
            }
            this.gameObject.transform.Translate(gap);
            char_stats.velocity.x = 0.0f;

            OnTouchWall();
        }
    }
Exemplo n.º 4
0
    /// <summary>
    /// Gets the collision type data out of a tile-bound object.
    /// </summary>
    /// <param name="collider">The collider of the object representing the tile</param>
    /// <returns></returns>
    public static CustomTileData GetCustomTileData(Collider2D collider)
    {
        if (collider == null)
        {
            return(null);
        }

        #region Non-TileMap
        // Tile-bound object
        CustomTileData custom_data = collider.gameObject.GetComponent <CustomTileData>();
        if (custom_data != null)
        {
            return(custom_data);
        }
        #endregion

        // We don't need this anymore, since we basically just use tilemap as a quick instantiator for gameobjects, b/c that is simpler and works with fewer edge cases.
        // Preserved in case we need to re-use the approach.
        /// <param name="hit_point">Only used when checking the collision type of tilemap tiles.
        ///     This should be a point in worldspace within the tile to retrieve the data from.
        ///     Typically should be obtained by taking a raycast hit point (will be outside the "hit" tile), and going 1-16 pixels further in the direction of the ray.
        /// </param>

        /*
         * // Performance: Luckily, we only need this method ~ once / frame.
         #region TileMap
         * // Tilemap tile
         * Tilemap tile_map = collider.gameObject.GetComponent<Tilemap>();
         * if ( tile_map != null )
         * {
         *  // need to get tile data out of the collider
         *  Grid layout_grid = tile_map.layoutGrid;
         *  if ( layout_grid == null ) { return null; }
         *
         *  Vector3Int grid_position = layout_grid.WorldToCell( new Vector3( hit_point.x, hit_point.y, 0.0f ) );
         *  Debug.Log( grid_position );
         *  if ( ! tile_map.HasTile( grid_position ) ) { return null; }
         *
         *  TileBase tile = tile_map.GetTile( grid_position );
         *  if ( tile == null ) { return null; }
         *
         *  TileData tile_data = new TileData();
         *  tile.GetTileData( grid_position, null, ref tile_data );
         *  GameObject obj = tile_data.gameObject;
         *  if ( obj == null ) { return null; }
         *
         *  custom_data = obj.GetComponent<CustomTileData>();
         *  if ( custom_data == null ) { return null; }
         *
         *  return custom_data;
         * }
         #endregion
         */

        return(null);
    }
Exemplo n.º 5
0
    void UpdateCursorPosition(Vector3Int offset)
    {
        Vector3Int newPosition = _currentPosition + offset;

        if (!_board.ContainsPoint(newPosition.x, newPosition.y))
        {
            return;
        }

        _currentPosition += offset;

        CustomTileData tileData = _board.tileData[_currentPosition.x, _currentPosition.y];
        Vector3Int     offsetNeededForRenderingOnMap = new Vector3Int(1, 1, tileData.position.z);

        transform.position = _tilemap.CellToLocal(_currentPosition + offsetNeededForRenderingOnMap);
    }
Exemplo n.º 6
0
        public void UpdateCustomTileset()
        {
            int num = 0;

            if (this._sprite != null)
            {
                num = this._sprite.frame;
            }
            if (this.tileset == "CUSTOM01")
            {
                CustomTileData data = Custom.GetData(0, CustomType.Block);
                this._sprite = data == null || data.texture == null ? new SpriteMap("blueprintTileset", 16, 16) : new SpriteMap((Tex2D)data.texture, 16, 16);
            }
            else if (this.tileset == "CUSTOM02")
            {
                CustomTileData data = Custom.GetData(1, CustomType.Block);
                this._sprite = data == null || data.texture == null ? new SpriteMap("blueprintTileset", 16, 16) : new SpriteMap((Tex2D)data.texture, 16, 16);
            }
            else if (this.tileset == "CUSTOM03")
            {
                CustomTileData data = Custom.GetData(2, CustomType.Block);
                this._sprite = data == null || data.texture == null ? new SpriteMap("blueprintTileset", 16, 16) : new SpriteMap((Tex2D)data.texture, 16, 16);
            }
            else if (this.tileset == "CUSTOMPLAT01")
            {
                CustomTileData data = Custom.GetData(0, CustomType.Platform);
                this._sprite = data == null || data.texture == null ? new SpriteMap("scaffolding", 16, 16) : new SpriteMap((Tex2D)data.texture, 16, 16);
            }
            else if (this.tileset == "CUSTOMPLAT02")
            {
                CustomTileData data = Custom.GetData(1, CustomType.Platform);
                this._sprite = data == null || data.texture == null ? new SpriteMap("scaffolding", 16, 16) : new SpriteMap((Tex2D)data.texture, 16, 16);
            }
            else if (this.tileset == "CUSTOMPLAT03")
            {
                CustomTileData data = Custom.GetData(2, CustomType.Platform);
                this._sprite = data == null || data.texture == null ? new SpriteMap("scaffolding", 16, 16) : new SpriteMap((Tex2D)data.texture, 16, 16);
            }
            if (this._sprite == null)
            {
                this._sprite = new SpriteMap(this.tileset, 16, 16);
            }
            this.graphic       = (Sprite)this._sprite;
            this._sprite.frame = num;
        }
        public CustomTileData GetTileData()
        {
            CustomTileData customTileData = new CustomTileData();

            if (this.textureData == null)
            {
                return(customTileData);
            }
            customTileData.path               = this.path;
            customTileData.texture            = Editor.StringToTexture(this.textureData);
            customTileData.verticalWidthThick = this.verticalWidthThick;
            customTileData.verticalWidth      = this.verticalWidth;
            customTileData.horizontalHeight   = this.horizontalHeight;
            customTileData.leftNubber         = this.leftNubber;
            customTileData.rightNubber        = this.rightNubber;
            customTileData.checksum           = this.textureChecksum;
            return(customTileData);
        }
Exemplo n.º 8
0
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            RaycastHit2D hit;

            hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);

            if (hit.collider != null)
            {
                CustomTileData tileData = hit.collider.GetComponent <CustomTileData>();
                if (tileData != null)
                {
                    Debug.LogError("custom tile data");
                }
            }
        }
    }
    /// <summary>
    /// Checks if the player will bump their head on the ceiling
    /// </summary>
    private void CheckCollisionUp()
    {
        if (char_stats.velocity.y <= 0.0f)
        {
            return;
        }                                                                                            // immobile or moving down, don't need to check

        Vector2      collision_box_size = new Vector2(char_stats.char_collider.bounds.size.x, 1.0f); // width x 1 px box
        Vector2      origin             = new Vector2(char_stats.char_collider.bounds.center.x, char_stats.char_collider.bounds.max.y - collision_box_size.y);
        Vector2      direction          = Vector2.up;
        float        distance           = Mathf.Abs(char_stats.velocity.y) * Time.deltaTime * Time.timeScale + ONE_PIXEL_BUFFER;
        RaycastHit2D hit = Physics2D.BoxCast(origin, collision_box_size, 0.0f, direction, distance, CollisionMasks.upwards_collision_mask);

        if (hit.collider == null)
        {
            return;
        }

        float          hit_distance   = hit.distance - ONE_PIXEL_BUFFER;
        CustomTileData tile_data      = Utils.GetCustomTileData(hit.collider);
        CollisionType  collision_type = null;

        if (tile_data != null)
        {
            collision_type = tile_data.collision_type;
        }

        if (collision_type != null)
        {
            //if ( ! collision_type.IsBlocking ) { return; }  // non-blocking objects now are on their own layer so they are ignored by this boxcast
            // Prevents bug: if you had blocking and non-blocking geometry [X][ ][X],
            // Boxcast collision only returns 1 hit. It could get only the non-blocking object, so you could pass through solid walls.
            // Moving it to its own layer was simpler than using Boxcastall + aggregation.
        }
        // hit the ceiling, stop upward movement
        this.gameObject.transform.Translate(new Vector3(0.0f, hit_distance, 0.0f));
        char_stats.velocity.y = 0.0f;
        char_stats.is_jumping = false;

        OnTouchCeiling();
    }
    /// <summary>
    /// Checks if the player will hit the floor with their feet
    /// </summary>
    private void CheckCollisionDown()
    {
        if (char_stats.velocity.y >= 0.0f)
        {
            return;
        }                                                                                            // immobile or moving up, don't need to check

        Vector2      collision_box_size = new Vector2(char_stats.char_collider.bounds.size.x, 1.0f); // width x 1 px box
        Vector2      origin             = new Vector2(char_stats.char_collider.bounds.center.x, char_stats.char_collider.bounds.min.y + collision_box_size.y);
        Vector2      direction          = Vector2.down;
        float        distance           = Mathf.Abs(char_stats.velocity.y) * Time.deltaTime * Time.timeScale + ONE_PIXEL_BUFFER;
        RaycastHit2D hit = Physics2D.BoxCast(origin, collision_box_size, 0.0f, direction, distance, CollisionMasks.standard_collision_mask);

        if (hit.collider == null)   // if there is no floor, just fall
        {
            FallingLogic();
            return;
        }
        // hit the floor, stop falling ... probably

        CustomTileData tile_data      = Utils.GetCustomTileData(hit.collider);
        CollisionType  collision_type = null;

        if (tile_data != null)
        {
            collision_type = tile_data.collision_type;
        }
        Collider2D collider = hit.collider; // for enemies + objects lacking custom tile data

        if (tile_data != null)
        {
            collider = tile_data.gameObject.GetComponent <Collider2D>();
        }

        bool did_touch_ground = true;

        if (collision_type != null)
        {
            //if ( ! collision_type.IsBlocking ) { return; } // non-blocking objects now are on their own layer so they are ignored by this boxcast
            // special types of floor can change behaviour.
            if (FallthroughPlatform(collision_type, collider))
            {
                did_touch_ground = false;
            }
            if (ShuntPlayer(collision_type, collider))
            {
                // Prevent bug: if a non-walkoff collider is adjacent to another collider, this could cause players to fall through the floor.
                Vector2      shunted_origin = new Vector2(char_stats.char_collider.bounds.center.x, char_stats.char_collider.bounds.min.y + collision_box_size.y);
                RaycastHit2D shunt_hit      = Physics2D.BoxCast(shunted_origin, collision_box_size, 0.0f, direction, distance, CollisionMasks.standard_collision_mask);
                // Is the player cleared to continue falling?
                if (shunt_hit.collider == null)
                {
                    did_touch_ground = false;
                }
            }
        }
        else
        {
            // Enemies and objects will use default behaviour. No tile should be missing this data, though.
            if (tile_data != null)
            {
                #if UNITY_EDITOR
                Debug.LogError("Improper configuration: platform is missing a CollisionType component. Will use default behaviour.");
                #endif
            }
        }

        if (did_touch_ground)
        {
            // close the gap between the player's feet and the floor

            // min y (player) = max y (tile)
            // center - 1/2 size = max y
            // position + offset - 1/2 size = collider.bounds.max.y
            transform.position    = new Vector3(transform.position.x, collider.bounds.max.y + char_stats.char_collider.bounds.size.y / 2.0f - char_stats.char_collider.offset.y + ONE_PIXEL_BUFFER / 2.0f, transform.position.z);
            char_stats.velocity.y = 0.0f;
            OnTouchGround(collider);
        }

        CheckPlatformEdge(collision_type, collider);   // TODO: move to horizontal collision, get floor collision data to it efficiently somehow.
    }
Exemplo n.º 11
0
 /// <summary>
 /// Constructor of the Tile
 /// </summary>
 /// <param name="ID">ID of the tile</param>
 /// <param name="data">If there is custom data pass it here</param>
 public Tile(int ID, CustomTileData data, Chunk chunk)
 {
     tileID = ID;
     customTileData.Add(data);
     isInChunk = chunk;
 }
Exemplo n.º 12
0
 /// <summary>
 /// Constructor of the Tile
 /// </summary>
 /// <param name="ID">ID of the tile</param>
 /// <param name="data">If there is custom data pass it here</param>
 public Tile(int ID, CustomTileData data, TileGameObject assosiateWithThis)
 {
     tileID = ID;
     customTileData.Add(data);
     associatesWithThisGameObject = assosiateWithThis;
 }
Exemplo n.º 13
0
 /// <summary>
 /// Constructor of the Tile
 /// </summary>
 /// <param name="ID">ID of the tile</param>
 /// <param name="data">If there is custom data pass it here</param>
 public Tile(int ID, CustomTileData data)
 {
     tileID = ID;
     customTileData.Add(data);
 }
Exemplo n.º 14
0
    /// <summary>
    /// Launches the hookshot!
    /// </summary>
    /// <param name="target">The position to fire the hookshot at.</param>
    void Fire(Vector2 target)
    {
        bool hit_good_surface = false;
        bool hit_bad_surface  = false;
        bool hit_enemy        = false;

        // raycast, check if object is hookshottable (pass through pass through platforms)
        Vector3 character_position_3D = char_stats.char_collider.bounds.center;
        Vector2 character_position    = new Vector2(character_position_3D.x, character_position_3D.y);
        Vector2 direction             = target - character_position;

        // Use "upward" collision mask b/c hookshot is allowed to go through fallthrough platforms.
        RaycastHit2D hit = Physics2D.Raycast(character_position, direction, MAX_RANGE, CollisionMasks.hookshot_mask);

        if (hit.collider == null)
        {
            return;
        }                                               // TODO: hit nothing: misfire / animate failure / do nothing?

        // TODO: hmm.... So if an enemy bullet gets in the way while aiming, hookshotting fails? Fishy. Might need to adjust masking?
        // TODO: check for enemies.
        CustomTileData tile_data      = Utils.GetCustomTileData(hit.collider);
        CollisionType  collision_type = null;

        if (tile_data != null)
        {
            collision_type = tile_data.collision_type;
        }


        if (collision_type == null)
        {
            return;
        }
        if (collision_type.CanHookshotTo)
        {
            hit_good_surface = true;
        }
        else
        {
            hit_bad_surface = true;
        }

        distance_to_target   = hit.distance;
        distance_from_target = 0.0f;
        if (hit_bad_surface)
        {
            target = distance_to_target * direction.normalized + character_position;
        }
        // TODO: consider snapping to a predefined position on a predefined designed hookshottable object. Makes edge case handling easier.
        // The alternative best way for static geometry would be to raycast from the 4 corners of the player hitbox, and if the center ray works,
        // fire the hookshot, attach, and retract it. Then STOP when you reach the distance where a corner ray hit an obstacle.
        // won't work vs. moving platforms well, so might need to do collision checks every frame (or ignore them?).
        if (hit_good_surface)
        {
            BoxCollider2D box = tile_data.gameObject.GetComponent <BoxCollider2D>();
            if (box != null)
            {
                target             = box.bounds.center;
                distance_to_target = Vector2.Distance(character_position, box.bounds.center);
            }
        }

        if (hit_good_surface)
        {
            StartGrapple(target);
        }
        else if (hit_enemy)
        {
            GetOverHere();
        }
        else if (hit_bad_surface)
        {
            NoisilyBounceOffWall(target);
        }
    }