Fancy Mansion: Lootable objects

So this week I’ve been working on some level design to replace the current placeholder level, expanding the waypoint system for the pathing ai, and adding some lootable objects. The lootable objects comprise our game’s “power-ups” (a minimum of three powerups was part of the assignment criteria). As our thief explores the mansion looking for valuable items to pocket and pilfer, they may come across larger objects that result in special effects while being carried.

Here are a few examples:

Candle: Increases field of view. No economic value.Group15_ConceptDocument2-7

Bear pelt: Gives the player the ability to hide on the floor, making the player invisible to the enemy. The player cannot hide with the bear pelt while carrying another item. The player  cannot move while hiding. 100 gold.

Painting: Carrying it limits the walking speed. It functions as a shield against the enemy, as long as the player only moves towards the enemy or sideways. Turning away to run will nullify the protection by exposing the player’s back to him. 150 gold.

Vase: Carrying it limits walking speed. If the player gets shot the vase breaks but the player survives. 300 gold.

Armor: The enemy can hear the player at all times if they move while the armor is worn. It  slows the player. The player can hide with it, and if the player gets shot the armor breaks but the player survives.The enemy can move the player hiding in the armour to another location. 500 gold.

Clock: It slows the player. If the player gets shot, the clock breaks but the player survives. 200 gold.

I’ll take you through an example of how I coded the clock, an object that slows the player while carried, but saves the player from one hit from Otto von Fancy’s tesla gun. I made a class for the clock that takes in a pointer to the player object in its constructor: this way we can access and alter protected variables in the player class, such as adding picked up items to the player’s inventory. The clock class has all the usual functions and datamembers you would expect (getters and setters for position, entity type, state, visibility, colliders, a sprite, and so on).

In the clock’s Update() function, we have a switch to handle its three states: when it’s lootable on the ground (STATE_NOT_LOOTED), when it’s currently being carried by the player (STATE_LOOTED), and when the player drops off the clock to cash it on the balcony (STATE_SOLD). The code within these states describe the different behaviour that occurs in these states. In the unlooted state, the clock will get an aura around it showing it is lootable. If the player is not already holding a heavy item, only one of which can be carried at a time, the aura around the lootable item will be green. If the player is already holding a heavy item, the aura will be red, to signify the player cannot carry more heavy items at the moment. The player will not be able to pick up another heavy item while already carrying one.

In the looted state, the clock displays in front of the player, in a position that will give the player the appearance of their avatar carrying the object. In order to accomplish the slowed movement while the player is carrying the clock, I made two player movement states, one for carrying a “lighter” object and another for carrying a “heavy” one. These states decrease the player’s movespeed by different amounts, and “heavy” objects even disable the sprint ability. In the clock’s looted state, I run player’s SetState() function and set it to STATE_CARRYHEAVY, signifying that the player is carrying a heavy object. In the player class, this state results in slowed movement and disallows springing, in two switches in the player’s Update() function.

In the sold state, we currently just turn the clock sprite invisible and place it offscreen, but will run delete and .erase to remove the clock, its pointer and its position in the entities vector, after the beta deadline, in order to remove the memory leak that results otherwise (this due to request from other group members to save time for other features/implementation before the beta).

In GameState’s Update() function, we allow the clock to be picked up by the player on collision with the player sprite and a keypress of E. We allow the clock to be dropped on a keypress of Q, and if the clock is dropped on a balcony tile, we add the clock’s value to the player’s score.

The clock is currently being carried by the player. It's a placeholder sprite so the alignment isn't right. The UI elements are also placeholders.

The clock is currently being carried by the player. It’s a placeholder sprite so the alignment isn’t right. The UI elements are also placeholders.

So that’s pretty much it for the basic code for adding items that change the player’s abilities when carried! Here are some relevant code snippets from GameState’s Update() function:

//Looting and dropping the clock (on a non-balcony tile)
        if (m_entities[i]->GetType() == ENTITY_CLOCK)
        {
            Clock* clock = static_cast(m_entities[i]);
            if (abs(p_player->GetSpriteCenter().x - clock->GetPos().x) GetSpriteCenter().y - clock->GetPos().y) GetState() == STATE_NOT_LOOTED)
                {
                    clock->Hover(true);
                    if (m_actions[ACTION_PICKUPITEM] && !p_player->GetHoldingItem())
                    {
                        p_player->SetLootSound("../assets/dropoff.wav");
                        p_player->PlayLootSound();
                        p_player->SetHoldingItem(clock);
                        clock->SetState(STATE_LOOTED);
                    }

                }
            }
            else
            {
                clock->Hover(false);
            }

        }

}


//Drop off loot if on a balcony tile
                        if (m_actions[ACTION_DROPITEM])
                        {
                            p_player->SetScore(p_player->GetInventory()->Empty());

                            if (p_player->GetHoldingItem())
                            {
                                //Add to score when dropping off items
                                p_player->SetLootSound("../assets/dropoff2.wav");
                                p_player->PlayLootSound();
                                p_player->GetHoldingItem()->SetState(STATE_SOLD);
                                p_player->SetScore(p_player->GetHoldingItem()->GetItemValue());
                                p_player->SetHoldingItem(nullptr);
                                
                                //return player's movespeed to normal
                                p_player->SetState(STATE_NORMAL);

                                //IMPORTANT: Later use delete and .erase here to remove entities AND their pointers AND position in m_entities vector!
                            }
                        }
                        p_player->SetFootStep("duct4.wav");
                    }
                    //Otherwise if not on a balcony tile, just drop
                    else
                    {
                        p_HUD->setSellable(false);

                        if (m_actions[ACTION_DROPITEM] && p_player->GetHoldingItem())
                        {
                            p_player->GetHoldingItem()->SetState(STATE_NOT_LOOTED);
                            p_player->SetHoldingItem(nullptr);

                            //return player's movespeed to normal
                            p_player->SetState(STATE_NORMAL);
                        }
                    }

//IF the player is hit with a projectile
            if (m_entities[i]->GetType() == ENTITY_PROJECTILE && m_entities[i]->IsVisible())
            {
                Projectile* projectile = static_cast(m_entities[i]);
                if (CollisionManager::Check(projectile->GetCollider(), p_player->GetCollider(), overlapX, overlapY))
                {
                    //If the player is hit by a projectile but is currently holding a clock
                    if (!p_player->GetHoldingItem())
                    {

                        //Player dies if hit by a projectile and not currently carrying an item with a shielding effect
                        p_player->KillPlayer();

                    }

                    else if (p_player->GetHoldingItem()->GetType() == ENTITY_CLOCK)
                    {
                        //destroy the clock, player takes no damage

                        //IMPORTANT: Later use delete and .erase here to remove entities AND their pointers AND position in m_entities vector!
                        p_player->GetHoldingItem()->SetState(STATE_SOLD);
                        p_player->GetHoldingItem()->SetVisible(false);
                        p_player->SetHoldingItem(nullptr);

                        //Set player's movespeed back to normal
                        p_player->SetState(STATE_NORMAL);

                        //play some sfx / some animation

                    }
                }

About Dee Majek

2014  Programming