// // 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(); }