added double jump and sitting state
This commit is contained in:
parent
2e5c5a8dde
commit
90d07dde3f
148 changed files with 13050 additions and 0 deletions
64
term2/seminar03_state/src/animation.hpp
Normal file
64
term2/seminar03_state/src/animation.hpp
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
#pragma once
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include <iostream>
|
||||
using std::cout, std::endl;
|
||||
|
||||
|
||||
class Animation
|
||||
{
|
||||
public:
|
||||
enum class AnimationType {Repeat, OneIteration};
|
||||
|
||||
Animation(AnimationType type = AnimationType::Repeat) : mType{type}
|
||||
{
|
||||
}
|
||||
|
||||
void addTextureRect(sf::IntRect rect)
|
||||
{
|
||||
mTextureRects.push_back(rect);
|
||||
}
|
||||
|
||||
void setAnimationSpeed(float animationSpeed)
|
||||
{
|
||||
mAnimationSpeed = animationSpeed;
|
||||
}
|
||||
|
||||
sf::Vector2i getSize()
|
||||
{
|
||||
return {mTextureRects[mCurrentFrame].width, mTextureRects[mCurrentFrame].height};
|
||||
}
|
||||
|
||||
void update(float dt)
|
||||
{
|
||||
mTime += dt;
|
||||
mCurrentFrame = static_cast<int>(mAnimationSpeed * mTime);
|
||||
|
||||
if (mCurrentFrame >= mTextureRects.size())
|
||||
{
|
||||
if (mType == AnimationType::Repeat)
|
||||
{
|
||||
mCurrentFrame = 0;
|
||||
mTime = 0;
|
||||
}
|
||||
else if (mType == AnimationType::OneIteration)
|
||||
{
|
||||
mCurrentFrame = mTextureRects.size() - 1;
|
||||
mTime = mCurrentFrame / mAnimationSpeed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void updateSprite(sf::Sprite& sprite) const
|
||||
{
|
||||
sprite.setTextureRect(mTextureRects[mCurrentFrame]);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::vector<sf::IntRect> mTextureRects {};
|
||||
|
||||
int mCurrentFrame {0};
|
||||
float mAnimationSpeed {1};
|
||||
float mTime {0};
|
||||
AnimationType mType {AnimationType::OneIteration};
|
||||
};
|
||||
BIN
term2/seminar03_state/src/hero.png
Normal file
BIN
term2/seminar03_state/src/hero.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 66 KiB |
62
term2/seminar03_state/src/main.cpp
Normal file
62
term2/seminar03_state/src/main.cpp
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
#include <SFML/Window.hpp>
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include "world.hpp"
|
||||
|
||||
|
||||
/*
|
||||
Для компиляции:
|
||||
g++ main.cpp player.cpp player_states.cpp -lsfml-window -lsfml-system -lsfml-graphics
|
||||
|
||||
Графика взята отсюда:
|
||||
https://rvros.itch.io/animated-pixel-hero
|
||||
*/
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
sf::ContextSettings settings;
|
||||
settings.antialiasingLevel = 8.0;
|
||||
sf::RenderWindow window(sf::VideoMode(1200, 900), "Player states", sf::Style::Close, settings);
|
||||
window.setVerticalSyncEnabled(true);
|
||||
window.setFramerateLimit(60);
|
||||
|
||||
double time = 0;
|
||||
double dt = 1.0 / 60;
|
||||
|
||||
World world;
|
||||
world.addBlock({-500, 770, 20000, 400});
|
||||
world.addBlock({-400, 100, 700, 300});
|
||||
world.addBlock({600, 500, 300, 120});
|
||||
world.addBlock({800, 0, 400, 200});
|
||||
world.addBlock({-100, -700, 400, 100});
|
||||
world.addBlock({700, -700, 400, 100});
|
||||
world.addBlock({1500, -700, 400, 100});
|
||||
world.addBlock({1100, -300, 400, 100});
|
||||
world.addBlock({1100, 400, 400, 400});
|
||||
world.addBlock({1900, -100, 200, 800});
|
||||
world.addBlock({3000, 500, 1000, 200});
|
||||
|
||||
while (window.isOpen())
|
||||
{
|
||||
sf::Event event;
|
||||
while(window.pollEvent(event))
|
||||
{
|
||||
if(event.type == sf::Event::Closed)
|
||||
window.close();
|
||||
|
||||
world.handleEvents(event);
|
||||
}
|
||||
window.clear(sf::Color::Black);
|
||||
world.update(dt);
|
||||
world.draw(window);
|
||||
|
||||
window.display();
|
||||
|
||||
time += dt;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
153
term2/seminar03_state/src/player.cpp
Normal file
153
term2/seminar03_state/src/player.cpp
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
#include <SFML/Window.hpp>
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include "player.hpp"
|
||||
#include "player_states.hpp"
|
||||
|
||||
|
||||
|
||||
Player::Player(sf::Vector2f position) : mPosition{position}
|
||||
{
|
||||
if (!mTexture.loadFromFile("./hero.png"))
|
||||
{
|
||||
std::cerr << "Can't load image ./hero.png for Player class" << std::endl;
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
setState(new Idle(this));
|
||||
|
||||
mSprite.setTexture(mTexture);
|
||||
mSprite.setOrigin(mSprite.getLocalBounds().width / 2, mSprite.getLocalBounds().height / 2);
|
||||
mSprite.setPosition(mPosition);
|
||||
|
||||
|
||||
mScaleFactor = 4;
|
||||
mSprite.setScale(mScaleFactor, mScaleFactor);
|
||||
}
|
||||
|
||||
void Player::setState(PlayerState* pNewState)
|
||||
{
|
||||
delete mpState;
|
||||
mpState = pNewState;
|
||||
}
|
||||
|
||||
|
||||
sf::Vector2f Player::getCenter() const
|
||||
{
|
||||
return mPosition;
|
||||
}
|
||||
|
||||
|
||||
void Player::applyVelocity(sf::Vector2f velocity)
|
||||
{
|
||||
mVelocity += velocity;
|
||||
}
|
||||
|
||||
void Player::update(float dt)
|
||||
{
|
||||
mpState->update(this, dt);
|
||||
mPosition += mVelocity * dt;
|
||||
|
||||
mSprite.setOrigin(mSprite.getLocalBounds().width / 2, mSprite.getLocalBounds().height / 2);
|
||||
mSprite.setPosition(mPosition);
|
||||
mpState->updateSprite(mSprite, mIsFacedRight, mScaleFactor);
|
||||
}
|
||||
|
||||
void Player::draw(sf::RenderWindow& window)
|
||||
{
|
||||
window.draw(mSprite);
|
||||
|
||||
if (false) // For debuging
|
||||
{
|
||||
sf::RectangleShape shape {{mCollisionRect.width, mCollisionRect.height}};
|
||||
shape.setPosition(mPosition.x + mCollisionRect.left, mPosition.y + mCollisionRect.top);
|
||||
shape.setFillColor(sf::Color(150, 50, 50, 50));
|
||||
window.draw(shape);
|
||||
|
||||
sf::CircleShape center {6};
|
||||
center.setFillColor(sf::Color::Red);
|
||||
center.setOrigin(center.getRadius(), center.getRadius());
|
||||
center.setPosition(mPosition);
|
||||
window.draw(center);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Player::handleEvents(const sf::Event& event)
|
||||
{
|
||||
mpState->handleEvents(this, event);
|
||||
}
|
||||
|
||||
bool Player::handleCollision(const sf::FloatRect& rect)
|
||||
{
|
||||
sf::FloatRect playerRect = {mPosition.x + mCollisionRect.left, mPosition.y + mCollisionRect.top, mCollisionRect.width, mCollisionRect.height};
|
||||
|
||||
float overlapx1 = playerRect.left + playerRect.width - rect.left;
|
||||
float overlapx2 = rect.left + rect.width - playerRect.left;
|
||||
float overlapy1 = playerRect.top + playerRect.height - rect.top;
|
||||
float overlapy2 = rect.top + rect.height - playerRect.top;
|
||||
|
||||
if (overlapx1 < 0 || overlapx2 < 0 || overlapy1 < 0 || overlapy2 < 0)
|
||||
return false;
|
||||
|
||||
|
||||
int minOverlapDirection = 0;
|
||||
float minOvelap = overlapx1;
|
||||
if (overlapx2 < minOvelap) {minOverlapDirection = 1; minOvelap = overlapx2;}
|
||||
if (overlapy1 < minOvelap) {minOverlapDirection = 2; minOvelap = overlapy1;}
|
||||
if (overlapy2 < minOvelap) {minOverlapDirection = 3;}
|
||||
|
||||
switch (minOverlapDirection)
|
||||
{
|
||||
case 0:
|
||||
mPosition.x -= overlapx1 - 1;
|
||||
if (mVelocity.y > 0 && playerRect.top < rect.top + Hooked::kMaxHookOffset && playerRect.top > rect.top - Hooked::kMaxHookOffset)
|
||||
{
|
||||
mpState->hook(this);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
mPosition.x += overlapx2 - 1;
|
||||
if (mVelocity.y > 0 && playerRect.top < rect.top + Hooked::kMaxHookOffset && playerRect.top > rect.top - Hooked::kMaxHookOffset)
|
||||
{
|
||||
mpState->hook(this);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
mPosition.y -= overlapy1 - 1;
|
||||
mVelocity.y = 0;
|
||||
mVelocity.y = 0;
|
||||
mpState->hitGround(this);
|
||||
break;
|
||||
case 3:
|
||||
mPosition.y += overlapy2 - 1;
|
||||
if (mVelocity.y < 0)
|
||||
{
|
||||
mVelocity.y = 0;
|
||||
mVelocity.y = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Player::handleAllCollisions(const std::vector<sf::FloatRect>& blocks)
|
||||
{
|
||||
mIsColliding = false;
|
||||
|
||||
for (const sf::FloatRect& block : blocks)
|
||||
{
|
||||
if (handleCollision(block))
|
||||
mIsColliding = true;
|
||||
}
|
||||
|
||||
if (!mIsColliding)
|
||||
mpState->startFalling(this);
|
||||
}
|
||||
|
||||
|
||||
Player::~Player()
|
||||
{
|
||||
delete mpState;
|
||||
}
|
||||
51
term2/seminar03_state/src/player.hpp
Normal file
51
term2/seminar03_state/src/player.hpp
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
#pragma once
|
||||
|
||||
#include <SFML/Window.hpp>
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include "player_states.hpp"
|
||||
|
||||
class PlayerState;
|
||||
|
||||
class Player
|
||||
{
|
||||
public:
|
||||
|
||||
Player(sf::Vector2f position);
|
||||
|
||||
sf::Vector2f getCenter() const;
|
||||
void applyVelocity(sf::Vector2f velocity);
|
||||
|
||||
void update(float dt);
|
||||
void draw(sf::RenderWindow& window);
|
||||
void handleEvents(const sf::Event& event);
|
||||
bool handleCollision(const sf::FloatRect& rect);
|
||||
void handleAllCollisions(const std::vector<sf::FloatRect>& blocks);
|
||||
|
||||
~Player();
|
||||
|
||||
friend class PlayerState;
|
||||
friend class Idle;
|
||||
friend class Running;
|
||||
friend class Falling;
|
||||
friend class Sliding;
|
||||
friend class Hooked;
|
||||
friend class Sitting;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
sf::Vector2f mPosition {0, 0};
|
||||
sf::Vector2f mVelocity {0, 0};
|
||||
|
||||
bool mIsColliding {false};
|
||||
sf::FloatRect mCollisionRect {-40, -60, 80, 120};
|
||||
|
||||
PlayerState* mpState {nullptr};
|
||||
sf::Texture mTexture {};
|
||||
sf::Sprite mSprite {};
|
||||
float mScaleFactor {1};
|
||||
bool mIsFacedRight {true};
|
||||
|
||||
|
||||
void setState(PlayerState* pNewState);
|
||||
};
|
||||
425
term2/seminar03_state/src/player_states.cpp
Normal file
425
term2/seminar03_state/src/player_states.cpp
Normal file
|
|
@ -0,0 +1,425 @@
|
|||
#include <SFML/Window.hpp>
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include "animation.hpp"
|
||||
#include "player.hpp"
|
||||
#include "player_states.hpp"
|
||||
|
||||
using std::cout, std::endl;
|
||||
|
||||
PlayerState::PlayerState()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void PlayerState::updateSprite(sf::Sprite& sprite, bool isFacedRight, float scaleFactor)
|
||||
{
|
||||
mAnimation.updateSprite(sprite);
|
||||
|
||||
if (!isFacedRight)
|
||||
{
|
||||
sprite.setScale({-scaleFactor, scaleFactor});
|
||||
}
|
||||
else
|
||||
{
|
||||
sprite.setScale({scaleFactor, scaleFactor});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PlayerState::jump(Player* player)
|
||||
{
|
||||
player->mPosition.y -= 1;
|
||||
player->mVelocity.y = -kJumpingVelocity;
|
||||
startFalling(player);
|
||||
}
|
||||
|
||||
PlayerState::~PlayerState()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
sf::FloatRect operator*(float x, sf::FloatRect rect)
|
||||
{
|
||||
return {x * rect.left, x * rect.top, x * rect.width, x * rect.height};
|
||||
}
|
||||
|
||||
|
||||
|
||||
Idle::Idle(Player* player)
|
||||
{
|
||||
player->mVelocity = {0, 0};
|
||||
mAnimation = Animation();
|
||||
mAnimation.setAnimationSpeed(6);
|
||||
mAnimation.addTextureRect({ 14, 6, 21, 30});
|
||||
mAnimation.addTextureRect({ 64, 6, 21, 30});
|
||||
mAnimation.addTextureRect({114, 6, 21, 30});
|
||||
mAnimation.addTextureRect({164, 6, 21, 30});
|
||||
|
||||
player->mCollisionRect = player->mScaleFactor * sf::FloatRect(-10, -15, 20, 30);
|
||||
|
||||
cout << "Creating Idle state" << endl;
|
||||
}
|
||||
|
||||
|
||||
void Idle::hook(Player* player)
|
||||
{
|
||||
}
|
||||
|
||||
void Idle::update(Player* player, float dt)
|
||||
{
|
||||
mAnimation.update(dt);
|
||||
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left) || sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
|
||||
{
|
||||
player->setState(new Running(player));
|
||||
}
|
||||
}
|
||||
|
||||
void Idle::handleEvents(Player* player, const sf::Event& event)
|
||||
{
|
||||
if (event.type == sf::Event::KeyPressed)
|
||||
{
|
||||
if (event.key.code == sf::Keyboard::Left || event.key.code == sf::Keyboard::Right)
|
||||
{
|
||||
player->setState(new Running(player));
|
||||
}
|
||||
|
||||
else if (event.key.code == sf::Keyboard::Space)
|
||||
{
|
||||
jump(player);
|
||||
}
|
||||
else if (event.key.code == sf::Keyboard::LShift)
|
||||
{
|
||||
player->mVelocity.x = player->mIsFacedRight ? -100 : 100;
|
||||
player->setState(new Sitting(player));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Idle::startFalling(Player* player)
|
||||
{
|
||||
player->setState(new Falling(player));
|
||||
}
|
||||
|
||||
void Idle::hitGround(Player* player)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Running::Running(Player* player) : PlayerState()
|
||||
{
|
||||
mRunningSpeed = 900;
|
||||
mAnimation = Animation();
|
||||
mAnimation.setAnimationSpeed(12);
|
||||
mAnimation.addTextureRect({ 67, 45, 20, 27});
|
||||
mAnimation.addTextureRect({116, 46, 20, 27});
|
||||
mAnimation.addTextureRect({166, 48, 20, 27});
|
||||
mAnimation.addTextureRect({217, 45, 20, 27});
|
||||
mAnimation.addTextureRect({266, 46, 20, 27});
|
||||
mAnimation.addTextureRect({316, 48, 20, 27});
|
||||
|
||||
player->mCollisionRect = player->mScaleFactor * sf::FloatRect(-10, -15, 20, 30);;
|
||||
|
||||
cout << "Creating Running state" << endl;
|
||||
}
|
||||
|
||||
void Running::hook(Player* player)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void Running::update(Player* player, float dt)
|
||||
{
|
||||
mAnimation.update(dt);
|
||||
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
|
||||
{
|
||||
player->mVelocity.x = -mRunningSpeed;
|
||||
player->mIsFacedRight = false;
|
||||
}
|
||||
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
|
||||
{
|
||||
player->mVelocity.x = mRunningSpeed;
|
||||
player->mIsFacedRight = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Running::handleEvents(Player* player, const sf::Event& event)
|
||||
{
|
||||
if (event.type == sf::Event::KeyPressed)
|
||||
{
|
||||
if (event.key.code == sf::Keyboard::Space)
|
||||
{
|
||||
jump(player);
|
||||
return;
|
||||
}
|
||||
|
||||
else if (event.key.code == sf::Keyboard::LShift)
|
||||
{
|
||||
player->setState(new Sliding(player));
|
||||
}
|
||||
|
||||
}
|
||||
else if (event.type == sf::Event::KeyReleased)
|
||||
{
|
||||
if (event.key.code == sf::Keyboard::Left && !sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
|
||||
{
|
||||
player->setState(new Idle(player));
|
||||
player->mVelocity.x = 0;
|
||||
}
|
||||
|
||||
else if (event.key.code == sf::Keyboard::Right && !sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
|
||||
{
|
||||
player->setState(new Idle(player));
|
||||
player->mVelocity.x = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Running::startFalling(Player* player)
|
||||
{
|
||||
player->setState(new Falling(player));
|
||||
}
|
||||
|
||||
void Running::hitGround(Player* player)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Sliding::Sliding(Player* player) : PlayerState()
|
||||
{
|
||||
if (player->mVelocity.x > 0)
|
||||
player->mVelocity.x = kSlidingVelocity;
|
||||
else if (player->mVelocity.x < 0)
|
||||
player->mVelocity.x = -kSlidingVelocity;
|
||||
|
||||
mAnimation = Animation(Animation::AnimationType::OneIteration);
|
||||
mAnimation.setAnimationSpeed(10);
|
||||
mAnimation.addTextureRect({155, 119, 34, 28});
|
||||
mAnimation.addTextureRect({205, 119, 34, 28});
|
||||
mAnimation.addTextureRect({255, 119, 34, 28});
|
||||
mAnimation.addTextureRect({307, 119, 34, 28});
|
||||
mAnimation.addTextureRect({ 9, 156, 34, 28});
|
||||
|
||||
player->mCollisionRect = sf::FloatRect(-80, -20, 160, 80);
|
||||
player->mCollisionRect = player->mScaleFactor * sf::FloatRect(-20, -5, 40, 20);;
|
||||
mCurrentTime = kSlidingTime;
|
||||
|
||||
cout << "Creating Sliding state" << endl;
|
||||
}
|
||||
|
||||
void Sliding::hook(Player* player)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void Sliding::update(Player* player, float dt)
|
||||
{
|
||||
mAnimation.update(dt);
|
||||
player->mVelocity.x *= kVelocityDecay;
|
||||
mCurrentTime -= dt;
|
||||
if (mCurrentTime < 0 && player->mIsColliding)
|
||||
{
|
||||
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left) || sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
|
||||
player->setState(new Running(player));
|
||||
else
|
||||
player->setState(new Idle(player));
|
||||
return;
|
||||
}
|
||||
}
|
||||
void Sliding::handleEvents(Player* player, const sf::Event& event)
|
||||
{
|
||||
if (event.type == sf::Event::KeyPressed)
|
||||
{
|
||||
if (event.key.code == sf::Keyboard::Left || event.key.code == sf::Keyboard::Right)
|
||||
player->setState(new Running(player));
|
||||
|
||||
|
||||
if (event.key.code == sf::Keyboard::Space && player->mIsColliding)
|
||||
{
|
||||
jump(player);
|
||||
player->setState(new Falling(player));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Sliding::startFalling(Player* player)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Sliding::hitGround(Player* player)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Falling::Falling(Player* player) : PlayerState()
|
||||
{
|
||||
mAnimation = Animation();
|
||||
mAnimation.setAnimationSpeed(12);
|
||||
mAnimation.addTextureRect({321, 155, 15, 26});
|
||||
|
||||
player->mCollisionRect = player->mScaleFactor * sf::FloatRect(-10, -15, 20, 30);;
|
||||
|
||||
cout << "Creating Falling state" << endl;
|
||||
}
|
||||
|
||||
void Falling::hook(Player* player)
|
||||
{
|
||||
player->setState(new Hooked(player));
|
||||
}
|
||||
|
||||
|
||||
void Falling::update(Player* player, float dt)
|
||||
{
|
||||
mAnimation.update(dt);
|
||||
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
|
||||
{
|
||||
player->mVelocity.x = -kHorizontalVelocity;
|
||||
player->mIsFacedRight = false;
|
||||
}
|
||||
|
||||
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
|
||||
{
|
||||
player->mVelocity.x = kHorizontalVelocity;
|
||||
player->mIsFacedRight = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Falling::handleEvents(Player* player, const sf::Event& event)
|
||||
{
|
||||
if (event.type == sf::Event::KeyPressed)
|
||||
{
|
||||
if (event.key.code == sf::Keyboard::Space && !hasJumped) {
|
||||
kJumpingVelocity = 1000;
|
||||
jump(player);
|
||||
hasJumped = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Falling::startFalling(Player* player)
|
||||
{
|
||||
}
|
||||
|
||||
void Falling::hitGround(Player* player)
|
||||
{
|
||||
player->setState(new Idle(player));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Hooked::Hooked(Player* player) : PlayerState()
|
||||
{
|
||||
mAnimation = Animation(Animation::AnimationType::OneIteration);
|
||||
mAnimation.setAnimationSpeed(12);
|
||||
mAnimation.addTextureRect({ 70, 151, 16, 34});
|
||||
mAnimation.addTextureRect({119, 151, 16, 34});
|
||||
mAnimation.addTextureRect({169, 151, 16, 34});
|
||||
mAnimation.addTextureRect({219, 151, 16, 34});
|
||||
|
||||
player->mCollisionRect = player->mScaleFactor * sf::FloatRect(-10, -15, 20, 30);;
|
||||
|
||||
cout << "Creating Hooked state" << endl;
|
||||
}
|
||||
|
||||
void Hooked::hook(Player* player)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void Hooked::update(Player* player, float dt)
|
||||
{
|
||||
player->mVelocity = {0, 0};
|
||||
mAnimation.update(dt);
|
||||
}
|
||||
|
||||
void Hooked::handleEvents(Player* player, const sf::Event& event)
|
||||
{
|
||||
if (event.type == sf::Event::KeyPressed)
|
||||
{
|
||||
if (event.key.code == sf::Keyboard::Space)
|
||||
jump(player);
|
||||
|
||||
else if (event.key.code == sf::Keyboard::Down)
|
||||
{
|
||||
player->mVelocity.x = player->mIsFacedRight ? -100 : 100;
|
||||
player->setState(new Falling(player));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Hooked::startFalling(Player* player)
|
||||
{
|
||||
player->setState(new Falling(player));
|
||||
}
|
||||
|
||||
void Hooked::hitGround(Player* player)
|
||||
{
|
||||
player->setState(new Idle(player));
|
||||
}
|
||||
|
||||
|
||||
/* Sitting */
|
||||
Sitting::Sitting(Player* player) : PlayerState()
|
||||
{
|
||||
// mAnimation = Animation(Animation::AnimationType::OneIteration);
|
||||
|
||||
mAnimation = Animation();
|
||||
mAnimation.setAnimationSpeed(4);
|
||||
|
||||
mAnimation.addTextureRect({168, 340, 18, 30});
|
||||
mAnimation.addTextureRect({219, 340, 18, 30});
|
||||
mAnimation.addTextureRect({267, 340, 18, 30});
|
||||
|
||||
// player->mCollisionRect = player->mScaleFactor * sf::FloatRect(-20, -20, 20, 40);;
|
||||
player->mCollisionRect = sf::FloatRect(-80, -10, 160, 80);
|
||||
player->mCollisionRect = player->mScaleFactor * sf::FloatRect(-20, -5, 40, 20);;
|
||||
cout << "Creating Sitting state" << endl;
|
||||
}
|
||||
|
||||
void Sitting::update(Player* player, float dt)
|
||||
{
|
||||
player->mVelocity = {0, 0};
|
||||
mAnimation.update(dt);
|
||||
}
|
||||
|
||||
void Sitting::handleEvents(Player* player, const sf::Event& event)
|
||||
{
|
||||
if (event.type == sf::Event::KeyPressed)
|
||||
{
|
||||
if (event.key.code == sf::Keyboard::LShift)
|
||||
{
|
||||
player->mVelocity.x = player->mIsFacedRight ? -100 : 100;
|
||||
player->setState(new Idle(player));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Sitting::hook(Player* player) {}
|
||||
|
||||
void Sitting::startFalling(Player* player) {}
|
||||
|
||||
void Sitting::hitGround(Player* player) {}
|
||||
125
term2/seminar03_state/src/player_states.hpp
Normal file
125
term2/seminar03_state/src/player_states.hpp
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
#pragma once
|
||||
|
||||
#include <SFML/Window.hpp>
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include "animation.hpp"
|
||||
#include "player.hpp"
|
||||
|
||||
class Player;
|
||||
|
||||
class PlayerState
|
||||
{
|
||||
public:
|
||||
PlayerState();
|
||||
|
||||
virtual void update(Player* player, float dt) = 0;
|
||||
virtual void handleEvents(Player* player, const sf::Event& event) = 0;
|
||||
virtual void hook(Player* player) = 0;
|
||||
virtual void startFalling(Player* player) = 0;
|
||||
virtual void hitGround(Player* player) = 0;
|
||||
virtual ~PlayerState();
|
||||
|
||||
void updateSprite(sf::Sprite& sprite, bool isFacedRight, float scaleFactor);
|
||||
|
||||
protected:
|
||||
Animation mAnimation;
|
||||
|
||||
float kJumpingVelocity = 1500;
|
||||
|
||||
void jump(Player* player);
|
||||
};
|
||||
|
||||
|
||||
class Idle : public PlayerState
|
||||
{
|
||||
public:
|
||||
Idle(Player* player);
|
||||
|
||||
void update(Player* player, float dt);
|
||||
void handleEvents(Player* player, const sf::Event& event);
|
||||
void hook(Player* player);
|
||||
void startFalling(Player* player);
|
||||
void hitGround(Player* player);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
class Running : public PlayerState
|
||||
{
|
||||
public:
|
||||
Running(Player* player);
|
||||
void update(Player* player, float dt);
|
||||
void handleEvents(Player* player, const sf::Event& event);
|
||||
void hook(Player* player);
|
||||
void startFalling(Player* player);
|
||||
void hitGround(Player* player);
|
||||
|
||||
private:
|
||||
float mRunningSpeed;
|
||||
};
|
||||
|
||||
|
||||
class Sliding : public PlayerState
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
Sliding(Player* player);
|
||||
void update(Player* player, float dt);
|
||||
void handleEvents(Player* player, const sf::Event& event);
|
||||
void hook(Player* player);
|
||||
void startFalling(Player* player);
|
||||
void hitGround(Player* player);
|
||||
|
||||
private:
|
||||
|
||||
float mCurrentTime;
|
||||
static constexpr float kSlidingTime = 0.50;
|
||||
static constexpr float kSlidingVelocity = 2000;
|
||||
static constexpr float kVelocityDecay = 0.99;
|
||||
};
|
||||
|
||||
|
||||
class Falling : public PlayerState
|
||||
{
|
||||
public:
|
||||
Falling(Player* player);
|
||||
void update(Player* player, float dt);
|
||||
void handleEvents(Player* player, const sf::Event& event);
|
||||
void hook(Player* player);
|
||||
void startFalling(Player* player);
|
||||
void hitGround(Player* player);
|
||||
|
||||
private:
|
||||
bool hasJumped = false;
|
||||
static constexpr float kHorizontalVelocity = 800;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class Hooked : public PlayerState
|
||||
{
|
||||
public:
|
||||
|
||||
static constexpr float kMaxHookOffset = 15;
|
||||
|
||||
Hooked(Player* player);
|
||||
void update(Player* player, float dt);
|
||||
void handleEvents(Player* player, const sf::Event& event);
|
||||
void hook(Player* player);
|
||||
void startFalling(Player* player);
|
||||
void hitGround(Player* player);
|
||||
};
|
||||
|
||||
|
||||
class Sitting : public PlayerState
|
||||
{
|
||||
public:
|
||||
Sitting(Player* player);
|
||||
void update(Player* player, float dt);
|
||||
void handleEvents(Player* player, const sf::Event& event);
|
||||
void hook(Player* player);
|
||||
void startFalling(Player* player);
|
||||
void hitGround(Player* player);
|
||||
};
|
||||
78
term2/seminar03_state/src/world.hpp
Normal file
78
term2/seminar03_state/src/world.hpp
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
#pragma once
|
||||
|
||||
#include <SFML/Window.hpp>
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include "player.hpp"
|
||||
#include "player_states.hpp"
|
||||
|
||||
|
||||
|
||||
|
||||
class World
|
||||
{
|
||||
public:
|
||||
|
||||
void addBlock(sf::FloatRect block)
|
||||
{
|
||||
mBlocks.push_back(block);
|
||||
}
|
||||
|
||||
void setView()
|
||||
{
|
||||
sf::Vector2f playerCenter = mPlayer.getCenter();
|
||||
float mViewRatio = 0.6;
|
||||
if (playerCenter.x > mView.getCenter().x + mViewRatio * mView.getSize().x / 2)
|
||||
mView.move({playerCenter.x - mView.getCenter().x - mViewRatio * mView.getSize().x / 2, 0});
|
||||
|
||||
else if (playerCenter.x < mView.getCenter().x - mViewRatio * mView.getSize().x / 2)
|
||||
mView.move({playerCenter.x - mView.getCenter().x + mViewRatio * mView.getSize().x / 2, 0});
|
||||
|
||||
|
||||
if (playerCenter.y > mView.getCenter().y + mViewRatio * mView.getSize().y / 2)
|
||||
mView.move({0, playerCenter.y - mView.getCenter().y - mViewRatio * mView.getSize().y / 2});
|
||||
|
||||
else if (playerCenter.y < mView.getCenter().y - mViewRatio * mView.getSize().y / 2)
|
||||
mView.move({0, playerCenter.y - mView.getCenter().y+ mViewRatio * mView.getSize().y / 2});
|
||||
|
||||
}
|
||||
|
||||
void update(float dt)
|
||||
{
|
||||
setView();
|
||||
mPlayer.applyVelocity({0, mGravity * dt});
|
||||
mPlayer.update(dt);
|
||||
mPlayer.handleAllCollisions(mBlocks);
|
||||
}
|
||||
|
||||
void draw(sf::RenderWindow& window)
|
||||
{
|
||||
static sf::RectangleShape blockShape;
|
||||
blockShape.setFillColor(sf::Color(58, 69, 55));
|
||||
|
||||
window.setView(mView);
|
||||
|
||||
for (const sf::FloatRect& b : mBlocks)
|
||||
{
|
||||
blockShape.setPosition(b.left, b.top);
|
||||
blockShape.setSize({b.width, b.height});
|
||||
window.draw(blockShape);
|
||||
}
|
||||
mPlayer.draw(window);
|
||||
}
|
||||
|
||||
void handleEvents(const sf::Event& event)
|
||||
{
|
||||
mPlayer.handleEvents(event);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private:
|
||||
std::vector<sf::FloatRect> mBlocks {};
|
||||
Player mPlayer {{400, 400}};
|
||||
float mGravity {3600};
|
||||
|
||||
sf::View mView {sf::FloatRect(0, 0, 1200, 900)};
|
||||
};
|
||||
Reference in a new issue