#include "gamecode.h" #include "main_code.h" const int CONST_LEVELSTATE_STANDBY = 0; const int CONST_LEVELSTATE_PLAYING = 1; const int CONST_LEVELSTATE_GO_TO_PAUSE = 2; const int CONST_LEVELSTATE_PAUSE = 3; const int CONST_LEVELSTATE_LOADING = 4; const int CONST_LEVELSTATE_NODRAW = 5; const int CONST_LEVELSTATE_FINISH_FREEZE = 6; const int CONST_LEVELSTATE_FINISHED = 7; const float CONST_TIMER_LOADING = 150.f; const float CONST_PAUSE_APPEAR_TIME = 150.f; const float CONST_FINISH_FREEZE_TIME = 1000.f; const float CONST_FINISHING_TIME = 250.f; const float CONST_BALL_VELOCITY = 200.f; const vec2 CONST_SLIDE_UP_POS(240.f, 64.f); const vec2 CONST_TAP_TO_CONTINUE_POS(240.f, 200.f); bool operator<(const PairColorTexture& p1, const PairColorTexture& p2) { if (p1.second == p2.second) { if (p1.first.v[0] == p2.first.v[0]) { if (p1.first.v[1] == p2.first.v[1]) { if (p1.first.v[2] == p2.first.v[2]) { return p1.first.v[3] < p2.first.v[3]; } else { return p1.first.v[2] < p2.first.v[2]; } } else { return p1.first.v[1] < p2.first.v[1]; } } else { return p1.first.v[0] < p2.first.v[0]; } } return (p1.second < p2.second); } TBrick::TBrick() : State(CONST_BRICKSTATE_VISIBLE) , StateTimer(0.f) , Color(vec4(0.f, 0.f, 0.f, 1.f)) , Locked(0) , InitialLocked(0) { } void TBrick::SetVisible(vec4 color, int locked) { State = CONST_BRICKSTATE_VISIBLE; Color = color; InitialLocked = locked; Locked = InitialLocked; } void TBrick::SetInvisible() { State = CONST_BRICKSTATE_INVISIBLE; } void TBrick::TryDrawAppear(int ipos, int jpos) { vec2 centerPos = GetPosFrom(ipos, jpos); vec2 blockHalfSize = vec2(0.5f*CONST_BRICK_WIDTH, 0.5f*CONST_BRICK_HEIGHT); std::string texName; if (Locked == 2) { texName = CONST_BLOCK_TEXTURE3; } else if (Locked == 1) { texName = CONST_BLOCK_TEXTURE2; } else { texName = CONST_BLOCK_TEXTURE1; } if (State == CONST_BRICKSTATE_DISAPPEAR) { RenderUniform1f("Transparency", StateTimer/CONST_BRICK_DISAPPEAR_TIME); RenderUniform4fv("BrickColor", Color.v); glBindTexture(GL_TEXTURE_2D,ResourceManager->TexList[texName]); Renderer->DrawRect(centerPos - blockHalfSize, centerPos + blockHalfSize); } else if (State == CONST_BRICKSTATE_APPEAR) { RenderUniform1f("Transparency", 1.f - StateTimer/CONST_BRICK_APPEAR_TIME); RenderUniform4fv("BrickColor", Color.v); glBindTexture(GL_TEXTURE_2D,ResourceManager->TexList[texName]); Renderer->DrawRect(centerPos - blockHalfSize, centerPos + blockHalfSize); } } void TBrick::Update(cardinal dt) { if (State == CONST_BRICKSTATE_DISAPPEAR) { StateTimer -= dt; if (StateTimer < 0.f) { StateTimer = 0.f; State = CONST_BRICKSTATE_INVISIBLE; } } if (State == CONST_BRICKSTATE_APPEAR) { StateTimer -= dt; if (StateTimer < 0.f) { StateTimer = 0.f; State = CONST_BRICKSTATE_VISIBLE; } } } vec4 TBrick::GetColor() { return Color; } vec2 TBrick::GetPosFrom(int ipos, int jpos) { const vec2 BorderShift(CONST_BRICK_SHIFT_X, CONST_BRICK_SHIFT_Y); return BorderShift+vec2(CONST_BRICK_WIDTH*ipos + 0.5f*CONST_BRICK_WIDTH, 320.f - CONST_BRICK_HEIGHT*(jpos)-0.5f*CONST_BRICK_HEIGHT); } void TBrick::Disappear() { StateTimer = CONST_BRICK_DISAPPEAR_TIME; State = CONST_BRICKSTATE_DISAPPEAR; } void TBrick::Hit() { if (Locked == 0) { Disappear(); } else { Locked--; } } void TBrick::Appear(vec4 color, int locked) { StateTimer = CONST_BRICK_APPEAR_TIME; State = CONST_BRICKSTATE_APPEAR; Color = color; InitialLocked = locked; Locked = InitialLocked; } void TBrick::Appear() { Appear(Color, InitialLocked); } int TBrick::GetLocked() { return Locked; } bool TBrick::CanReact() { return (State == CONST_BRICKSTATE_VISIBLE) || (State == CONST_BRICKSTATE_APPEAR); } //=========================================== //=========================================== //=========================================== TBonusFalling::TBonusFalling(vec2 pos) : BonusType(rand() % 3) , Pos(pos) , Lifetime(0.f) { if (BonusType == 0) { TexName = CONST_BONUS_MULTIPLIER_TEXTURE; } if (BonusType == 1) { TexName = CONST_BONUS_GOTHROUGH_TEXTURE; } if (BonusType == 2) { TexName = CONST_BONUS_FLOOR_TEXTURE; } } vec2 TBonusFalling::GetPos() { return Pos; } int TBonusFalling::GetType() { return BonusType; } void TBonusFalling::Draw() { vec2 BonusHalfSize = vec2(16.f, 16.f); float transparency = min(Lifetime/CONST_BONUS_APPEAR_TIME , 1.f); RenderUniform4fv("BrickColor", vec4(1.0f, 1.0f, 1.0f, 1.0f).v); RenderUniform1f("Transparency", transparency); glBindTexture(GL_TEXTURE_2D,ResourceManager->TexList[TexName]); Renderer->DrawRect(Pos - BonusHalfSize, Pos + BonusHalfSize); } void TBonusFalling::Update(cardinal dt) { Lifetime += dt; Pos.v[1] -= dt * CONST_BONUS_FALL_SPEED / 1000.f; } //=========================================== //=========================================== //=========================================== TBall::TBall(vec2 pos, vec2 velocity, vec4 color) : Pos(pos) , Velocity(velocity) , Color(color) { //must be 5 TalePos.push_back(Pos); TalePos.push_back(Pos); TalePos.push_back(Pos); TalePos.push_back(Pos); TalePos.push_back(Pos); } vec2 TBall::GetPos() { return Pos; } vec2 TBall::GetVelocityVector() { return Velocity; } void TBall::Go() { Velocity = Normalize(vec2(2.f, 1.f)); } void TBall::ReflectToLeft() { if (Velocity.v[0] > 0.f) { Velocity.v[0] = - Velocity.v[0]; } } void TBall::ReflectToRight() { if (Velocity.v[0] < 0.f) { Velocity.v[0] = - Velocity.v[0]; } } void TBall::ReflectToUp() { if (Velocity.v[1] < 0.f) { Velocity.v[1] = - Velocity.v[1]; } } void TBall::ReflectToDown() { if (Velocity.v[1] > 0.f) { Velocity.v[1] = - Velocity.v[1]; } } //function for reflector surface. float ReflectorPlaneFunction(float shift) { /* _______ / \ | | Something like this */ if (shift>=-70.f && shift < -40.f) { float t = (shift+70.f)/30.f; //0 to 1 return 9.f + 21.f * t; } if (shift>=-40.f && shift < 40.f) { return 30.f; } if (shift >= 40.f && shift <= 70.f) { float t = (70.f - shift)/30.f; //1 to 0 return 9.f + 21.f * t; } return 0.f; } void TBall::TryReflectOnReflector(vec2 refPos) { const float reflectionShiftY = 13.f; const float reflectionMaxHeight = 30.f; if ((Pos.v[1] < reflectionMaxHeight + reflectionShiftY) && Pos.v[1] > 0.0f && Velocity.v[1] < 0) { float dy = ReflectorPlaneFunction(Pos.v[0] - refPos.v[0]); if (dy > 0 && (dy + reflectionShiftY > Pos.v[1])) { float shift = (Pos.v[0] - refPos.v[0]) / 128.f; shift = min(shift, 0.5f); shift = max(shift, -0.5f); vec2 n = Normalize(vec2(shift, 1.0f)); Velocity = Velocity - n * 2.f * (Velocity.v[0]*n.v[0] + Velocity.v[1]*n.v[1]); if ((Velocity.v[1] <= 0) || (fabs(Velocity.v[0]/Velocity.v[1]) > 4.f)) { Velocity.v[0] = 4.f*sign(Velocity.v[0]); Velocity.v[1] = 1.f; Velocity = Normalize(Velocity); } } } } void TBall::Update(cardinal dt) { Pos += Velocity * (CONST_BALL_VELOCITY * dt / 1000.f); TalePos.push_back(Pos); if (TalePos.size() > 4) { TalePos.erase(TalePos.begin()); } } //=========================================== //=========================================== //=========================================== TGameLevel::TGameLevel() { BkgTexture = "bkg"; RenderBufferReady = false; PrevLevelStateIsStandby = false; OutScale = 1.f; OutScaleVelocity = 0.f; StateTimer = 0.f; LevelState = CONST_LEVELSTATE_NODRAW; BallColor = vec4(0.2f, 0.8f, 1.0f, 1.0f); BonusFloorPosY = 0.f; } TGameLevel::~TGameLevel() { } void TGameLevel::ReloadBlockInstansingList() { std::map ConstTextureBlockMap = boost::assign::map_list_of (0,CONST_BLOCK_TEXTURE1) (1,CONST_BLOCK_TEXTURE2) (2,CONST_BLOCK_TEXTURE3); std::pair tempPair; BlockInstansingList.ColorBlockList.clear(); for (int i=0; i>::iterator itr = BlockInstansingList.ColorBlockList.end(); for (auto b = BlockInstansingList.ColorBlockList.begin(); b != BlockInstansingList.ColorBlockList.end(); ++b) { if (b->first == tempPair) { itr = b; } } if (itr == BlockInstansingList.ColorBlockList.end()) { BlockInstansingList.ColorBlockList.push_back(std::pair(tempPair, TTriangleList())); itr = BlockInstansingList.ColorBlockList.end(); itr--; } vec2 posFrom = BlockMatrix[i][j].GetPosFrom(i,j) + vec2(-0.5f*CONST_BRICK_WIDTH, -0.5f*CONST_BRICK_HEIGHT); vec2 posTo = BlockMatrix[i][j].GetPosFrom(i,j) + vec2(+0.5f*CONST_BRICK_WIDTH, +0.5f*CONST_BRICK_HEIGHT); itr->second.Data += MakeDataTriangleList(posFrom, posTo); } } } for (auto it = BlockInstansingList.ColorBlockList.begin(); it != BlockInstansingList.ColorBlockList.end(); ++it) { it->second.RefreshBuffer(); } } vec2 TGameLevel::GetBlock(const vec2& pos) { int x = static_cast((pos.v[0] - CONST_BRICK_SHIFT_X) / CONST_BRICK_WIDTH); int y = static_cast((320.0f + CONST_BRICK_SHIFT_Y - pos.v[1]) / CONST_BRICK_HEIGHT); if (x < 0) x = 0; if (x > CONST_BRICKMATRIX_WIDTH-1) x = CONST_BRICKMATRIX_WIDTH-1; if (y < 0) y = 0; if (y > CONST_BRICKMATRIX_HEIGHT-1) y = CONST_BRICKMATRIX_HEIGHT-1; return vec2(x, y); } bool TGameLevel::TapInBackBtnArea(const vec2& pos) { return (pos.v[1] > 320.f - 64.f) && (pos.v[0]>=240.f-75.f) && (pos.v[0]<=240.f+75.f); } void TGameLevel::SetFinishFreeze() { StateTimer = CONST_FINISH_FREEZE_TIME; LevelState = CONST_LEVELSTATE_FINISH_FREEZE; } void TGameLevel::SetFinished() { StateTimer = CONST_FINISHING_TIME; LevelState = CONST_LEVELSTATE_FINISHED; OutScale = 1.f; } vec4 TGameLevel::ParseColor(const std::string& s) { vec4 r; std::string ss(s); int i = ss.find(", "); int c = toint(ss.substr(0, i)); ss.erase(0, i+2); r.v[0] = c / 255.f; i = ss.find(", "); c = toint(ss.substr(0, i)); ss.erase(0, i+2); r.v[1] = c / 255.f; i = ss.find(", "); c = toint(ss.substr(0, i)); ss.erase(0, i+2); r.v[2] = c / 255.f; c = toint(ss); r.v[3] = c / 255.f; return r; } void TGameLevel::ReloadLevel() { cardinal byteCount; boost::shared_array file = CreateMemFromFile(LevelFileName, byteCount); std::string fileString(&file[0]); char c; //int n = 0; std::vector rows; int rowLen; while (fileString.size() > 0) { rowLen = fileString.find(fendl); rows.push_back(fileString.substr(0, rowLen)); fileString.erase(0, rowLen+2); } std::vector::iterator rowIterator = rows.begin(); BallColor = ParseColor(*rowIterator); ++rowIterator; std::vector colors; vec4 tc; while (*rowIterator != "Colormap") { tc = ParseColor(*rowIterator); colors.push_back(tc); ++rowIterator; } std::vector::iterator rowColorIterator; std::vector::iterator rowLockIterator; rowColorIterator = rowIterator + 1; rowLockIterator = rowColorIterator + 14; for (int j=0; jBallInBlock = GetBlock(ballPos); BallList.begin()->PrevBallInBlock = BallList.begin()->BallInBlock; BonusGothroughTimer = 0.f; BonusFloorTimer = 0.f; BonusFallingList.clear(); RenderBufferReady = false; ReloadBallInstancingList(); BonusFloorPosY = 0.f; } bool TGameLevel::IsLoaded() { return (LevelState == CONST_LEVELSTATE_STANDBY); } void TGameLevel::Draw() { if (LevelState == CONST_LEVELSTATE_NODRAW) { CheckGlError(); return; } if (LevelState == CONST_LEVELSTATE_LOADING) { Renderer->PushMatrix(); float scale = 1.f - 0.5f*StateTimer/CONST_TIMER_LOADING; if (scale < 0.5f) scale = 0.5f; if (scale > 1.f) scale = 1.f; Renderer->TranslateMatrix(vec3(Renderer->GetMatrixWidth() * 0.5f, Renderer->GetMatrixHeight() * 0.5f, 0)); Renderer->ScaleMatrix(scale); Renderer->TranslateMatrix(-vec3(Renderer->GetMatrixWidth() * 0.5f, Renderer->GetMatrixHeight() * 0.5f, 0)); glBindTexture(GL_TEXTURE_2D,ResourceManager->TexList[LevelScreenTexture]); Renderer->DrawRect(vec2(0, 0), vec2(480.f, 320.f)); Renderer->PopMatrix(); CheckGlError(); return; } bool mustShowButtons = ((LevelState == CONST_LEVELSTATE_PAUSE) || (LevelState == CONST_LEVELSTATE_GO_TO_PAUSE)); bool pause = (mustShowButtons || (LevelState == CONST_LEVELSTATE_FINISHED)); bool renderBufferReady = RenderBufferReady; if (pause && renderBufferReady) { //See also below (same method) Renderer->PushMatrix(); Renderer->TranslateMatrix(vec3(Renderer->GetMatrixWidth() * 0.5f, Renderer->GetMatrixHeight() * 0.5f, 0)); Renderer->ScaleMatrix(OutScale); Renderer->TranslateMatrix(-vec3(Renderer->GetMatrixWidth() * 0.5f, Renderer->GetMatrixHeight() * 0.5f, 0)); DrawBuffer(); if (mustShowButtons) { DrawPauseButtons(); } Renderer->PopMatrix(); CheckGlError(); return; } if (pause && !renderBufferReady) { Renderer->SwitchToFrameBuffer("LevelBuffer"); Renderer->SetProjectionMatrix(480.f, 320.f); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); CheckGlError(); } glBindTexture(GL_TEXTURE_2D,ResourceManager->TexList[BkgTexture]); Renderer->DrawRect(vec2(0, 0), vec2(480.f, 320.f)); std::list::iterator iBall; Renderer->PushShader("BrickShader"); for (int i=0; i>::iterator colorBlockIterator; for (colorBlockIterator = BlockInstansingList.ColorBlockList.begin(); colorBlockIterator != BlockInstansingList.ColorBlockList.end(); ++colorBlockIterator) { RenderUniform4fv("BrickColor", colorBlockIterator->first.first.v); glBindTexture(GL_TEXTURE_2D,ResourceManager->TexList[colorBlockIterator->first.second]); Renderer->DrawTriangleList(colorBlockIterator->second); } std::list::iterator iBonus; for (iBonus = BonusFallingList.begin(); iBonus != BonusFallingList.end(); ++iBonus) { iBonus->Draw(); } DrawBallInstancingList(); Renderer->PopShader(); glBindTexture(GL_TEXTURE_2D,ResourceManager->TexList[CONST_REFLECTOR_TEXTURE]); Renderer->DrawRect(vec2(-128.f, -16.f)+ReflectorPos, vec2(128.f, 16.f)+ReflectorPos); const vec2 wallUpPos1(240.f-256.f, 320.f-64.f); const vec2 wallUpPos2(240.f+256.f, 320.f); glBindTexture(GL_TEXTURE_2D,ResourceManager->TexList[CONST_WALL_UP_TEXTURE]); Renderer->DrawRect(wallUpPos1, wallUpPos2); const vec2 wallLeftPos1(0.f, 320.f - 512.f); const vec2 wallLeftPos2(32.f, 320.f); glBindTexture(GL_TEXTURE_2D,ResourceManager->TexList[CONST_WALL_LEFT_TEXTURE]); Renderer->DrawRect(wallLeftPos1, wallLeftPos2); const vec2 wallRightPos1(480.f-32.f, 320.f - 512.f); const vec2 wallRightPos2(480.f, 320.f); glBindTexture(GL_TEXTURE_2D,ResourceManager->TexList[CONST_WALL_RIGHT_TEXTURE]); Renderer->DrawRect(wallRightPos1, wallRightPos2); if (BonusFloorTimer>0.f) { const vec2 wallDownPos(240.f, BonusFloorPosY); glBindTexture(GL_TEXTURE_2D,ResourceManager->TexList[CONST_WALL_BONUS_TEXTURE]); Renderer->DrawRect(vec2(-256.f, -16.f)+wallDownPos, vec2(256.f, 16.f)+wallDownPos); } if (!pause) { RenderUniform1f("Transparency", 1.f); glBindTexture(GL_TEXTURE_2D,ResourceManager->TexList[CONST_BACK_BTN_TEXTURE]); const vec2 BackBtnPos(240.f, 320.f - 32.f - 20.f); Renderer->DrawRect(vec2(-128.f, -32.f)+BackBtnPos, vec2(128.f, 32.f)+BackBtnPos); } if (pause && !renderBufferReady) { //ololo //See also above (same method) Renderer->SwitchToScreen(); Renderer->SetFullScreenViewport(); Renderer->PushMatrix(); //Renderer->LoadIdentity(); Renderer->TranslateMatrix(vec3(Renderer->GetMatrixWidth() * 0.5f, Renderer->GetMatrixHeight() * 0.5f, 0)); Renderer->ScaleMatrix(OutScale); Renderer->TranslateMatrix(-vec3(Renderer->GetMatrixWidth() * 0.5f, Renderer->GetMatrixHeight() * 0.5f, 0)); DrawBuffer(); if (mustShowButtons) { DrawPauseButtons(); } Renderer->PopMatrix(); RenderBufferReady = true; CheckGlError(); } CheckGlError(); } void TGameLevel::DrawPauseButtons() { glBindTexture(GL_TEXTURE_2D,ResourceManager->TexList[CONST_SLIDE_UP_BTN_TEXTURE]); Renderer->DrawRect(vec2(-128.f, -64.f)+CONST_SLIDE_UP_POS, vec2(128.f, 64.f)+CONST_SLIDE_UP_POS); glBindTexture(GL_TEXTURE_2D,ResourceManager->TexList[CONST_TAP_TO_CONTINUE_BTN_TEXTURE]); Renderer->DrawRect(vec2(-128.f, -128.f)+CONST_TAP_TO_CONTINUE_POS, vec2(128.f, 128.f)+CONST_TAP_TO_CONTINUE_POS); } void TGameLevel::DrawBallInstancingList() { RenderUniform1f("Transparency", 1.f); RenderUniform4fv("BrickColor", BallColor.v); if (BonusGothroughTimer > 0.f) { glBindTexture(GL_TEXTURE_2D,ResourceManager->TexList[CONST_BALLGLOW_TEXTURE]); Renderer->DrawTriangleList(BallInstancingList.BallAndGlowList[1]); } glBindTexture(GL_TEXTURE_2D,ResourceManager->TexList[CONST_BALL_TEXTURE]); Renderer->DrawTriangleList(BallInstancingList.BallAndGlowList[0]); } void TGameLevel::DrawBuffer() { Renderer->PushShader("FrameShader"); float brightness; if (CONST_LEVELSTATE_GO_TO_PAUSE) { brightness = 0.3f + 0.7f * StateTimer / CONST_PAUSE_APPEAR_TIME; } else { brightness = 0.3f; } RenderUniform1f("Brightness", brightness); glBindTexture(GL_TEXTURE_2D,ResourceManager->FrameManager.GetFrameTexture("LevelBuffer")); //Matrix switched to identity //vec2 RectPos = vec2(-1, -1); //vec2 RectSize = vec2(2, 2); vec2 RectPos = vec2(240.f, 160.f); vec2 RectSize = vec2(240.f, 160.f); Renderer->DrawRect(RectPos-RectSize, RectPos+RectSize); Renderer->PopShader(); CheckGlError(); } void TGameLevel::SetPause() { OutScaleVelocity = 0.f; OutScale = 1.f; RenderBufferReady = false; LevelState = CONST_LEVELSTATE_GO_TO_PAUSE; StateTimer = CONST_PAUSE_APPEAR_TIME; App->MarkSetGameLevelPause(); } void TGameLevel::ReleasePause() { RenderBufferReady = false; if (PrevLevelStateIsStandby) { LevelState = CONST_LEVELSTATE_STANDBY; PrevLevelStateIsStandby = false; } else { LevelState = CONST_LEVELSTATE_PLAYING; } App->MarkReleaseGameLevelPause(); } bool TGameLevel::IsPaused() { return ((LevelState == CONST_LEVELSTATE_PAUSE) || (LevelState == CONST_LEVELSTATE_GO_TO_PAUSE) || (LevelState == CONST_LEVELSTATE_FINISHED)); } void TGameLevel::Update(cardinal dt) { if (LevelState == CONST_LEVELSTATE_NODRAW) { return; } if (LevelState == CONST_LEVELSTATE_GO_TO_PAUSE) { StateTimer -= dt; if (StateTimer <= 0.f) { StateTimer = 0.f; LevelState = CONST_LEVELSTATE_PAUSE; } return; } if (LevelState == CONST_LEVELSTATE_PAUSE) { OutScale += OutScaleVelocity * dt; TryGoToMenu(); CheckGlError(); return; } if (LevelState == CONST_LEVELSTATE_FINISHED) { StateTimer -= dt; OutScale = StateTimer/CONST_FINISHING_TIME; if (StateTimer <= 0.f) { TryGoToMenu(); } CheckGlError(); return; } if (LevelState == CONST_LEVELSTATE_LOADING) { StateTimer -= dt; if (StateTimer <= 0.f) { StateTimer = 0.f; RenderBufferReady = false; LevelState = CONST_LEVELSTATE_STANDBY; } } if (LevelState == CONST_LEVELSTATE_FINISH_FREEZE) { StateTimer -= dt; if (StateTimer <= 0.f) { SetFinished(); CheckGlError(); return; } //To make the whole scene like freeze dt = static_cast(dt / max((CONST_FINISH_FREEZE_TIME-StateTimer)/100.f, 1.f)); } if (BonusGothroughTimer > 0.f) { BonusGothroughTimer -= dt; BonusGothroughTimer = max(BonusGothroughTimer, 0.f); } if (BonusFloorTimer > 0.f) { BonusFloorTimer -= dt; BonusFloorTimer = max(BonusFloorTimer, 0.f); } UpdateBallList(dt); for (int i=0; i::iterator iBonus = BonusFallingList.begin(); while (iBonus != BonusFallingList.end()) { iBonus->Update(dt); if ((fabs(ReflectorPos.v[0] - iBonus->GetPos().v[0])GetPos().v[1])GetType(); iBonus = BonusFallingList.erase(iBonus); if (bonusType == CONST_BONUS_TYPE_GOTHROUGH) { BonusGothroughTimer = CONST_BONUS_GOTHROUGH_TIME; } else if (bonusType == CONST_BONUS_TYPE_MULTIPLIER) { vec2 pos = BallList.begin()->GetPos(); vec2 velocity = BallList.begin()->GetVelocityVector(); MultiplyBalls(pos, velocity); } else if (bonusType == CONST_BONUS_TYPE_FLOOR) { BonusFloorTimer = CONST_BONUS_FLOOR_TIME; } } else if (iBonus->GetPos().v[1] < -15.f) { iBonus = BonusFallingList.erase(iBonus); } if (iBonus != BonusFallingList.end()) { ++iBonus; } } //Bonus floor pos if (BonusFloorTimer/CONST_BONUS_GOTHROUGH_TIME < 0.2f) { //Bonus must go down until 0.f if (BonusFloorPosY > 0.f) { BonusFloorPosY -= CONST_BONUS_FLOOR_APPEAR_SPEED * dt / 1000.f; BonusFloorPosY = max(BonusFloorPosY, 0.f); } } else { //Bonus must go up until 16.f if (BonusFloorPosY < 16.f) { BonusFloorPosY += CONST_BONUS_FLOOR_APPEAR_SPEED * dt / 1000.f; BonusFloorPosY = min(BonusFloorPosY, 16.f); } } bool noMoreBlocks = true; for (int i=0; iOpenNextLevel(); App->MarkSetGameLevelPause(); SetFinishFreeze(); CheckGlError(); } if (BallList.size() == 0 && LevelState != CONST_LEVELSTATE_FINISH_FREEZE) { SetStandBy(); } } void TGameLevel::ReloadBallInstancingList() { //Changing this function? Don't forget to change next one! BallInstancingList.BallAndGlowList.clear(); std::list::iterator i; /* vec3 p1; vec3 p2; vec3 p3; vec3 p4; vec2 t1 = vec2(0.0f, 0.0f); vec2 t2 = vec2(0.0f, 1.0f); vec2 t3 = vec2(1.0f, 1.0f); vec2 t4 = vec2(1.0f, 0.0f); */ for (i = BallList.begin(); i != BallList.end(); ++i) { /* p1 = vec3(i->Pos, 0.f) + vec3(-8.f, -8.f, 0.f); p2 = vec3(i->Pos, 0.f) + vec3(-8.f, +8.f, 0.f); p3 = vec3(i->Pos, 0.f) + vec3(+8.f, +8.f, 0.f); p4 = vec3(i->Pos, 0.f) + vec3(+8.f, -8.f, 0.f); BallInstancingList.BallAndGlowList[0].Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].push_back(p1); BallInstancingList.BallAndGlowList[0].Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].push_back(p2); BallInstancingList.BallAndGlowList[0].Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].push_back(p3); BallInstancingList.BallAndGlowList[0].Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].push_back(p3); BallInstancingList.BallAndGlowList[0].Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].push_back(p4); BallInstancingList.BallAndGlowList[0].Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].push_back(p1); BallInstancingList.BallAndGlowList[0].Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB].push_back(t1); BallInstancingList.BallAndGlowList[0].Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB].push_back(t2); BallInstancingList.BallAndGlowList[0].Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB].push_back(t3); BallInstancingList.BallAndGlowList[0].Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB].push_back(t3); BallInstancingList.BallAndGlowList[0].Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB].push_back(t4); BallInstancingList.BallAndGlowList[0].Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB].push_back(t1); */ BallInstancingList.BallAndGlowList[0].Data += MakeDataTriangleList(i->Pos + vec2(-8.f, -8.f), i->Pos + vec2(8.f, 8.f)); //Replace6PointsInTriangleList(BallInstancingList.BallAndGlowList[0].Data, n, i->Pos + vec2(-8.f, -8.f), i->Pos + vec2(8.f, 8.f)); //n += 6; } std::list::iterator j; for (i = BallList.begin(); i != BallList.end(); ++i) { for (j = i->TalePos.begin(); j != i->TalePos.end(); ++j) { /* p1 = vec3(*j, 0.f) + vec3(-16.f, -16.f, 0.f); p2 = vec3(*j, 0.f) + vec3(-16.f, +16.f, 0.f); p3 = vec3(*j, 0.f) + vec3(+16.f, +16.f, 0.f); p4 = vec3(*j, 0.f) + vec3(+16.f, -16.f, 0.f); BallInstancingList.BallAndGlowList[1].Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].push_back(p1); BallInstancingList.BallAndGlowList[1].Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].push_back(p2); BallInstancingList.BallAndGlowList[1].Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].push_back(p3); BallInstancingList.BallAndGlowList[1].Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].push_back(p3); BallInstancingList.BallAndGlowList[1].Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].push_back(p4); BallInstancingList.BallAndGlowList[1].Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].push_back(p1); BallInstancingList.BallAndGlowList[1].Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB].push_back(t1); BallInstancingList.BallAndGlowList[1].Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB].push_back(t2); BallInstancingList.BallAndGlowList[1].Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB].push_back(t3); BallInstancingList.BallAndGlowList[1].Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB].push_back(t3); BallInstancingList.BallAndGlowList[1].Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB].push_back(t4); BallInstancingList.BallAndGlowList[1].Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB].push_back(t1); */ BallInstancingList.BallAndGlowList[1].Data += MakeDataTriangleList(*j + vec2(-16.f, -16.f), *j + vec2(16.f, 16.f)); //Replace6PointsInTriangleList(BallInstancingList.BallAndGlowList[1].Data, n, *j + vec2(-16.f, -16.f), *j + vec2(16.f, 16.f)); //n += 6; } } //std::map::iterator it; auto it = BallInstancingList.BallAndGlowList.begin(); for (; it != BallInstancingList.BallAndGlowList.end(); ++it) //for (auto it = BallInstancingList.BallAndGlowList.begin(); it != BallInstancingList.BallAndGlowList.end(); ++it) { it->second.RefreshBuffer(); } } void TGameLevel::RefreshBallInstancingList() { //Changing this function? Don't forget to change previous one! /* vec3 p1; vec3 p2; vec3 p3; vec3 p4; vec2 t1 = vec2(0.0f, 0.0f); vec2 t2 = vec2(0.0f, 1.0f); vec2 t3 = vec2(1.0f, 1.0f); vec2 t4 = vec2(1.0f, 0.0f); */ int n = 0; int m = 0; std::list::iterator i; for (i = BallList.begin(); i != BallList.end(); ++i) { /* p1 = vec3(i->Pos, 0.f) + vec3(-8.f, -8.f, 0.f); p2 = vec3(i->Pos, 0.f) + vec3(-8.f, +8.f, 0.f); p3 = vec3(i->Pos, 0.f) + vec3(+8.f, +8.f, 0.f); p4 = vec3(i->Pos, 0.f) + vec3(+8.f, -8.f, 0.f); BallInstancingList.BallAndGlowList[0].Vec3CoordArr[CONST_STRING_POSITION_ATTRIB][n++] = p1; BallInstancingList.BallAndGlowList[0].Vec3CoordArr[CONST_STRING_POSITION_ATTRIB][n++] = p2; BallInstancingList.BallAndGlowList[0].Vec3CoordArr[CONST_STRING_POSITION_ATTRIB][n++] = p3; BallInstancingList.BallAndGlowList[0].Vec3CoordArr[CONST_STRING_POSITION_ATTRIB][n++] = p3; BallInstancingList.BallAndGlowList[0].Vec3CoordArr[CONST_STRING_POSITION_ATTRIB][n++] = p4; BallInstancingList.BallAndGlowList[0].Vec3CoordArr[CONST_STRING_POSITION_ATTRIB][n++] = p1; BallInstancingList.BallAndGlowList[0].Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB][m++] = t1; BallInstancingList.BallAndGlowList[0].Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB][m++] = t2; BallInstancingList.BallAndGlowList[0].Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB][m++] = t3; BallInstancingList.BallAndGlowList[0].Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB][m++] = t3; BallInstancingList.BallAndGlowList[0].Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB][m++] = t4; BallInstancingList.BallAndGlowList[0].Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB][m++] = t1; */ Replace6PointsInTriangleList(BallInstancingList.BallAndGlowList[0].Data, n, i->Pos + vec2(-8.f, -8.f), i->Pos + vec2(8.f, 8.f)); n += 6; } std::list::iterator j; n = 0; m = 0; for (i = BallList.begin(); i != BallList.end(); ++i) { for (j = i->TalePos.begin(); j != i->TalePos.end(); ++j) { /* p1 = vec3(*j, 0.f) + vec3(-16.f, -16.f, 0.f); p2 = vec3(*j, 0.f) + vec3(-16.f, +16.f, 0.f); p3 = vec3(*j, 0.f) + vec3(+16.f, +16.f, 0.f); p4 = vec3(*j, 0.f) + vec3(+16.f, -16.f, 0.f); BallInstancingList.BallAndGlowList[1].Vec3CoordArr[CONST_STRING_POSITION_ATTRIB][n++] = p1; BallInstancingList.BallAndGlowList[1].Vec3CoordArr[CONST_STRING_POSITION_ATTRIB][n++] = p2; BallInstancingList.BallAndGlowList[1].Vec3CoordArr[CONST_STRING_POSITION_ATTRIB][n++] = p3; BallInstancingList.BallAndGlowList[1].Vec3CoordArr[CONST_STRING_POSITION_ATTRIB][n++] = p3; BallInstancingList.BallAndGlowList[1].Vec3CoordArr[CONST_STRING_POSITION_ATTRIB][n++] = p4; BallInstancingList.BallAndGlowList[1].Vec3CoordArr[CONST_STRING_POSITION_ATTRIB][n++] = p1; BallInstancingList.BallAndGlowList[1].Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB][m++] = t1; BallInstancingList.BallAndGlowList[1].Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB][m++] = t2; BallInstancingList.BallAndGlowList[1].Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB][m++] = t3; BallInstancingList.BallAndGlowList[1].Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB][m++] = t3; BallInstancingList.BallAndGlowList[1].Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB][m++] = t4; BallInstancingList.BallAndGlowList[1].Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB][m++] = t1;*/ //BallInstancingList.BallAndGlowList[1].Data += MakeDataTriangleList(); Replace6PointsInTriangleList(BallInstancingList.BallAndGlowList[1].Data, n, *j + vec2(-16.f, -16.f), *j + vec2(16.f, 16.f)); n += 6; } } std::map::iterator it; for (it = BallInstancingList.BallAndGlowList.begin(); it != BallInstancingList.BallAndGlowList.end(); ++it) { it->second.RefreshBuffer(); } } void TGameLevel::UpdateBallList(cardinal dt) { std::list::iterator iBall; bool mustReloadBalls = false; //If not loaded - force load if (BallInstancingList.BallAndGlowList.size() == 0) { mustReloadBalls = true; } if (BonusFloorTimer == 0.f) { vec2 ballPos; iBall = BallList.begin(); while (iBall != BallList.end()) { ballPos = iBall->GetPos(); if (ballPos.v[1]<0.f) { iBall = BallList.erase(iBall); mustReloadBalls = true; } if (iBall != BallList.end()) { ++iBall; } } } bool blockListChanged = false; for (iBall = BallList.begin(); iBall != BallList.end(); ++iBall) { iBall->Update(dt); vec2 ballPos = iBall->GetPos(); if (ballPos.v[0] > 480.f-15.f) { iBall->ReflectToLeft(); } if (ballPos.v[0] < 15.f) { iBall->ReflectToRight(); } if (ballPos.v[1] > 320.0f-16.f) { iBall->ReflectToDown(); } if (BonusFloorTimer > 0.f) { if (ballPos.v[1] < 13.0f) { iBall->ReflectToUp(); } } iBall->TryReflectOnReflector(ReflectorPos); vec2 ipos = GetBlock(ballPos); if (!(ipos == iBall->BallInBlock)) { iBall->PrevBallInBlock = iBall->BallInBlock; iBall->BallInBlock = ipos; int i = static_cast(iBall->BallInBlock.v[0]); int j = static_cast(iBall->BallInBlock.v[1]); int iprev = static_cast(iBall->PrevBallInBlock.v[0]); int jprev = static_cast(iBall->PrevBallInBlock.v[1]); if (BlockMatrix[i][j].CanReact()) { bool canThrowBonus; blockListChanged = true; if (BonusGothroughTimer > 0.f) { BlockMatrix[i][j].Disappear(); canThrowBonus = true; } else { canThrowBonus = (BlockMatrix[i][j].GetLocked() == 0); BlockMatrix[i][j].Hit(); } vec2 blockPos = BlockMatrix[i][j].GetPosFrom(i, j); if (canThrowBonus && rand() % 20 == 0) { BonusFallingList.push_back(TBonusFalling(blockPos)); } if (BonusGothroughTimer == 0.f) { if (j < jprev) { iBall->ReflectToDown(); } else if (j > jprev) { iBall->ReflectToUp(); } else if (i < iprev) { iBall->ReflectToRight(); } else if (i > iprev) { iBall->ReflectToLeft(); } } } } } if (blockListChanged) { ReloadBlockInstansingList(); } if (mustReloadBalls) { ReloadBallInstancingList(); } else { RefreshBallInstancingList(); } } void TGameLevel::MultiplyBalls(vec2 pos, vec2 velocity) { mat2 r; vec2 v; for (int i = -2; i<=2; i++) { r = mat2(i*pi/4.f); v = r*velocity; v.v[1] = max(static_cast(fabs(v.v[1])), 0.2f) * sign(v.v[1]); //Prevent velocityY from being ~= 0 BallList.push_back(TBall(pos, v, BallColor)); } ReloadBallInstancingList(); } void TGameLevel::OnTapDown(vec2 pos) { if (LevelState == CONST_LEVELSTATE_STANDBY) { if (TapInBackBtnArea(pos)) { SetPause(); PrevLevelStateIsStandby = true; } else { LevelState = CONST_LEVELSTATE_PLAYING; BallList.begin()->Go(); } } else if (LevelState == CONST_LEVELSTATE_PLAYING) { if (TapInBackBtnArea(pos)) { SetPause(); } else if (fabs(ReflectorPos.v[0] - pos.v[0])>64.f) { ReflectorPos.v[0] = pos.v[0]; } } else if (LevelState == CONST_LEVELSTATE_PAUSE) { if (pos.v[1] > 128.f) { ReleasePause(); } } } void TGameLevel::OnTapUp(vec2 pos) { } void TGameLevel::OnFling(vec2 slideSpeed) { if (LevelState == CONST_LEVELSTATE_PAUSE) { OutScaleVelocity = slideSpeed.v[1]/320.f; } } void TGameLevel::OnScroll(vec2 shift) { const float CONST_SCROLL_SCALE = 1.1f; if (LevelState == CONST_LEVELSTATE_PLAYING || LevelState == CONST_LEVELSTATE_STANDBY) { ReflectorPos.v[0] -= CONST_SCROLL_SCALE*shift.v[0]; } else if (LevelState == CONST_LEVELSTATE_PAUSE) { #ifdef TARGET_WIN32 OutScale += shift.v[1]/320.f; #else OutScale -= shift.v[1]/320.f; #endif TryGoToMenu(); } } void TGameLevel::TryGoToMenu() { if (OutScale < 0.5f) { OutScale = 0.5f; LevelState = CONST_LEVELSTATE_NODRAW; App->GoFromGameToMenu(); } if (OutScale > 1.f) { OutScale = 1.f; } }