// emission void Fluid2::fluidEmission() { if( Scene::testcase >= Scene::SMOKE ) { Bbox2 source( -0.18f, -1.9f, 0.18f, -1.7f ); Vec2 ismin = grid.getCellIndex( source.minPosition ); Vec2 ismax = grid.getCellIndex( source.maxPosition ); Index2 cornermin( (int) floor( ismin.x ), (int) floor( ismin.y ) ); Index2 cornermax( (int) ceil( ismax.x ), (int) ceil(ismax.y ) ); for( unsigned int i = cornermin.x; i <= cornermax.x; ++i ) for( unsigned int j = cornermin.y; j <= cornermax.y; ++j ) ink[ Index2( i, j ) ] = 1.0f; for( unsigned int i = cornermin.x; i <= cornermax.x+1; ++i ) for( unsigned int j = cornermin.y; j <= cornermax.y; ++j ) velocityX[ Index2( i, j ) ] = 0.0f; for( unsigned int i = cornermin.x; i <= cornermax.x; ++i ) for( unsigned int j = cornermin.y; j <= cornermax.y+1; ++j ) velocityY[ Index2( i, j ) ] = 8.0f; } }
void Data2 (int period, double value) { Put_Field (Index2 (period), value); }
double Data2 (int period) { Get_Field (Index2 (period), &dvalue); return (dvalue); }
// advection void Fluid2::fluidAdvection( const float dt ) { // ink { Array2<float> inkcopy( ink ); CellSampler inksampler( grid, inkcopy ); const Index2& size = ink.getSize(); for( unsigned int i = 0; i < size.x; ++i ) for( unsigned int j = 0; j < size.y; ++j ) { const Index2 id( i, j ); const Vec2 pos( grid.getCellPos( id ) ); const Vec2 vel( ( velocityX[ id ] + velocityX[ Index2( i+1, j ) ] ) * 0.5f, ( velocityY[ id ] + velocityY[ Index2( i, j+1 ) ] ) * 0.5f ); const Vec2 endpos( pos - dt * vel ); ink[ id ] = inksampler.getValue( endpos );; } } // velocity { Array2< float > ucopy( velocityX ); Array2< float > vcopy( velocityY ); FaceSampler usampler( grid, ucopy, 0 ); FaceSampler vsampler( grid, vcopy, 1 ); const Index2& sizeu = velocityX.getSize(); const Index2& sizev = velocityY.getSize(); for( unsigned int i = 0; i < sizeu.x; ++i ) for( unsigned int j = 0; j < sizeu.y; ++j ) { const Index2 id( i, j ); const Index2 idv1( clamp( i-1, 0, sizev.x-1 ), clamp( j , 0, sizev.y-1 ) ); const Index2 idv2( clamp( i , 0, sizev.x-1 ), clamp( j , 0, sizev.y-1 ) ); const Index2 idv3( clamp( i-1, 0, sizev.x-1 ), clamp( j+1, 0, sizev.y-1 ) ); const Index2 idv4( clamp( i , 0, sizev.x-1 ), clamp( j+1, 0, sizev.y-1 ) ); const Vec2 pos( grid.getFaceXPos( id ) ); const Vec2 vel( ucopy[ id ], ( vcopy[ idv1 ] + vcopy[ idv2 ] + vcopy[ idv3 ] + vcopy[ idv4 ] ) * 0.25f ); const Vec2 endpos( pos - dt * vel ); velocityX[ id ] = usampler.getValue( endpos ); } for( unsigned int i = 0; i < sizev.x; ++i ) for( unsigned int j = 0; j < sizev.y; ++j ) { const Index2 id( i, j ); const Index2 idu1( clamp( i , 0, sizeu.x-1 ), clamp( j-1, 0, sizeu.y-1 ) ); const Index2 idu2( clamp( i , 0, sizeu.x-1 ), clamp( j , 0, sizeu.y-1 ) ); const Index2 idu3( clamp( i+1, 0, sizeu.x-1 ), clamp( j-1, 0, sizeu.y-1 ) ); const Index2 idu4( clamp( i+1, 0, sizeu.x-1 ), clamp( j , 0, sizeu.y-1 ) ); const Vec2 pos( grid.getFaceYPos( id ) ); const Vec2 vel( ( ucopy[ idu1 ] + ucopy[ idu2 ] + ucopy[ idu3 ] + ucopy[ idu4 ] ) * 0.25f, vcopy[ id ] ); const Vec2 endpos( pos - dt * vel ); velocityY[ id ] = vsampler.getValue( endpos ); } } }
// pressure void Fluid2::fluidPressureProjection( const float dt ) { if( Scene::testcase >= Scene::SMOKE ) { const Vec2 dx = grid.getCellDx(); const Vec2 invDx( 1.0f / dx.x, 1.0f / dx.y ); const Vec2 invDxSq( 1.0f / ( dx.x * dx.x ), 1.0f / ( dx.y * dx.y ) ); const Index2& size = pressure.getSize(); const Index2& sizeu = velocityX.getSize(); const Index2& sizev = velocityY.getSize(); // wall boundary conditions for( unsigned int j = 0; j < sizeu.y; ++j ) { velocityX[ Index2( 0, j ) ] = 0.0f; velocityX[ Index2( sizeu.x-1, j ) ] = 0.0f; } for( unsigned int i = 0; i < sizev.x; ++i ) { velocityY[ Index2( i, 0 ) ] = 0.0f; // TOP as solid //velocityY[ Index2( i, sizev.y-1 ) ] = 0.0f; } // rhs const float rhoOverDt = Scene::kDensity / dt; std::vector< double > rhs( size.x * size.y ); for( unsigned int i = 0; i < size.x; ++i ) for( unsigned int j = 0; j < size.y; ++j ) { const Index2 id( i, j ); rhs[ pressure.getLinearIndex( i, j ) ] = - rhoOverDt * ( ( velocityX[ Index2( i+1, j ) ] - velocityX[ id ] ) * invDx.x + ( velocityY[ Index2( i, j+1 ) ] - velocityY[ id ] ) * invDx.y ); } // A SparseMatrix< double > A( size.x * size.y, 5 ); for( unsigned int i = 0; i < size.x; ++i ) for( unsigned int j = 0; j < size.y; ++j ) { const unsigned int id = pressure.getLinearIndex( i, j ); if( i > 0 ) { const unsigned int id1 = pressure.getLinearIndex( i-1, j ); A.add_to_element( id, id, 1. * invDxSq.x ); A.add_to_element( id, id1, -1. * invDxSq.x ); } if( i < size.x-1 ) { const unsigned int id1 = pressure.getLinearIndex( i+1, j ); A.add_to_element( id, id, 1. * invDxSq.x ); A.add_to_element( id, id1, -1. * invDxSq.x ); } if( j > 0 ) { const unsigned int id1 = pressure.getLinearIndex( i, j-1 ); A.add_to_element( id, id, 1. * invDxSq.y ); A.add_to_element( id, id1, -1. * invDxSq.y ); } // TOP as air A.add_to_element( id, id, 1. * invDxSq.y ); if( j < size.y-1 ) { const unsigned int id1 = pressure.getLinearIndex( i, j+1 ); A.add_to_element( id, id1, -1. * invDxSq.y ); } //// TOP as wall //if( j < size.y-1 ) { // const unsigned int id1 = pressure.getLinearIndex( i, j+1 ); // A.add_to_element( id, id, 1. * invDxSq.y ); // A.add_to_element( id, id1, -1. * invDxSq.y ); } } // pcg solver PCGSolver< double > solver; solver.set_solver_parameters( 1e-6, 10000 ); double residual_out; int iterations_out; std::vector< double > p( size.x * size.y ); solver.solve( A, rhs, p, residual_out, iterations_out ); std::cout << "Pressure system result: res=" << residual_out << ", iter=" << iterations_out << std::endl; // set pressure for( unsigned int i = 0, n = size.x * size.y; i < n; ++i ) pressure[ i ] = (float) p[ i ]; // apply pressure gradient const float dtOverRho = dt / Scene::kDensity; for( unsigned int i = 1; i < sizeu.x - 1; ++i ) for( unsigned int j = 0; j < sizeu.y; ++j ) { const Index2 id( i, j ); const float gradp = ( pressure[ id ] - pressure[ Index2( i-1, j ) ] ) * invDx.x; velocityX[ id ] -= dtOverRho * gradp; } for( unsigned int i = 0; i < sizev.x; ++i ) for( unsigned int j = 1; j < sizev.y - 1; ++j ) { const Index2 id( i, j ); const float gradp = ( pressure[ id ] - pressure[ Index2( i, j-1 ) ] ) * invDx.y; velocityY[ id ] -= dtOverRho * gradp; } // apply pressure gradient: TOP as air for( unsigned int i = 0; i < sizev.x; ++i ) { const Index2 id( i, sizev.y-1 ); const float gradp = ( 0.0f - pressure[ Index2( i, size.y-1 ) ] ) * invDx.y; velocityY[ id ] -= dtOverRho * gradp; } } }
bool GameMap::initWithLevel( int mainLevel, int viceLevel ) { Return_False_If(!Node::init()); this->makeMap(mainLevel, viceLevel); const int order = m_objects.size()*m_objects[0].size(); const Size size = this->getContentSize(); float x = 0; float up_height = 0; while (x<size.width) { Sprite* sp = Sprite::create("bound_up.png"); sp->setPosition(x, size.height); sp->setAnchorPoint(Point(0,0)); addChild(sp, order); x += sp->getContentSize().width; up_height = sp->getContentSize().height; } x = 0; float bottom_height = 0; while (x<size.width) { Sprite* sp = Sprite::create("bound_bottom.png"); sp->setPosition(x, 0); sp->setAnchorPoint(Point(0,1)); addChild(sp, order+1); x += sp->getContentSize().width; bottom_height = sp->getContentSize().height; } float y = -bottom_height; float left_width = 0; while (y<size.height) { Sprite* sp = Sprite::create("bound_left.png"); sp->setPosition(0, y); sp->setAnchorPoint(Point(1,0)); addChild(sp, order); left_width = sp->getContentSize().width; sp = Sprite::create("bound_left.png"); sp->setAnchorPoint(Point(0,0)); sp->setRotation(180); sp->setPosition(size.width+left_width, y+sp->getContentSize().height); addChild(sp, order); y += sp->getContentSize().height; } //init display number for (int r=0; r<m_objects.size(); ++r) { for (int c=0; c<m_objects[r].size(); ++c) { int mine_count = 0; for (auto&x : getSurrounding(Index2(r,c))) { if (m_objects[x.first][x.second]->isMine()) { ++mine_count; } } m_objects[ r ][ c ]->setSurroundMineCount(mine_count); } } CCAssert(NULL!=m_pPlayer, ""); dig(pointToIndex2(m_pPlayer->getPosition())); // Size size = this->getContentSize(); // -m_border.width, -m_border.height, size.width+m_border.width*2, size.height+m_border.height*2 const float tool = toolbar->getContentSize().height*4/5; this->runAction( Follow::create(m_pPlayer, Rect(-left_width, -bottom_height-tool, size.width+left_width*2, size.height+up_height+bottom_height+tool))); return true; }