tranerius

3) 2 + взаимодействие с объектами

Apr 13th, 2018
194
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.44 KB | None | 0 0
  1. #include <SFML\Graphics.hpp>
  2. #include <string>
  3. #include <iostream>
  4. #include <utility>
  5. #include <set>
  6. #include <vector>
  7.  
  8. class Level {
  9. public:
  10. enum ObjectType {
  11. Intangible,
  12. Material
  13. };
  14. enum Change {
  15. High,
  16. Low,
  17. Right,
  18. Left,
  19. Nothing
  20. };
  21. private:
  22. sf::Image image;
  23. sf::Texture texture;
  24. sf::Sprite sprite;
  25. std::string path_to_textures;
  26. sf::Vector2u window_size;
  27. sf::Vector2<int> last_object_size; //размер последнего установленного спрайта. Нужен для передачи объекта в контейнер, в методе SetObjectPosition
  28. class Object {
  29. public:
  30. float x_position, y_position;
  31. Level::ObjectType object_type;
  32. sf::Vector2<int> object_size;
  33. Object(const float& x_position) {
  34. this->x_position = x_position;
  35. }
  36. Object(const float& x_position, const float& y_position, const sf::Vector2<int>& object_size, const Level::ObjectType& object_type) {
  37. this->x_position = x_position;
  38. this->y_position = y_position;
  39. this->object_type = object_type;
  40. this->object_size = object_size;
  41. }
  42. bool operator < (const Object& object) const {
  43. if (x_position < object.x_position) {
  44. return true;
  45. }
  46. else if (x_position == object.x_position) {
  47. if (y_position < object.y_position) {
  48. return true;
  49. }
  50. }
  51. return false;
  52. }
  53. };
  54. std::set<Object> level_material_objects; //контейнер для хранения объектов карты
  55. public:
  56. Level(const std::string& path_to_textures, const sf::Vector2u& window_size) {
  57. this->path_to_textures = path_to_textures;
  58. this->window_size = window_size;
  59. image.loadFromFile(path_to_textures);
  60. texture.loadFromImage(image);
  61. sprite.setTexture(texture);
  62. }
  63. const sf::Sprite& GetSprite() const {
  64. return sprite;
  65. }
  66. void SetSprite(const int& x_texture_coord, const int& y_texture_coord, const int& texture_width, const int& texture_height) {
  67. sprite.setTextureRect(sf::IntRect(x_texture_coord, y_texture_coord, texture_width, texture_height));
  68. last_object_size.x = texture_width;
  69. last_object_size.y = texture_height;
  70. }
  71. void SetObjectPosition(const float& x_position, const float& y_position, const ObjectType& object_type) {
  72. sprite.setPosition(x_position, y_position);
  73. if (object_type == Material) {
  74. level_material_objects.emplace(x_position, y_position, last_object_size, object_type);
  75. }
  76. }
  77. std::pair<sf::Vector2f, sf::Vector2u> NearMaterialObject(const float& x_position, const float& y_position, const int& width, const int& height) {
  78. bool find_object = false;
  79. std::pair<sf::Vector2f, sf::Vector2u> object;
  80. std::set<Object>::iterator it = --(level_material_objects.lower_bound(x_position));
  81. if (it == --(level_material_objects.begin())) {
  82. it = level_material_objects.begin();
  83. }
  84. else {
  85. --it;
  86. if (it == --(level_material_objects.begin())) {
  87. it = level_material_objects.begin();
  88. }
  89. }
  90. for (it; it != level_material_objects.end(); ++it) {
  91. if (((x_position <= it->x_position) && ((x_position + width) > it->x_position)) // правая часть в объекте или внутри объекта, или с краю (слева)
  92. || ((x_position > it->x_position) && ((x_position + width) < (it->x_position + it->object_size.x))) //внутри объекта
  93. || (((x_position + width) >= (it->x_position + it->object_size.x)) && (x_position < (it->x_position + it->object_size.x)))/* левая часть в объекте или внутри объекта, или с краю (справа) */) {
  94. if (!find_object) {
  95. find_object = true;
  96. object.first.x = it->x_position;
  97. object.first.y = it->y_position;
  98. object.second.x = it->object_size.x;
  99. object.second.y = it->object_size.y;
  100. }
  101. if (((y_position < it->y_position) && ((y_position + height) > it->y_position))
  102. || ((y_position > it->y_position) && ((y_position + height) < (it->y_position + it->object_size.y)))
  103. || ((y_position < (it->y_position + it->object_size.y)) && ((y_position + height) >=(it->y_position + it->object_size.y)))) {
  104. object.first.x = it->x_position;
  105. object.first.y = it->y_position;
  106. object.second.x = it->object_size.x;
  107. object.second.y = it->object_size.y;
  108. break;
  109. }
  110. if (find_object && ((it->y_position - (y_position + height)) >= 0) && ((it->y_position - (y_position + height)) < (object.first.y - (y_position + height)))) {
  111. object.first.x = it->x_position;
  112. object.first.y = it->y_position;
  113. object.second.x = it->object_size.x;
  114. object.second.y = it->object_size.y;
  115. }
  116. //std::cout << "Объект: " << it->x_position << ";" << it->y_position << " " << it->object_size.x << "x" << it->object_size.y << std::endl;
  117. //std::cout << "Персонаж: " << y_position + height << " Объект: " << it->y_position + it->object_size.y << std::endl;
  118. //std::cout << "Объект для возврата: " << object.first.x << ";" << object.first.y << " " << object.second.x << "x" << object.second.y << std::endl;
  119. }
  120. else if (find_object) {
  121. break;
  122. }
  123. //system("pause");
  124. }
  125. //std::cout << "Объект: " << object.first.x << ";" << object.first.y << " " << object.second.x << "x" << object.second.y << std::endl;
  126. return object;
  127. }
  128. };
  129.  
  130. class Character {
  131. public:
  132. enum Direction {
  133. Forward = 1,
  134. Backward = -1,
  135. Up = 2,
  136. Stay = 0
  137. };
  138. private:
  139. sf::Image image;
  140. sf::Texture texture;
  141. sf::Sprite sprite;
  142. std::string path_to_textures;
  143. sf::Vector2u window_size;
  144. sf::Vector2f last_position; //последняя позиция персонажа
  145. sf::Vector2u base_character_rack_coords, base_character_rack_size; //координаты и размер базовой стойки персонажа
  146. float character_speed = 0, character_weight = 0;
  147. sf::Vector2f character_dimensions; //габариты персонажа
  148. float jump_speed, fall_speed;
  149. sf::Clock clock;
  150. double time;
  151. bool is_jump = false, is_fall = false;
  152. bool block_control = false;
  153. void CharacterDirection(const Direction& direction) {
  154. if (direction == Direction::Forward) {
  155. sprite.setOrigin(0, 0);
  156. sprite.setScale(character_dimensions.x / base_character_rack_size.x, character_dimensions.y / base_character_rack_size.y);
  157. }
  158. else if (direction == Direction::Backward) {
  159. sprite.setOrigin(base_character_rack_size.x, 0);
  160. sprite.setScale(-character_dimensions.x / base_character_rack_size.x, character_dimensions.y / base_character_rack_size.y);
  161. }
  162. }
  163. public:
  164. Character(const std::string& path_to_textures, const sf::Vector2u& window_size, const sf::Vector2u& base_character_rack_coords, const sf::Vector2u& base_character_rack_size) {
  165. this->path_to_textures = path_to_textures;
  166. image.loadFromFile(path_to_textures);
  167. image.createMaskFromColor(sf::Color(0, 14, 88));
  168. texture.loadFromImage(image);
  169. sprite.setTexture(texture);
  170. sprite.setTextureRect(sf::IntRect(base_character_rack_coords.x, base_character_rack_coords.y, base_character_rack_size.x, base_character_rack_size.y));
  171. this->window_size = window_size;
  172. this->base_character_rack_coords = base_character_rack_coords;
  173. this->base_character_rack_size = base_character_rack_size;
  174. character_dimensions.x = base_character_rack_size.x;
  175. character_dimensions.y = base_character_rack_size.y;
  176. }
  177. const sf::Sprite& GetSprite() const {
  178. return sprite;
  179. }
  180. void SetCharacterSpeed(const float& character_speed) {
  181. this->character_speed = character_speed;
  182. }
  183. const float& GetChatacterSpeed() const {
  184. return character_speed;
  185. }
  186. void SetCharacterWeight(const float& character_weight) {
  187. this->character_weight = character_weight;
  188. }
  189. const float& GetChatacterWeight() const {
  190. return character_weight;
  191. }
  192. void Update() {
  193. time = clock.getElapsedTime().asMicroseconds()*0.000001;
  194. clock.restart();
  195. if (is_jump) {
  196. Jump();
  197. }
  198. }
  199. void Move(const Direction& direction) {
  200. last_position = sprite.getPosition();
  201. if (direction != Stay) {
  202. if (!block_control) {
  203. if (direction == Forward || direction == Backward) {
  204. CharacterDirection(direction);
  205. sprite.move(direction*character_speed * 1000 * 0.07*time, 0);
  206. }
  207. else if (direction == Up) {
  208. Jump();
  209. }
  210. }
  211. }
  212. else {
  213.  
  214. }
  215. }
  216. const sf::Vector2f& GetCharacterPosition() const {
  217. return sprite.getPosition();
  218. }
  219. void SetCharacterPosition(const float& x, const float& y) {
  220. sprite.setPosition(x, y);
  221. }
  222. const bool& IsJump() const {
  223. return is_jump;
  224. }
  225. const bool& IsFall() const {
  226. return is_fall;
  227. }
  228. void Fall(const bool& fall) {
  229. if (!is_jump) {
  230. if (!is_fall) {
  231. is_fall = true;
  232. fall_speed = 0;
  233. }
  234. if (!fall) {
  235. is_fall = false;
  236. }
  237. else {
  238. last_position = sprite.getPosition();
  239. sprite.move(0, fall_speed * 1000 * 0.07*time);
  240. fall_speed += 9.8*time;
  241. }
  242. }
  243. }
  244. void Jump(const bool& jump = true) {
  245. if (!jump) {
  246. is_jump = false;
  247. is_fall = true;
  248. fall_speed = 0;
  249. }
  250. if (!is_fall) {
  251. if (!is_jump) {
  252. jump_speed = 300 / character_weight;
  253. is_jump = true;
  254. }
  255. else {
  256. last_position = sprite.getPosition();
  257. sprite.move(0, -jump_speed * 1000 * 0.07*time);
  258. jump_speed -= 9.8*time;
  259. if (jump_speed <= 0) {
  260. is_jump = false;
  261. is_fall = true;
  262. fall_speed = 0;
  263. }
  264. }
  265. }
  266. }
  267. void SetCharacterDimensions(const float& scale) {
  268. sprite.setScale(1 * scale, 1 * scale);
  269. character_dimensions.x *= scale;
  270. character_dimensions.y *= scale;
  271. }
  272. const sf::Vector2f& GetCharacterDimensions() const {
  273. return character_dimensions;
  274. }
  275. const sf::Vector2f& GetCharacterLastPosition() const {
  276. return last_position;
  277. }
  278. void SetBlock(const bool& block) {
  279. block_control = block;
  280. }
  281. };
  282.  
  283. void Move(Character*& character, Level*& level) {
  284. if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) {
  285. character->Move(Character::Direction::Forward);
  286. }
  287. if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) {
  288. character->Move(Character::Direction::Backward);
  289. }
  290. std::pair<sf::Vector2f, sf::Vector2u> object = level->NearMaterialObject(character->GetCharacterPosition().x + 22, character->GetCharacterPosition().y, character->GetCharacterDimensions().x - 44, character->GetCharacterDimensions().y); // +22 по X и -44 по размеру спрайта для того, чтобы были задействованы только ноги персонажа
  291. if (!character->IsJump()) {
  292. if (!character->IsFall()) {
  293. if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) {
  294. character->Move(Character::Direction::Up);
  295. }
  296. }
  297. if ((character->GetCharacterPosition().y + character->GetCharacterDimensions().y) >= object.first.y) { // если персонаж на объекте
  298. character->Fall(false);
  299. character->SetBlock(false);
  300. if ((character->GetCharacterPosition().y + character->GetCharacterDimensions().y) > object.first.y) { // если персонаж внутри объекта
  301. if ((character->GetCharacterPosition().y + character->GetCharacterDimensions().y) - object.first.y <= 2) { //если разница между положением персонажа и объекта составляет 2 пикселя
  302. character->SetCharacterPosition(character->GetCharacterLastPosition().x, object.first.y - character->GetCharacterDimensions().y);
  303. }
  304. else {
  305. character->SetBlock(true);
  306. character->SetCharacterPosition(character->GetCharacterLastPosition().x, character->GetCharacterLastPosition().y);
  307. }
  308. }
  309. }
  310. else {
  311. character->Fall(true);
  312. }
  313. /*std::cout << "Положение объекта: x [" << object.first.x << ";" << object.first.x + object.second.x << ")"
  314. << ", y [" << object.first.y << "; " << object.first.y + object.second.y << ")" << std::endl;
  315. std::cout << "Положение персонажа: x [" << character->GetCharacterPosition().x + 22 << "; " << character->GetCharacterPosition().x + character->GetCharacterDimensions().x - 44 << ")"
  316. << ", y [" << character->GetCharacterPosition().y << "; " << character->GetCharacterPosition().y + character->GetCharacterDimensions().y << ")\n" << std::endl;*/
  317. //std::cout << "Падение " << character->IsFall() << std::endl;
  318. }
  319. else {
  320. if ((character->GetCharacterPosition().y < (object.first.y + object.second.y)) && ((character->GetCharacterPosition().y + character->GetCharacterDimensions().y) > (object.first.y + object.second.y))) { //если персонаж в прыжке ударяется об объект
  321. character->SetCharacterPosition(character->GetCharacterLastPosition().x, character->GetCharacterLastPosition().y);
  322. character->Jump(false);
  323. }
  324. }
  325. }
  326.  
  327. int main() {
  328. setlocale(LC_ALL, "ru");
  329. sf::RenderWindow window(sf::VideoMode(1000, 388), "Uganda Adventure");
  330. sf::Event window_event;
  331. Character* main_character = new Character("uganda_textures.png", window.getSize(), sf::Vector2u(1, 1), sf::Vector2u(144, 164));
  332. main_character->SetCharacterSpeed(1);
  333. main_character->SetCharacterWeight(50);
  334. main_character->SetCharacterDimensions(0.5);
  335. main_character->SetCharacterPosition(1, 0);
  336. Level* level1 = new Level("level_1.png", window.getSize());
  337. while (window.isOpen()) {
  338. main_character->Update();
  339. if (window.pollEvent(window_event)) {
  340. if (window_event.type == sf::Event::EventType::Closed) {
  341. window.close();
  342. }
  343. }
  344. window.clear(); // очистка предыдущего кадра
  345. for (float x = -20; x < 1200; x += 97) {
  346. level1->SetSprite(1, 1, 97, 97); // спрайт неба
  347. level1->SetObjectPosition(x, 0, Level::ObjectType::Intangible);
  348. window.draw(level1->GetSprite());
  349. level1->SetObjectPosition(x, 97, Level::ObjectType::Intangible);
  350. window.draw(level1->GetSprite());
  351. level1->SetObjectPosition(x, 194, Level::ObjectType::Intangible);
  352. window.draw(level1->GetSprite());
  353. level1->SetSprite(1, 100, 97, 97); // спрайт земли
  354. level1->SetObjectPosition(x, 291, Level::ObjectType::Material);
  355. window.draw(level1->GetSprite());
  356. }
  357. level1->SetSprite(1, 100, 97, 97); // спрайт земли
  358. level1->SetObjectPosition(220, 194, Level::ObjectType::Material);
  359. window.draw(level1->GetSprite());
  360. level1->SetSprite(1, 100, 97, 97); // спрайт земли
  361. level1->SetObjectPosition(420, 20, Level::ObjectType::Material);
  362. window.draw(level1->GetSprite());
  363. Move(main_character, level1);
  364. window.draw(main_character->GetSprite());
  365. window.display();
  366. }
  367. system("pause");
  368. delete level1;
  369. delete main_character;
  370. return 0;
  371. }
Advertisement
Add Comment
Please, Sign In to add comment