レポジトリ種類: Mercurial

#include "render.hh"
#include "ball.hh"
#include "player.hh"
#include "brick.hh"

#define PI 3.14

void Render::gameOver(Player &p, Brick &br, bool winner) {
  if (winner) {
    Render::winner = true;
  } else {
    Render::winner = false;
  }

  Render::gameover = true;
  Mix_HaltMusic();
}

void Render::write(Player &p, Brick &br, std::string text, int x, int y) {
  SDL_Surface *surface;
  SDL_Texture *texture;
  const char* t = text.c_str();
  surface = TTF_RenderText_Solid(Render::font, t, br.color);
  texture = SDL_CreateTextureFromSurface(Render::renderer, surface);

  p.lives.w = surface->w;
  p.lives.h = surface->h;
  p.lives.x = x - p.lives.w;
  p.lives.y = y - p.lives.h;

  SDL_FreeSurface(surface);
  SDL_RenderCopy(Render::renderer, texture, NULL, &p.lives);
  SDL_DestroyTexture(texture);
}

void Render::update(Render &r, Player &p, Ball &bl, Brick &br) {
  if (p.livesCount <= 0) {
    gameOver(p, br, false);
  }

  if (SDL_HasIntersection(&bl.ball, &p.player)) {
    double rel = (p.player.x + ((float)p.player.w/2)) - ((float)bl.ball.x + ((float)bl.size/2));
    double norm = rel / ((float)p.player.w/2);
    double bounce = norm * (5*PI/12);

    bl.yvelocity = -bl.ballspeed * cos(bounce);
    bl.xvelocity = bl.ballspeed * -sin(bounce);
    p.scoreMultiplier = 1;
  }

  if (bl.ball.y <= 0) {
    bl.yvelocity = -bl.yvelocity;
  }
  if (bl.ball.y + bl.size >= Render::height) {
    bl.yvelocity = -bl.yvelocity;
    p.livesCount--;
    bl.resetBall(r, p);
  }
  if (bl.ball.x <= 0 || bl.ball.x + bl.size >= Render::width) {
    bl.xvelocity = -bl.xvelocity;
  }
  bl.ball.x += bl.xvelocity;
  bl.ball.y += bl.yvelocity;
  if (p.player.x < 0) {
    p.player.x = 0;
  }
  if (p.player.x + p.player.w > Render::width) {
    p.player.x = Render::width - p.player.w;
  }

  bool reset = true;
  for (int i = 0; i < br.col*br.row; i++) {
    br.setBricks(i);
 
    if (SDL_HasIntersection(&bl.ball, &br.brick) && br.bricks[i]) {
      br.bricks[i] = 0;
      p.score += 100 * p.scoreMultiplier;
      p.scoreMultiplier++;

      if (bl.ball.x >= br.brick.x) {
        bl.xvelocity = -bl.xvelocity;
        bl.ball.x -= 1;
      }
      if (bl.ball.x <= br.brick.x) {
        bl.xvelocity = -bl.xvelocity;
        bl.ball.x += 1;
      }
      if (bl.ball.y <= br.brick.y) {
        bl.yvelocity = -bl.yvelocity;
        bl.xvelocity = -bl.xvelocity;
        bl.ball.y -= 1;
      }
      if (bl.ball.y >= br.brick.y) {
        bl.yvelocity = -bl.yvelocity;
        bl.xvelocity = -bl.xvelocity;
        bl.ball.y += 1;
      }
    }

    if (br.bricks[i]) {
      reset = false;
    }
  }

  if (reset) {
    Render::level++;
    if (r.level > 7) {
      gameOver(p, br, true);
    } else {
      br.resetBricks(r, p, bl);
    }
  }
}

void Render::input(Player &p) {
  SDL_Event e;
  const Uint8 *keystates = SDL_GetKeyboardState(NULL);

  while (SDL_PollEvent(&e)) {
    if (e.type == SDL_QUIT) {
      Render::running = false;
    }
  }

  if (keystates[SDL_SCANCODE_Q]) Render::running = false;
  if (!Render::gameover) {
    if (keystates[SDL_SCANCODE_LEFT]) p.player.x -= Render::xpos;
    if (keystates[SDL_SCANCODE_RIGHT]) p.player.x += Render::xpos;
  }
}

void Render::render(Player &p, Ball &bl, Brick &br) {
  SDL_SetRenderDrawColor(Render::renderer, 0x00, 0x00, 0x00, 255);
  SDL_RenderClear(Render::renderer);

  Render::frameCount++;
  Render::timerFPS = SDL_GetTicks() - Render::lastFrame;

  if (Render::timerFPS < (1000/60)) {
    SDL_Delay((1000/60) - Render::timerFPS);
  }

  SDL_SetRenderDrawColor(Render::renderer, 255, 255, 255, 255);
  SDL_RenderFillRect(Render::renderer, &p.player);
  SDL_RenderFillRect(Render::renderer, &bl.ball);
  write(p, br, "SCORE: " + std::to_string(p.score), Render::width, Render::fontsize*1.5f);
  write(p, br, "LIVES: " + std::to_string(p.livesCount), 130, Render::fontsize*1.5f);
  write(p, br, "LEVEL: " + std::to_string(Render::level), 130, Render::fontsize*3.5f);

  if (Render::gameover) {
    if (Render::winner) write(p, br, "YOU WIN", Render::width/2+Render::fontsize, Render::height/2);
    else write(p, br, "YOU LOSS", Render::width/2+Render::fontsize, Render::height/2);
  }

  for (int i = 0; i < br.col*br.row; i++) {
    SDL_SetRenderDrawColor(Render::renderer, c1r, c1g, c1b, 255);
    if (i%2 == 0) SDL_SetRenderDrawColor(Render::renderer, c2r, c2g, c2b, 255);
    if (i%3 == 0) SDL_SetRenderDrawColor(Render::renderer, c3r, c3g, c3b, 255);
    if (i%4 == 0) SDL_SetRenderDrawColor(Render::renderer, c4r, c4g, c4b, 255);
    if (i%5 == 0) SDL_SetRenderDrawColor(Render::renderer, c5r, c5g, c5b, 255);
    if (i%6 == 0) SDL_SetRenderDrawColor(Render::renderer, c6r, c6g, c6b, 255);

    if (br.bricks[i]) {
      br.setBricks(i);
      SDL_RenderFillRect(Render::renderer, &br.brick);
    }
  }

  SDL_RenderPresent(Render::renderer);
}