예제 #1
0
void
Box2DComponent::update(float d)
{
	MMUNUSED(d);

	if (!m_p->position) {
		m_p->position = entity().getComponentType("Game::PositionComponent").
		    staticCast<PositionComponent>();
	}

	if (!m_p->render) {
		m_p->render = entity().getComponentType("Game::RenderComponent").
		    staticCast<RenderComponent>();
	}

	if (!m_p->init && !m_p->b2layer && m_p->position) {
		WeakSceneLayer l_layer = entity().layer().scene().getLayerType("Game::Box2DSceneLayer");
		m_p->b2layer = l_layer.cast<Box2DSceneLayer>();

		if (!m_p->b2layer) {
			MMWARNING("Box2DComponent used with non Box2D Scene!");
			return;
		}

		b2World &l_world = m_p->b2layer->world();

		/* create box2d body */
		b2BodyDef bodyDef;
		bodyDef.type = static_cast<b2BodyType>(m_p->body_type);
#define DEGREE_TO_RADIAN 0.0174532925f
		if (m_p->render) bodyDef.angle = m_p->render->mesh()->rotation() * DEGREE_TO_RADIAN;
		bodyDef.position.Set
		    (m_p->position->position().x,
		     m_p->position->position().y);
		m_p->body = l_world.CreateBody(&bodyDef);

		/* create shape */
		b2PolygonShape l_dynamicBox;
		l_dynamicBox.SetAsBox(m_p->size.width  / 2.f,
		                      m_p->size.height / 2.f);

		/* create fixture */
		b2FixtureDef l_fixtureDef;
		l_fixtureDef.shape = &l_dynamicBox;
		l_fixtureDef.density = m_p->density;
		l_fixtureDef.friction = m_p->friction;
		m_p->body->CreateFixture(&l_fixtureDef);

		m_p->init = true;
	}

	/* abort if not initialized */
	if (!m_p->init)
		return;

	b2Vec2 l_position = m_p->body->GetPosition();
	float32 l_angle = m_p->body->GetAngle();

	/* entity position */
	m_p->position->position().x = l_position.x;
	m_p->position->position().y = l_position.y;

	/* render mesh rotation */
	if (m_p->render) {
#define RADIAN_TO_DEGREE 57.2957795f
		Graphics::WeakMeshBase l_gbase(m_p->render->mesh().staticCast<Graphics::MeshBase>());
		if (l_gbase) l_gbase->setRotation(fmodf(l_angle * RADIAN_TO_DEGREE, 360.f));
	}
}
예제 #2
0
bool
TMXLoader::Private::processObjectGroup(XMLElement &e)
{
	const char *l_name;

	if ((!(l_name = e.Attribute("name")))) {
		MMWARNING("Object group element is missing one or more required attributes.");
		return(false);
	}

	Game::EntitySceneLayer *l_layer = new Game::EntitySceneLayer(l_name, scene);

	XMLElement *l_object = e.FirstChildElement(TMXOBJECTGROUP_OBJECT_NODE);
	while (l_object) {
		const char *l_object_name;
		const char *l_object_type;
		int l_object_gid;
		int l_object_x;
		int l_object_y;
		int l_object_width = tile_size.width;
		int l_object_height = tile_size.height;

		l_object_name = l_object->Attribute("name");
		l_object_type = l_object->Attribute("type");

		Game::SharedEntity l_entity = Game::Factory::Instance()->
		    createEntity(l_object_type, l_object_name ? l_object_name : "", *l_layer);
		if (!l_entity) {
			MMWARNING("Object '" << l_object_name << "' of type '" << l_object_type << "' was left unhandled.");
			return(false);
		}

		if ((XML_SUCCESS != l_object->QueryIntAttribute("x", &l_object_x))
		 || (XML_SUCCESS != l_object->QueryIntAttribute("y", &l_object_y))) {
			MMWARNING("Object element is missing one or more required attributes.");
			return(false);
		}

		/* map offset position (0 in the middle) */
		l_object_x -= (map_size.width * tile_size.width) / 2;
		l_object_y -= (map_size.height * tile_size.height) / 2;
		l_object_y *= -1; /* invert top/bottom */

		/* object size (later initialized) */
		Math::Size2f l_object_rsize;
		Math::Size2f l_object_hrsize;

		/* standard object */
		if (XML_SUCCESS != l_object->QueryIntAttribute("gid", &l_object_gid)) {
			l_object->QueryIntAttribute("width",  &l_object_width);
			l_object->QueryIntAttribute("height", &l_object_height);

			/* calculate object size */
			l_object_rsize.width = scale.width * static_cast<float>(l_object_width);
			l_object_rsize.height = scale.height * static_cast<float>(l_object_height);
			l_object_hrsize = l_object_rsize / 2.f;

		}

		/* tile object */
		else {
			bool l_found = false;
			uint16_t l_ts_firstgid = 0;

			/* offset position to top-left (later centered) */
			l_object_y += l_object_height;

			/* look for appropriate tileset */
			TilesetCollection::iterator l_tileset_i;
			for (l_tileset_i = tilesets.begin(); l_tileset_i != tilesets.end(); ++l_tileset_i)
				if (l_tileset_i->first > l_ts_firstgid && l_tileset_i->first <= l_object_gid) {
					l_ts_firstgid = l_tileset_i->first;
					l_found = true;
				}

			if (!l_found) {
				MMWARNING("Object tile GID tileset was not found.");
				return(false);
			}

			Graphics::SharedTileset l_tileset = tilesets[l_ts_firstgid];

			/* calculate object size from tileset */
			l_object_width  = l_tileset->tileSize().width;
			l_object_height = l_tileset->tileSize().height;
			l_object_rsize.width  = scale.width  * static_cast<float>(l_object_width);
			l_object_rsize.height = scale.height * static_cast<float>(l_object_height);
			l_object_hrsize = l_object_rsize / 2.f;

			/* attach tileset used */

			Game::TilesetComponent *l_tscomponent = new Game::TilesetComponent("tileset", *l_entity);
			l_tscomponent->tileset() = l_tileset;
			l_entity->pushComponent(l_tscomponent);

			/* generate tile mesh */

			Game::RenderComponent *l_render = new Game::RenderComponent("render", *l_entity);

			Graphics::SharedVertexData l_vdata = Graphics::Factory::CreateVertexData(MARSHMALLOW_QUAD_VERTEXES);
			l_vdata->set(0, -l_object_hrsize.width,  l_object_hrsize.height);
			l_vdata->set(1, -l_object_hrsize.width, -l_object_hrsize.height);
			l_vdata->set(2,  l_object_hrsize.width,  l_object_hrsize.height);
			l_vdata->set(3,  l_object_hrsize.width, -l_object_hrsize.height);

			Graphics::SharedTextureCoordinateData l_tdata =
			    l_tileset->getTextureCoordinateData(static_cast<uint16_t>(l_object_gid - l_ts_firstgid));

			l_render->mesh() =
			    new Graphics::QuadMesh(l_tdata, l_tileset->textureData(), l_vdata);

			l_entity->pushComponent(l_render);
		}

		/* create position component */
		Game::PositionComponent *l_pos_component = new Game::PositionComponent("position", *l_entity);
		l_pos_component->position().x = scale.width  * static_cast<float>(l_object_x);
		l_pos_component->position().y = scale.height * static_cast<float>(l_object_y);

		/* change position to center of object (offset) */
		l_pos_component->position().x += l_object_hrsize.width;
		l_pos_component->position().y -= l_object_hrsize.height;

		l_entity->pushComponent(l_pos_component);

		/* create size component */
		Game::SizeComponent *l_size = new Game::SizeComponent("size", *l_entity);
		l_size->size() = l_object_rsize;
		l_entity->pushComponent(l_size);

		/* object properties */
		XMLElement *l_properties = l_object->FirstChildElement(TMXPROPERTIES_NODE);
		XMLElement *l_property = l_properties ? l_properties->FirstChildElement(TMXPROPERTIES_PROPERTY_NODE) : 0;
		if (l_property) {
			Game::PropertyComponent *l_pcomponent = new Game::PropertyComponent("property", *l_entity);

			do {
				const char *l_pname = l_property->Attribute("name");
				const char *l_value = l_property->Attribute("value");

				if (!l_pname || !l_value)
					continue;

				l_pcomponent->set(l_pname, l_value);
			} while ((l_property = l_property->NextSiblingElement(TMXPROPERTIES_PROPERTY_NODE)));

			l_entity->pushComponent(l_pcomponent);
		}

		/* add entity to layer */
		l_layer->addEntity(l_entity);

		l_object = l_object->NextSiblingElement(TMXOBJECTGROUP_OBJECT_NODE);
	}

	layers.push_back(l_layer);

	return(true);
}
예제 #3
0
bool
TMXLoader::Private::processMap(XMLElement &m)
{
	if ((XML_SUCCESS != m.QueryIntAttribute("width", &map_size.width))
	 || (XML_SUCCESS != m.QueryIntAttribute("height", &map_size.height))
	 || (XML_SUCCESS != m.QueryIntAttribute("tilewidth", &tile_size.width))
	 || (XML_SUCCESS != m.QueryIntAttribute("tileheight", &tile_size.height))) {
		MMWARNING("Map element is missing one or more required attributes.");
		return(false);
	}

	/* default scale */
	scale.set(1.f, 1.f);

	/* process properties */
	XMLElement *l_properties = m.FirstChildElement(TMXPROPERTIES_NODE);
	XMLElement *l_property = l_properties ? l_properties->FirstChildElement(TMXPROPERTIES_PROPERTY_NODE) : 0;
	if (l_property)
	do {
		const char *l_pname = l_property->Attribute("name");
		if (!l_pname)
			continue;

		/* scale property */
		if (0 == MMSTRCASECMP(l_pname, "scale")) {
			const char *l_value = l_property->Attribute("value");
			if (!l_value) {
				MMWARNING("Skipping incomplete scale property.");
				continue;
			}

			if (0 == MMSTRCASECMP(l_value, "screen")) {
				const Math::Size2f &l_vsize = Graphics::Viewport::Size();
				const Math::Size2i &l_wsize = Graphics::Viewport::WindowSize();

				/*
				 * calculate pixels per viewport coordinate ratio
				 * scale ratio = vSize (vcoord)) / wSize (pixels)
				 */
				scale = l_vsize / l_wsize.cast<float>();

				continue;
			}
			else if (2 == sscanf(l_value, "%fx%f", &scale.width, &scale.height))
				continue;
			else if (1 == sscanf(l_value, "%f", &scale.width)) {
				scale.height = scale.width;
				continue;
			}

			MMERROR("Invalid scale value encountered.");
			continue;
		}

		/*
		 * Parse scene background color
		 */
		else if (0 == MMSTRCASECMP(l_pname, "bgcolor")) {
			const char *l_value = l_property->Attribute("value");
			if (!l_value) {
				MMWARNING("Skipping incomplete background color property.");
				continue;
			}

			/*
			 * Valid formats: #RRGGBB, RRGGBB.
			 */
			uint16_t l_pxl[3];
			if ((sscanf(l_value, "#%2hx%2hx%2hx",
			        &l_pxl[0], &l_pxl[1], &l_pxl[2]) != 3) &&
			    (sscanf(l_value,  "%2hx%2hx%2hx",
			        &l_pxl[0], &l_pxl[1], &l_pxl[2]) != 3)) {
				MMWARNING("Skipping invalid background color value.");
				continue;
			}

			/* set background color */
			Game::SceneBase &l_scene_base =
			    static_cast<Game::SceneBase &>(scene);
			l_scene_base.setBackground(PixelToColor(l_pxl));
			continue;
		}

	} while ((l_property = l_property->NextSiblingElement(TMXPROPERTIES_PROPERTY_NODE)));

	MMINFO("Map scale size (" << scale.width << "x" << scale.height << ")");

	/* calculate half-relative map size (used to offset coordinates) */
	hrmap_size.width = scale.width
	    * static_cast<float>(map_size.width  * tile_size.width);
	hrmap_size.height = scale.height
	    * static_cast<float>(map_size.height * tile_size.height);

	return(true);
}
예제 #4
0
bool
TMXLoader::Private::processLayer(XMLElement &e)
{
	const char *l_name;
	float l_opacity = 1.f;
	int l_visible = 1;

	if ((!(l_name = e.Attribute("name")))) {
		MMWARNING("Layer element is missing one or more required attributes.");
		return(false);
	}

	MMIGNORE e.QueryFloatAttribute("opacity", &l_opacity);
	MMIGNORE e.QueryIntAttribute("visible", &l_visible);

	XMLElement *l_data = e.FirstChildElement(TMXLAYER_DATA_NODE);

	if (!l_data) {
		MMWARNING("Layer element is missing data element.");
		return(false);
	}

	const char *l_data_encoding;
	const char *l_data_compression;

	if (!(l_data_encoding = l_data->Attribute("encoding")) ||
	    !(l_data_compression = l_data->Attribute("compression"))) {
		MMWARNING("Layer data element is missing one or more required attributes.");
		return(false);
	}
	const char *l_data_raw = XMLUtil::SkipWhiteSpace(l_data->GetText());
	size_t l_data_raw_len = strlen(l_data_raw);

	/* right-side data trim */
	while (l_data_raw_len > 0 && isspace(l_data_raw[l_data_raw_len - 1]))
		--l_data_raw_len;

	if (!l_data_raw_len) {
		MMWARNING("Zero size layer data encountered.");
		return(false);
	}

	char *l_data_array = 0;

#define TMXDATA_ENCODING_BASE64 "base64"
	if (0 == strcmp(l_data_encoding, TMXDATA_ENCODING_BASE64)) {
		char *l_decoded_data;
		size_t l_decoded_data_size =
		    Core::Base64::Decode(l_data_raw, l_data_raw_len, &l_decoded_data);

#define TMXDATA_COMPRESSION_ZLIB "zlib"
		if (0 == strcmp(l_data_compression, TMXDATA_COMPRESSION_ZLIB)) {
			char *l_inflated_data;
			if (0 < Core::Zlib::Inflate(l_decoded_data, l_decoded_data_size,
			    static_cast<size_t>(map_size.width * map_size.height * 4), &l_inflated_data))
				l_data_array = l_inflated_data;
		}
#define TMXDATA_COMPRESSION_GZIP "gzip"
		else if (0 == strcmp(l_data_compression, TMXDATA_COMPRESSION_GZIP)) {
			char *l_inflated_data;
			if (0 < Core::Gzip::Inflate(l_decoded_data, l_decoded_data_size,
			    static_cast<size_t>(map_size.width * map_size.height * 4), &l_inflated_data))
				l_data_array = l_inflated_data;
		}

		delete[] l_decoded_data;
	}

#define TMXDATA_ENCODING_CSV "csv"
	else if (0 == strcmp(l_data_encoding, TMXDATA_ENCODING_CSV)) {
		// TODO(gamaral)
		assert(0 && "CSV data encoding is currently unimplemented");
		return(false);
	}

	if (!l_data_array)
		return(false);

	Game::TilemapSceneLayer *l_layer = new Game::TilemapSceneLayer(l_name, scene);
	l_layer->setData(reinterpret_cast<uint32_t *>(l_data_array));
	l_layer->setOpacity(l_opacity);
	l_layer->setSize(map_size);
	l_layer->setTileSize(tile_size);
	l_layer->setScale(scale);
	l_layer->setVisibility(1 == l_visible);

	/* process properties */
	XMLElement *l_properties = e.FirstChildElement(TMXPROPERTIES_NODE);
	XMLElement *l_property = l_properties ? l_properties->FirstChildElement(TMXPROPERTIES_PROPERTY_NODE) : 0;
	if (l_property)
	do {
		const char *l_pname = l_property->Attribute("name");
		const char *l_value = l_property->Attribute("value");
		if (!l_pname)
			continue;

		/* scale property */
		if (0 == strcmp(l_pname, "scale")) {
			if (!l_value) {
				MMWARNING("Skipping incomplete scale property.");
				continue;
			}

			Math::Size2f l_scale = l_layer->scale();
			if (0 == MMSTRCASECMP(l_value, "screen")) {
				const Math::Size2f &l_vsize = Graphics::Viewport::Size();
				const Math::Size2i &l_wsize = Graphics::Viewport::WindowSize();

				/*
				 * calculate pixels per viewport coordinate ratio
				 * scale ratio = vSize (vcoord)) / wSize (pixels)
				 */
				l_scale = l_vsize / l_wsize.cast<float>();
				l_layer->setScale(l_scale);

				continue;
			}
			else if (2 == sscanf(l_value, "%fx%f", &l_scale.width, &l_scale.height)) {
				l_layer->setScale(l_scale);
				continue;
			} else if (1 == sscanf(l_value, "%f", &l_scale.width)) {
				l_scale.height = l_scale.width;
				l_layer->setScale(l_scale);
				continue;
			}

			MMERROR("Invalid scale value encountered.");
			continue;
		}
		else l_layer->setProperty(l_name, l_value ? l_value : std::string());

	} while ((l_property = l_property->NextSiblingElement(TMXPROPERTIES_PROPERTY_NODE)));

	/* attach tilesets */
	TilesetCollection::iterator l_tileset_i;
	for (l_tileset_i = tilesets.begin(); l_tileset_i != tilesets.end(); ++l_tileset_i)
		l_layer->attachTileset(l_tileset_i->first, l_tileset_i->second);

	layers.push_back(l_layer);

	return(true);
}
void
ColliderComponent::update(float d)
{
	if (!m_p->movement) {
		m_p->movement = entity().getComponentType("Game::MovementComponent").
		    staticCast<MovementComponent>();
	}

	if (!m_p->position) {
		m_p->position = entity().getComponentType("Game::PositionComponent").
		    staticCast<PositionComponent>();
	}

	if (!m_p->size) {
		m_p->size = entity().getComponentType("Game::SizeComponent").
		    staticCast<SizeComponent>();
	}

	if (!m_p->init && !m_p->layer && m_p->position && m_p->size) {
		m_p->layer = entity().layer().scene()
		    .getLayerType("Game::CollisionSceneLayer").staticCast<CollisionSceneLayer>();
		if (!m_p->layer) {
			MMWARNING("Collider component used with no collision scene layer!");
			return;
		}

		/* register as collider */
		m_p->layer->registerCollider(*this);

		m_p->init = true;
	}

	if (m_p->active && m_p->init && m_p->movement && m_p->size && m_p->position) {
		ColliderList::const_iterator l_i;
		ColliderList::const_iterator l_c = m_p->layer->colliders().end();

		for (l_i = m_p->layer->colliders().begin(); l_i != l_c; ++l_i) {
			if (*l_i == this) continue;

			ColliderComponent *l_collider = *l_i;
			CollisionData data;

			if (m_p->bullet) {
				int l_steps = m_p->bullet_resolution;
				const float l_delta_step = d / static_cast<float>(l_steps);
				float l_bullet_delta = 0;

				for(int i = 1; i < l_steps; ++i) {
					if (isColliding(*l_collider, l_bullet_delta += l_delta_step, &data)) {
						collision(*l_collider, l_bullet_delta, data);
						continue;
					}
				}
			}
			else {
				if (isColliding(*l_collider, d, &data))
					collision(*l_collider, d, data);
				continue;
			}
		}
	}
}