2d_patformer/player.cpp
2026-01-09 10:24:15 +00:00

140 lines
4.5 KiB
C++

#include "player.hpp"
#include <iostream>
using namespace std;
Player::Player()
: shape(sf::Vector2f(60.f, 60.f)),
speed(500.f),
velocityY(0.f),
jumpStrength(700.f),
onGround(true),
gravity(1500.f),
groundLevel(1040.f),
facingRight(true),
runFrames(),
idleFrame(),
sprite(),
currentFrame(0),
animationTimer(0.f),
animationSpeed(0.1f),
isMoving(false)
{
shape.setFillColor(sf::Color::Green);
shape.setPosition(50.f, groundLevel);
loadIdleFrame();
loadRunAnimation();
sprite.setTexture(idleFrame);
sprite.setOrigin(idleFrame.getSize().x / 2.f, idleFrame.getSize().y / 2.f);
float scaleX = shape.getSize().x / idleFrame.getSize().x;
float scaleY = shape.getSize().y / idleFrame.getSize().y;
// Початкове віддзеркалення: PNG дивиться вліво, потрібно вправо
sprite.setScale(-scaleX, scaleY);
sprite.setPosition(
shape.getPosition().x + shape.getSize().x / 2.f,
shape.getPosition().y + shape.getSize().y / 2.f
);
}
void Player::loadIdleFrame() {
if (!idleFrame.loadFromFile("img/FA_PENGUIN_Idle_000.png")) {
cout << "Cannot load idle frame\n";
}
}
void Player::loadRunAnimation() {
runFrames.clear();
for (size_t i = 0; i < 10; ++i) { // припустимо 10 кадрів
sf::Texture tex;
string filename = "img/04-Run/FA_PENGUIN_Run_00" + to_string(i) + ".png";
if (!tex.loadFromFile(filename)) {
cout << "Cannot load " << filename << "\n";
} else {
runFrames.push_back(tex);
}
}
}
void Player::update(float deltaTime, const std::vector<Platform>& platforms) {
float moveX = 0.f;
isMoving = false;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) {
moveX -= speed * deltaTime;
facingRight = false;
isMoving = true;
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) {
moveX += speed * deltaTime;
facingRight = true;
isMoving = true;
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W) && onGround)
velocityY = -jumpStrength;
velocityY += gravity * deltaTime;
shape.move(moveX, 0.f);
shape.move(0.f, velocityY * deltaTime);
// Земля
if (shape.getPosition().y + shape.getSize().y >= groundLevel) {
shape.setPosition(shape.getPosition().x, groundLevel - shape.getSize().y);
velocityY = 0.f;
onGround = true;
} else onGround = false;
// Колізії з платформами
for (const auto& platform : platforms) {
sf::FloatRect playerBounds = shape.getGlobalBounds();
sf::FloatRect platBounds = platform.getBounds();
if (playerBounds.intersects(platBounds)) {
if (playerBounds.top + playerBounds.height <= platBounds.top + 20.f) {
shape.setPosition(shape.getPosition().x, platBounds.top - shape.getSize().y);
velocityY = 0.f;
onGround = true;
} else if (playerBounds.top > platBounds.top) {
shape.setPosition(shape.getPosition().x, platBounds.top + platBounds.height);
velocityY = 0.f;
}
}
}
// Межі екрану
if (shape.getPosition().x < 0.f) shape.setPosition(0.f, shape.getPosition().y);
if (shape.getPosition().x + shape.getSize().x > 1925.f)
shape.setPosition(1925.f - shape.getSize().x, shape.getPosition().y);
// Анімація
animationTimer += deltaTime;
if (isMoving && !runFrames.empty()) {
if (animationTimer >= animationSpeed) {
animationTimer = 0.f;
currentFrame = (currentFrame + 1) % runFrames.size();
sprite.setTexture(runFrames[currentFrame]);
}
} else {
sprite.setTexture(idleFrame);
}
// Центруємо спрайт по хітбоксу
sprite.setOrigin(sprite.getTexture()->getSize().x / 2.f,
sprite.getTexture()->getSize().y / 2.f);
sprite.setPosition(shape.getPosition().x + shape.getSize().x / 2.f,
shape.getPosition().y + shape.getSize().y / 2.f);
float scaleX = shape.getSize().x / sprite.getTexture()->getSize().x;
float scaleY = shape.getSize().y / sprite.getTexture()->getSize().y;
// Віддзеркалення за напрямком погляду
sprite.setScale(facingRight ? -scaleX : scaleX, scaleY);
}
void Player::draw(sf::RenderWindow& window) {
window.draw(sprite);
}