碰撞的简单例子
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了碰撞的简单例子相关的知识,希望对你有一定的参考价值。
1. 注意m_offset的值大小,这个值会导致当Player卡在两个Object时跳跃失效的程度
2. 注意Player类中调用handleKeyPressed函数的位置,主要是为了取到Player移动的方向
3. Object类中lastTop等函数,主要是为了获取前一次的位置
4. 注意PlayState类中handleCollision函数,优先检测左右碰撞
1 #ifndef OBJECT_HPP 2 #define OBJECT_HPP 3 4 #include <SFML/Graphics/RectangleShape.hpp> 5 #include <SFML/Graphics/RenderTarget.hpp> 6 7 class Object : public sf::Drawable { 8 public: 9 Object() 10 : m_velocityX(0.f) 11 , m_velocityY(0.f) 12 , m_gravity(0.8f) 13 , m_lastTop(top()) 14 , m_lastBottom(bottom()) 15 , m_lastLeft(left()) 16 , m_lastRight(right()) 17 , m_offset(1.f) 18 { 19 m_object.setFillColor(sf::Color::Transparent); 20 m_object.setOutlineColor(sf::Color::Red); 21 m_object.setOutlineThickness(-2.f); 22 } 23 24 virtual ~Object() = default; 25 26 float top() { return m_object.getPosition().y; } 27 float bottom() { return m_object.getPosition().y + m_object.getSize().y; } 28 float left() { return m_object.getPosition().x; } 29 float right() { return m_object.getPosition().x + m_object.getSize().x; } 30 31 float lastTop() { return m_lastTop; } 32 float lastBottom() { return m_lastBottom; } 33 float lastLeft() { return m_lastLeft; } 34 float lastRight() { return m_lastRight; } 35 36 sf::Vector2f getPosition() { return m_object.getPosition(); } 37 38 void setPosition(float x, float y) { setPositionX(x); setPositionY(y); } 39 void setPositionX(float x) { m_object.setPosition(x, m_object.getPosition().y); } 40 void setPositionY(float y) { m_object.setPosition(m_object.getPosition().x, y); } 41 42 sf::Vector2f getVelocity() { return{ getVelocityX(), getVelocityY() }; } 43 float getVelocityX() { return m_velocityX; } 44 float getVelocityY() { return m_velocityY; } 45 46 void setVelocity(float velocityX, float velocityY) { setVelocityX(velocityX); setVelocityY(velocityY); } 47 void setVelocityX(float velocityX) { m_velocityX = velocityX; } 48 void setVelocityY(float velocityY) { m_velocityY = velocityY; } 49 50 sf::Vector2f getSize() { return{ getWidth(), getHeight() }; } 51 float getWidth() { return m_object.getSize().x; } 52 float getHeight() { return m_object.getSize().y; } 53 54 void setSize(float width, float height) { setWidth(width); setHeight(height); } 55 void setWidth(float width) { m_object.setSize(sf::Vector2f(width, m_object.getSize().y)); } 56 void setHeight(float height) { m_object.setSize(sf::Vector2f(m_object.getSize().x, height)); } 57 58 sf::FloatRect getGlobalBounds() { return m_object.getGlobalBounds(); } 59 60 virtual void Object::update() { 61 if (m_velocityY > 0.f) { 62 m_lastTop = top() - m_velocityY - m_offset; 63 m_lastBottom = bottom() - m_velocityY - m_offset; 64 } 65 else { 66 m_lastTop = top() - m_velocityY + m_offset; 67 m_lastBottom = bottom() - m_velocityY + m_offset; 68 } 69 70 if (m_velocityX > 0.f) { 71 m_lastLeft = left() - m_velocityX - m_offset; 72 m_lastRight = right() - m_velocityX - m_offset; 73 } 74 else { 75 m_lastLeft = left() - m_velocityX + m_offset; 76 m_lastRight = right() - m_velocityX + m_offset; 77 } 78 } 79 80 protected: 81 sf::RectangleShape m_object; 82 83 float m_velocityX; 84 float m_velocityY; 85 float m_gravity; 86 87 float m_lastTop; 88 float m_lastBottom; 89 float m_lastLeft; 90 float m_lastRight; 91 92 float m_offset; 93 94 private: 95 void draw(sf::RenderTarget& rt, sf::RenderStates states) const override { 96 rt.draw(m_object, states); 97 } 98 }; 99 100 #endif
1 #ifndef PLAYER_HPP 2 #define PLAYER_HPP 3 4 #include "Object.hpp" 5 6 #include <SFML/Window/Keyboard.hpp> 7 8 class Player : public Object { 9 public: 10 Player::Player() 11 : m_leftForce(-4.f) 12 , m_rightForce(4.f) 13 , m_jumpForce(-12.f) 14 , m_groundLeft(0.f) 15 , m_groundRight(0.f) 16 , m_ground(false) 17 { 18 19 } 20 21 void Player::update() { 22 Object::update(); 23 24 m_object.move(m_velocityX, 0.f); 25 m_velocityX = 0.f; 26 27 if (!m_ground) { 28 m_object.move(0.f, m_velocityY); 29 m_velocityY += m_gravity; 30 } 31 32 handleKeyPressed(); 33 34 if (right() < m_groundLeft || left() > m_groundRight) { 35 m_ground = false; 36 } 37 } 38 39 void Player::setGround(float left, float right) { 40 m_groundLeft = left; 41 m_groundRight = right; 42 m_ground = true; 43 } 44 45 bool isGround() { return m_ground; } 46 47 private: 48 float m_leftForce; 49 float m_rightForce; 50 51 float m_jumpForce; 52 53 float m_groundLeft; 54 float m_groundRight; 55 56 bool m_ground; 57 58 void Player::handleKeyPressed() { 59 if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) { 60 m_velocityX = m_leftForce; 61 } 62 63 if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) { 64 m_velocityX = m_rightForce; 65 } 66 67 if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space) && m_ground) { 68 m_velocityY = m_jumpForce; 69 m_ground = false; 70 } 71 72 if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) { 73 //m_ground = false; 74 //m_velocityY = m_jumpForce; 75 } 76 } 77 }; 78 79 #endif
1 #ifndef PLAY_STATE_HPP 2 #define PLAY_STATE_HPP 3 4 #include "State.hpp" 5 #include "Player.hpp" 6 7 #include <tmxlite/Map.hpp> 8 9 #include <memory> 10 11 class StateMachine; 12 13 namespace sf { 14 class RenderWindow; 15 } 16 17 class PlayState : public State { 18 public: 19 PlayState(StateMachine &machine, sf::RenderWindow &window, bool replace = true); 20 21 void pause(); 22 void resume(); 23 void update(); 24 void draw(); 25 26 private: 27 tmx::Map m_map; 28 29 Player m_player; 30 31 std::vector<Object> m_objects; 32 33 void handleClosed(); 34 void handleKeyPressed(); 35 36 void handleCollision(); 37 }; 38 39 #endif
1 #include "PlayState.hpp" 2 #include "StateMachine.hpp" 3 //#include "PauseState.hpp" 4 5 #include <iostream> 6 7 PlayState::PlayState(StateMachine &machine, sf::RenderWindow &window, bool replace) 8 : State{ machine, window, replace } 9 { 10 m_map.load("assets/test.tmx"); 11 12 if (m_map.getOrientation() == tmx::Orientation::Orthogonal) { 13 const auto& layers = m_map.getLayers(); 14 //sf::Vector2f tileCount(m_chunkSize.x / map.getTileSize().x, m_chunkSize.y / map.getTileSize().y); 15 16 for (size_t i = 0; i < layers.size(); i++) { 17 if (layers[i]->getVisible()) { 18 switch (layers[i]->getType()) { 19 case tmx::Layer::Type::Tile: 20 //m_tileLayers.push_back(std::make_shared<TileLayer>(m_map, m_objects, layers[i])); 21 break; 22 case tmx::Layer::Type::Object: 23 { 24 const auto& objects = dynamic_cast<tmx::ObjectGroup*>(layers[i].get())->getObjects(); 25 26 for (const auto& object : objects) { 27 if (strcmp("Player", object.getType().c_str()) == 0) { 28 m_player.setPosition(object.getAABB().left, object.getAABB().top); 29 m_player.setSize(object.getAABB().width, object.getAABB().height); 30 } 31 else if (strcmp("Object", object.getType().c_str()) == 0) { 32 m_objects.emplace_back(); 33 m_objects.back().setPosition(object.getAABB().left, object.getAABB().top); 34 m_objects.back().setSize(object.getAABB().width, object.getAABB().height); 35 } 36 } 37 } 38 break; 39 default: 40 break; 41 } 42 } 43 } 44 } 45 } 46 47 void PlayState::pause() { 48 49 } 50 51 void PlayState::resume() { 52 53 } 54 55 void PlayState::update() { 56 while (m_window.pollEvent(m_event)) { 57 switch (m_event.type) { 58 case sf::Event::Closed: 59 handleClosed(); 60 break; 61 case sf::Event::KeyPressed: 62 handleKeyPressed(); 63 break; 64 default: 65 break; 66 } 67 } 68 69 m_player.update(); 70 71 handleCollision(); 72 } 73 74 void PlayState::draw() { 75 m_window.clear(); 76 77 for (auto & object : m_objects) { 78 m_window.draw(object); 79 } 80 81 m_window.draw(m_player); 82 83 m_window.display(); 84 } 85 86 void PlayState::handleClosed() { 87 m_machine.quit(); 88 } 89 90 void PlayState::handleKeyPressed() { 91 switch (m_event.key.code) { 92 case sf::Keyboard::Escape: 93 { 94 //m_next = StateMachine::build<MenuState>(m_machine, m_window, false); 95 //m_machine.lastState(); 96 } 97 break; 98 default: 99 break; 100 } 101 } 102 103 void PlayState::handleCollision() { 104 for (auto &object : m_objects) { 105 if (m_player.getGlobalBounds().intersects(object.getGlobalBounds())) { 106 if (m_player.getVelocityX() > 0.f && m_player.lastRight() < object.left()) { 107 // 从左往右碰撞 108 m_player.setPositionX(object.left() - m_player.getWidth()); 109 m_player.setVelocityX(0.f); 110 } 111 else if (m_player.getVelocityX() < 0.f && m_player.lastLeft() > object.right()) { 112 // 从右往左碰撞 113 m_player.setPositionX(object.right()); 114 m_player.setVelocityX(0.f); 115 } 116 117 if (!(m_player.isGround())) { 118 if (m_player.getVelocityY() > 0.f && m_player.lastBottom() < object.top()) { 119 // 上方下落 120 m_player.setPositionY(object.top() - m_player.getHeight()); 121 m_player.setVelocityY(0.f); 122 m_player.setGround(object.left(), object.right()); 123 } 124 else if (m_player.getVelocityY() < 0.f && m_player.lastTop() > object.bottom()) { 125 // 下方跳跃 126 m_player.setPositionY(object.bottom()); 127 m_player.setVelocityY(0.f); 128 } 129 } 130 } 131 } 132 }
以上是关于碰撞的简单例子的主要内容,如果未能解决你的问题,请参考以下文章
golang goroutine例子[golang并发代码片段]
用pygame实现网上游戏‘球球情侣‘(检测矩形和某颜色碰撞的例子)