Пример #1
0
EventDataPtr EventData::clone() const
{
    // not implemented, but do not make it pure virtual to avoid
    // breaking compatibility with existing code.   
    abort();
    return EventDataPtr();
}
Пример #2
0
void Hero::DamagedMobilityState::enter() {
    hero.isStunned = true;
    hero.invincibilityTimer = 1.4667f;
    hero.stopShooting();
    hero.chooseAnimation();

    // If we're facing left, move right, if right, move left.
    if(hero.getDirection() == Directions::Left) {
        horizontalVelocity.setX(NESNumber(0x00, 0x80).toFloat());
    } else {
        horizontalVelocity.setX(-(NESNumber(0x00, 0x80).toFloat()));
    }

    // Special case for sliding and climbing:
    // * If damaged mid-slide there is no knockback
    // * If damaged while climbing there is no knockback
    if(hero.isSliding || hero.isClimbing) {
        horizontalVelocity.setX(0.0f);
    }

    // Ensure we get knocked back
    hero.body.setGravitated(true);
    hero.body.setApplyHorizontalVelocity(true);

    // Make sure we start falling immediately
    hero.setVelocityY(0.0f);

    // Make sure animations will play (like when you're on a ladder)
    hero.getAnimatedSprite()->unpause();

    if(auto events = hero.getEventBus().lock()) {
        events->triggerEvent(EventDataPtr(new EntityDamageEventData(hero.getId(), 0.0f)));
    }
}
Пример #3
0
    void Enemy::update(float dt) {
        Entity::update(dt);

        if(getHitPoints() <= 0.0f) {
            if(auto eventManagetPtr = getEventBus().lock()) {
                eventManagetPtr->queueEvent(EventDataPtr(new EntityDeathEventData(getId(), EntityDeathEventData::Enemy)));
            }
        }
        
        if(brain) {
            brain->update(dt);
        }

        if(damageTickCounter > 0) {
            // setVulnerable(false);
            damageTickCounter++;
            damageTickCounter %= 2;
        } else {
            // setVulnerable(true);
        }
    }
Пример #4
0
EventDataPtr EventData::clone() const
{
    abort(); // not implemented
    return EventDataPtr();
}
Пример #5
0
EventDataPtr CreateEvent(EventType eventType)
{
    return EventDataPtr(
                g_eventFactory.create(eventType)
    );
}
Пример #6
0
    void BlockSequence::update(float dt) {
        if(isActive()) {
            timer += dt;

            const auto & timing = descriptor.getTiming();

            // First we need to hide any entities that are older than they should be.
            for(auto it = std::begin(blockEntities), end = std::end(blockEntities); it != end; it++) {
                auto & entity = *it;

                if(entity && entity->isActive()) {
                    if(entity->getAge() >= descriptor.getMaximumBlockAge()) {
                        entity->reset();
                        entity->setActive(false);
                        world.queueObjectRemoval(entity);
                    }
                }
            }

            if(timer >= descriptor.getSpawnInterval()) {
                timer = 0.0f;

                const BlockTiming & timingStep = timing.at(step);

                for(auto it = std::begin(timingStep.getBlockIndicies()), end = std::end(timingStep.getBlockIndicies()); it != end; it++) {
                    int id = *it;
                    auto & entity = blockEntities[id];

                    blockRects[id].setFillColor({ 32, 255, 32, 196 });

                    if(entity) {
                        entity->setActive(true);
                        entity->setAgeless(false);
                        world.queueObjectAddition(blockEntities[id]);
                    }
                }

                if(timingStep.getBlockIndicies().size()) {
                    if(auto events = eventBus.lock()) {
                        events->triggerEvent(
                            EventDataPtr(
                                new AudioEventData(
                                    AudioEventData::ACTION_PLAY_SAMPLE,
                                    descriptor.getSoundName()
                                )
                            )
                        );
                    }
                }

                step++;
            }

            if(step >= timing.size()) {
                reset();
            }



            // // Check if we want to advance along in the sequence...
            // if(timer >= timingStep.getAtTime()) {
            //     // Process activiations
            //     for(auto it = std::begin(timingStep.getActivations()), end = std::end(timingStep.getActivations()); it != end; it++) {
            //         int id = *it;
            //         auto & entity = blockEntities[id];

            //         blockRects[id].setFillColor({ 32, 255, 32, 196 });

            //         if(entity) {
            //             entity->setActive(true);
            //             world.queueObjectAddition(blockEntities[id]);
            //         }
            //     }

            //     for(auto it = std::begin(timingStep.getDeactivations()), end = std::end(timingStep.getDeactivations()); it != end; it++) {
            //         int id = *it;
            //         auto & entity = blockEntities[id];

            //         blockRects[id].setFillColor({ 255, 32, 32, 128 });

            //         if(entity) {
            //             entity->reset();
            //             entity->setActive(false);
            //             world.queueObjectRemoval(entity);
            //         }
            //     }

            //     if(timingStep.getActivations().size()) {
            //         if(auto events = eventBus.lock()) {
            //             events->triggerEvent(
            //                 EventDataPtr(
            //                     new AudioEventData(
            //                         AudioEventData::ACTION_PLAY_SAMPLE,
            //                         descriptor.getSoundName()
            //                     )
            //                 )
            //             );
            //         }
            //     }

            //     // Advance the step counter
            //     step++;
            // }

            // // We got to the end so reset.
            // if(step >= timing.size()) {
            //     reset();
            // }
        }
    }
Пример #7
0
 EventDataPtr ObjectRemovedEventData::copy() const {
     return EventDataPtr(new ObjectRemovedEventData(getObjectId()));
 }
Пример #8
0
    Hero::Hero(int id, std::shared_ptr<Room> room)
        : Entity(id, room)
        , isDecelerating(false)
        , isStanding(false)
        , isWalking(false)
        , isSliding(false)
        , isInTunnel(false)
        , isJumping(false)
        , isFalling(false)
        , isAirborn(false)
        , isClimbing(false)
        , isTouchingLadderTop(false)
        , isFullyAccelerated(false)
        , isShooting(false)
        , isTeleporting(false)
        , isMorphing(false)
        , isStunned(false)
        , isInvincible(false)
        , isUnderWater(false)
        , wasUnderWaterLastFrame(false)
        , climbableRegion(0, 0, 0, 0)
        , actionController(nullptr)
        , mobilityState(nullptr)
        , nextMobilityState(nullptr)
        , temporaryMobilityState(nullptr)
        , shootingState(nullptr)
        , nextShootingState(nullptr) 
    {
        setDeathType(EntityDeathType::Hero);

        body.setGravitated(true);
        body.setHasWorldCollision(true);

        body.setCollisionCallback(std::bind(&Entity::handleCollision, this, std::placeholders::_1, std::placeholders::_2));
        body.setLandingCallback([this](Movable& movable, CollisionInfo& collisionInfo) {
            if(actionController->shouldMoveRight() || actionController->shouldMoveLeft()) {
                this->isFullyAccelerated = true;
            }

            this->isJumping = false;
            this->isFalling = false;
            this->isAirborn = false;

            if(auto events = this->getEventBus().lock()) {
                events->triggerEvent(EventDataPtr(new EntityStateChangeEventData(getId(), "landed")));
            }

#ifdef HIKARI_DEBUG_HERO_PHYSICS
            this->countAscendingFrames = 0;
            this->countDecendingFrames = 0;
#endif // HIKARI_DEBUG_HERO_PHYSICS
        });

        invincibilityTimer = 0;
        blinkTimer = 0;
        isBlinking = false;
        isVisible = true;

        walkVelocity = Vector2<float>(NESNumber(0x01, 0x4C).toFloat(), 0.0f);
        climbVelocity = Vector2<float>(walkVelocity.getY(), walkVelocity.getX()); // Climbs at same speed as he walks
        jumpVelocity = Vector2<float>(0.0f, -(NESNumber(0x04, 0xA5) + NESNumber(0, 0x40) + NESNumber(0, 0x40)).toFloat());
        suddenFallVelocity = Vector2<float>(0.0f, NESNumber(0, 0x80).toFloat());
        slideVelocity = Vector2<float>(NESNumber(0x02, 0x80).toFloat(), 0.0f);
        hurtVelocity = Vector2<float>();

        accelerationDelay = 0;
        accelerationDelayThreshold = 6;
#ifdef HIKARI_DEBUG_HERO_PHYSICS
        this->countAscendingFrames = 0;
        this->countDecendingFrames = 0;
#endif // HIKARI_DEBUG_HERO_PHYSICS

        isFullyAccelerated = false;

        setFaction(Factions::Hero);

        changeMobilityState(std::unique_ptr<MobilityState>(new IdleMobilityState(*this)));
        changeShootingState(std::unique_ptr<ShootingState>(new NotShootingState(*this)));

        getAnimatedSprite()->setUsePalette(true);
        getAnimatedSprite()->setUseSharedPalette(true);
    }
