<commit_before>/******************************
** Tsunagari Tile Engine     **
** area.cpp                  **
** Copyright 2011 OmegaSDG   **
******************************/

#include <boost/foreach.hpp>
#include <boost/shared_ptr.hpp>

#include "area.h"
#include "common.h"
#include "entity.h"
#include "log.h"
#include "resourcer.h"
#include "sprite.h"
#include "window.h"
#include "world.h"

/* NOTE: Tileset tiles start counting their positions from 0, while layer tiles
         start counting from 1. I can't imagine why the author did this, but we
         have to take it into account. 
*/

Area::Area(Resourcer* rc,
           World* world,
           Entity* player,
           const std::string& descriptor)
	: rc(rc), world(world), player(player), descriptor(descriptor)
{
	dim.x = dim.y = dim.z = 0;
}

Area::~Area()
{
	// Delete each Tile. If a Tile has an allocated Door struct, delete
	// that as well.
	BOOST_FOREACH(grid_t grid, map) {
		BOOST_FOREACH(row_t row, grid) {
			BOOST_FOREACH(Tile* tile, row) {
				delete tile->door;
				delete tile;
			}
		}
	}

	// Each Area owns its own Tileset objects. Delete tileset graphics.
	BOOST_FOREACH(Tileset tileset, tilesets) {
		BOOST_FOREACH(TileType type, tileset.defaults) {
			BOOST_FOREACH(Gosu::Image* img, type.graphics) {
				delete img;
			}
			// TODO: delete TileEvents when we start using them
		}
	}
}

bool Area::init()
{
	return processDescriptor();
}

void Area::buttonDown(const Gosu::Button btn)
{
	bool attemptingMove = false;
	coord_t posMove;

	if (btn == Gosu::kbRight) {
		posMove = coord(1, 0, 0);
		attemptingMove = true;
	}
	else if (btn == Gosu::kbLeft) {
		posMove = coord(-1, 0, 0);
		attemptingMove = true;
	}
	else if (btn == Gosu::kbUp) {
		posMove = coord(0, -1, 0);
		attemptingMove = true;
	}
	else if (btn == Gosu::kbDown) {
		posMove = coord(0, 1, 0);
		attemptingMove = true;
	}

	if (attemptingMove) {
		coord_t newCoord = player->getCoordsByTile();
		newCoord.x += posMove.x;
		newCoord.y += posMove.y;
		newCoord.z += posMove.z;
		Tile* dest = getTile(newCoord);
		if ((dest->flags       & player_nowalk) != 0 ||
		    (dest->type->flags & player_nowalk) != 0) {
			// The tile we're trying to move onto is set as nowalk
			// for the player. Stop here.
			return;
		}
		if (dest->door) {
			world->loadArea(dest->door->area, dest->door->coord);
		}
		else {
			player->moveByTile(posMove);
		}
	}
}

void Area::draw()
{
	GameWindow* window = GameWindow::getWindow();
	Gosu::Graphics* graphics = &window->graphics();
	Gosu::Transform trans = translateCoords();
	graphics->pushTransform(trans);

	for (unsigned int layer = 0; layer != map.size(); layer++)
	{
		grid_t grid = map[layer];
		for (unsigned int y = 0; y != grid.size(); y++)
		{
			row_t row = grid[y];
			for (unsigned int x = 0; x != row.size(); x++)
			{
				// TODO support animations
				Tile* tile = row[x];
				Gosu::Image* img = tile->type->graphics[0];
				img->draw(x*img->width(), y*img->height(), 0);
			}
		}
	}
	player->draw();

	graphics->popTransform();
}

//! Returns the number closest to x within the range [low, high].
/*!
	\param low Lowest possible return.
	\param x Value to be bounded.
	\param high Highest possible return.
	\return A number close to x.
	\sa center() and translateCoords()
*/
static double bound(double low, double x, double high)
{
	if (low > x)
		x = low;
	if (x > high)
		x = high;
	return x;
}

static double center(double w, double g, double p)
{
	return w>g ? (w-g)/2.0 : bound(w-g, w/2.0-p, 0);
}

Gosu::Transform Area::translateCoords()
{
	GameWindow* window = GameWindow::getWindow();
	Gosu::Graphics* graphics = &window->graphics();

	double tileWidth = (double)tilesets[0].tiledim.x;
	double tileHeight = (double)tilesets[0].tiledim.y;
	double windowWidth = (double)graphics->width() / tileWidth;
	double windowHeight = (double)graphics->height() / tileHeight;
	double gridWidth = (double)dim.x;
	double gridHeight = (double)dim.y;
	double playerX = (double)player->getCoordsByPixel().x / tileWidth + 0.5;
	double playerY = (double)player->getCoordsByPixel().y / tileHeight + 0.5;

	coord_t c;
	c.x = (long)center(windowWidth, gridWidth, playerX) * (long)tileWidth;
	c.y = (long)center(windowHeight, gridHeight, playerY) * (long)tileHeight;

	Gosu::Transform trans = Gosu::translate((double)c.x, (double)c.y);
	return trans;
}

