Пример #1
0
void PGE_LevelCamera::sortElements()
{
    if(objects_to_render.size()<=1) return; //Nothing to sort!
    QStack<int> beg;
    QStack<int> end;
    PGE_Phys_Object* piv;
    int i=0, L, R, swapv;
    beg.push_back(0);
    end.push_back(objects_to_render.size());
    while (i>=0)
    {
        L=beg[i]; R=end[i]-1;
        if (L<R)
        {
            piv=objects_to_render[L];
            while (L<R)
            {
                while ((objects_to_render[R]->zIndex()>=piv->zIndex()) && (L<R)) R--;
                if (L<R) objects_to_render[L++]=objects_to_render[R];

                while ((objects_to_render[L]->zIndex()<=piv->zIndex()) && (L<R)) L++;
                if (L<R) objects_to_render[R--]=objects_to_render[L];
            }
            objects_to_render[L]=piv; beg.push_back(L+1); end.push_back(end[i]); end[i++]=(L);
            if((end[i]-beg[i]) > (end[i-1]-beg[i-1]))
            {
                swapv=beg[i]; beg[i]=beg[i-1]; beg[i-1]=swapv;
                swapv=end[i]; end[i]=end[i-1]; end[i-1]=swapv;
            }
        }
        else
        {
            i--;
            beg.pop_back();
            end.pop_back();
        }
    }
}
void InAreaDetector::processDetector()
{
    _contacts = 0;
    _detected = false;
    _trapZone = _srcTrapZone;

    _trapZone.setPos(
        _parentNPC->posCenterX() + _srcTrapZone.left(),
        _parentNPC->posCenterY() + _srcTrapZone.top()
    );

    if(_parentNPC->direction() < 0)
    {
        double x_pos = _trapZone.left() + (_parentNPC->posCenterX() - _trapZone.center().x()) * 2.0;
        _trapZone.setPos(x_pos, _trapZone.y());
    }

    detectedPLR.clear();
    detectedBLK.clear();
    detectedBGO.clear();
    detectedNPC.clear();
    detectedBlocks.clear();
    detectedBGOs.clear();
    detectedNPCs.clear();
    detectedPlayers.clear();

    std::vector<PGE_Phys_Object *> bodies;
    _scene->queryItems(_trapZone, &bodies);

    for(PGE_RenderList::iterator it = bodies.begin(); it != bodies.end(); it++)
    {
        PGE_Phys_Object *visibleBody = *it;
        if(visibleBody == _parentNPC) continue;
        if(visibleBody == nullptr)
            continue;
        if(!visibleBody->isVisible()) //Don't whip elements from hidden layers!
            continue;
        switch(visibleBody->type)
        {
        case PGE_Phys_Object::LVLPlayer:
            if((_filters & F_PLAYER) == 0) continue;
            {
                LVL_Player *p = dynamic_cast<LVL_Player *>(visibleBody);
                if(!p) continue;
                detectedPlayers.push_back(p);
                detectedPLR[p->data.id] = 1;
                break;
            }
        case PGE_Phys_Object::LVLBGO:
            if((_filters & F_BGO) == 0) continue;
            {
                LVL_Bgo *b = dynamic_cast<LVL_Bgo *>(visibleBody);
                if(!b) continue;
                detectedBGOs.push_back(b);
                detectedBGO[b->data.id] = 1;
                break;
            }
        case PGE_Phys_Object::LVLNPC:
            if((_filters & F_NPC) == 0) continue;
            {
                LVL_Npc *n = dynamic_cast<LVL_Npc *>(visibleBody);
                if(!n) continue;
                detectedNPCs.push_back(n);
                detectedNPC[n->_npc_id] = 1;
                break;
            }
        case PGE_Phys_Object::LVLBlock:
            if((_filters & F_BLOCK) == 0) continue;
            {
                LVL_Block *s = dynamic_cast<LVL_Block *>(visibleBody);
                if(!s) continue;
                if(!s->m_destroyed)
                    detectedBlocks.push_back(s);
                detectedBLK[s->data.id] = 1;
                break;
            }
        default:
            continue;
        }
        _detected = true;
        _contacts++;
    }
}
void LevelScene::render()
{
    GlRenderer::clearScreen();
    size_t c = 0;

    if(!m_isInit)
        goto renderBlack;

    GlRenderer::setTextureColor(1.0f, 1.0f, 1.0f, 1.0f);

    for(PGE_LevelCamera &cam : m_cameras)
    {
        if(m_numberOfPlayers > 1)
            GlRenderer::setViewport(static_cast<int>(cam.renderX()),
                                    static_cast<int>(cam.renderY()),
                                    static_cast<int>(cam.w()),
                                    static_cast<int>(cam.h()));

        cam.drawBackground();
        double camPosX = cam.posX();
        double camPosY = cam.posY();
        //Size of array with objects catched by camera
        int render_sz = cam.renderObjects_count();
        //Pointer to array with objects catched by camera
        PGE_Phys_Object **render_obj = cam.renderObjects_arr();
        //Index of array with lua-drawn elements
        size_t currentLuaRenderObj = 0;
        //Size of array with lua-drawn elements
        size_t currentLuaRenderSz = luaRenders.size();

        for(int i = 0; i < render_sz; i++)
        {
            switch(render_obj[i]->type)
            {
            case PGE_Phys_Object::LVLBlock:
            case PGE_Phys_Object::LVLBGO:
            case PGE_Phys_Object::LVLNPC:
            case PGE_Phys_Object::LVLPlayer:
            {
                PGE_Phys_Object *obj = render_obj[i];
                //Get Z-index of current element
                long double Z = obj->zIndex();

                //Draw lua-drew elements which are less than current Z-index
                while(currentLuaRenderObj < currentLuaRenderSz)
                {
                    RenderFuncs &r = luaRenders[currentLuaRenderObj];

                    if(r.z_index > Z)
                        break;

                    r.render(camPosX, camPosY);
                    currentLuaRenderObj++;
                }

                //Draw element itself
                obj->render(camPosX, camPosY);
                break;
            }

            default:
                break;
            }
        }

        //Draw elements left after all camera objects are drawn
        while(currentLuaRenderObj < currentLuaRenderSz)
        {
            RenderFuncs &r = luaRenders[currentLuaRenderObj];
            r.render(camPosX, camPosY);
            currentLuaRenderObj++;
        }

        if(PGE_Window::showPhysicsDebug)
        {
            for(int i = 0; i < render_sz; i++)
            {
                PGE_Phys_Object *obj = render_obj[i];
                obj->renderDebug(camPosX, camPosY);

                if(obj->type == PGE_Phys_Object::LVLNPC)
                {
                    auto *npc = dynamic_cast<LVL_Npc *>(obj);
                    for(auto &i : npc->detectors_inarea)
                    {
                        PGE_RectF trapZone = i.trapZone();
                        GlRenderer::renderRect(static_cast<float>(trapZone.x() - camPosX),
                                               static_cast<float>(trapZone.y() - camPosY),
                                               static_cast<float>(trapZone.width()),
                                               static_cast<float>(trapZone.height()),
                                               1.0f, 0.0, 0.0f, 1.0f, false);
                    }
                }
            }
        }

        cam.drawForeground();

        if(m_numberOfPlayers > 1)
            GlRenderer::resetViewport();

        c++;
    }

    //Draw camera separators
    for(c = 1; c < m_cameras.size(); c++)
        GlRenderer::renderRect(0, float(m_cameras[c].h()) * c - 1, m_cameras[c].w(), 2, 0.f, 0.f, 0.f, 1.f);

    if(PGE_Window::showDebugInfo)
    {
        //FontManager::printText(fmt::format_ne("Camera X={0} Y={1}", cam_x, cam_y), 200,10);
        int dpos = 60;
        FontManager::printText(fmt::format_ne("Player J={0} G={1} F={2}; TICK-SUB: {3}\n"
                                           "NPC's: {4}, Active {5}; BLOCKS: {6}",
                                           int(m_debug_player_jumping),
                                           int(m_debug_player_onground),
                                           int(m_debug_player_foots),
                                           uTickf,
                                           m_itemsNpc.size(),
                                           m_npcActive.size(),
                                           m_itemsBlocks.size()), 10, dpos);
        dpos += 35;
        FontManager::printText(fmt::format_ne("Visible objects: {0}", !m_cameras.empty() ? m_cameras[0].renderObjects_count() : 0), 10, dpos);
        dpos += 35;
        FontManager::printText(fmt::format_ne("Delays E={0} R={1} P={2}",
                                           m_debug_event_delay,
                                           m_debug_render_delay,
                                           m_debug_phys_delay), 10, dpos);
        dpos += 35;
        FontManager::printText(fmt::format_ne("Time Real:{0}\nTime Loop:{1}",
                                           debug_TimeReal.elapsed(),
                                           debug_TimeCounted), 10, dpos);
        dpos += 35;

        if(!m_isLevelContinues)
        {
            FontManager::printText(fmt::format_ne("Exit delay {0}, {1}",
                                               m_exitLevelDelay,
                                               uTickf), 10, dpos, FontManager::DefaultRaster, 1.0, 0, 0, 1.0);
            dpos += 35;
        }

        if(m_placingMode)
            FontManager::printText(fmt::format_ne("Placing! {0} X={1} Y={2}",
                                               m_placingMode_item_type,
                                               m_placingMode_renderAt.x(),
                                               m_placingMode_renderAt.y()), 10, 10, FontManager::DefaultRaster);
        else
            FontManager::printText(fmt::format_ne("{0}", PGE_MusPlayer::getTitle()), 10, 10, FontManager::DefaultRaster);
    }

renderBlack:
    {
        if(!m_fader.isNull())
            GlRenderer::renderRect(0.f,
                                   0.f,
                                   static_cast<float>(PGE_Window::Width),
                                   static_cast<float>(PGE_Window::Height),
                                   0.f, 0.f, 0.f,
                                   static_cast<float>(m_fader.fadeRatio()));
    }

    if(m_placingMode)
        drawPlacingItem();
    if(m_loaderIsWorks)
        drawLoader();
    if(m_isPauseMenu)
        m_pauseMenu.render();
    // Flip the syncronious blinker flag
    m_blinkStateFlag = !m_blinkStateFlag;
}
Пример #4
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();
}
Пример #5
0
void PGE_LevelCamera::update(float ticks)
{
    objects_to_render.clear();

    if(!cur_section) return;
    fader.tickFader(ticks);

    if(isAutoscroll) processAutoscroll(ticks);

    LvlSceneP::s->queryItems(posRect, &objects_to_render);

    int contacts = 0;
    for(int i=0; i<objects_to_render.size();i++)
    {
        contacts++;
        PGE_Phys_Object * visibleBody = objects_to_render[i];
        bool renderable=false;
        if(!visibleBody->isVisible())
        {
            objects_to_render.removeAt(i); i--; continue;
        }
        switch(visibleBody->type)
        {
            case PGE_Phys_Object::LVLBlock:
            case PGE_Phys_Object::LVLBGO:
            case PGE_Phys_Object::LVLNPC:
            case PGE_Phys_Object::LVLPlayer:
            case PGE_Phys_Object::LVLEffect:
                renderable=true;
        }

        if(visibleBody->type==PGE_Phys_Object::LVLNPC)
        {
            LVL_Npc *npc = dynamic_cast<LVL_Npc*>(visibleBody);
            if(npc && npc->isVisible())
            {
                if(!npc->isActivated && !npc->wasDeactivated)
                {
                    npc->Activate();
                    LvlSceneP::s->active_npcs.push_back(npc);
                }
                else
                {
                    if(npc->wasDeactivated)
                        npc->activationTimeout=0;
                    else
                    {
                        if(npc->is_activity)
                            npc->activationTimeout = npc->setup->deactivetionDelay;
                        else
                            npc->activationTimeout = 150;
                    }
                }
            }
        }

        if(!PGE_Window::showPhysicsDebug && !renderable)
        {
            objects_to_render.removeAt(i); i--;
        }
    }

    //Sort array
    sortElements();
}