A 2D tile-based sandbox game.
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

Chunk.cc 4.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. #include "Chunk.h"
  2. #include <SFML/System/Clock.hpp>
  3. #include <zlib.h>
  4. #include "World.h"
  5. #include "Game.h"
  6. #include "Win.h"
  7. namespace Swan {
  8. sf::Uint8 *Chunk::renderbuf = new sf::Uint8[CHUNK_WIDTH * TILE_SIZE * CHUNK_HEIGHT * TILE_SIZE * 4];
  9. Tile::ID *Chunk::getTileData() {
  10. keepActive();
  11. return (Tile::ID *)data_.get();
  12. }
  13. Tile::ID Chunk::getTileID(RelPos pos) {
  14. return getTileData()[pos.y * CHUNK_WIDTH + pos.x];
  15. }
  16. void Chunk::setTileID(RelPos pos, Tile::ID id) {
  17. getTileData()[pos.y * CHUNK_WIDTH + pos.x] = id;
  18. }
  19. void Chunk::drawBlock(RelPos pos, const Tile &t) {
  20. keepActive();
  21. //visuals_->tex_.update(*t.image_, pos.x * TILE_SIZE, pos.y * TILE_SIZE);
  22. visuals_->dirty_ = true;
  23. }
  24. void Chunk::compress() {
  25. if (isCompressed())
  26. return;
  27. sf::Clock clock;
  28. // We only need a fixed-length temp buffer;
  29. // if the compressed data gets too big, there's no point in compressing
  30. uint8_t dest[CHUNK_WIDTH * CHUNK_HEIGHT * sizeof(Tile::ID)];
  31. uLongf destlen = sizeof(dest);
  32. int ret = compress2(
  33. (Bytef *)dest, &destlen,
  34. (Bytef *)data_.get(), CHUNK_WIDTH * CHUNK_HEIGHT * sizeof(Tile::ID),
  35. Z_BEST_COMPRESSION);
  36. if (ret == Z_OK) {
  37. data_.reset(new uint8_t[destlen]);
  38. memcpy(data_.get(), dest, destlen);
  39. visuals_.reset();
  40. compressed_size_ = destlen;
  41. fprintf(stderr, "Compressed chunk %i,%i from %lu bytes to %lu bytes in %.3fs.\n",
  42. pos_.x, pos_.y, CHUNK_WIDTH * CHUNK_HEIGHT * sizeof(Tile::ID), destlen,
  43. clock.getElapsedTime().asSeconds());
  44. } else if (ret == Z_BUF_ERROR) {
  45. fprintf(stderr, "Didn't compress chunk %i,%i because compressing it would've made it bigger.\n",
  46. pos_.x, pos_.y);
  47. } else {
  48. fprintf(stderr, "Chunk compression error: %i (Out of memory?)\n", ret);
  49. }
  50. }
  51. void Chunk::decompress() {
  52. if (!isCompressed())
  53. return;
  54. sf::Clock clock;
  55. uint8_t *dest = new uint8_t[CHUNK_WIDTH * CHUNK_HEIGHT * sizeof(Tile::ID)];
  56. uLongf destlen = CHUNK_WIDTH * CHUNK_HEIGHT * sizeof(Tile::ID);
  57. int ret = uncompress(
  58. dest, &destlen,
  59. (Bytef *)data_.get(), compressed_size_);
  60. if (ret != Z_OK) {
  61. fprintf(stderr, "Decompressing chunk failed: %i\n", ret);
  62. delete[] dest;
  63. abort();
  64. }
  65. data_.reset(dest);
  66. visuals_.reset(new Visuals());
  67. visuals_->tex_.create(CHUNK_WIDTH * TILE_SIZE, CHUNK_HEIGHT * TILE_SIZE);
  68. visuals_->sprite_ = sf::Sprite();
  69. visuals_->dirty_ = true;
  70. need_render_ = true;
  71. fprintf(stderr, "Decompressed chunk %i,%i from %li bytes to %lu bytes in %.3fs.\n",
  72. pos_.x, pos_.y, compressed_size_, CHUNK_WIDTH * CHUNK_HEIGHT * sizeof(Tile::ID),
  73. clock.getElapsedTime().asSeconds());
  74. compressed_size_ = -1;
  75. }
  76. void Chunk::render(const Context &ctx) {
  77. Tile::ID prevID = Tile::INVALID_ID;
  78. Tile *tile = ctx.game.invalid_tile_.get();
  79. for (int x = 0; x < CHUNK_WIDTH; ++x) {
  80. for (int y = 0; y < CHUNK_HEIGHT; ++y) {
  81. Tile::ID id = getTileID(RelPos(x, y));
  82. if (id != prevID) {
  83. prevID = id;
  84. tile = &ctx.world.getTileByID(id);
  85. }
  86. const sf::Uint8 *imgptr = NULL;
  87. //const sf::Uint8 *imgptr = tile->image->getPixelsPtr();
  88. for (int imgy = 0; imgy < TILE_SIZE; ++imgy) {
  89. int pixx = x * TILE_SIZE;
  90. int pixy = y * TILE_SIZE + imgy;
  91. sf::Uint8 *pix = renderbuf +
  92. pixy * CHUNK_WIDTH * TILE_SIZE * 4 +
  93. pixx * 4;
  94. memcpy(pix, imgptr + imgy * TILE_SIZE * 4, TILE_SIZE * 4);
  95. }
  96. }
  97. }
  98. visuals_->tex_.update(renderbuf, CHUNK_WIDTH * TILE_SIZE, CHUNK_HEIGHT * TILE_SIZE, 0, 0);
  99. visuals_->dirty_ = true;
  100. }
  101. void Chunk::draw(const Context &ctx, Win &win) {
  102. if (isCompressed())
  103. return;
  104. if (need_render_) {
  105. render(ctx);
  106. need_render_ = false;
  107. }
  108. if (visuals_->dirty_) {
  109. visuals_->sprite_.setTexture(visuals_->tex_);
  110. visuals_->dirty_ = false;
  111. }
  112. win.setPos(pos_ * Vec2i(CHUNK_WIDTH, CHUNK_HEIGHT));
  113. win.draw(visuals_->sprite_);
  114. }
  115. void Chunk::tick(float dt) {
  116. if (deactivate_timer_ <= 0)
  117. return;
  118. deactivate_timer_ -= dt;
  119. if (deactivate_timer_ <= 0) {
  120. compress();
  121. }
  122. }
  123. bool Chunk::keepActive() {
  124. bool wasActive = isActive();
  125. deactivate_timer_ = DEACTIVATE_INTERVAL;
  126. if (wasActive)
  127. return false;
  128. decompress();
  129. return true;
  130. }
  131. }