void Board::roll(GroupSphere spheres) { int col = 0; GroupSphere spheres_end_board; _match_lock(); spheres_end_board.clear(); for(auto &sphere: spheres) { _grid.push_front(col, sphere); auto pos = PointGrid(col, 0); sphere->setPosition(pos); auto sphere_view = sphere->getView(); _node->addChild(sphere_view); auto poss = pos.toPoint(); poss.x += GRID_SIZE/2; poss.y *= -1; //invierte, para mostrar hacia abajo poss.y += _node->getContentSize().height; sphere_view->setPosition(poss); //std::cout << "Rolling sphere first" << std::endl; for(int row = _grid.getRows(); row > 0; row--){ Sphere* data = static_cast<Sphere*>(_grid.get(PointGrid(col, row))); if(!_grid.Empty(data)){ auto pos = PointGrid(col, row); auto sphere_view = data->getView(); data->setPosition(pos); auto poss = pos.toPoint(); poss.x += GRID_SIZE/2; poss.y *= -1; //invierte, para mostrar hacia abajo poss.y += _node->getContentSize().height; sphere_view->setPosition(poss); sphere_view->retain(); //std::cout << "Rolling sphere down" << std::endl; if(data->getPosition().y == _grid.getRows() - 1 //@patch para permitir colision ultima esfera ){ data->retain(); spheres_end_board.push_back(data); } } } col += 1; } _match_unlock(); for(auto &func: onAttachRoll) { func(spheres); } if(spheres_end_board.size()>0){ for(auto &func: onAttachEndBoard) { func(spheres_end_board); } } }
//-------------------------------------------------------------------------------------------- Uint8 FindTileInPassage( const int x0, const int y0, const int tiletype, const int passageID, int *px1, int *py1 ) { /// @author ZZ /// @details This function finds the next tile in the passage, x0 and y0 /// must be set first, and are set on a find. Returns true or false /// depending on if it finds one or not int x, y; ego_tile_info_t * ptile = NULL; const std::shared_ptr<Passage> &passage = _currentModule->getPassageByID(passageID); if ( !passage ) return false; // Do the first row x = x0 / GRID_ISIZE; y = y0 / GRID_ISIZE; if ( x < passage->getLeft() ) x = passage->getLeft(); if ( y < passage->getTop() ) y = passage->getTop(); if ( y < passage->getBottom() ) { for ( /*nothing*/; x <= passage->getRight(); x++ ) { TileIndex fan = _currentModule->getMeshPointer()->get_tile_int(PointGrid(x, y)); ptile = _currentModule->getMeshPointer()->get_ptile(fan); if ( NULL != ptile && tiletype == ( ptile->img & TILE_LOWER_MASK ) ) { *px1 = ( x * GRID_ISIZE ) + 64; *py1 = ( y * GRID_ISIZE ) + 64; return true; } } y++; } // Do all remaining rows for ( /* nothing */; y <= passage->getBottom(); y++ ) { for ( x = passage->getLeft(); x <= passage->getRight(); x++ ) { TileIndex fan = _currentModule->getMeshPointer()->get_tile_int(PointGrid(x, y)); ptile = _currentModule->getMeshPointer()->get_ptile(fan); if ( NULL != ptile && tiletype == ( ptile->img & TILE_LOWER_MASK ) ) { *px1 = x * GRID_ISIZE + 64; *py1 = y * GRID_ISIZE + 64; return true; } } } return false; }
void Board::fallSpheres(std::function<void(Sphere*,PointGrid)> logic){ GroupSphere spheres_fall; std::vector<PointGrid> spheres_fall_old_pos; std::vector<PointGrid> spheres_fall_new_pos; _match_lock(); //esto correge error de mal cambio de columna 0 a 11 //imprevistamente spheres_fall.clear(); std::cout << "GridCols:" << _grid.getCols() << " GridRows:" << _grid.getRows() << std::endl; for(int col=_grid.getCols()-1; col >= 0; col--){ for(int row=0; row < _grid.getRows(); row++){ PointGrid sphere_pos(col, row); Sphere* sphere = _grid.get(sphere_pos); //std::cout << "TryingFallingSphere:" << sphere_pos.x << "," << sphere_pos.y << std::endl; if(_grid.Empty(sphere)) continue; std::cout << "FallingSphere:" << sphere->getPosition().x << "," << sphere->getPosition().y << " Col: " << col << std::endl; sphere->retain(); PointGrid sphere_new_pos = PointGrid::BAD; for(int row_row=row-1; row_row>=0; row_row--){ if(_grid.Empty(PointGrid(col, row_row))){ std::cout << "FallingSphere::newpos:" << sphere_pos.x << "," << row_row << std::endl; sphere_new_pos = PointGrid(col, row_row); }else{ break; } } if(sphere_new_pos != PointGrid::BAD){ sphere->retain(); spheres_fall.push_back(sphere); spheres_fall_new_pos.push_back(sphere_new_pos); spheres_fall_old_pos.push_back(sphere->getPosition()); std::cout << "FallingSphere::newpos sended:" << sphere_new_pos.x << "," << sphere_new_pos.y << std::endl; if(logic) logic(sphere, sphere_new_pos); _grid.move(sphere->getPosition(), sphere_new_pos); sphere->setPosition(sphere_new_pos); } } } _match_unlock(); for(auto ifunc = onAttachFall.begin(); ifunc != onAttachFall.end(); ifunc++){ (*ifunc)(spheres_fall, spheres_fall_old_pos, spheres_fall_new_pos); } std::cout << "FallingSphere::End" << std::endl; }
void Board::updateView() { for(int col = _grid.getCols(); col > 0; col--){ for(int row = _grid.getRows(); row > 0; row--){ Sphere* data = static_cast<Sphere*>(_grid.get(PointGrid(col, row))); if(!_grid.Empty(data)){ data->updateView(GRID_SIZE/2, _node->getContentSize().height); } } } }
void Passage::open() { //no need to do this if it already is open if ( isOpen() ) { return; } if ( _area._top <= _area._bottom ) { _open = true; for ( int y = _area._top; y <= _area._bottom; y++ ) { for ( int x = _area._left; x <= _area._right; x++ ) { //clear impassable and wall bits TileIndex fan = _currentModule->getMeshPointer()->get_tile_int(PointGrid(x, y)); ego_mesh_clear_fx( _currentModule->getMeshPointer(), fan, MAPFX_WALL | MAPFX_IMPASS ); } } } }
void Passage::flashColor(uint8_t color) { for (int y = _area._top; y <= _area._bottom; y++ ) { for (int x = _area._left; x <= _area._right; x++ ) { TileIndex fan = _currentModule->getMeshPointer()->get_tile_int(PointGrid(x, y)); ego_tile_info_t *ptile = _currentModule->getMeshPointer()->get_ptile(fan); if ( NULL == ptile ) continue; for (int cnt = 0; cnt < 4; cnt++ ) { // set the color ptile->lcache[cnt] = color; // force the lighting code to update ptile->request_clst_update = true; ptile->clst_frame = -1; } } } }
Sphere::Sphere() : _pos(PointGrid(0,0)), _node(NULL) { }
GroupSphere Board::_match(PointGrid start) { GroupSphere spheres; spheres.clear(); if(start.x < 0) { return spheres; } if(start.y < 0) { return spheres; } Sphere* start_sphere = _grid.getPop(start.x); unsigned int start_count_match = 0; if(_grid.Empty(start_sphere)) { return spheres; } if(_grid.getLastRow(start.x) == 0) { return spheres; } std::cout << "Match::PoinTStart:" << start.x << " LastRow:" << _grid.getLastRow(start.x) << std::endl; std::cout << "Match::StartSphereType:" << start_sphere->getType() << std::endl; //start_sphere->retain(); if(!_grid.Empty(start_sphere)){ start_count_match += 1; spheres.push_back(start_sphere); //vertical int last_row = _grid.getLastRow(start.x); if(last_row <= 0) { return spheres; } for(int row=last_row; row >= 0; row--){ PointGrid pos_match(start.x, row); Sphere* sphere_to_match = _grid.get(pos_match); //sphere_to_match->retain(); if(!_grid.Empty(sphere_to_match) && sphere_to_match->getType() == start_sphere->getType() ){ spheres.push_back(sphere_to_match); start_count_match += 1; }else{ break; } std::cout << "Match::PosMatch: " << start.x << "," << row << "Type:" << sphere_to_match->getType() << std::endl; //por derecha GroupSphere spheres_right = _match_right(PointGrid(start.x, row)); for(auto it = spheres_right.begin(); it != spheres_right.end(); it++){ if((*it)) spheres.push_back((*it)); } //por izquierda GroupSphere spheres_left = _match_left(PointGrid(start.x, row)); for(auto it = spheres_left.begin(); it != spheres_left.end(); it++){ if((*it)) spheres.push_back((*it)); } } } std::unique(spheres.begin(), spheres.end(),[](Sphere* a, Sphere *b) -> bool{ return a == b; }); for(auto it = onAttachMatch.begin(); it != onAttachMatch.end(); it++){ (*it)(spheres, start_count_match); } return spheres; }
void Board::takeSphere(int col, GroupSphere& spheres) { populateCol(col, spheres); _match_lock(); _match(PointGrid(col,_grid.getRows())); _match_unlock(); }
bool Passage::close() { //is it already closed? if(!isOpen()) { return true; } // don't compute all of this for nothing if ( EMPTY_BIT_FIELD == _mask ) { return true; } // check to see if a wall can close if ( 0 != HAS_SOME_BITS( _mask, MAPFX_IMPASS | MAPFX_WALL ) ) { std::vector<std::shared_ptr<Object>> crushedCharacters; // Make sure it isn't blocked for(const std::shared_ptr<Object> &object : _currentModule->getObjectHandler().iterator()) { if(object->isTerminated()) { continue; } //Don't do held items if (object->isBeingHeld()) continue; if ( 0.0f != object->bump_stt.size ) { if ( objectIsInPassage( object->getPosX(), object->getPosY(), object->bump_1.size ) ) { if ( !object->canbecrushed || ( object->isAlive() && object->getProfile()->canOpenStuff() ) ) { // Someone is blocking who can open stuff, stop here return false; } else { crushedCharacters.push_back(object); } } } } // Crush any unfortunate characters for(const std::shared_ptr<Object> &character : crushedCharacters) { SET_BIT( character->ai.alert, ALERTIF_CRUSHED ); } } // Close it off _open = false; for ( int y = _area._top; y <= _area._bottom; y++ ) { for ( int x = _area._left; x <= _area._right; x++ ) { TileIndex fan = _currentModule->getMeshPointer()->get_tile_int(PointGrid(x, y)); ego_mesh_add_fx( _currentModule->getMeshPointer(), fan, _mask ); } } return true; }
//-------------------------------------------------------------------------------------------- bool line_of_sight_with_mesh( line_of_sight_info_t * plos ) { int Dx, Dy; int ix, ix_stt, ix_end; int iy, iy_stt, iy_end; int Dbig, Dsmall; int ibig, ibig_stt, ibig_end; int ismall, ismall_stt, ismall_end; int dbig, dsmall; int TwoDsmall, TwoDsmallMinusTwoDbig, TwoDsmallMinusDbig; bool steep; if ( NULL == plos ) return false; //is there any point of these calculations? if ( EMPTY_BIT_FIELD == plos->stopped_by ) return false; ix_stt = std::floor( plos->x0 / GRID_FSIZE ); /// @todo We have a projection function for that. ix_end = std::floor( plos->x1 / GRID_FSIZE ); iy_stt = std::floor( plos->y0 / GRID_FSIZE ); /// @todo We have a projection function for that. iy_end = std::floor( plos->y1 / GRID_FSIZE ); Dx = plos->x1 - plos->x0; Dy = plos->y1 - plos->y0; steep = (std::abs(Dy) >= std::abs(Dx)); // determine which are the big and small values if ( steep ) { ibig_stt = iy_stt; ibig_end = iy_end; ismall_stt = ix_stt; ismall_end = ix_end; } else { ibig_stt = ix_stt; ibig_end = ix_end; ismall_stt = iy_stt; ismall_end = iy_end; } // set up the big loop variables dbig = 1; Dbig = ibig_end - ibig_stt; if ( Dbig < 0 ) { dbig = -1; Dbig = -Dbig; ibig_end--; } else { ibig_end++; } // set up the small loop variables dsmall = 1; Dsmall = ismall_end - ismall_stt; if ( Dsmall < 0 ) { dsmall = -1; Dsmall = -Dsmall; } // pre-compute some common values TwoDsmall = 2 * Dsmall; TwoDsmallMinusTwoDbig = TwoDsmall - 2 * Dbig; TwoDsmallMinusDbig = TwoDsmall - Dbig; TileIndex fan_last = TileIndex::Invalid; for ( ibig = ibig_stt, ismall = ismall_stt; ibig != ibig_end; ibig += dbig ) { if ( steep ) { ix = ismall; iy = ibig; } else { ix = ibig; iy = ismall; } // check to see if the "ray" collides with the mesh TileIndex fan = _currentModule->getMeshPointer()->get_tile_int(PointGrid(ix, iy)); if (TileIndex::Invalid != fan && fan != fan_last ) { Uint32 collide_fx = ego_mesh_t::test_fx( _currentModule->getMeshPointer(), fan, plos->stopped_by ); // collide the ray with the mesh if ( EMPTY_BIT_FIELD != collide_fx ) { plos->collide_x = ix; plos->collide_y = iy; plos->collide_fx = collide_fx; return true; } fan_last = fan; } // go to the next step if ( TwoDsmallMinusDbig > 0 ) { TwoDsmallMinusDbig += TwoDsmallMinusTwoDbig; ismall += dsmall; } else { TwoDsmallMinusDbig += TwoDsmall; } } return false; }