Skip to content

Instantly share code, notes, and snippets.

@untodesu
Created March 8, 2020 13:06
Show Gist options
  • Save untodesu/9edb2e6627bb5ed22b59099a68ad36b6 to your computer and use it in GitHub Desktop.
Save untodesu/9edb2e6627bb5ed22b59099a68ad36b6 to your computer and use it in GitHub Desktop.
#include "chunk.h"
namespace rg
{
TileChunk::TileChunk(sf::Texture &tileSet, const size_t tileSize) : m_tileSize(tileSize)
{
m_tileSet = &tileSet;
m_vbo = sf::VertexBuffer(sf::Quads, sf::VertexBuffer::Dynamic);
m_vbo.create(CHUNK_SIZE * CHUNK_SIZE * 4);
m_vertices = new sf::Vertex[m_vbo.getVertexCount()];
m_tiles = new uint16_t[CHUNK_SIZE * CHUNK_SIZE];
for(size_t y = 0; y < CHUNK_SIZE; y++) {
for(size_t x = 0; x < CHUNK_SIZE; x++) {
const float ts = static_cast<float>(m_tileSize);
const size_t idx = ((y * CHUNK_SIZE) + x) * 4;
m_tiles[(y * CHUNK_SIZE) + x] = 0;
m_vertices[idx + 0].position = sf::Vector2f((ts * x), (ts * y));
m_vertices[idx + 1].position = sf::Vector2f((ts * (x + 1)), (ts * y));
m_vertices[idx + 3].position = sf::Vector2f((ts * x), (ts * (y + 1)));
m_vertices[idx + 2].position = sf::Vector2f((ts * (x + 1)), (ts * (y + 1)));
}
}
update();
}
TileChunk::~TileChunk()
{
delete[] m_vertices;
delete[] m_tiles;
}
const size_t TileChunk::getTileSize() const
{
return m_tileSize;
}
const sf::FloatRect TileChunk::getBox() const
{
const sf::Vector2f size(
static_cast<float>(CHUNK_SIZE * m_tileSize),
static_cast<float>(CHUNK_SIZE * m_tileSize));
return sf::FloatRect(getPosition(), size);
}
void TileChunk::update()
{
const float ts = static_cast<float>(m_tileSize);
for(size_t x = 0; x < CHUNK_SIZE; x++) {
for(size_t y = 0; y < CHUNK_SIZE; y++) {
const size_t idx = ((y * CHUNK_SIZE) + x) * 4;
const uint16_t id = m_tiles[(y * CHUNK_SIZE) + x];
const float tx = static_cast<float>((id * m_tileSize) % m_tileSet->getSize().x);
const float ty = static_cast<float>((id * m_tileSize) / m_tileSet->getSize().x) * m_tileSize;
m_vertices[idx + 0].texCoords = sf::Vector2f(tx, ty);
m_vertices[idx + 1].texCoords = sf::Vector2f((ts + tx), ty);
m_vertices[idx + 2].texCoords = sf::Vector2f((ts + tx), (ts + ty));
m_vertices[idx + 3].texCoords = sf::Vector2f(tx, (ts + ty));
}
}
m_vbo.update(m_vertices);
}
void TileChunk::draw(sf::RenderTarget &target, sf::RenderStates states) const
{
if(!states.texture) {
states.texture = m_tileSet;
}
states.transform *= getTransform();
target.draw(m_vbo, states);
}
void TileChunk::setTile(const uint32_t x, const uint32_t y, const uint16_t id)
{
if((x >= CHUNK_SIZE) || (y >= CHUNK_SIZE)) {
return;
}
const float ts = static_cast<float>(m_tileSize);
const size_t idx = ((y * CHUNK_SIZE) + x) * 4;
m_tiles[(y * CHUNK_SIZE) + x] = id;
const float tx = static_cast<float>((id * m_tileSize) % m_tileSet->getSize().x);
const float ty = static_cast<float>((id * m_tileSize) / m_tileSet->getSize().x) * m_tileSize;
m_vertices[idx + 0].texCoords = sf::Vector2f(tx, ty);
m_vertices[idx + 1].texCoords = sf::Vector2f((ts + tx), ty);
m_vertices[idx + 2].texCoords = sf::Vector2f((ts + tx), (ts + ty));
m_vertices[idx + 3].texCoords = sf::Vector2f(tx, (ts + ty));
m_vbo.update(m_vertices + idx, 4, (unsigned int)idx);
}
void TileChunk::setTile(const sf::Vector2u &pos, const uint16_t id)
{
if((pos.x >= CHUNK_SIZE) || (pos.y >= CHUNK_SIZE)) {
return;
}
const uint32_t x = pos.x;
const uint32_t y = pos.y;
const float ts = static_cast<float>(m_tileSize);
const uint32_t idx = ((y * CHUNK_SIZE) + x) * 4;
m_tiles[(y * CHUNK_SIZE) + x] = id;
const float tx = static_cast<float>((id * m_tileSize) % m_tileSet->getSize().x);
const float ty = static_cast<float>((id * m_tileSize) / m_tileSet->getSize().x) * m_tileSize;
m_vertices[idx + 0].texCoords = sf::Vector2f(tx, ty);
m_vertices[idx + 1].texCoords = sf::Vector2f((ts + tx), ty);
m_vertices[idx + 2].texCoords = sf::Vector2f((ts + tx), (ts + ty));
m_vertices[idx + 3].texCoords = sf::Vector2f(tx, (ts + ty));
m_vbo.update(m_vertices + idx, 4, idx);
}
uint16_t TileChunk::getTile(const uint32_t x, const uint32_t y) const
{
if((x >= CHUNK_SIZE) || (y >= CHUNK_SIZE)) {
return 0;
}
return m_tiles[(y * CHUNK_SIZE) + x];
}
uint16_t TileChunk::getTile(const sf::Vector2u &pos) const
{
if((pos.x >= CHUNK_SIZE) || (pos.y >= CHUNK_SIZE)) {
return 0;
}
return m_tiles[(pos.y * CHUNK_SIZE) + pos.x];
}
uint16_t * TileChunk::getTilesPtr() const
{
return m_tiles;
}
}
#ifndef CHUNK_H
#define CHUNK_H
#include <core/libc.h>
#include <SFML/Graphics.hpp>
namespace rg
{
//
// The tile chunk.
// This thing contains actual tiles.
//
class TileChunk : public sf::Drawable, public sf::Transformable {
public:
static constexpr size_t CHUNK_SIZE = 16;
private:
const size_t m_tileSize;
sf::Texture *m_tileSet;
uint16_t *m_tiles;
private:
sf::VertexBuffer m_vbo;
sf::Vertex *m_vertices;
private:
virtual void draw(sf::RenderTarget &target, sf::RenderStates states) const;
public:
TileChunk(sf::Texture &tileset, const size_t tileSize = 16);
~TileChunk();
const size_t getTileSize() const;
const sf::FloatRect getBox() const;
void update();
void setTile(const uint32_t x, const uint32_t y, const uint16_t id);
void setTile(const sf::Vector2u &pos, const uint16_t id);
uint16_t getTile(const uint32_t x, const uint32_t y) const;
uint16_t getTile(const sf::Vector2u &pos) const;
uint16_t * getTilesPtr() const;
};
}
#endif
#include "map.h"
namespace rg
{
TileMap::TileMap(sf::Texture &tileset, const size_t width, const size_t height, const size_t tileSize) : m_width(width), m_height(height), m_tileSize(tileSize)
{
m_ccx = ((m_width - 1) / TileChunk::CHUNK_SIZE) + 1;
m_ccy = ((m_height - 1) / TileChunk::CHUNK_SIZE) + 1;
m_chunks = new TileChunk*[m_ccy * m_ccx];
for(size_t x = 0; x < m_ccx; x++) {
for(size_t y = 0; y < m_ccy; y++) {
const size_t i = (y * m_ccy) + x;
m_chunks[i] = new TileChunk(tileset, m_tileSize);
m_chunks[i]->setPosition(
static_cast<float>(TileChunk::CHUNK_SIZE * m_tileSize * x),
static_cast<float>(TileChunk::CHUNK_SIZE * m_tileSize * y)
);
}
}
}
TileMap::~TileMap()
{
for(size_t x = 0; x < m_ccx; x++) {
for(size_t y = 0; y < m_ccy; y++) {
delete m_chunks[(y * m_ccy) + x];
}
}
delete[] m_chunks;
}
void TileMap::draw(sf::RenderTarget &target, sf::RenderStates states) const
{
sf::View view = target.getView();
const sf::Vector2f viewSize = view.getSize();
const sf::Vector2f viewPos(
view.getCenter().x - (viewSize.x / 2),
view.getCenter().y - (viewSize.y / 2)
);
const sf::FloatRect viewRect(viewPos, viewSize);
for(size_t i = 0; i < (m_ccx * m_ccy); i++) {
if(m_chunks[i]->getBox().intersects(viewRect)) {
target.draw(*m_chunks[i], states);
}
}
}
void TileMap::setTile(const uint32_t x, const uint32_t y, const uint16_t id)
{
if((x >= m_width) || (y >= m_height)) {
return;
}
const size_t cx = (x / TileChunk::CHUNK_SIZE);
const size_t cy = (y / TileChunk::CHUNK_SIZE);
const size_t i = (cy * m_ccy) + cx;
m_chunks[i]->setTile((x % TileChunk::CHUNK_SIZE), (y % TileChunk::CHUNK_SIZE), id);
}
void TileMap::setTile(const sf::Vector2u &pos, const uint16_t id)
{
if((pos.x >= m_width) || (pos.y >= m_height)) {
return;
}
const uint32_t cx = (pos.x / TileChunk::CHUNK_SIZE);
const uint32_t cy = (pos.y / TileChunk::CHUNK_SIZE);
m_chunks[(cy * m_ccy) + cx]->setTile((pos.x % TileChunk::CHUNK_SIZE), (pos.y % TileChunk::CHUNK_SIZE), id);
}
uint16_t TileMap::getTile(const uint32_t x, const uint32_t y) const
{
if((x >= m_width) || (y >= m_height)) {
return 0;
}
const uint32_t cx = (x / TileChunk::CHUNK_SIZE);
const uint32_t cy = (y / TileChunk::CHUNK_SIZE);
const size_t i = (cy * m_ccy) + cx;
return m_chunks[i]->getTile((x % TileChunk::CHUNK_SIZE), (y % TileChunk::CHUNK_SIZE));
}
uint16_t TileMap::getTile(const sf::Vector2u &pos) const
{
if((pos.x >= m_width) || (pos.y >= m_height)) {
return 0;
}
const uint32_t cx = (pos.x / TileChunk::CHUNK_SIZE);
const uint32_t cy = (pos.y / TileChunk::CHUNK_SIZE);
const size_t i = (cy * m_ccy) + cx;
return m_chunks[i]->getTile((pos.x % TileChunk::CHUNK_SIZE), (pos.y % TileChunk::CHUNK_SIZE));
}
}
#ifndef MAP_H
#define MAP_H
#include <core/libc.h>
#include <SFML/Graphics.hpp>
#include <game/chunk.h>
namespace rg
{
//
// The tile map.
// Contains chunks.
//
class TileMap : public sf::Drawable {
private:
TileChunk **m_chunks;
const size_t m_width, m_height;
const size_t m_tileSize;
size_t m_ccx, m_ccy;
private:
virtual void draw(sf::RenderTarget &target, sf::RenderStates states) const;
public:
TileMap(sf::Texture &tileset, const size_t width, const size_t height, const size_t tileSize = 16);
~TileMap();
void setTile(const uint32_t x, const uint32_t y, const uint16_t id);
void setTile(const sf::Vector2u &pos, const uint16_t id);
uint16_t getTile(const uint32_t x, const uint32_t y) const;
uint16_t getTile(const sf::Vector2u &pos) const;
};
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment