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)); } }
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); }
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); }
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; } } } }