/**\brief Draws the target. */ void Hud::DrawTarget( SpriteManager* sprites ) { Sprite* target = sprites->GetSpriteByID( targetID ); if(target != NULL) { int edge = (target->GetImage())->GetWidth() / 6; Coordinate targetScreenPosition = target->GetScreenPosition(); if(edge > 25) edge = 25; int x = targetScreenPosition.GetX(); int y = targetScreenPosition.GetY(); int r = target->GetRadarSize(); Color c = target->GetRadarColor(); if( (Timer::GetTicks() - timeTargeted) < OPTION(Uint32, "options/timing/target-zoom")) { r += Video::GetHalfHeight() - Video::GetHalfHeight()*(Timer::GetTicks()-timeTargeted)/OPTION(Uint32,"options/timing/target-zoom"); for( int i = 0; i < RETICLE_BLUR; i++ ) { c = c * .9f; edge += 3; r *= 1.1f; Video::DrawTarget(x,y,r,r,edge,c.r,c.g,c.b); } } else { Video::DrawTarget(x,y,r,r,edge,c.r,c.g,c.b); } } }
// // Shoot // void Game::Shoot() { static Uint32 lShot = SDL_GetTicks() - RELOAD_TIME; static list<SprDraw> killableSprites; static list<SprDraw>::iterator ksIt; static float distance, a, b, c, d; if(SDL_GetTicks() - lShot > RELOAD_TIME) { list<Sprite *>::iterator it; Sprite *spr; if(player->GetWeapon() == 0) { player->DecrementAmmo(1); if(player->GetAmmo() == 0) { AddMessage("Out of ammo!"); return; } } else if(player->GetWeapon() == 1) { player->DecrementMGAmmo(1); if(player->GetMGAmmo() == 0) { AddMessage("Out of ammo!"); return; } } fireStart = SDL_GetTicks(); fireVisible = true; if(player->GetWeapon()==0) framework->PlaySound(shootSnd); else if(player->GetWeapon()==1) framework->PlaySound(MGshootSnd); for(it = sprites.begin(); it != sprites.end(); it++) { spr = *it; if(spr->GetLookingAt() && spr->GetId() == ET_FURBY) { SprDraw ks; ks.original = spr; ks.x = spr->GetPosX(); ks.y = spr->GetPosY(); ks.image = spr->GetImage(); a = raycaster->GetPosX() - ks.x; b = raycaster->GetPosY() - ks.y; distance = sqrt(a*a+b*b); ks.distance = distance; killableSprites.push_back(ks); } if(spr->GetLookingAt() && spr->GetId() == ET_SKULL) { SprDraw ks; ks.original = spr; ks.x = spr->GetPosX(); ks.y = spr->GetPosY(); ks.image = spr->GetImage(); c = raycaster->GetPosX() - ks.x; d = raycaster->GetPosY() - ks.y; distance = sqrt(a*a+b*b); ks.distance = distance; killableSprites.push_back(ks); } } if(!killableSprites.empty()) { killableSprites.sort(); killableSprites.reverse(); ksIt = killableSprites.begin(); Furby *thisFurby = (Furby *)(*ksIt).original; Skull *thisSkull = (Skull*)(*ksIt).original; if(!thisFurby->IsDead()&&thisFurby->GetId()==ET_FURBY) { thisFurby->NextImage(); framework->PlaySound(EnemyHurt); } else if(thisFurby->IsDead() && thisFurby->GetId()==ET_FURBY) { SDL_Surface *daFrames[NUM_DEATH_ANIM_FRAMES]; daFrames[0] = spriteImgs[11]; daFrames[1] = spriteImgs[12]; daFrames[2] = spriteImgs[13]; DeathAnimation *deathAnim = new DeathAnimation(daFrames, (*ksIt).original->GetPosX(), (*ksIt).original->GetPosY()); sprites.push_back(deathAnim); delete (*ksIt).original; sprites.remove((*ksIt).original); framework->PlaySound(killSnd); AddMessage("You killed a furby!"); } if(!thisSkull->IsDead() && thisSkull->GetId()==ET_SKULL) { thisSkull->NextImage(); framework->PlaySound(EnemyHurt); } else if(thisSkull->IsDead() && thisSkull->GetId()==ET_SKULL) { SDL_Surface *skdaFrames[NUM_DEATH_ANIM_FRAMES]; skdaFrames[0] = spriteImgs[17]; skdaFrames[1] = spriteImgs[18]; skdaFrames[2] = spriteImgs[19]; SKDeathAnimation *skdeathAnim = new SKDeathAnimation(skdaFrames, (*ksIt).original->GetPosX(), (*ksIt).original->GetPosY()); sprites.push_back(skdeathAnim); delete (*ksIt).original; sprites.remove((*ksIt).original); framework->PlaySound(killSnd); AddMessage("You killed a skull!"); } //} killableSprites.clear(); } lShot = SDL_GetTicks(); } }
// // DrawSprites // // Note: My version of the calculations for the sprite distance and x-coord using only trigonometric functions // was giving pretty ugly results. Of course it was working, but in small rooms you could see some wrong clipping // and other messy things. Therefore I replaced these calculations by others using vectors and matrizes in order // to get the right values for the x-coord of the projected sprite and the distance for correct clipping. And // I have to say that this solution is very much based on what Lode Vandevenne explains in his raycasting tutorial. // void Raycaster::DrawSprites() { static SDL_Rect sprRect; int i, j, startX, startY; float distance, height; float a, b; list<Sprite *>::iterator sprIt; list<SprDraw>::iterator it; SprDraw curSpr; Sprite *anotherSpr; Uint32 color; bool partlyDrawn = false; float sprX, sprY; float yStepWidth, xStepWidth; //float beta; float inverse, transX, transY; // Put sprites into list for sorting for(sprIt = sprites->begin(); sprIt != sprites->end(); sprIt++) { anotherSpr = (*sprIt); SprDraw spr; spr.x = anotherSpr->GetPosX(); spr.y = anotherSpr->GetPosY(); spr.original = anotherSpr; a = spr.x - posX; b = spr.y - posY; distance = sqrt(a*a+b*b); spr.image = anotherSpr->GetImage(); spr.distance = distance; sprsToDraw.push_back(spr); } // Sort from far away to near sprsToDraw.sort(); // Draw them from the back for(it = sprsToDraw.begin(); it != sprsToDraw.end(); it++) { // Draw sprite curSpr = *it; a = curSpr.x - posX; b = curSpr.y - posY; inverse = 1.0f / (camPlane.x * lookDir.y - lookDir.x * camPlane.y); transX = inverse * (lookDir.y * a - lookDir.x * b); transY = inverse * (-camPlane.y * a + camPlane.x * b); height = DistToWallHeight(transY) * 1.0f; startX = (int)(-height / 2 + (target->w / 2) * (1 + transX / transY)); startY = (target->h - (int)height) / 2; sprX = sprY = 0; xStepWidth = (float)SPRITE_WIDTH / (float)height; yStepWidth = (float)SPRITE_HEIGHT / (float)height; if(startX + height < 0 || startX >= target->w || curSpr.distance < SPR_NEAR_CLIP_DIST) continue; partlyDrawn = false; // Horizontal for(i=0; i<height; i++) { if(startX + i < 0 || startX + i >= target->w || transY > zBuffer[i+startX]) { sprX += xStepWidth; continue; } // Vertical for(j=0; j<height; j++) { if(!badQuality || j % 4 == 0) color = framework->GetPixelColor(curSpr.image, (int)sprX, (int)sprY); if(color != framework->GetMagenta()) partlyDrawn |= framework->DrawPixel(startX + i, startY + j, color); sprY += yStepWidth; } sprY = 0; sprX += xStepWidth; } sprRect.w = (int)height; sprRect.x = startX; sprRect.h = (int)height; sprRect.y = startY; if(partlyDrawn && framework->Coll(&sprRect, crosshairRect)) curSpr.original->SetLookingAt(true); else curSpr.original->SetLookingAt(false); if(curSpr.original->GetId() == ET_FURBY)//||!curSpr.original->GetId() == ET_SKULL) { Furby *fb = (Furby *)curSpr.original; fb->SetVisible(partlyDrawn); } if(curSpr.original->GetId() == ET_SKULL)//||!curSpr.original->GetId() == ET_FURBY); { Skull *sk = (Skull *)curSpr.original; sk->SetVisible(partlyDrawn); } } sprsToDraw.clear(); }
void BGASprite::Setup(float Time, Sprite& sprite) { auto T = &pivotTransform[mOrigin]; if (!mParent) return; // We need this. if (mImageIndex == -1) // We haven't initialized from the parent's data yet? Alright. { assert(mParent != nullptr); mImageIndex = mParent->GetIndexFromFilename(mFile); mTransform.ChainTransformation(&mParent->GetTransformation()); } sprite.ChainTransformation(T); T->ChainTransformation(&mTransform); // Now get the values for all the different stuff. // Set the image and reset size since we're using the pivot. // Also forces the matrix to be recalculated. sprite.SetImage(mParent->GetImageFromIndex(mImageIndex), false); sprite.SetSize(1, 1); if (sprite.GetImage()) { auto i = sprite.GetImage(); T->SetSize(i->w, i->h); } // Okay, a pretty long function follows. Fade first. auto fade_evt = GetEvent(Time, EVT_FADE); if (IsValidEvent(fade_evt, EVT_FADE)) sprite.Alpha = event_cast<FadeEvent>(fade_evt)->LerpValue(Time); else sprite.Alpha = 0; // Now position. auto movx_evt = GetEvent(Time, EVT_MOVEX); if (IsValidEvent(movx_evt, EVT_MOVEX)) mTransform.SetPositionX(event_cast<MoveXEvent>(movx_evt)->LerpValue(Time)); else mTransform.SetPositionX(mStartPos.x); auto movy_evt = GetEvent(Time, EVT_MOVEY); if (IsValidEvent(movy_evt, EVT_MOVEY)) mTransform.SetPositionY(event_cast<MoveYEvent>(movy_evt)->LerpValue(Time)); else mTransform.SetPositionY(mStartPos.y); // We already unpacked move events, so no need for this next snip. /* auto mov_evt = GetEvent(Time, EVT_MOVE); if (IsValidEvent(mov_evt, EVT_MOVE)) mTransform.SetPosition(event_cast<MoveEvent>(mov_evt)->LerpValue(Time)); */ // Now scale and rotation. auto scale_evt = GetEvent(Time, EVT_SCALE); if (IsValidEvent(scale_evt, EVT_SCALE)) mTransform.SetScale(event_cast<ScaleEvent>(scale_evt)->LerpValue(Time)); else mTransform.SetScale(1); // Since scale is just applied to size straight up, we can use this extra scale // defaulting at 1,1 to be our vector scale. That way they'll pile up. auto vscale_evt = GetEvent(Time, EVT_SCALEVEC); if (IsValidEvent(scale_evt, EVT_SCALEVEC)) mTransform.SetSize(event_cast<VectorScaleEvent>(vscale_evt)->LerpValue(Time)); else mTransform.SetSize(1, 1); auto rot_evt = GetEvent(Time, EVT_ROTATE); if (IsValidEvent(rot_evt, EVT_ROTATE)) mTransform.SetRotation(glm::degrees(event_cast<RotateEvent>(rot_evt)->LerpValue(Time))); else mTransform.SetRotation(0); auto additive_evt = GetEvent(Time, EVT_ADDITIVE); if (IsValidEvent(additive_evt, EVT_ADDITIVE)) sprite.SetBlendMode(BLEND_ADD); else sprite.SetBlendMode(BLEND_ALPHA); // Flip events are skipped for now. }