void Entity::move(sfld::Vector2f direction, int frameTime, float magnitude){ EntityList* list = entityManager_->getEntities(); for (auto& it : *list){ if (it.get() != this){ float dist = sfld::Vector2f(it->getPosition() - getPosition()).length(); if (!it->isWalkthrough()){ if (dist <= TILE_SIZE*1.5f){ //need accurate collisions here MTV mtv(Collision::getCollision(getSprite(), getShape(), it->getSprite(), it->getShape())); if (!(mtv.axis == MTV::NONE.axis && mtv.overlap == MTV::NONE.overlap)){; //collided sfld::Vector2f n = mtv.axis; sfld::Vector2f comp_u(0, 0); if (direction.dot(n) < 0){ if (n != sfld::Vector2f(0, 0)){ comp_u = n * (direction.dot(n) / n.dot(n)); //component of hit axis in dir } } direction = direction - comp_u; collided(it.get()); if (it->getDynamic() == DYNAMIC_STATIC){ //because then it won't resolve its own collisions it->collided(this); } } } } else{//otherwise, it's a circle, and we are only concerned with checking if they touch, no more if (dist <= TILE_SIZE*1.5f){ MTV mtv(Collision::getCollision(getSprite(), getShape(), it->getSprite(), it->getShape())); if (!(mtv.axis == MTV::NONE.axis && mtv.overlap == MTV::NONE.overlap)){ collided(it.get()); if (it->getDynamic() == DYNAMIC_STATIC){ //because then it won't resolve its own collisions it->collided(this); } } } } } } if (direction != sf::Vector2f(0, 0) && !rotating_){ //lastdir = dir; sprite_.setRotation(maths::toDegrees(atan2(direction.y, direction.x))); } doOffset(direction*(float)frameTime*magnitude); }
void ProcessView::onModulesActionTriggered() { // Alternative way: currentIndex().row() QModelIndexList indexList = this->selectionModel()->selectedRows(); unsigned int pid = model()->data(model()->index(indexList.first().row(), 1)).toUInt(); if (pid >= 0) { ModulesTableView mtv(pid); mtv.exec(); } }
void LSCompiler::processTypes(ModuleBuildInfo *mbi) { // process the fully qualified type information for (UTsize j = 0; j < mbi->getNumSourceFiles(); j++) { utString filename = mbi->getSourceFilename(j); CompilationUnit *cunit = mbi->getCompilationUnit(filename); logVerbose("Type Qualifying Visitor %s", cunit->filename.c_str()); TypeQualifyVisitor tqv(vm); tqv.visit(cunit); } // process the member types, so everything is available once // we get to the method code for (UTsize j = 0; j < mbi->getNumSourceFiles(); j++) { utString filename = mbi->getSourceFilename(j); CompilationUnit *cunit = mbi->getCompilationUnit(filename); logVerbose("Type Member Visitor %s", cunit->filename.c_str()); MemberTypeVisitor mtv(vm, cunit); mtv.processMemberTypes(); } // generate type info for method code for (UTsize j = 0; j < mbi->getNumSourceFiles(); j++) { utString filename = mbi->getSourceFilename(j); CompilationUnit *cunit = mbi->getCompilationUnit(filename); logVerbose("Type Visitor %s", cunit->filename.c_str()); TypeVisitor tv(vm); tv.visit(cunit); } // if we have any compiler errors, dump them and exit if (LSCompilerLog::getNumErrors()) { LSCompilerLog::dump(); exit(EXIT_FAILURE); } // validate types for (UTsize j = 0; j < mbi->getNumSourceFiles(); j++) { utString filename = mbi->getSourceFilename(j); CompilationUnit *cunit = mbi->getCompilationUnit(filename); logVerbose("Type Validating %s", cunit->filename.c_str()); for (UTsize k = 0; k < cunit->classDecls.size(); k++) { TypeValidator tv(vm, cunit, cunit->classDecls.at(k)); tv.validate(); } } // if we have any compiler errors, dump them and exit if (LSCompilerLog::getNumErrors()) { LSCompilerLog::dump(); exit(EXIT_FAILURE); } }
///////////////////// // static QVector<QSharedPointer<MetaTypeVariant> > MarshallRuby::VALUE2MTVariant(VALUE v) { QVector<QSharedPointer<MetaTypeVariant> > rvs(1); QSharedPointer<MetaTypeVariant> rv; QString str, str2; void *ci = NULL; QObject *obj = NULL; VALUE v1, v2, v3; switch (TYPE(v)) { case T_NONE: rv = QSharedPointer<MetaTypeVariant>(new MetaTypeVariant()); break; case T_FIXNUM: { QVariant num = (int)FIX2INT(v); rv = QSharedPointer<MetaTypeVariant>(new MetaTypeVariant(QMetaType::Int, &num)); }; break; case T_STRING: { QVariant str = QString(RSTRING_PTR(v)); rv = QSharedPointer<MetaTypeVariant>(new MetaTypeVariant(QMetaType::QString, &str)); }; break; case T_FLOAT: { QVariant num = RFLOAT_VALUE(v); rv = QSharedPointer<MetaTypeVariant>(new MetaTypeVariant(QMetaType::Double, &num)); }; break; case T_NIL: { QVariant num = 0; rv = QSharedPointer<MetaTypeVariant>(new MetaTypeVariant(QMetaType::Int, &num)); }; break; case T_TRUE: { QVariant ok = true; rv = QSharedPointer<MetaTypeVariant>(new MetaTypeVariant(QMetaType::Bool, &ok)); }; break; case T_FALSE: { QVariant ok = false; rv = QSharedPointer<MetaTypeVariant>(new MetaTypeVariant(QMetaType::Bool, &ok)); }; break; case T_OBJECT: { str = QString(rb_class2name(RBASIC_CLASS(v))); ci = Qom::inst()->getObject(v); // obj = dynamic_cast<QObject*>(ci); qDebug()<<"unimpl VALUE:"<<str<<ci<<obj; // rv = QVariant(QMetaType::VoidStar, ci); // rv = QVariant::fromValue(ci); QVariant vrv = QVariant::fromValue(ci); rv = QSharedPointer<MetaTypeVariant>(new MetaTypeVariant(QMetaType::VoidStar, &vrv)); }; break; case T_ARRAY: { QStringList ary; // ary << "a123" << "b3456"; qDebug()<<RARRAY_LEN(v)<<QT_VERSION; for (int i = 0; i < RARRAY_LEN(v); i++) { // FIXME: 也可能是对象数组,如Qt5::QString,但toString方法不好用。 // FIXME: 如,[Qt5::QApplication.translate("MainWindow", "acbc", nil), "efgggggg", "hijjjjjjjj"] ary << VALUE2Variant(rb_ary_entry(v, i)).toString(); } // rv = QVariant(ary); QVariant vary(ary); rv = QSharedPointer<MetaTypeVariant>(new MetaTypeVariant(QMetaType::QStringList, &vary)); }; break; case T_STRUCT: { // for ruby range str = rb_class2name(RBASIC_CLASS(v)); if (str == "Range") { // qDebug()<<"Range is struct???"<<BUILTIN_TYPE(v) // <<rb_class2name(RBASIC_CLASS(v)) // <<RSTRUCT_LEN(v); v1 = RSTRUCT_GET(v, 0); v2 = RSTRUCT_GET(v, 1); v3 = RSTRUCT_GET(v, 2); // qDebug()<<TYPE(v1)<<TYPE(v2)<<TYPE(v3); // qDebug()<<FIX2INT(v1)<<FIX2INT(v2); // rv = QVariant(FIX2INT(v1)); // rvs.append(QVariant(FIX2INT(v2))); QVariant num1 = FIX2INT(v1); QVariant num2 = FIX2INT(v2); rv = QSharedPointer<MetaTypeVariant>(new MetaTypeVariant(QMetaType::Int, &num1)); QSharedPointer<MetaTypeVariant> mtv(new MetaTypeVariant(QMetaType::Int, &num2)); rvs.append(mtv); } else { qDebug()<<"unsupported struct type:"<<str; } }; break; case T_CLASS: default: qDebug()<<"unknown VALUE type:"<<TYPE(v); break; } rvs[0] = rv; return (rvs); }
MTV Collision::getCollision(const sf::Sprite& object1,Entity::ENTITY_SHAPE shape1,const sf::Sprite& object2,Entity::ENTITY_SHAPE shape2){ //Use Separating Axis Theorem to determine whether two objects are overlapping //See documentation for full explanation of this algorithm //Get the oriented bounding box in world coordinates (includes rotation) of objects OBB obb1 = getOBB(object1); OBB obb2 = getOBB(object2); float rot = object1.getRotation(); double overlap = LONG_MAX; maths::Vector2 smallest(0,0); std::vector<maths::Vector2> axis1; std::vector<maths::Vector2> axis2; maths::Vector2 circleCentre1; maths::Vector2 circleCentre2; sf::FloatRect gbounds1 = object1.getGlobalBounds(); sf::FloatRect gbounds2 = object2.getGlobalBounds(); //Find all the axes to check using SAT based on shapes of objects //Works with squares/rectangles or circles //Rectangles only need 2 axes because they have 2 sets of parallel lines if(shape1 == Entity::SHAPE_CIRCLE && shape2 == Entity::SHAPE_CIRCLE){ //If both shapes are circles, the only axis needed is the axis between centres of circles circleCentre1 = maths::Vector2(gbounds1.left + gbounds1.width / 2, gbounds1.top + gbounds1.height / 2); circleCentre2 = maths::Vector2(gbounds2.left + gbounds2.width / 2, gbounds2.top + gbounds2.height / 2); axis1.push_back(maths::Vector2(circleCentre1 - circleCentre2).normalise()); }else if(shape1 != shape2){ //if one shape is circle and one shape is rectangle maths::Vector2 circleCentre; sf::FloatRect squareRect; float rotation; //First get the unrotated bounding box and centre of the circle of the 2 objects if(shape1 == Entity::SHAPE_CIRCLE){ circleCentre = maths::Vector2(gbounds1.left + gbounds1.width / 2, gbounds1.top + gbounds1.height / 2); circleCentre1 = circleCentre; squareRect = getOriginalBoundingBox(object2); rotation = object2.getRotation(); }else if(shape2 == Entity::SHAPE_CIRCLE){ circleCentre = maths::Vector2(gbounds2.left + gbounds2.width / 2, gbounds2.top + gbounds2.height / 2); circleCentre2 = circleCentre; squareRect = getOriginalBoundingBox(object1); rotation = object1.getRotation(); } maths::Vector2 squareCentre(squareRect.left + squareRect.width / 2, squareRect.top + squareRect.height / 2); OBB* square = (shape1 == Entity::SHAPE_SQUARE ? &obb1 : &obb2); maths::Vector2 relativeCircleCentre = circleCentre.rotate(-rotation, squareCentre); //get circle centre in relation to the rotated square bool vertice = false; maths::Vector2 axis; maths::Vector2 topLeft(squareRect.left, squareRect.top); maths::Vector2 topRight(squareRect.left + squareRect.width, squareRect.top); maths::Vector2 botLeft(squareRect.left, squareRect.top + squareRect.height); maths::Vector2 botRight(squareRect.left + squareRect.width, squareRect.top + squareRect.height); //Get the closest vertex of the rectangle to the circle centre. //The axis to check is the vector between these 2 points. if(circleCentre.x < topLeft.x){ if(circleCentre.y < topLeft.y){ vertice = true; axis = topLeft; }else if(circleCentre.y > botLeft.y){ vertice = true; axis = botLeft; }else{ axis = maths::Vector2(topLeft - botLeft).normalise(); } }else if(circleCentre.x > topRight.x){ if(circleCentre.y < topLeft.y){ vertice = true; axis = topRight; }else if(circleCentre.y > botLeft.y){ vertice = true; axis = botRight; }else{ axis = maths::Vector2(topRight - botRight).normalise(); } }else{ if(circleCentre.y < topLeft.y){ axis = maths::Vector2(topRight - topLeft).normalise(); }else if(circleCentre.y > botLeft.y){ axis = maths::Vector2(botLeft - botRight).normalise(); }else{ //contains point! } } if(vertice){ axis1.push_back(maths::Vector2(circleCentre - axis).normalise()); }else{ axis1.push_back(maths::Vector2(topRight - topLeft).normalise()); axis1.push_back(maths::Vector2(topRight - botRight).normalise()); } }else{ //If both shapes are rectangles //Get vectors for sides of shapes maths::Vector2 Xside1(obb1.bot_left - obb1.bot_right); maths::Vector2 Yside1(obb1.top_left - obb1.bot_left); maths::Vector2 Xside2(obb2.bot_left - obb2.bot_right); maths::Vector2 Yside2(obb2.top_left - obb2.bot_left); //Axes requires are perpendicular to the sides of the shape //Vector2.perpendicular() normalises for greater accuracy axis1.push_back(Xside1.perpendicular()); axis1.push_back(Yside1.perpendicular()); axis2.push_back(Xside2.perpendicular()); axis2.push_back(Yside2.perpendicular()); } //We have all the axes to check. //Now find details on collisions with projections. for(int i=0;i<axis1.size();i++){ //Get projection of axis for both shapes maths::Vector2 axis = axis1[i]; Projection projection1 = project(obb1, axis); if(shape1 == Entity::SHAPE_CIRCLE){ float radius = gbounds1.width / 2; projection1 = projectCircle(circleCentre1, radius, axis); } Projection projection2 = project(obb2, axis); if (shape2 == Entity::SHAPE_CIRCLE){ float radius = gbounds2.width / 2; projection2 = projectCircle(circleCentre2, radius, axis); } //If a projection does not overlap, we know the objects do not collide so we can exit the function. //Otherwise, the MTV (minimum translation vector required to make the objects not collide) is calculated. if(!projection1.overlap(projection2)){ return MTV::NONE; }else{ //The axis with the smallest overlap is the axis used to calculate MTV, so record it. double o = projection1.getOverlap(projection2); if(o < overlap){ overlap = o; //set smallest overlap smallest = axis; //set smallest separation vector } } } //Repeat the same process as above with the other set of axes. for(int i=0;i<axis2.size();i++){ maths::Vector2 axis = axis2[i]; Projection projection1 = project(obb1, axis); if(shape1 == Entity::SHAPE_CIRCLE){ float radius = gbounds1.width/2; projection1 = projectCircle(circleCentre1, radius, axis); } Projection projection2 = project(obb2,axis); if(shape2 == Entity::SHAPE_CIRCLE){ float radius = gbounds2.width / 2; projection2 = projectCircle(circleCentre2, radius, axis); } if(!projection1.overlap(projection2)){ return MTV::NONE; }else{ double o = projection1.getOverlap(projection2); if(o < overlap){ overlap = o; smallest = axis; } } } //Get the vector from the centre of object 2 to the centre of object 1 maths::Vector2 centre1 = maths::Vector2(gbounds1.left + gbounds1.width / 2, gbounds1.top + gbounds1.height / 2); maths::Vector2 centre2 = maths::Vector2(gbounds2.left + gbounds2.width / 2, gbounds2.top + gbounds2.height / 2); maths::Vector2 between = centre1 - centre2; //If the separation vector is in the opposite direction of 'between', flip it round by negating it if(between.dot(smallest) < 0){ smallest = -smallest; } MTV mtv(overlap, smallest); return mtv; }