KrEngine::KrEngine( SDL_Surface* _screen ) : paintInfo( _screen ) { Rectangle2I bounds; bounds.Set( 0, 0, _screen->w - 1, _screen->h - 1 ); Init( _screen, 1, &bounds, 0 ); }
Rectangle2I MapSpatialComponent::PorchPos() const { Rectangle2I v; v.Set( 0, 0, 0, 0 ); if ( !hasPorch ) return v; float yRotation = YRotation(parentChit->Rotation()); v = CalcPorchPos(bounds.min, bounds.Width(), yRotation); return v; }
bool PitMorph::DoSequence( TimeClock* timeClock ) { const float SPEED = 4.0f * ( TERRAIN_HEIGHT / 10.0f ); // m term in y = mx+b const float SLOPE = 1.0f; bool last = false; Lilith3D* lilith = Lilith3D::Instance(); TerrainMesh* tmesh = lilith->GetTerrainMesh(); float height = tmesh->Height( terrainX, terrainY ) - timeClock->CalcVelocity( SPEED ); height = Clamp( height, TERRAIN_MIN, TERRAIN_MAX ); // essentially the x-intecept: // y = mx + b, b=height // x = -height / m float radius = ( TERRAIN_MAX - height ) / SLOPE; int irad = int( radius ) + 1; Rectangle2I bounds; bounds.Set( terrainX - irad, terrainY - irad, terrainX + irad, terrainY + irad ); Rectangle2I constrain; constrain.Set( 0, 0, lilith3d::VERTEXSIZE-1, lilith3d::VERTEXSIZE-1 ); bounds.DoIntersection( constrain ); // Do the center first. if ( height <= altitude ) last = true; if ( tmesh->Height( terrainX, terrainY ) > altitude ) { tmesh->StartHeightChange(); tmesh->SetHeight( terrainX, terrainY, height ); for( int j=bounds.min.y; j<=bounds.max.y; ++j ) { for( int i=bounds.min.x; i<=bounds.max.x; ++i ) { if ( i != terrainX || j != terrainY ) { float len = Length( float( terrainX-i ), float( terrainY-j ), 0.0f ); float setHeight = len*SLOPE + height; if ( setHeight < tmesh->Height( i, j ) ) tmesh->SetHeight( i, j, setHeight ); } } } tmesh->EndHeightChange(); } for( Publisher< PitMorphListener >::const_iterator it = publish.begin(); it != publish.end(); ++it ) { if ( last ) (*it)->PitDone( this, terrainX, terrainY, height ); else (*it)->PitSink( this, terrainX, terrainY, height ); } return last; }
bool VolcanoMorph::DoSequence( TimeClock* timeClock ) { const float SPEED = 4.0f * ( TERRAIN_HEIGHT / 10.0f ); // m term in y = mx+b const float SLOPE = -1.3f; const float SMOOTH_RADIUS = 3.0f; bool last = false; Lilith3D* lilith = Lilith3D::Instance(); TerrainMesh* tmesh = lilith->GetTerrainMesh(); float height = tmesh->Height( terrainX, terrainY ) + timeClock->CalcVelocity( SPEED ); height = Clamp( height, TERRAIN_MIN, TERRAIN_MAX ); // essentially the x-intecept: // y = mx + b, b=height // x = -height / m float radius = -( height - TERRAIN_MIN ) / SLOPE; int irad = int( radius ) + 1; Rectangle2I bounds; bounds.Set( terrainX - irad, terrainY - irad, terrainX + irad, terrainY + irad ); Rectangle2I constrain; constrain.Set( 0, 0, lilith3d::VERTEXSIZE-1, lilith3d::VERTEXSIZE-1 ); bounds.DoIntersection( constrain ); // Do the center first. if ( height >= altitude ) last = true; if ( tmesh->Height( terrainX, terrainY ) < altitude ) { tmesh->StartHeightChange(); tmesh->SetHeight( terrainX, terrainY, height ); for( int j=bounds.min.y; j<=bounds.max.y; ++j ) { for( int i=bounds.min.x; i<=bounds.max.x; ++i ) { if ( i != terrainX || j != terrainY ) { float len = Length( float( terrainX-i ), float( terrainY-j ) ); float setHeight = len*SLOPE + height; if ( len < SMOOTH_RADIUS ) setHeight += fuzzHeight[ (j*lilith3d::VERTEXSIZE+i) % FUZZ_SIZE ]; if ( setHeight > tmesh->Height( i, j ) ) tmesh->SetHeight( i, j, setHeight ); } } } tmesh->EndHeightChange(); } // Inform listeners of changes. for( Publisher< VolcanoMorphListener >::const_iterator it = publish.begin(); it != publish.end(); ++it ) { if ( !last ) (*it)->VolcanoGrow( this, terrainX, terrainY, height ); else (*it)->VolcanoDone( this, terrainX, terrainY, height ); } // And now the particles and lights! const float FUZZ = 4.0f; const float FUZZMORE = 8.0f; float alt = tmesh->Height( terrainX, terrainY ); GravParticles* grav = lilith->GetGravParticles(); TimeClock* tc = Lilith3D::GetTimeClock(); while ( tc->Msec() > lastParticleTime ) { lastParticleTime += 50; Vector3F loc = { (float)terrainX, (float)terrainY, alt }; Vector3F vel = { -FUZZ / 2 + rand.FRand( FUZZ ), // velocity -FUZZ / 2 + rand.FRand( FUZZ ), SPEED * 1.3f }; Color3F col = { 0.8f + rand.FRand(0.2f), // coloring 0.6f + rand.FRand(0.2f), 0.0f }; grav->Create( loc, vel, col, GravParticles::GRAVITY, 1.0f, GravParticles::FLAME0 ); for( int i=0; i<3; ++i ) { Vector3F vel2 = { -FUZZMORE / 2 + rand.FRand( FUZZMORE ), -FUZZMORE / 2 + rand.FRand( FUZZMORE ), SPEED * 0.8f }; Color3F col2 = { 1.0f, 0.0f, 0.0f }; grav->Create( loc, vel2, col2, GravParticles::GRAVITY, GravParticles::MEDIUM ); } } // glowLight->SetPos( (float)terrainX, (float)terrainY, alt ); if ( decal ) { decal->SetAlpha( 1.0f ); const float FADEOUT = 0.8f * altitude; if ( alt > FADEOUT ) { decal->SetAlpha( Interpolate( FADEOUT, 1.0f, altitude, 0.0f, alt )); } } return last; }
void KrEngine::Draw( bool updateRect, std::vector< Rectangle2I >* _rectangles ) { std::vector< Rectangle2I > rectArrayOnStack; #if defined( DRAWDEBUG_RLE ) || defined( DRAWDEBUG_BLTRECTS ) debugFrameCounter++; #endif // GLOUTPUT( "Engine::Draw Walk\n" ); tree->Walk(); // We either use the passed in rectangles, // or the one here on the stack. Set the pointer // rectArray to the right thing. std::vector< Rectangle2I >* rectArray = ( _rectangles ) ? _rectangles : &rectArrayOnStack; rectArray->resize(0); if ( !paintInfo.openGL ) { // Queue up the rectangles that will be used to blit to screen: if ( needFullScreenUpdate ) { needFullScreenUpdate = false; Rectangle2I rect; rect.Set( 0, 0, screen->w-1, screen->h-1 ); rectArray->push_back( rect ); } else { for ( int i=0; i<nWindows; ++i ) { for ( int j=0; j<dirtyRectangle[i].NumRect(); ++j ) { rectArray->push_back( dirtyRectangle[i].Rect(j) ); } } } } if ( paintInfo.openGL ) { #ifdef KYRA_SUPPORT_OPENGL // OpenGL drawing glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); for( int j=0; j<nWindows; ++j ) { if ( fillBackground[j] ) { glBindTexture( GL_TEXTURE_2D, 0 ); glColor4f( backgroundColor[j].Redf(), backgroundColor[j].Greenf(), backgroundColor[j].Bluef(), 1.0f ); glBegin( GL_QUADS ); { glVertex3i( screenBounds[j].min.x, screenBounds[j].min.y, 0 ); glVertex3i( screenBounds[j].min.x + screenBounds[j].Width(), screenBounds[j].min.y, 0 ); glVertex3i( screenBounds[j].min.x + screenBounds[j].Width(), screenBounds[j].min.y + screenBounds[j].Height(), 0 ); glVertex3i( screenBounds[j].min.x, screenBounds[j].min.y + screenBounds[j].Height(), 0 ); } glEnd(); } bool clipping = ( screenBounds[j] != windowBounds ); if ( clipping ) { glEnable(GL_CLIP_PLANE0); glEnable(GL_CLIP_PLANE1); glEnable(GL_CLIP_PLANE2); glEnable(GL_CLIP_PLANE3); double plane0[4] = { 1.0, 0.0, 0.0, -screenBounds[j].min.x }; double plane1[4] = { -1.0, 0.0, 0.0, (screenBounds[j].min.x + screenBounds[j].Width() ) }; double plane2[4] = { 0.0, 1.0, 0.0, -screenBounds[j].min.y }; double plane3[4] = { 0.0, -1.0, 0.0, (screenBounds[j].min.y + screenBounds[j].Height() ) }; glClipPlane( GL_CLIP_PLANE0, plane0 ); glClipPlane( GL_CLIP_PLANE1, plane1 ); glClipPlane( GL_CLIP_PLANE2, plane2 ); glClipPlane( GL_CLIP_PLANE3, plane3 ); } tree->DrawWalk( screenBounds[j], &paintInfo, j ); if ( clipping ) { glDisable(GL_CLIP_PLANE0); glDisable(GL_CLIP_PLANE1); glDisable(GL_CLIP_PLANE2); glDisable(GL_CLIP_PLANE3); } dirtyRectangle[j].Clear(); } UpdateScreen( 0 ); #else // No openGl support, but openGl surface used GLASSERT( 0 ); #endif } else { // Bitmap drawing. // Draw the background, if necessary. Then // do a draw walk for every DR. for( int win=0; win<nWindows; ++win ) { for( int i=0; i<dirtyRectangle[win].NumRect(); ++i ) { const Rectangle2I& rect = dirtyRectangle[win].Rect( i ); // Draw the background. //GLASSERT( fillBackground[j] ); if ( fillBackground[win] ) { SDL_Rect sdlrect = { rect.min.x, rect.min.y, rect.Width(), rect.Height() }; U32 sdlColor = SDL_MapRGB( screen->format, backgroundColor[win].c.red, backgroundColor[win].c.green, backgroundColor[win].c.blue ); //GLASSERT( sdlColor == 0 ); SDL_FillRect( screen, &sdlrect, sdlColor ); } tree->DrawWalk( rect, &paintInfo, win ); /* #ifdef DRAWDEBUG_BLTRECTS KrPainter painter( &paintInfo ); painter.DrawBox( rect.xmin, rect.ymin, rect.Width(), rect.Height(), 200, 0, 0 ); #endif */ } #ifdef DRAWDEBUG_BLTRECTS dirtyRectangle[win].DrawRects( screen ); #endif dirtyRectangle[win].Clear(); } // The windows and DRs have been walked. Now transfer to physical screen. if ( updateRect ) { // Use the composite list of rectangles. UpdateScreen( rectArray ); } } }
Chit* LumosChitBag::NewBuilding(const Vector2I& pos, const char* name, int team) { const ChitContext* context = Context(); Chit* chit = NewChit(); const GameItem& rootItem = ItemDefDB::Instance()->Get(name); GameItem* item = rootItem.Clone(); // Hack...how to do this better?? if (item->IResourceName() == "pyramid0") { CStr<32> str; str.Format("pyramid%d", random.Rand(3)); item->SetResource(str.c_str()); } if (item->IResourceName() == ISC::kiosk) { switch (random.Rand(4)) { case 0: item->SetResource("kiosk.n"); break; case 1: item->SetResource("kiosk.m"); break; case 2: item->SetResource("kiosk.s"); break; default:item->SetResource("kiosk.c"); break; } } int size = 1; rootItem.keyValues.Get(ISC::size, &size); int porch = 0; rootItem.keyValues.Get(ISC::porch, &porch); const int circuit = 0; // Should be pre-cleared. But recover from weird situations by clearing. // Note that water is a real problem. Rectangle2I r; r.Set(pos.x, pos.y, pos.x + size - 1, pos.y + size - 1); for (Rectangle2IIterator it(r); !it.Done(); it.Next()) { const WorldGrid& wg = context->worldMap->GetWorldGrid(it.Pos()); GLASSERT(wg.IsLand()); (void)wg; context->worldMap->SetRock(it.Pos().x, it.Pos().y, 0, false, 0); context->worldMap->SetPlant(it.Pos().x, it.Pos().y, 0, 0); } MapSpatialComponent* msc = new MapSpatialComponent(); msc->SetBuilding(size, porch != 0, circuit); msc->SetBlocks((rootItem.flags & GameItem::PATH_NON_BLOCKING) ? false : true); chit->Add(msc); MapSpatialComponent::SetMapPosition(chit, pos.x, pos.y); chit->Add(new RenderComponent(item->ResourceName())); chit->Add(new HealthComponent()); AddItem(item, chit, context->engine, team, 0); IString script = rootItem.keyValues.GetIString("script"); if (!script.empty()) { Component* s = ComponentFactory::Factory(script.c_str(), &chitContext); GLASSERT(s); chit->Add(s); } IString proc = rootItem.keyValues.GetIString("procedural"); if (!proc.empty()) { ProcRenderInfo info; AssignProcedural(chit->GetItem(), &info); chit->GetRenderComponent()->SetProcedural(0, info); } IString consumes = rootItem.keyValues.GetIString(ISC::zone); if (!consumes.empty()) { Component* s = ComponentFactory::Factory("EvalBuildingScript", &chitContext); GLASSERT(s); chit->Add(s); } IString nameGen = rootItem.keyValues.GetIString( "nameGen"); if ( !nameGen.empty() ) { IString p = Context()->chitBag->NameGen(nameGen.c_str(), chit->random.Rand()); chit->GetItem()->SetProperName( p ); } #if 0 // debugging SectorPort sp; sp.sector.Set( pos.x/SECTOR_SIZE, pos.y/SECTOR_SIZE ); sp.port = 1; worldMap->SetRandomPort( sp ); #endif context->engine->particleSystem->EmitPD( ISC::constructiondone, ToWorld3F( pos ), V3F_UP, 0 ); if (XenoAudio::Instance()) { Vector3F pos3 = ToWorld3F(pos); XenoAudio::Instance()->PlayVariation(ISC::rezWAV, random.Rand(), &pos3); } return chit; }