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; }
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(); }
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(); }