bool Area::needsRedraw() const
{
	return player->needsRedraw();<commit_msg>area.cpp: fix type aliasing with centering player<commit_after>/******************************
** Tsunagari Tile Engine     **
** area.cpp                  **
** Copyright 2011 OmegaSDG   **
******************************/

#include <boost/foreach.hpp>
#include <boost/shared_ptr.hpp>

#include "area.h"
#include "common.h"
#include "entity.h"
#include "log.h"
#include "resourcer.h"
#include "sprite.h"
#include "window.h"
#include "world.h"

/* NOTE: Tileset tiles start counting their positions from 0, while layer tiles
         start counting from 1. I can't imagine why the author did this, but we
         have to take it into account. 
*/

Area::Area(Resourcer* rc,
           World* world,
           Entity* player,
           const std::string& descriptor)
	: rc(rc), world(world), player(player), descriptor(descriptor)
{
	dim.x = dim.y = dim.z = 0;
}

Area::~Area()
{
	// Delete each Tile. If a Tile has an allocated Door struct, delete
	// that as well.
	BOOST_FOREACH(grid_t grid, map) {
		BOOST_FOREACH(row_t row, grid) {
			BOOST_FOREACH(Tile* tile, row) {
				delete tile->door;
				delete tile;
			}
		}
	}

	// Each Area owns its own Tileset objects. Delete tileset graphics.
	BOOST_FOREACH(Tileset tileset, tilesets) {
		BOOST_FOREACH(TileType type, tileset.defaults) {
			BOOST_FOREACH(Gosu::Image* img, type.graphics) {
				delete img;
			}
			// TODO: delete TileEvents when we start using them
		}
	}
}

bool Area::init()
{
	return processDescriptor();
}

void Area::buttonDown(const Gosu::Button btn)
{
	bool attemptingMove = false;
	coord_t posMove;

	if (btn == Gosu::kbRight) {
		posMove = coord(1, 0, 0);
		attemptingMove = true;
	}
	else if (btn == Gosu::kbLeft) {
		posMove = coord(-1, 0, 0);
		attemptingMove = true;
	}
	else if (btn == Gosu::kbUp) {
		posMove = coord(0, -1, 0);
		attemptingMove = true;
	}
	else if (btn == Gosu::kbDown) {
		posMove = coord(0, 1, 0);
		attemptingMove = true;
	}

	if (attemptingMove) {
		coord_t newCoord = player->getCoordsByTile();
		newCoord.x += posMove.x;
		newCoord.y += posMove.y;
		newCoord.z += posMove.z;
		Tile* dest = getTile(newCoord);
		if ((dest->flags       & player_nowalk) != 0 ||
		    (dest->type->flags & player_nowalk) != 0) {
			// The tile we're trying to move onto is set as nowalk
			// for the player. Stop here.
			return;
		}
		if (dest->door) {
			world->loadArea(dest->door->area, dest->door->coord);
		}
		else {
			player->moveByTile(posMove);
		}
	}
}

void Area::draw()
{
	GameWindow* window = GameWindow::getWindow();
	Gosu::Graphics* graphics = &window->graphics();
	Gosu::Transform trans = translateCoords();
	graphics->pushTransform(trans);

	for (unsigned int layer = 0; layer != map.size(); layer++)
	{
		grid_t grid = map[layer];
		for (unsigned int y = 0; y != grid.size(); y++)
		{
			row_t row = grid[y];
			for (unsigned int x = 0; x != row.size(); x++)
			{
				// TODO support animations
				Tile* tile = row[x];
				Gosu::Image* img = tile->type->graphics[0];
				img->draw(x*img->width(), y*img->height(), 0);
			}
		}
	}
	player->draw();

	graphics->popTransform();
}

//! Returns the number closest to x within the range [low, high].
/*!
	\param low Lowest possible return.
	\param x Value to be bounded.
	\param high Highest possible return.
	\return A number close to x.
	\sa center() and translateCoords()
*/
static double bound(double low, double x, double high)
{
	if (low > x)
		x = low;
	if (x > high)
		x = high;
	return x;
}

static double center(double w, double g, double p)
{
	return w>g ? (w-g)/2.0 : bound(w-g, w/2.0-p, 0);
}

Gosu::Transform Area::translateCoords()
{
	GameWindow* window = GameWindow::getWindow();
	Gosu::Graphics* graphics = &window->graphics();

	double tileWidth = (double)tilesets[0].tiledim.x;
	double tileHeight = (double)tilesets[0].tiledim.y;
	double windowWidth = (double)graphics->width() / tileWidth;
	double windowHeight = (double)graphics->height() / tileHeight;
	double gridWidth = (double)dim.x;
	double gridHeight = (double)dim.y;
	double playerX = (double)player->getCoordsByPixel().x / tileWidth + 0.5;
	double playerY = (double)player->getCoordsByPixel().y / tileHeight + 0.5;

	coord_t c;
	c.x = (long)(center(windowWidth, gridWidth, playerX) * tileWidth);
	c.y = (long)(center(windowHeight, gridHeight, playerY) * tileHeight);

	Gosu::Transform trans = Gosu::translate((double)c.x, (double)c.y);
	return trans;
}

bool Area::needsRedraw() const
{
	return player->needsRedraw();
{'fraction_non_alphanumeric': 0.16636609558160506, 'fraction_numerical': 0.008340847610459874, 'mean_word_length': 3.5690010298661172, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 67, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5470339', 'n_tokens_mistral': 3400, 'n_tokens_neox': 3129, 'n_words': 843}