Esempio n. 1
0
void LVL_Npc::transformTo_x(long id)
{
    if(_isInited)
    {
        if(data.id==(unsigned)abs(id)) return;
        if(!ConfigManager::lvl_npc_indexes.contains(id))
            return;
        setup = &ConfigManager::lvl_npc_indexes[id];
    }

    data.id=id;

    double targetZ = 0;
    if(setup->foreground)
        targetZ = LevelScene::Z_npcFore;
    else
    if(setup->background)
        targetZ = LevelScene::Z_npcBack;
    else
        targetZ = LevelScene::Z_npcStd;

    z_index += targetZ;

    LevelScene::zCounter += 0.00000001;
    z_index += LevelScene::zCounter;

    long tID = ConfigManager::getNpcTexture(data.id);
    if( tID >= 0 )
    {
        texId = ConfigManager::level_textures[tID].texture;
        texture = ConfigManager::level_textures[tID];
        animated = ((setup->frames>1) || (setup->framestyle>0));
        animator_ID = setup->animator_ID;
    }

    warpFrameW = texture.w;
    warpFrameH = texture.h;

    setSize(setup->width, setup->height);

    if(data.generator)
    {
        isGenerator=true;
        generatorDirection=data.generator_direct;
        generatorTimeLeft= data.generator_period*100;
        generatorType    = data.generator_type;

        deActivatable    = true;
        activationTimeout= 150;
        collide_npc=COLLISION_NONE;
        collide_player=COLLISION_NONE;
        disableBlockCollision=true;
        setGravityScale(0.0f);
        return;
    }

    deActivatable = ((setup->deactivation)||(setup->scenery));
    activationTimeout= setup->deactivetionDelay;

    disableBlockCollision=!setup->collision_with_blocks;
    disableNpcCollision  = setup->no_npc_collions;

    setDirection(_direction);
    frameSize.setSize(setup->gfx_w, setup->gfx_h);
    animator.construct(texture, *setup);

    setDefaults();
    setGravityScale(setup->gravity ? 1.0f : 0.f);

    if(setup->block_player)
        collide_player = COLLISION_ANY;
    else
    if(setup->block_player_top)
        collide_player = COLLISION_TOP;
    else
        collide_player = COLLISION_NONE;

    if(setup->block_npc)
        collide_npc = COLLISION_ANY;
    else
    if(setup->block_npc_top)
        collide_npc = COLLISION_TOP;
    else
        collide_npc = COLLISION_NONE;
    if(setup->no_npc_collions)
        collide_npc=COLLISION_NONE;

    if(_isInited)
    {
       int leftHealth=setup->health-(setup->health-health);
       health=(leftHealth>0)? leftHealth : 1;
    }
    else
       health=(setup->health>0)?setup->health : 1;
}
void LVL_Player::solveCollision(PGE_Phys_Object *collided)
{
    if(!collided) return;

    switch(collided->type)
    {
        case PGE_Phys_Object::LVLBlock:
        {
            LVL_Block *blk= static_cast<LVL_Block*>(collided);
            if(blk)
            {
                if(blk->destroyed)
                {
                    #ifdef COLLIDE_DEBUG
                    qDebug() << "Destroyed!";
                    #endif
                    break;
                }
            }
            else
            {
                #ifdef COLLIDE_DEBUG
                qDebug() << "Wrong cast";
                #endif
                break;
            }

            if( ((!forceCollideCenter)&&(!collided->posRect.collideRect(posRect)))||
                ((forceCollideCenter)&&(!collided->posRect.collideRectDeep(posRect, 1.0, -3.0))) )
            {
                #ifdef COLLIDE_DEBUG
                qDebug() << "No, is not collidng";
                #endif
                break;
            }
            #ifdef COLLIDE_DEBUG
            qDebug() << "Collided item! "<<collided->type<<" " <<collided->posRect.center().x()<<collided->posRect.center().y();
            #endif

            if((bumpUp||bumpDown)&&(!forceCollideCenter))
            {
                #ifdef COLLIDE_DEBUG
                qDebug() << "Bump? U'r dumb!";
                #endif
                break;
            }

//            PGE_PointF c1 = posRect.center();
//            PGE_RectF &r1 = posRect;
//            PGE_PointF cc = collided->posRect.center();
//            PGE_RectF  rc = collided->posRect;

            switch(collided->collide_player)
            {
                case COLLISION_TOP:
                {
                    if(isCollideFloorToponly(collided))
                    {
                        if(blk->isHidden) break;
                        collided_bottom[(intptr_t)collided]=collided;//bottom of player
                        if(blk->setup->lava) kill(DEAD_burn);
                        else if(blk->setup->danger==2||blk->setup->danger==-3||blk->setup->danger==4) harm(1);
                        #ifdef COLLIDE_DEBUG
                        qDebug() << "Top of block";
                        #endif
                    }
                }
                break;
                case COLLISION_ANY:
                {
                    #ifdef COLLIDE_DEBUG
                    bool found=false;
                    #endif
                    //*****************************Feet of player****************************/
                    if(
                        (( (blk->shape==LVL_Block::shape_rect)||
                           (blk->shape==LVL_Block::shape_tr_bottom_left)||
                           (blk->shape==LVL_Block::shape_tr_bottom_right) ) && isCollideFloor(collided))||
                        ((blk->shape==LVL_Block::shape_tr_top_right)&&isCollideSlopeFloor(collided, SLOPE_RIGHT)) ||
                        ((blk->shape==LVL_Block::shape_tr_top_left)&&isCollideSlopeFloor(collided, SLOPE_LEFT))

                      ){
                        if(blk->isHidden) break;
                        collided_bottom[(intptr_t)collided]=collided;//bottom of player
                        if(blk->setup->lava) kill(DEAD_burn);
                        else if(blk->setup->danger==2||blk->setup->danger==-3||blk->setup->danger==4) harm(1);
                    }
                    //*****************************Head of player****************************/
                    else if(
                            (( (blk->shape==LVL_Block::shape_rect)||
                                (blk->shape==LVL_Block::shape_tr_top_left)||
                                (blk->shape==LVL_Block::shape_tr_top_right)) &&
                                isCollideCelling(collided, _heightDelta, forceCollideCenter))||
                            ((blk->shape==LVL_Block::shape_tr_bottom_right)&&isCollideSlopeCelling(collided, SLOPE_RIGHT)) ||
                            ((blk->shape==LVL_Block::shape_tr_bottom_left)&&isCollideSlopeCelling(collided, SLOPE_LEFT))
                           )
                    {
                        collided_top[(intptr_t)collided]=collided;//top of player
                        if(blk->setup->lava) kill(DEAD_burn);
                        else if(blk->setup->danger==-2||blk->setup->danger==-3||blk->setup->danger==4) harm(1);
                    }
                    //*****************************Left****************************/
                    else if( (isCollideLeft(collided)&&(blk->shape==LVL_Block::shape_rect))||
                             (isCollideLeft(collided)&&(blk->shape==LVL_Block::shape_tr_top_left)
                              &&(posRect.bottom()>=(collided->posRect.top()+SL_HeightTopRight(collided)+1.0)))||
                             (isCollideLeft(collided)&&(blk->shape==LVL_Block::shape_tr_bottom_left)
                              &&(posRect.top()<=(collided->posRect.bottom()-SL_HeightTopRight(collided)-1.0))) )
                    {
                        if(blk->isHidden) break;
                        collided_left[(intptr_t)collided]=collided;//right of player
                        if(blk->setup->lava) kill(DEAD_burn);
                        else if(blk->setup->danger==-1||blk->setup->danger==3||blk->setup->danger==4) harm(1);
                    }
                    //*****************************Right****************************/
                    else if( (isCollideRight(collided)&&(blk->shape==LVL_Block::shape_rect))||
                             (isCollideRight(collided)&&(blk->shape==LVL_Block::shape_tr_top_right)
                             &&(posRect.bottom()>=(collided->posRect.top()+SL_HeightTopLeft(collided)+1.0)))||
                             (isCollideRight(collided)&&(blk->shape==LVL_Block::shape_tr_bottom_right)
                             &&(posRect.top()<=(collided->posRect.bottom()-SL_HeightTopLeft(collided)-1.0)))
                           )
                    {
                        if(blk->isHidden) break;
                        collided_right[(intptr_t)collided]=collided;//left of player
                        if(blk->setup->lava) kill(DEAD_burn);
                        else if(blk->setup->danger==1||blk->setup->danger==3||blk->setup->danger==4) harm(1);
                    }


                    float c=forceCollideCenter? 0.0f : 1.0f;
                    //*****************************Center****************************/
                    if( ((!forceCollideCenter && blk->shape==LVL_Block::shape_rect)||(forceCollideCenter))
                            && blk->posRect.collideRectDeep(posRect,
                                                     fabs(_velocityX_prev+_velocityX_add)*c+c*2.0,
                                                     fabs(_velocityY_prev+_velocityY_add)*c+c*2.0)
                            )
                    {
                        if(blk->isHidden && !forceCollideCenter) break;
                        collided_center[(intptr_t)collided]=collided;
                    }
                    break;
                }
            default: break;
            }
            break;
        }
        case PGE_Phys_Object::LVLWarp:
        {
            contactedWarp = static_cast<LVL_Warp*>(collided);
            if(contactedWarp)
                contactedWithWarp=true;
            break;
        }
        case PGE_Phys_Object::LVLBGO:
        {
            LVL_Bgo *bgo= static_cast<LVL_Bgo*>(collided);
            if(bgo)
            {
                if(bgo->setup->climbing)
                {
                    bool set=climbable_map.isEmpty();
                    climbable_map[(intptr_t)collided]=collided;
                    if(set)
                        climbableHeight=collided->posRect.top();
                    else if(collided->top()<climbableHeight)
                        climbableHeight=collided->top();
                }
            }
            break;
        }
        case PGE_Phys_Object::LVLNPC:
        {
            LVL_Npc *npc= static_cast<LVL_Npc*>(collided);
            if(npc)
            {
                if(npc->isKilled())        break;

                if(!npc->data.msg.isEmpty())
                {
                    collided_talkable_npc=npc;
                }
                if(npc->data.friendly) break;
                if(npc->isGenerator) break;
                if(npc->setup->climbable)
                {
                    bool set=climbable_map.isEmpty();
                    climbable_map[(intptr_t)collided]=collided;
                    if(set)
                        climbableHeight=collided->posRect.top();
                    else if(collided->top()<climbableHeight)
                        climbableHeight=collided->top();
                }

                if((!npc->data.friendly)&&(npc->setup->takable))
                {
                    collided_talkable_npc=NULL;
                    npc->doHarm(LVL_Npc::DAMAGE_TAKEN);
                    kill_npc(npc, LVL_Player::NPC_Taked_Coin);
                }


                if( ((!forceCollideCenter)&&(!collided->posRect.collideRect(posRect)))||
                    ((forceCollideCenter)&&(!collided->posRect.collideRectDeep(posRect, 1.0, -3.0))) )
                {
                    break;
                }

                if((bumpUp||bumpDown)&&(!forceCollideCenter))
                    break;

                if(!npc->isActivated) break;

                //PGE_PointF c1 = posRect.center();
                //PGE_RectF &r1 = posRect;
                //PGE_PointF cc = collided->posRect.center();
                //PGE_RectF  rc = collided->posRect;

                switch(collided->collide_player)
                {
                    case COLLISION_TOP:
                    {
                        if(isCollideFloorToponly(collided))
                        {
                            collided_bottom[(intptr_t)collided]=collided;//bottom of player
                            #ifdef COLLIDE_DEBUG
                            qDebug() << "Top of block";
                            #endif
                        } else {
                            if( npc->posRect.collideRect(posRect))
                            {
                               if(npc->setup->hurt_player & !npc->setup->kill_on_jump) harm(1);
                            }
                        }

                    }
                    break;
                    case COLLISION_ANY:
                    {
                        #ifdef COLLIDE_DEBUG
                        bool found=false;
                        #endif
                        //double xSpeed = Maths::max(fabs(speedX()+_velocityX_add), fabs(_velocityX_prev+_velocityX_add)) * Maths::sgn(speedX()+_velocityX_add);
                        //double ySpeed = Maths::max(fabs(speedY()+_velocityY_add), fabs(_velocityY_prev+_velocityY_add)) * Maths::sgn(speedY()+_velocityY_add);
                        //*****************************Feet of player****************************/
                        if(isCollideFloor(collided))
                        {
                                collided_bottom[(intptr_t)collided]=collided;//bottom of player
                                #ifdef COLLIDE_DEBUG
                                qDebug() << "Top of block";
                                found=true;
                                #endif
                        }
                        //*****************************Head of player****************************/
                        else if( isCollideCelling(collided, _heightDelta, forceCollideCenter) )
                        {
                            collided_top[(intptr_t)collided]=collided;//top of player
                            if(npc->setup->hurt_player) harm(1);
                            #ifdef COLLIDE_DEBUG
                            qDebug() << "Bottom of block";
                            found=true;
                            #endif
                        }
                        //*****************************Left****************************/
                        else if( isCollideLeft(collided) )
                        {
                            collided_left[(intptr_t)collided]=collided;//right of player
                            if(npc->setup->hurt_player) harm(1);
                            #ifdef COLLIDE_DEBUG
                            qDebug() << "Right of block";
                            #endif
                        }
                        //*****************************Right****************************/
                        else if( isCollideRight(collided) )
                        {
                            collided_right[(intptr_t)collided]=collided;//left of player
                            if(npc->setup->hurt_player) harm(1);
                            #ifdef COLLIDE_DEBUG
                            qDebug() << "Left of block";
                            found=true;
                            #endif
                        }


                        float c=forceCollideCenter? 0.0f : 1.0f;
                        //*****************************Center****************************/
                        #ifdef COLLIDE_DEBUG
                        qDebug() << "block" <<posRect.top()<<":"<<blk->posRect.bottom()
                                 << "block" <<posRect.bottom()<<":"<<blk->posRect.top()<<" collide?"<<
                                    blk->posRect.collideRectDeep(posRect,
                                                                                         fabs(_velocityX_prev)*c+c*2.0,
                                                                                         fabs(_velocityY_prev)*c+c*2.0) <<
                                    "depths: "<< fabs(_velocityX_prev)*c+c*2.0 <<
                                fabs(_velocityY_prev)*c+c;
                        #endif
                        if( npc->posRect.collideRectDeep(posRect,
                                                         fabs(_velocityX_prev)*c+c*2.0,
                                                         fabs(_velocityY_prev)*c+c*2.0)
                                )
                        {
                            if(npc->setup->hurt_player) harm(1);
                            if(!forceCollideCenter) break;
                            collided_center[(intptr_t)collided]=collided;
                            #ifdef COLLIDE_DEBUG
                            qDebug() << "Center of block";
                            found=true;
                            #endif
                        }

                        #ifdef COLLIDE_DEBUG
                        qDebug() << "---checked---" << (found?"and found!": "but nothing..." )<<
                                    r1.left()<< "<="<< rc.right()<<"+"<<xSpeed ;
                        #endif
                        break;
                    }
                case COLLISION_NONE:
                    { //Detect top of stompable NPC!
                        if(!npc->setup->kill_on_jump)
                        {
                            if( npc->posRect.collideRect(posRect))
                            {
                               if(npc->setup->hurt_player) harm(1);
                            }
                            break;
                        }

//                        PGE_RectF &r1=posRect;
//                        PGE_RectF  rc = collided->posRect;
//                        float summSpeedY=(speedY()+_velocityY_add)-(collided->speedY()+collided->_velocityY_add);
//                        float summSpeedYprv=_velocityY_prev-collided->_velocityY_prev;
                        if(isCollideFloorToponly(collided))
//                                (
//                                    (summSpeedY >= 0.0)
//                                    &&
//                                    (r1.bottom() < rc.top()+summSpeedYprv)
//                                    &&
//                                    (
//                                         (r1.left()<rc.right()-1 ) &&
//                                         (r1.right()>rc.left()+1 )
//                                     )
//                                 )
//                                ||
//                                (r1.bottom() <= rc.top())
//                                )
                        {
                            npc->doHarm(LVL_Npc::DAMAGE_STOMPED);
                            this->bump(true);
                            //Reset floating state
                            floating_timer = floating_maxtime;
                            if(floating_isworks)
                            {
                                floating_isworks=false;
                                setGravityScale(climbing?0:physics_cur.gravity_scale);
                            }
                            kill_npc(npc, NPC_Stomped);
                        } else {
                            if( npc->posRect.collideRect(posRect))
                            {
                                //The second half of this "if" statement is there to fix a bug with falling collisions,
                                //and should NOT remain here because it is not how we should handle this!
                                //The bug occurs when the player is moving fast enough when they land on an enemy that they
                                //partially enter the enemy before the collision is resolved, causing the engine to think
                                //that the player is INSIDE the NPC, when they are actually only JUMPING on the NPC.
                                if(npc->setup->hurt_player & (!npc->setup->kill_on_jump || colliding_ySpeed > -1.0f)) harm(1);
                            }
                        }
                        break;
                    }//case COLLISION_NONE
                default: break;
                }
            }
            break;
        }
        case PGE_Phys_Object::LVLPhysEnv:
        {
            LVL_PhysEnv *env= static_cast<LVL_PhysEnv*>(collided);
            if(env)
            {
                if(env) environments_map[(intptr_t)env]=env->env_type;
            }
            break;
        }
    default: break;
    }
}
Esempio n. 3
0
void LVL_Player::update(float ticks)
{
    if(isLocked) return;
    if(!_isInited) return;
    if(!camera) return;
    LVL_Section* section = sct();
    if(!section) return;

    event_queue.processEvents(ticks);

    if((isWarping) || (!isAlive))
    {
        animator.tickAnimation(ticks);
        updateCamera();
        return;
    }

    _onGround = !foot_contacts_map.isEmpty();
    on_slippery_surface = !foot_sl_contacts_map.isEmpty();
    bool climbableUp  = !climbable_map.isEmpty();
    bool climbableDown= climbableUp && !_onGround;
    climbing = (climbableUp && climbing && !_onGround && (posRect.center().y()>=(climbableHeight-physics_cur.velocity_climb_y_up)) );
    if(_onGround)
    {
        phys_setup.decelerate_x =
                (fabs(speedX())<=physics_cur.MaxSpeed_walk)?
                (on_slippery_surface?physics_cur.decelerate_stop/physics_cur.slippery_c : physics_cur.decelerate_stop):
                (on_slippery_surface?physics_cur.decelerate_run/physics_cur.slippery_c : physics_cur.decelerate_run);

        if(physics_cur.strict_max_speed_on_ground)
        {
            if((speedX()>0)&&(speedX()>phys_setup.max_vel_x))
                setSpeedX(phys_setup.max_vel_x);
            else
            if((speedX()<0)&&(speedX()<phys_setup.min_vel_x))
                setSpeedX(phys_setup.min_vel_x);
        }
    }
    else
        phys_setup.decelerate_x = physics_cur.decelerate_air;

    if(doKill)
    {
        doKill=false;
        isAlive = false;
        setPaused(true);
        LvlSceneP::s->checkPlayers();
        return;
    }

    if(climbing)
    {
        PGE_Phys_Object* climbableItem = static_cast<PGE_Phys_Object*>((void*)(intptr_t)climbable_map[climbable_map.keys().first()]);
        if(climbableItem)
        {
            _velocityX_add=climbableItem->speedX();
            _velocityY_add=climbableItem->speedY();
        } else
        {
            _velocityX_add=0.0f;
            _velocityY_add=0.0f;
        }

        if(gscale_Backup != 1)
        {
            setGravityScale(0);
            gscale_Backup = 1;
        }
    }
    else
    {
        if(gscale_Backup != 0.f)
        {
            setGravityScale(physics_cur.gravity_scale);
            gscale_Backup = 0.f;
        }
    }

    if(climbing)
    {
        setSpeed(0,0);
    }

    if(environments_map.isEmpty())
    {
        if(last_environment!=section->getPhysicalEnvironment() )
        {
            environment = section->getPhysicalEnvironment();
        }
    }
    else
    {
        int newEnv = section->getPhysicalEnvironment();

        foreach(int x, environments_map)
        {
            newEnv = x;
        }

        if(last_environment != newEnv)
        {
            qDebug()<<"Enter to environment" << newEnv;
            environment = newEnv;
        }
    }

    refreshEnvironmentState();

    if(_onGround)
    {
        if(!floating_isworks)
        {
            floating_timer=floating_maxtime;
        }
    }

    //Running key
    if(keys.run)
    {
        if(!_isRunning)
        {
            phys_setup.max_vel_x = physics_cur.MaxSpeed_run;
            phys_setup.min_vel_x = -physics_cur.MaxSpeed_run;
            _isRunning=true;
        }
    }
    else
    {
        if(_isRunning)
        {
            phys_setup.max_vel_x = physics_cur.MaxSpeed_walk;
            phys_setup.min_vel_x = -physics_cur.MaxSpeed_walk;
            _isRunning=false;
        }
    }
    if((physics_cur.ground_c_max!=1.0f))
    {
        phys_setup.max_vel_x = fabs(_isRunning ?
                    physics_cur.MaxSpeed_run :
                    physics_cur.MaxSpeed_walk) *(_onGround?physics_cur.ground_c_max:1.0f);
        phys_setup.min_vel_x = -fabs(_isRunning ?
                    physics_cur.MaxSpeed_run :
                    physics_cur.MaxSpeed_walk) *(_onGround?physics_cur.ground_c_max:1.0f);
    }


    if(keys.alt_run)
    {
        if(attack_enabled && !attack_pressed && !climbing)
        {
            attack_pressed=true;

            if(keys.up)
                attack(Attack_Up);
            else
            if(keys.down)
                attack(Attack_Down);
            else
            {
                attack(Attack_Forward);
                PGE_Audio::playSoundByRole(obj_sound_role::PlayerTail);
                animator.playOnce(MatrixAnimator::RacoonTail, _direction, 75, true, true, 1);
            }
        }
    }
    else
    {
        if(attack_pressed) attack_pressed=false;
    }



    //if
    if(!keys.up && !keys.down && !keys.left && !keys.right)
    {
        if(wasEntered)
        {
            wasEntered = false;
            wasEnteredTimeout=0;
        }
    }

    //Reset state
    if(wasEntered)
    {
        wasEnteredTimeout-=ticks;
        if(wasEnteredTimeout<0)
        {
            wasEnteredTimeout=0;
            wasEntered=false;
        }
    }

    if(keys.up)
    {
        if(climbableUp&&(jumpTime<=0))
        {
            setDuck(false);
            climbing=true;
            floating_isworks=false;//!< Reset floating on climbing start
        }

        if(climbing)
        {
            if(posRect.center().y() >= climbableHeight)
                setSpeedY(-physics_cur.velocity_climb_y_up);
        }
    }

    if(keys.down)
    {
        if( climbableDown && (jumpTime<=0) )
        {
            setDuck(false);
            climbing=true;
            floating_isworks=false;//!< Reset floating on climbing start
        }
        else
        {
            if((duck_allow & !ducking)&&( (animator.curAnimation()!=MatrixAnimator::RacoonTail) ) )
            {
                setDuck(true);
            }
        }

        if(climbing)
        {
            setSpeedY(physics_cur.velocity_climb_y_down);
        }
    }
    else
    {
        if(ducking)
            setDuck(false);
    }

    if( (!keys.left) || (!keys.right) )
    {
        bool turning=(((speedX()>0)&&(_direction<0))||((speedX()<0)&&(_direction>0)));

        float force = turning?
                    physics_cur.decelerate_turn :
                    (fabs(speedX())>physics_cur.MaxSpeed_walk)?physics_cur.run_force : physics_cur.walk_force;

        if(on_slippery_surface) force=force/physics_cur.slippery_c;
        else if((_onGround)&&(physics_cur.ground_c!=1.0f)) force=force*physics_cur.ground_c;

        if(keys.left) _direction=-1;
        if(keys.right) _direction=1;

        if(!ducking || !_onGround)
        {
            //If left key is pressed
            if(keys.right && collided_right.isEmpty())
            {
                if(climbing)
                    setSpeedX(physics_cur.velocity_climb_x);
                else
                    applyAccel(force, 0);
            }
            //If right key is pressed
            if(keys.left && collided_left.isEmpty())
            {
                if(climbing)
                    setSpeedX(-physics_cur.velocity_climb_x);
                else
                    applyAccel(-force, 0);
            }
        }
    }

    if( keys.alt_jump )
    {
        //Temporary it is ability to fly up!
        if(!bumpDown && !bumpUp) {
            setSpeedY(-physics_cur.velocity_jump);
        }
    }

    if( keys.jump )
    {
        if(!JumpPressed)
        {
            if(environment!=LVL_PhysEnv::Env_Water)
                { if(climbing || _onGround || (environment==LVL_PhysEnv::Env_Quicksand))
                    PGE_Audio::playSoundByRole(obj_sound_role::PlayerJump); }
            else
                PGE_Audio::playSoundByRole(obj_sound_role::PlayerWaterSwim);
        }

        if((environment==LVL_PhysEnv::Env_Water)||(environment==LVL_PhysEnv::Env_Quicksand))
        {
            if(!JumpPressed)
            {
                if(environment==LVL_PhysEnv::Env_Water)
                {
                    if(!ducking) animator.playOnce(MatrixAnimator::SwimUp, _direction, 75);
                }
                else
                if(environment==LVL_PhysEnv::Env_Quicksand)
                {
                    if(!ducking) animator.playOnce(MatrixAnimator::JumpFloat, _direction, 64);
                }

                JumpPressed=true;
                jumpTime = physics_cur.jump_time;
                jumpVelocity=physics_cur.velocity_jump;
                floating_timer = floating_maxtime;
                setSpeedY(speedY()-jumpVelocity);
            }
        }
        else
        if(!JumpPressed)
        {
            JumpPressed=true;
            if(_onGround || climbing)
            {
                climbing=false;
                jumpTime=physics_cur.jump_time;
                jumpVelocity=physics_cur.velocity_jump;
                floating_timer = floating_maxtime;
                setSpeedY(-jumpVelocity-fabs(speedX()/physics_cur.velocity_jump_c));
            }
            else
            if((floating_allow)&&(floating_timer>0))
            {
                floating_isworks=true;

                //if true - do floating with sin, if false - do with cos.
                floating_start_type=(speedY()<0);

                setSpeedY(0);
                setGravityScale(0);
            }
        }
        else
        {
            if(jumpTime>0)
            {
                jumpTime -= ticks;
                setSpeedY(-jumpVelocity-fabs(speedX()/physics_cur.velocity_jump_c));
            }

            if(floating_isworks)
            {
                floating_timer -= ticks;
                if(floating_start_type)
                    setSpeedY( state_cur.floating_amplitude*(-cos(floating_timer/80.0)) );
                else
                    setSpeedY( state_cur.floating_amplitude*(cos(floating_timer/80.0)) );
                if(floating_timer<=0)
                {
                    floating_timer=0;
                    floating_isworks=false;
                    setGravityScale(climbing?0:physics_cur.gravity_scale);
                }
            }
        }
    }
    else
    {
        jumpTime=0;
        if(JumpPressed)
        {
            JumpPressed=false;
            if(floating_allow)
            {
                if(floating_isworks)
                {
                    floating_timer=0;
                    floating_isworks=false;
                    setGravityScale(climbing?0:physics_cur.gravity_scale);
                }
            }
        }
    }

    refreshAnimation();
    animator.tickAnimation(ticks);

    PGE_RectF sBox = section->sectionLimitBox();

    //Return player to start position on fall down
    if( posY() > sBox.bottom()+_height )
    {
        kill(DEAD_fall);
    }

    if(bumpDown)
    {
        bumpDown=false;
        jumpTime=0;
        setSpeedY(bumpVelocity);
    }
    else
    if(bumpUp)
    {
        bumpUp=false;
        if(keys.jump)
        {
            jumpTime=bumpJumpTime;
            jumpVelocity=bumpJumpVelocity;
        }
        setSpeedY( (keys.jump ?
                        (-fabs(bumpJumpVelocity)-fabs(speedX()/physics_cur.velocity_jump_c)):
                         -fabs(bumpJumpVelocity)) );
    }


    //Connection of section opposite sides
    if(isExiting) // Allow walk offscreen if exiting
    {
        if((posX() < sBox.left()-_width-1 )||(posX() > sBox.right() + 1 ))
        {
            setGravityScale(0.0);//Prevent falling [we anyway exited from this level, isn't it?]
            setSpeedY(0.0);
        }
        if(keys.left||keys.right)
        {
            if((environment==LVL_PhysEnv::Env_Water)||(environment==LVL_PhysEnv::Env_Quicksand))
            {
                keys.run=true;
                if(_exiting_swimTimer<0 && !keys.jump)
                    keys.jump=true;
                else
                if(_exiting_swimTimer<0 && keys.jump)
                {
                    keys.jump=false; _exiting_swimTimer=(environment==LVL_PhysEnv::Env_Quicksand)? 1 : 500;
                }
                _exiting_swimTimer-= ticks;
            } else keys.run=false;
        }
    }
    else
    if(section->isWarp())
    {
        if(posX() < sBox.left()-_width-1 )
            setPosX( sBox.right()+1 );
        else
        if(posX() > sBox.right() + 1 )
            setPosX( sBox.left()-_width-1 );
    }
    else
    {

        if(section->ExitOffscreen())
        {
            if(section->RightOnly())
            {
                if( posX() < sBox.left())
                {
                    setPosX( sBox.left() );
                    setSpeedX(0.0);
                }
            }

            if((posX() < sBox.left()-_width-1 ) || (posX() > sBox.right() + 1 ))
            {
                setLocked(true);
                _no_render=true;
                LvlSceneP::s->setExiting(1000, LvlExit::EXIT_OffScreen);
                return;
            }
        }
        else
        {
            //Prevent moving of player away from screen
            if( posX() < sBox.left())
            {
                setPosX(sBox.left());
                setSpeedX(0.0);
            }
            else
            if( posX()+_width > sBox.right())
            {
                setPosX(sBox.right()-_width);
                setSpeedX(0.0);
            }
        }
    }

    if(_stucked)
    {
        posRect.setX(posRect.x()-_direction*2);
        applyAccel(0, 0);
    }

    processWarpChecking();

    if(_doSafeSwitchCharacter) setCharacter(characterID, stateID);

    try {
        lua_onLoop();
    } catch (luabind::error& e) {
        LvlSceneP::s->getLuaEngine()->postLateShutdownError(e);
    }
    updateCamera();
}
Esempio n. 4
0
  Block::Block(int index, Game *game, const TileParam &tileParam)
    : Body(Body::BodyType::Block, game, tileParam)
    , mGravityScale(2.f)
    , mMinimumHitImpulse(0)
  {
    mName = Name;
    mMinimumHitImpulse = mTileParam.minimumHitImpulse;
    setScore(mTileParam.score);
    setEnergy(mTileParam.minimumKillImpulse);
    setGravityScale(mTileParam.gravityScale);

    const sf::Texture &texture = mGame->level()->tileParam(index).texture;
    sf::Image img;
    img.create(texture.getSize().x + 2 * TextureMargin, texture.getSize().y + 2 * TextureMargin, sf::Color(0, 0, 0, 0));
    img.copy(texture.copyToImage(), TextureMargin, TextureMargin, sf::IntRect(0, 0, 0, 0), true);
    mTexture.loadFromImage(img);
    setSmooth(mTileParam.smooth);

    setHalfTextureSize(texture);
    
    mSprite.setTexture(mTexture);
    mSprite.setOrigin(.5f * mTexture.getSize().x, .5f * mTexture.getSize().y);

    if (gLocalSettings().useShaders()) {
      mShader.loadFromFile(ShadersDir + "/fallingblock.fs", sf::Shader::Fragment);
      mShader.setParameter("uAge", 0.f);
      mShader.setParameter("uBlur", 0.f);
      mShader.setParameter("uColor", sf::Color(255U, 255U, 255U, 255U));
      mShader.setParameter("uResolution", float(mTexture.getSize().x), float(mTexture.getSize().y));
    }

    const unsigned int W = texture.getSize().x;
    const unsigned int H = texture.getSize().y;

    b2BodyDef bd;
    bd.type = b2_dynamicBody;
    bd.angle = .0f;
    bd.linearDamping = mTileParam.linearDamping.isValid() ? mTileParam.linearDamping.get() : DefaultLinearDamping;
    bd.angularDamping = mTileParam.angularDamping.isValid() ? mTileParam.angularDamping.get() : DefaultAngularDamping;
    bd.gravityScale = .0f;
    bd.allowSleep = true;
    bd.awake = false;
    bd.fixedRotation = false;
    bd.bullet = false;
    bd.userData = this;
    mBody = game->world()->CreateBody(&bd);

    b2PolygonShape polygon;
    const float32 hs = .5f * Game::InvScale;
    const float32 hh = hs * H;
    const float32 xoff = hs * (W - H);
    polygon.SetAsBox(xoff, hh);

    const float32 density = mTileParam.density.isValid() ? mTileParam.density.get() : DefaultDensity;
    const float32 friction = mTileParam.friction.isValid() ? mTileParam.friction.get() : DefaultFriction;
    const float32 restitution = mTileParam.restitution.isValid() ? mTileParam.restitution.get() : DefaultRestitution;

    b2FixtureDef fdBox;
    fdBox.shape = &polygon;
    fdBox.density = density;
    fdBox.friction = friction;
    fdBox.restitution = restitution;
    fdBox.userData = this;
    mBody->CreateFixture(&fdBox);

    b2CircleShape circleL;
    circleL.m_p.Set(-xoff, 0.f);
    circleL.m_radius = hh;

    b2FixtureDef fdCircleL;
    fdCircleL.shape = &circleL;
    fdCircleL.density = density;
    fdCircleL.friction = friction;
    fdCircleL.restitution = restitution;
    fdCircleL.userData = this;
    mBody->CreateFixture(&fdCircleL);

    b2CircleShape circleR;
    circleR.m_p.Set(xoff, 0.f);
    circleR.m_radius = hh;

    b2FixtureDef fdCircleR;
    fdCircleR.shape = &circleR;
    fdCircleR.density = density;
    fdCircleR.friction = friction;
    fdCircleR.restitution = restitution;
    fdCircleR.userData = this;
    mBody->CreateFixture(&fdCircleR);
  }