Пример #9
0
    void Hero::update(float dt) {
        if(wasUnderWaterLastFrame != isUnderWater) {
            if(wasUnderWaterLastFrame) {
                HIKARI_LOG(debug4) << "I'm not in water anymore!";
                body.setGravityApplicationThreshold(1);
            } else {
                HIKARI_LOG(debug4) << "I'm jumping in the water NOW!";
                body.setGravityApplicationThreshold(3);

                // Only emit event when plunging in to a body of water.
                if(auto events = this->getEventBus().lock()) {
                    events->triggerEvent(EventDataPtr(new EntityStateChangeEventData(getId(), "water")));
                }
            }
        }

        wasUnderWaterLastFrame = isUnderWater;

        if(const auto & room = getRoom()) {
            const int gridSize = room->getGridSize();

            if(invincibilityTimer > 0.0f) {
                invincibilityTimer -= dt;
                isInvincible = true;
            } else {
                isInvincible = false;
                isBlinking = false;
                isVisible = true;
            }

            if(isBlinking) {
                blinkTimer -= dt;

                if(blinkTimer <= 0.0f) {
                    blinkTimer = 0.0667f;
                    isVisible = !isVisible;
                }
            }

            //
            // Check if we're in a tunnel
            //
            if(isSliding) {
                const auto & bbox   = body.getBoundingBox();
                const int startingX = static_cast<int>(bbox.getLeft());
                const int endingX   = static_cast<int>(bbox.getRight());
                const int y         = static_cast<int>(bbox.getTop()) - 1; // Subtract 1 to test the tile directly *above* Rockman

                isInTunnel = false;

                int topLeftTile = room->getAttributeAt(startingX / gridSize, y / gridSize);
                int topRightTile = room->getAttributeAt((endingX - 1) / gridSize, y / gridSize);

                // Only check the top left and top right points
                if(((topLeftTile != Room::NO_TILE) && TileAttribute::hasAttribute(topLeftTile, TileAttribute::SOLID))
                    || ((topRightTile != Room::NO_TILE) && TileAttribute::hasAttribute(topRightTile, TileAttribute::SOLID))) {
                    isInTunnel = true;
                }
            }

            // Check if we're under water or starting to enter water
            {
                int bodyPositionTile = room->getAttributeAt(
                    static_cast<int>(getPosition().getX()) / gridSize,
                    static_cast<int>(getPosition().getY()) / gridSize);

                if((bodyPositionTile != Room::NO_TILE) && TileAttribute::hasAttribute(bodyPositionTile, TileAttribute::WATER)) {
                    isUnderWater = true;
                } else {
                    isUnderWater = false;
                }
            }

            //
            // State machine updates
            //

            if(temporaryMobilityState) {
                MobilityState::StateChangeAction action = temporaryMobilityState->update(dt);

                if(MobilityState::NEXT == action) {
                    popTemporaryMobilityState();
                }
            } else {
                if(shootingState) {
                    // Handle state change request actions...
                    ShootingState::StateChangeAction action = shootingState->update(dt);

                    if(ShootingState::NEXT == action) {
                        if(nextShootingState) {
                            changeShootingState(std::move(nextShootingState));
                        }
                    }
                }

                if(mobilityState) {
                    // Handle state change request actions...
                    MobilityState::StateChangeAction action = mobilityState->update(dt);

                    if(MobilityState::NEXT == action) {
                        if(nextMobilityState) {
                            changeMobilityState(std::move(nextMobilityState));
                        }
                    }
                }
            }    
        }

        Entity::update(dt);
    }