void Character2D::Update(float timeStep) { // Handle wounded/killed states if (killed_) return; if (wounded_) { HandleWoundedState(timeStep); return; } // Set temporary variables auto* input = GetSubsystem<Input>(); auto* body = GetComponent<RigidBody2D>(); auto* animatedSprite = GetComponent<AnimatedSprite2D>(); bool onGround = false; bool jump = false; // Collision detection (AABB query) Vector2 characterHalfSize = Vector2(0.16f, 0.16f); auto* physicsWorld = GetScene()->GetComponent<PhysicsWorld2D>(); PODVector<RigidBody2D*> collidingBodies; physicsWorld->GetRigidBodies(collidingBodies, Rect(node_->GetWorldPosition2D() - characterHalfSize - Vector2(0.0f, 0.1f), node_->GetWorldPosition2D() + characterHalfSize)); if (collidingBodies.Size() > 1 && !isClimbing_) onGround = true; // Set direction Vector2 moveDir = Vector2::ZERO; // Reset if (input->GetKeyDown(KEY_A) || input->GetKeyDown(KEY_LEFT)) { moveDir = moveDir + Vector2::LEFT; animatedSprite->SetFlipX(false); // Flip sprite (reset to default play on the X axis) } if (input->GetKeyDown(KEY_D) || input->GetKeyDown(KEY_RIGHT)) { moveDir = moveDir + Vector2::RIGHT; animatedSprite->SetFlipX(true); // Flip sprite (flip animation on the X axis) } // Jump if ((onGround || aboveClimbable_) && (input->GetKeyPress(KEY_W) || input->GetKeyPress(KEY_UP))) jump = true; // Climb if (isClimbing_) { if (!aboveClimbable_ && (input->GetKeyDown(KEY_UP) || input->GetKeyDown(KEY_W))) moveDir = moveDir + Vector2(0.0f, 1.0f); if (input->GetKeyDown(KEY_DOWN) || input->GetKeyDown(KEY_S)) moveDir = moveDir + Vector2(0.0f, -1.0f); } // Move if (!moveDir.Equals(Vector2::ZERO) || jump) { if (onSlope_) body->ApplyForceToCenter(moveDir * MOVE_SPEED / 2, true); // When climbing a slope, apply force (todo: replace by setting linear velocity to zero when will work) else node_->Translate(Vector3(moveDir.x_, moveDir.y_, 0) * timeStep * 1.8f); if (jump) body->ApplyLinearImpulse(Vector2(0.0f, 0.17f) * MOVE_SPEED, body->GetMassCenter(), true); } // Animate if (input->GetKeyDown(KEY_SPACE)) { if (animatedSprite->GetAnimation() != "attack") { animatedSprite->SetAnimation("attack", LM_FORCE_LOOPED); animatedSprite->SetSpeed(1.5f); } } else if (!moveDir.Equals(Vector2::ZERO)) { if (animatedSprite->GetAnimation() != "run") animatedSprite->SetAnimation("run"); } else if (animatedSprite->GetAnimation() != "idle") { animatedSprite->SetAnimation("idle"); } }