예제 #1
0
onut::Entity* LevelGenerator::createRoom(int startX, int startY, const sRoom& room)
{
    auto pRoomEntity = new onut::Entity();
    pRoomEntity->setPosition({static_cast<float>(startX), static_cast<float>(startY), 0.f});

    // Create floor. 5x5
    for (int y = 0; y < room.h; ++y)
    {
        for (int x = 0; x < room.w; ++x)
        {
            const auto& tileId = room.tiles[(room.h - y - 1) * room.w * 2 + x * 2];
            const auto& modifier = room.tiles[(room.h - y - 1) * room.w * 2 + x * 2 + 1];

            onut::Entity* pEntity = nullptr;

            // Solid
            if (isWall(tileId))
            {
                pEntity = onut::EntityFactory::createMesh({static_cast<float>(x), static_cast<float>(y), 0.f},
                                                          "assets/meshes/wall1.mesh", "assets/materials/wall1.material");
            }
            else if (isFloor(tileId))
            {
                if (onut::randb(.04f))
                {
                    pEntity = onut::EntityFactory::createMesh({static_cast<float>(x), static_cast<float>(y), 0.f},
                                                              "assets/meshes/floor2.mesh", "assets/materials/floor2.material");
                }
                else
                {
                    pEntity = onut::EntityFactory::createMesh({static_cast<float>(x), static_cast<float>(y), 0.f},
                                                              "assets/meshes/floor.mesh", "assets/materials/floor.material");
                }
            }

            // Addons
            if (pEntity)
            {
                if (isTorch(tileId) && onut::randb(.85f))
                {
                    pEntity->add(createTorch({0.f, 0.75f}));
                }
                pEntity->setRotation({0, 0, getAngle(modifier)});
            }

            pRoomEntity->add(pEntity);
        }
    }

    return pRoomEntity;
}
예제 #2
0
파일: Sewer.cpp 프로젝트: ronw23/prime-osx
//flood fills some muck starting at x,y
int
shMapLevel::floodMuck (int sx, int sy, shTerrainType type, int amount)
{
    int x, y, i;
    shDirection dirs[4] = { kNorth, kSouth, kEast, kWest };
    shDirection dir;
    int n = 0;
    shVector <int> points;

    points.add (xytop (sx, sy));

    for (n = 0; n < amount;) {
        int p;
        if (0 == points.count ()) {
            return n;
        }
        p = points.removeByIndex (RNG (points.count ()));
        x = ptox (p);
        y = ptoy (p);

        if (!isFloor (x, y) or kSewage == getSquare (x, y) ->mTerr) {
            continue;
        }
        n++;

        if (RNG(2))
            SETSQ (x, y, kSewage);

        for (i = 0; i < 4; i++) {
            dir = dirs[i];
            int x2 = x;
            int y2 = y;


            if (moveForward (dir, &x2, &y2) and
                RNG (20) >= points.count ())
            {
                points.add (xytop (x2, y2));
            }
        }
    }
    return n;
}
void LVL_Player::_collideUnduck()
{
    _syncPosition();
    if(isWarping) return;

    #ifdef COLLIDE_DEBUG
    qDebug() << "do unduck!";
    #endif

    //Detect collidable blocks!
    QVector<PGE_Phys_Object*> bodies;
    PGE_RectF posRectC = posRect;
    posRectC.setTop(posRectC.top()-4.0f);
    posRectC.setLeft(posRectC.left()+1.0f);
    posRectC.setRight(posRectC.right()-1.0f);
    posRectC.setBottom(posRectC.bottom()+ (ducking ? 0.0:(-posRect.height()/2.0))+4.0 );
    LvlSceneP::s->queryItems(posRectC, &bodies);

    forceCollideCenter=true;
    for(PGE_RenderList::iterator it=bodies.begin();it!=bodies.end(); it++ )
    {
        PGE_Phys_Object*body=*it;
        if(body==this) continue;
        if(body->isPaused()) continue;
        if(!body->isVisible()) continue;
        solveCollision(body);
    }
    forceCollideCenter=false;

    #ifdef COLLIDE_DEBUG
    int hited=0;
    PGE_RectF nearestRect;
    #endif

    bool resolveTop=false;
    double _floorY=0;
    QVector<PGE_Phys_Object*> blocks_to_hit;

    if((!collided_center.isEmpty())&&(collided_bottom.isEmpty()))
    {
        for(PlayerColliders::iterator it=collided_center.begin(); it!=collided_center.end() ; it++)
        {
            PGE_Phys_Object *collided= *it;
            LVL_Block *blk= static_cast<LVL_Block*>(collided);
            if(blk) blocks_to_hit.push_back(blk);
        }
        for(PlayerColliders::iterator it=collided_top.begin(); it!=collided_top.end() ; it++)
        {
            PGE_Phys_Object *collided= *it;
            LVL_Block *blk= static_cast<LVL_Block*>(collided);
            if(blk) blocks_to_hit.push_back(blk);
        }
        if(isFloor(blocks_to_hit))
        {
            PGE_Phys_Object*nearest = nearestBlockY(blocks_to_hit);
            if(nearest)
            {
                _floorY=nearest->posRect.bottom()+1.0;
                resolveTop=true;
            }
        }
    }

    if(resolveTop)
    {
        posRect.setY(_floorY);
        if(!blocks_to_hit.isEmpty())
        {
            PGE_Phys_Object*nearest_obj=nearestBlock(blocks_to_hit);
            if(nearest_obj && (nearest_obj->type==PGE_Phys_Object::LVLBlock))
            {
                LVL_Block*nearest = static_cast<LVL_Block*>(nearest_obj);
                resolveTop=true;
                long npcid=nearest->data.npc_id;
                nearest->hit();
                if( nearest->setup->hitable || (npcid!=0) || (nearest->destroyed) || (nearest->setup->bounce) )
                {
                    bump(false, speedY());
                }
            }
            else
            {
                PGE_Audio::playSoundByRole(obj_sound_role::BlockHit);
            }
        }
        setSpeedY(0.0);
        _syncPosition();
    }

    _heightDelta = 0.0;
    #ifdef COLLIDE_DEBUG
    qDebug() << "unduck: blocks to hit"<< hited << " Nearest: "<<nearestRect.top() << nearestRect.bottom() << "are bottom empty: " << collided_bottom.isEmpty() << "bodies found: "<<bodies.size() << "bodies at center: "<<collided_center.size();
    #endif
}
void LVL_Player::updateCollisions()
{
    foot_contacts_map.clear();
    _onGround=false;
    foot_sl_contacts_map.clear();
    contactedWarp = NULL;
    contactedWithWarp=false;
    climbable_map.clear();
    environments_map.clear();

    collided_top.clear();
    collided_left.clear();
    collided_right.clear();
    collided_bottom.clear();
    collided_center.clear();

    collided_talkable_npc = NULL;

    collided_slope=false;
    collided_slope_direct=0;
    collided_slope_angle_ratio=0.0f;

    _velocityX_add=0;
    _velocityY_add=0;

    #ifdef COLLIDE_DEBUG
    qDebug() << "=====Collision check and resolve begin======";
    #endif

    PGE_Phys_Object::updateCollisions();

    bool resolveBottom=false;
    bool resolveTop=false;
    bool resolveLeft=false;
    bool resolveRight=false;

    double backupX=posRect.x();
    double backupY=posRect.y();
    double _wallX=posRect.x();
    double _floorY=posRect.y();

    double _floorX_vel=0.0;//velocities sum
    double _floorX_num=0.0;//num of velocities
    double _floorY_vel=0.0;//velocities sum
    double _floorY_num=0.0;//num of velocities

    QVector<PGE_Phys_Object*> floor_blocks;
    QVector<PGE_Phys_Object*> wall_blocks;
    QVector<PGE_Phys_Object*> blocks_to_hit;
    //QVector<PGE_Phys_Object*> add_speed_to;

    if(!collided_bottom.isEmpty())
    {
        for(PlayerColliders::iterator it=collided_bottom.begin(); it!=collided_bottom.end() ; it++)
        {
            PGE_Phys_Object *collided= *it;
            switch(collided->type)
            {
                case PGE_Phys_Object::LVLBlock:
                {
                    LVL_Block *blk= static_cast<LVL_Block*>(collided);
                    if(!blk) continue;
                    foot_contacts_map[(intptr_t)collided]=collided;
                    if(blk->slippery_surface) foot_sl_contacts_map[(intptr_t)collided]=collided;
                    if(blk->setup->bounce) blocks_to_hit.push_back(blk);
                    floor_blocks.push_back(blk);
                    _floorY_vel+=blk->speedYsum();
                    _floorY_num+=1.0;
                    _floorX_vel+=blk->speedXsum();
                    _floorX_num+=1.0;
                } break;
                case PGE_Phys_Object::LVLNPC:
                {
                    LVL_Npc *npc= static_cast<LVL_Npc*>(collided);
                    if(!npc) continue;
                    foot_contacts_map[(intptr_t)collided]=collided;
                    if(npc->slippery_surface) foot_sl_contacts_map[(intptr_t)collided]=collided;
                    floor_blocks.push_back(npc);
                    _floorY_vel+=npc->speedYsum();
                    _floorY_num+=1.0;
                    _floorX_vel+=npc->speedXsum();
                    _floorX_num+=1.0;
                }
                break;
                default:break;
            }
        }
        if(_floorX_num!=0.0) _floorX_vel=_floorX_vel/_floorX_num;
        if(_floorY_num!=0.0) _floorY_vel=_floorY_vel/_floorY_num;
        if(!foot_contacts_map.isEmpty())
        {
            _velocityX_add=_floorX_vel;
            _velocityY_add=_floorY_vel;
        }

        if(isFloor(floor_blocks))
        {
            PGE_Phys_Object*nearest = nearestBlockY(floor_blocks);
            if(nearest)
            {
                LVL_Block *blk= static_cast<LVL_Block*>(nearest);
                if(blk && (blk->shape!=LVL_Block::shape_rect))
                {
                    if(blk->shape==LVL_Block::shape_tr_top_right)
                    {
                        _floorY = nearest->posRect.bottom()-SL_HeightTopRight(nearest);
                        if(_floorY<nearest->top()) _floorY=nearest->posRect.top();
                        else if(_floorY>nearest->bottom()) _floorY=nearest->posRect.bottom();
                    }
                    else
                    if(blk->shape==LVL_Block::shape_tr_top_left)
                    {
                        _floorY = nearest->posRect.bottom()-SL_HeightTopLeft(nearest);
                        if(_floorY<nearest->top()) _floorY=nearest->posRect.top();
                        else if(_floorY>nearest->bottom()) _floorY=nearest->posRect.bottom();
                    }
                    else
                    if(blk->shape==LVL_Block::shape_tr_bottom_right)
                    {
                        _floorY = nearest->posRect.top()+SL_HeightTopRight(nearest);
                        if(_floorY<nearest->top()) _floorY=nearest->posRect.top();
                        else if(_floorY>nearest->bottom()) _floorY=nearest->posRect.bottom();
                    }
                    else
                    if(blk->shape==LVL_Block::shape_tr_bottom_left)
                    {
                        _floorY = nearest->posRect.top()+SL_HeightTopLeft(nearest);
                        if(_floorY<nearest->top()) _floorY=nearest->posRect.top();
                        else if(_floorY>nearest->bottom()) _floorY=nearest->posRect.bottom();
                    }
                    else
                        _floorY = nearest->posRect.top();
                    _floorY-=posRect.height();
                } else {
                    _floorY = nearest->posRect.top()-posRect.height();
                }
                resolveBottom=true;
            }
        }
        else
        {
            foot_contacts_map.clear();
            foot_sl_contacts_map.clear();
        }
    }

    if(!collided_top.isEmpty())
    {
        blocks_to_hit.clear();
        for(PlayerColliders::iterator it=collided_top.begin(); it!=collided_top.end() ; it++)
        {
            PGE_Phys_Object *body= *it;
            if(body) blocks_to_hit.push_back(body);
            if(body) floor_blocks.push_back(body);
        }
        if(isFloor(floor_blocks))
        {
            PGE_Phys_Object*nearest = nearestBlockY(blocks_to_hit);
            if(nearest)
            {
                if(!resolveBottom)
                {
                    LVL_Block *blk= static_cast<LVL_Block*>(nearest);
                    if(blk && (blk->shape!=LVL_Block::shape_rect))
                    {
                        if(blk->shape==LVL_Block::shape_tr_bottom_right)
                        {
                            _floorY = nearest->posRect.top()+SL_HeightTopLeft(nearest);
                            if(_floorY<nearest->top()) _floorY=nearest->posRect.top();
                            else if(_floorY>nearest->bottom()) _floorY=nearest->posRect.bottom();
                        }
                        else
                        if(blk->shape==LVL_Block::shape_tr_bottom_left)
                        {
                            _floorY = nearest->posRect.top()+SL_HeightTopRight(nearest);
                            if(_floorY<nearest->top()) _floorY=nearest->posRect.top();
                            else if(_floorY>nearest->bottom()) _floorY=nearest->posRect.bottom();
                        }
                    }
                    else
                        _floorY = nearest->posRect.bottom();
                    _floorY+=1;
                }
                resolveTop=true;
            }
        }
    }

    bool wall=false;
    if(!collided_left.isEmpty())
    {
        for(PlayerColliders::iterator it=collided_left.begin(); it!=collided_left.end() ; it++)
        {
            PGE_Phys_Object *body= *it;
            if(body) wall_blocks.push_back(body);
        }
        if(isWall(wall_blocks))
        {
            PGE_Phys_Object*nearest = nearestBlock(wall_blocks);
            if(nearest)
            {
                _wallX = nearest->posRect.right();
                resolveLeft=true;
                wall=true;
            }
        }
    }

    if(!collided_right.isEmpty())
    {
        wall_blocks.clear();
        for(PlayerColliders::iterator it=collided_right.begin(); it!=collided_right.end() ; it++)
        {
            PGE_Phys_Object *body= *it;
            if(body) wall_blocks.push_back(body);
        }
        if(isWall(wall_blocks))
        {
            PGE_Phys_Object*nearest = nearestBlock(wall_blocks);
            if(nearest)
            {
                _wallX = nearest->posRect.left()-posRect.width();
                resolveRight=true;
                wall=true;
            }
        }
    }

    if((resolveLeft||resolveRight) && (resolveTop||resolveBottom))
    {
        //check if on floor or in air
        bool _iswall=false;
        bool _isfloor=false;
        posRect.setX(_wallX);
        _isfloor=isFloor(floor_blocks);
        posRect.setPos(backupX, _floorY);
        _iswall=isWall(wall_blocks);
        posRect.setX(backupX);
        if(!_iswall && _isfloor)
        {
            resolveLeft=false;
            resolveRight=false;
        }
        if(!_isfloor && _iswall)
        {
            resolveTop=false;
            resolveBottom=false;
        }
    }

    if(resolveLeft || resolveRight)
    {
        posRect.setX(_wallX);
        setSpeedX(0);
        _velocityX_add=0;
    }
    if(resolveBottom || resolveTop)
    {
        posRect.setY(_floorY);
        float bumpSpeed=speedY();
        setSpeedY(_floorY_vel);
        _velocityY_add=0;
        if(!blocks_to_hit.isEmpty())
        {
            PGE_Phys_Object* nearestObj=nearestBlock(blocks_to_hit);
            if(nearestObj && (nearestObj->type==PGE_Phys_Object::LVLBlock))
            {
                LVL_Block*nearest = static_cast<LVL_Block*>(nearestObj);
                long npcid=nearest->data.npc_id;
                if(resolveBottom) nearest->hit(LVL_Block::down); else nearest->hit();
                if( nearest->setup->hitable || (npcid!=0) || (nearest->destroyed) || nearest->setup->bounce )
                    bump(resolveBottom,
                         (resolveBottom ? physics_cur.velocity_jump_bounce : bumpSpeed),
                         physics_cur.jump_time_bounce);
            }
            else
            {
                PGE_Audio::playSoundByRole(obj_sound_role::BlockHit);
            }
        }
        if(resolveTop && !bumpUp && !bumpDown )
            jumpTime=0;
    }
    else
    {
        posRect.setY(backupY);
    }
    _stucked = ( (!collided_center.isEmpty()) && (!collided_bottom.isEmpty()) && (!wall) );

    #ifdef COLLIDE_DEBUG
    qDebug() << "=====Collision check and resolve end======";
    #endif
}