void GameLogicComponent::ResetLevel() { MovementData movementData = { 1, { -15.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } }; m_movement.SetData( 1, movementData ); movementData.m_entityID = 2; movementData.m_position[0] = 15.0f; m_movement.SetData( 2, movementData ); movementData.m_entityID = 3; movementData.m_position[0] = 0.0f; std::uniform_real_distribution<> speedY ( -3.0f, 3.0f ); std::uniform_real_distribution<> speedX ( -2.0f, -4.0f ); movementData.m_speed = vec::Vector3{ speedX(m_rng), speedY(m_rng), 0.0 }; m_movement.SetData( 3, movementData ); }
void MoveableItem::step(double msecs) { qreal newX = speedX() * msecs/1000.0 + x(); qreal newY = speedY() * msecs/1000.0 + y(); setX(newX); setY(newY); }
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 LVL_Player::_collideUnduck() { _syncPosition(); if(isWarping) return; #ifdef COLLIDE_DEBUG qDebug() << "do unduck!"; #endif //Detect collidable blocks! QVector<PGE_Phys_Object*> bodies; PGE_RectF posRectC = posRect; posRectC.setTop(posRectC.top()-4.0f); posRectC.setLeft(posRectC.left()+1.0f); posRectC.setRight(posRectC.right()-1.0f); posRectC.setBottom(posRectC.bottom()+ (ducking ? 0.0:(-posRect.height()/2.0))+4.0 ); LvlSceneP::s->queryItems(posRectC, &bodies); forceCollideCenter=true; for(PGE_RenderList::iterator it=bodies.begin();it!=bodies.end(); it++ ) { PGE_Phys_Object*body=*it; if(body==this) continue; if(body->isPaused()) continue; if(!body->isVisible()) continue; solveCollision(body); } forceCollideCenter=false; #ifdef COLLIDE_DEBUG int hited=0; PGE_RectF nearestRect; #endif bool resolveTop=false; double _floorY=0; QVector<PGE_Phys_Object*> blocks_to_hit; if((!collided_center.isEmpty())&&(collided_bottom.isEmpty())) { for(PlayerColliders::iterator it=collided_center.begin(); it!=collided_center.end() ; it++) { PGE_Phys_Object *collided= *it; LVL_Block *blk= static_cast<LVL_Block*>(collided); if(blk) blocks_to_hit.push_back(blk); } for(PlayerColliders::iterator it=collided_top.begin(); it!=collided_top.end() ; it++) { PGE_Phys_Object *collided= *it; LVL_Block *blk= static_cast<LVL_Block*>(collided); if(blk) blocks_to_hit.push_back(blk); } if(isFloor(blocks_to_hit)) { PGE_Phys_Object*nearest = nearestBlockY(blocks_to_hit); if(nearest) { _floorY=nearest->posRect.bottom()+1.0; resolveTop=true; } } } if(resolveTop) { posRect.setY(_floorY); if(!blocks_to_hit.isEmpty()) { PGE_Phys_Object*nearest_obj=nearestBlock(blocks_to_hit); if(nearest_obj && (nearest_obj->type==PGE_Phys_Object::LVLBlock)) { LVL_Block*nearest = static_cast<LVL_Block*>(nearest_obj); resolveTop=true; long npcid=nearest->data.npc_id; nearest->hit(); if( nearest->setup->hitable || (npcid!=0) || (nearest->destroyed) || (nearest->setup->bounce) ) { bump(false, speedY()); } } else { PGE_Audio::playSoundByRole(obj_sound_role::BlockHit); } } setSpeedY(0.0); _syncPosition(); } _heightDelta = 0.0; #ifdef COLLIDE_DEBUG qDebug() << "unduck: blocks to hit"<< hited << " Nearest: "<<nearestRect.top() << nearestRect.bottom() << "are bottom empty: " << collided_bottom.isEmpty() << "bodies found: "<<bodies.size() << "bodies at center: "<<collided_center.size(); #endif }
void LVL_Player::updateCollisions() { foot_contacts_map.clear(); _onGround=false; foot_sl_contacts_map.clear(); contactedWarp = NULL; contactedWithWarp=false; climbable_map.clear(); environments_map.clear(); collided_top.clear(); collided_left.clear(); collided_right.clear(); collided_bottom.clear(); collided_center.clear(); collided_talkable_npc = NULL; collided_slope=false; collided_slope_direct=0; collided_slope_angle_ratio=0.0f; _velocityX_add=0; _velocityY_add=0; #ifdef COLLIDE_DEBUG qDebug() << "=====Collision check and resolve begin======"; #endif PGE_Phys_Object::updateCollisions(); bool resolveBottom=false; bool resolveTop=false; bool resolveLeft=false; bool resolveRight=false; double backupX=posRect.x(); double backupY=posRect.y(); double _wallX=posRect.x(); double _floorY=posRect.y(); double _floorX_vel=0.0;//velocities sum double _floorX_num=0.0;//num of velocities double _floorY_vel=0.0;//velocities sum double _floorY_num=0.0;//num of velocities QVector<PGE_Phys_Object*> floor_blocks; QVector<PGE_Phys_Object*> wall_blocks; QVector<PGE_Phys_Object*> blocks_to_hit; //QVector<PGE_Phys_Object*> add_speed_to; if(!collided_bottom.isEmpty()) { for(PlayerColliders::iterator it=collided_bottom.begin(); it!=collided_bottom.end() ; it++) { PGE_Phys_Object *collided= *it; switch(collided->type) { case PGE_Phys_Object::LVLBlock: { LVL_Block *blk= static_cast<LVL_Block*>(collided); if(!blk) continue; foot_contacts_map[(intptr_t)collided]=collided; if(blk->slippery_surface) foot_sl_contacts_map[(intptr_t)collided]=collided; if(blk->setup->bounce) blocks_to_hit.push_back(blk); floor_blocks.push_back(blk); _floorY_vel+=blk->speedYsum(); _floorY_num+=1.0; _floorX_vel+=blk->speedXsum(); _floorX_num+=1.0; } break; case PGE_Phys_Object::LVLNPC: { LVL_Npc *npc= static_cast<LVL_Npc*>(collided); if(!npc) continue; foot_contacts_map[(intptr_t)collided]=collided; if(npc->slippery_surface) foot_sl_contacts_map[(intptr_t)collided]=collided; floor_blocks.push_back(npc); _floorY_vel+=npc->speedYsum(); _floorY_num+=1.0; _floorX_vel+=npc->speedXsum(); _floorX_num+=1.0; } break; default:break; } } if(_floorX_num!=0.0) _floorX_vel=_floorX_vel/_floorX_num; if(_floorY_num!=0.0) _floorY_vel=_floorY_vel/_floorY_num; if(!foot_contacts_map.isEmpty()) { _velocityX_add=_floorX_vel; _velocityY_add=_floorY_vel; } if(isFloor(floor_blocks)) { PGE_Phys_Object*nearest = nearestBlockY(floor_blocks); if(nearest) { LVL_Block *blk= static_cast<LVL_Block*>(nearest); if(blk && (blk->shape!=LVL_Block::shape_rect)) { if(blk->shape==LVL_Block::shape_tr_top_right) { _floorY = nearest->posRect.bottom()-SL_HeightTopRight(nearest); if(_floorY<nearest->top()) _floorY=nearest->posRect.top(); else if(_floorY>nearest->bottom()) _floorY=nearest->posRect.bottom(); } else if(blk->shape==LVL_Block::shape_tr_top_left) { _floorY = nearest->posRect.bottom()-SL_HeightTopLeft(nearest); if(_floorY<nearest->top()) _floorY=nearest->posRect.top(); else if(_floorY>nearest->bottom()) _floorY=nearest->posRect.bottom(); } else if(blk->shape==LVL_Block::shape_tr_bottom_right) { _floorY = nearest->posRect.top()+SL_HeightTopRight(nearest); if(_floorY<nearest->top()) _floorY=nearest->posRect.top(); else if(_floorY>nearest->bottom()) _floorY=nearest->posRect.bottom(); } else if(blk->shape==LVL_Block::shape_tr_bottom_left) { _floorY = nearest->posRect.top()+SL_HeightTopLeft(nearest); if(_floorY<nearest->top()) _floorY=nearest->posRect.top(); else if(_floorY>nearest->bottom()) _floorY=nearest->posRect.bottom(); } else _floorY = nearest->posRect.top(); _floorY-=posRect.height(); } else { _floorY = nearest->posRect.top()-posRect.height(); } resolveBottom=true; } } else { foot_contacts_map.clear(); foot_sl_contacts_map.clear(); } } if(!collided_top.isEmpty()) { blocks_to_hit.clear(); for(PlayerColliders::iterator it=collided_top.begin(); it!=collided_top.end() ; it++) { PGE_Phys_Object *body= *it; if(body) blocks_to_hit.push_back(body); if(body) floor_blocks.push_back(body); } if(isFloor(floor_blocks)) { PGE_Phys_Object*nearest = nearestBlockY(blocks_to_hit); if(nearest) { if(!resolveBottom) { LVL_Block *blk= static_cast<LVL_Block*>(nearest); if(blk && (blk->shape!=LVL_Block::shape_rect)) { if(blk->shape==LVL_Block::shape_tr_bottom_right) { _floorY = nearest->posRect.top()+SL_HeightTopLeft(nearest); if(_floorY<nearest->top()) _floorY=nearest->posRect.top(); else if(_floorY>nearest->bottom()) _floorY=nearest->posRect.bottom(); } else if(blk->shape==LVL_Block::shape_tr_bottom_left) { _floorY = nearest->posRect.top()+SL_HeightTopRight(nearest); if(_floorY<nearest->top()) _floorY=nearest->posRect.top(); else if(_floorY>nearest->bottom()) _floorY=nearest->posRect.bottom(); } } else _floorY = nearest->posRect.bottom(); _floorY+=1; } resolveTop=true; } } } bool wall=false; if(!collided_left.isEmpty()) { for(PlayerColliders::iterator it=collided_left.begin(); it!=collided_left.end() ; it++) { PGE_Phys_Object *body= *it; if(body) wall_blocks.push_back(body); } if(isWall(wall_blocks)) { PGE_Phys_Object*nearest = nearestBlock(wall_blocks); if(nearest) { _wallX = nearest->posRect.right(); resolveLeft=true; wall=true; } } } if(!collided_right.isEmpty()) { wall_blocks.clear(); for(PlayerColliders::iterator it=collided_right.begin(); it!=collided_right.end() ; it++) { PGE_Phys_Object *body= *it; if(body) wall_blocks.push_back(body); } if(isWall(wall_blocks)) { PGE_Phys_Object*nearest = nearestBlock(wall_blocks); if(nearest) { _wallX = nearest->posRect.left()-posRect.width(); resolveRight=true; wall=true; } } } if((resolveLeft||resolveRight) && (resolveTop||resolveBottom)) { //check if on floor or in air bool _iswall=false; bool _isfloor=false; posRect.setX(_wallX); _isfloor=isFloor(floor_blocks); posRect.setPos(backupX, _floorY); _iswall=isWall(wall_blocks); posRect.setX(backupX); if(!_iswall && _isfloor) { resolveLeft=false; resolveRight=false; } if(!_isfloor && _iswall) { resolveTop=false; resolveBottom=false; } } if(resolveLeft || resolveRight) { posRect.setX(_wallX); setSpeedX(0); _velocityX_add=0; } if(resolveBottom || resolveTop) { posRect.setY(_floorY); float bumpSpeed=speedY(); setSpeedY(_floorY_vel); _velocityY_add=0; if(!blocks_to_hit.isEmpty()) { PGE_Phys_Object* nearestObj=nearestBlock(blocks_to_hit); if(nearestObj && (nearestObj->type==PGE_Phys_Object::LVLBlock)) { LVL_Block*nearest = static_cast<LVL_Block*>(nearestObj); long npcid=nearest->data.npc_id; if(resolveBottom) nearest->hit(LVL_Block::down); else nearest->hit(); if( nearest->setup->hitable || (npcid!=0) || (nearest->destroyed) || nearest->setup->bounce ) bump(resolveBottom, (resolveBottom ? physics_cur.velocity_jump_bounce : bumpSpeed), physics_cur.jump_time_bounce); } else { PGE_Audio::playSoundByRole(obj_sound_role::BlockHit); } } if(resolveTop && !bumpUp && !bumpDown ) jumpTime=0; } else { posRect.setY(backupY); } _stucked = ( (!collided_center.isEmpty()) && (!collided_bottom.isEmpty()) && (!wall) ); #ifdef COLLIDE_DEBUG qDebug() << "=====Collision check and resolve end======"; #endif }