예제 #1
0
void
Canvas::draw_surface(const SurfacePtr& surface,
                     const Vector& position, float angle, const Color& color, const Blend& blend,
                     int layer)
{
  if (!surface) return;

  const auto& cliprect = m_context.get_cliprect();

  // discard clipped surface
  if (position.x > cliprect.get_right() ||
     position.y > cliprect.get_bottom() ||
     position.x + static_cast<float>(surface->get_width()) < cliprect.get_left() ||
     position.y + static_cast<float>(surface->get_height()) < cliprect.get_top())
    return;

  auto request = new(m_obst) TextureRequest();

  request->type = TEXTURE;
  request->layer = layer;
  request->flip = m_context.transform().flip ^ surface->get_flip();
  request->alpha = m_context.transform().alpha;
  request->blend = blend;

  request->srcrects.emplace_back(Rectf(surface->get_region()));
  request->dstrects.emplace_back(Rectf(apply_translate(position), Size(surface->get_width(), surface->get_height())));
  request->angles.emplace_back(angle);
  request->texture = surface->get_texture().get();
  request->displacement_texture = surface->get_displacement_texture().get();
  request->color = color;

  m_requests.push_back(request);
}
예제 #2
0
void
DrawingContext::draw_surface(SurfacePtr surface, const Vector& position,
                             float angle, const Color& color, const Blend& blend,
                             int layer)
{
  assert(surface != 0);

  DrawingRequest* request = new(obst) DrawingRequest();

  request->target = target;
  request->type = SURFACE;
  request->pos = transform.apply(position);

  if(request->pos.x >= SCREEN_WIDTH || request->pos.y >= SCREEN_HEIGHT
     || request->pos.x + surface->get_width() < 0
     || request->pos.y + surface->get_height() < 0)
    return;

  request->layer = layer;
  request->drawing_effect = transform.drawing_effect;
  request->alpha = transform.alpha;
  request->angle = angle;
  request->color = color;
  request->blend = blend;

  SurfaceRequest* surfacerequest = new(obst) SurfaceRequest();
  surfacerequest->surface = surface.get();
  request->request_data = surfacerequest;

  requests->push_back(request);
}
예제 #3
0
void
Canvas::draw_surface_scaled(const SurfacePtr& surface, const Rectf& dstrect,
                            int layer, const PaintStyle& style)
{
  draw_surface_part(surface, Rectf(0.0f, 0.0f, static_cast<float>(surface->get_width()), static_cast<float>(surface->get_height())),
                    dstrect, layer, style);
}
  void draw_particles()
  {
    glPushMatrix();
    glMultMatrixf(get_modelview().matrix);
    
    OpenGLState state;
    
    state.bind_texture(surface->get_texture());
    state.set_blend_func(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    state.enable(GL_BLEND);
    state.activate();    

    glBegin(GL_QUADS);
    for(ParticleSystem::Particles::iterator i = psys.begin(); i != psys.end(); ++i)
    {
      if (i->t != -1.0f)
      {
        float p = 1.0f - psys.get_progress(i->t);
        Color color(psys.get_color_start().r * p + psys.get_color_stop().r * (1.0f - p),
                    psys.get_color_start().g * p + psys.get_color_stop().g * (1.0f - p),
                    psys.get_color_start().b * p + psys.get_color_stop().b * (1.0f - p),
                    psys.get_color_start().a * p + psys.get_color_stop().a * (1.0f - p));

        // scale
        float scale  = psys.get_size_start() + 
          psys.get_progress(i->t) * (psys.get_size_stop() - psys.get_size_start());
          
        float width  = surface->get_width()  * scale;
        float height = surface->get_height() * scale;
              
        // rotate
        float x_rot = width/2;
        float y_rot = height/2; 

        if (i->angle != 0)
        {
          float s = sinf(math::pi * i->angle/180.0f);
          float c = cosf(math::pi * i->angle/180.0f);
          x_rot = (width/2) * c - (height/2) * s;
          y_rot = (width/2) * s + (height/2) * c;
        }

        glColor4f(color.r, color.g, color.b, color.a);
        glTexCoord2f(0, 0);
        glVertex2f(i->x - x_rot, i->y - y_rot);
        glTexCoord2f(1, 0);
        glVertex2f(i->x + y_rot, i->y - x_rot);
        glTexCoord2f(1, 1);
        glVertex2f(i->x + x_rot, i->y + y_rot);
        glTexCoord2f(0, 1);
        glVertex2f(i->x - y_rot, i->y + x_rot);
      }
    }
    glEnd();

    glPopMatrix();
  }
int main(int argc, char** argv)
{
  if (argc != 3) 
  {
    std::cout << "Usage: " << argv[0] << " FILENAME" << std::endl;
    return -1;
  }

  Uint32 flags = SDL_INIT_VIDEO | SDL_INIT_JOYSTICK;

  if (SDL_Init(flags) < 0)
  {
    std::stringstream msg;
    msg << "Couldn't initialize SDL: " << SDL_GetError();
    throw std::runtime_error(msg.str());
  }
  else
  {
    atexit(SDL_Quit);
    SDL_EnableUNICODE(1);
  }

  Size window_size(1024, 576);
  OpenGLWindow window("Image Blur", window_size, window_size);

  SDL_ShowCursor(SDL_DISABLE);

  SurfaceManager surface_manager;

  FramebufferPtr framebuffer = Framebuffer::create_hdr(window_size.width, window_size.height);

  SurfacePtr surface   = Surface::create(Pathname(argv[1], Pathname::kSysPath));
  SurfacePtr surface_2 = Surface::create(Pathname(argv[2], Pathname::kSysPath));

  float ray_length = 3.0f;
  Vector2f pos;
  Vector2f last_pos;
  int t = 0;
  std::vector<Vector2f> buffer(16);
  std::vector<Vector2f>::size_type buffer_pos = 0;
  bool quit = false;
  while(!quit)
  {
    SDL_Event event;
    last_pos = pos;
    while(SDL_PollEvent(&event))
    {
      switch(event.type)
      {
        case SDL_QUIT:
          // FIXME: This should be a bit more gentle, but will do for now
          std::cout << "Ctrl-c or Window-close pressed, game is going to quit" << std::endl;
          quit = true;
          break;

        case SDL_KEYDOWN:
          if (event.key.keysym.sym == SDLK_ESCAPE)
          {
            quit = true;
          }
          break;

        case SDL_MOUSEBUTTONDOWN:
          if (event.button.button == 1)
          {
            ray_length *= 1.0f/1.4f;
          }
          else if (event.button.button == 3)
          {
            ray_length *= 1.4f;
          }
          std::cout << ray_length << std::endl;
          break;
          
        case SDL_MOUSEMOTION:
          //std::cout << event.motion.x << ", " << event.motion.y << std::endl;
          last_pos = pos;
          pos = Vector2f(1024.0f - static_cast<float>(event.motion.x),
                         576.0f - static_cast<float>(event.motion.y));
          break;

        default:
          break;
      }
    }

    t += 30;
    //ray_length = sin(t/1000.0f);

    buffer[buffer_pos % buffer.size()] = pos;
    buffer_pos += 1;

    Display::push_framebuffer(framebuffer);

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    if (true)
    {
      if (false)
      {
        for(size_t i = 0; i < std::min(buffer_pos, buffer.size()); ++i)
        {
          size_t idx = (buffer_pos - buffer.size() + i) % buffer.size();
          pos = buffer[idx];

          float n = static_cast<float>(buffer.size());

          if (false)
          { // after image motion blur
            n = static_cast<float>(i) / ((n * n + n) / 2.0f);
          }
          else
          { // simple trail, doesn't fade out
            n = 1.0f / n;
          }

          surface->draw(SurfaceDrawingParameters()
                        .set_scale(1.0f)
                        .set_pos(pos - Vector2f(surface->get_width()/2, surface->get_height()/2))
                        .set_blend_func(GL_SRC_ALPHA, GL_ONE)
                        .set_color(Color(1.0f, 1.0f, 1.0f, n)));
        }
      }
      else
      {
        int n = 32;
        for(int i = 0; i < n; ++i)
        {
          surface->draw(SurfaceDrawingParameters()
                        .set_scale(1.0f)
                        .set_pos((static_cast<float>(i)/static_cast<float>(n-1)) * pos 
                                 + (static_cast<float>(n-i-1)/static_cast<float>(n-1)) * last_pos
                                 - Vector2f(surface->get_width()/2, surface->get_height()/2))
                        .set_blend_func(GL_SRC_ALPHA, GL_ONE)
                        .set_color(Color(1.0f, 1.0f, 1.0f, 1.0f / static_cast<float>(n))));
        }
      }
    }
    else
    {
      int n = 100;
      for(int i = 0; i < n; ++i)
      {
        float scale = 1.0f + static_cast<float>(i) / static_cast<float>(n) * ray_length;
        if (true)
          surface->draw(SurfaceDrawingParameters()
                        .set_scale(scale)
                        .set_pos(Vector2f(512, 288) - Vector2f(surface->get_width()/2 * scale, 
                                                               surface->get_height()/2 * scale)
                                 + (Vector2f(512, 288) - pos) * scale * 3.0f)
                        .set_blend_func(GL_SRC_ALPHA, GL_ONE)
                        .set_color(Color(1.0f, 1.0f, 1.0f, static_cast<float>(1)/static_cast<float>(n))));

        if (false && i == 1)
        {
          scale = 1.0f;
          //std::cout << "Black: " << pos << std::endl;
          surface_2->draw(SurfaceDrawingParameters()
                         .set_scale(scale)
                         .set_pos(Vector2f(512, 288) - Vector2f(surface_2->get_width()/2 * scale, 
                                                                surface_2->get_height()/2 * scale)
                                  + (Vector2f(512, 288) - pos) * scale * 3.0f)
                         .set_blend_func(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
                         .set_color(Color(1.0f, 1.0f, 1.0f, 1.0f)));
        }
      }
    }
    Display::pop_framebuffer();

    if (true)
    {
      glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->get_handle());
      glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);

      glBlitFramebufferEXT(0, 0, framebuffer->get_width(), framebuffer->get_height(), 
                           0, 0, framebuffer->get_width(), framebuffer->get_height(),
                           GL_COLOR_BUFFER_BIT, GL_LINEAR /*NEAREST*/);

      glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
      glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
    }

    SDL_GL_SwapBuffers();
    SDL_Delay(20);
  }

  return 0;
}
예제 #6
0
void
Statistics::draw_endseq_panel(DrawingContext& context, Statistics* best_stats, SurfacePtr backdrop)
{
  // skip draw if stats were declared invalid
  if (!valid) return;

  // abort if we have no backdrop
  if (!backdrop) return;

  // no sense drawing stats if there are none
  if (total_coins + total_badguys + total_secrets == 0) return;

  int box_w = 220+110+110;
  int box_h = 30+20+20+20;
  int box_x = (int)((SCREEN_WIDTH - box_w) / 2);
  int box_y = (int)(SCREEN_HEIGHT / 2) - box_h;

  int bd_w = (int)backdrop->get_width();
  int bd_h = (int)backdrop->get_height();
  int bd_x = (int)((SCREEN_WIDTH - bd_w) / 2);
  int bd_y = box_y + (box_h / 2) - (bd_h / 2);

  int col1_x = box_x;
  int col2_x = col1_x+200;
  int col3_x = col2_x+130;

  int row1_y = box_y;
  int row2_y = row1_y+30;
  int row3_y = row2_y+20;
  int row4_y = row3_y+20;
  int row5_y = row4_y+20;

  context.push_transform();
  context.set_alpha(0.5);
  context.draw_surface(backdrop, Vector(bd_x, bd_y), LAYER_HUD);
  context.pop_transform();

  context.draw_text(Resources::normal_font, _("You"), Vector(col2_x, row1_y), ALIGN_LEFT, LAYER_HUD, Statistics::header_color);
  if (best_stats)
    context.draw_text(Resources::normal_font, _("Best"), Vector(col3_x, row1_y), ALIGN_LEFT, LAYER_HUD, Statistics::header_color);

  context.draw_text(Resources::normal_font, _("Coins"), Vector(col2_x-16, row3_y), ALIGN_RIGHT, LAYER_HUD, Statistics::header_color);
  context.draw_text(Resources::normal_font, coins_to_string(coins, total_coins), Vector(col2_x, row3_y), ALIGN_LEFT, LAYER_HUD, Statistics::text_color);
  if (best_stats) {
    int coins_best = (best_stats->coins > coins) ? best_stats->coins : coins;
    int total_coins_best = (best_stats->total_coins > total_coins) ? best_stats->total_coins : total_coins;
    context.draw_text(Resources::normal_font, coins_to_string(coins_best, total_coins_best), Vector(col3_x, row3_y), ALIGN_LEFT, LAYER_HUD, Statistics::text_color);
  }

  context.draw_text(Resources::normal_font, _("Badguys"), Vector(col2_x-16, row4_y), ALIGN_RIGHT, LAYER_HUD, Statistics::header_color);
  context.draw_text(Resources::normal_font, frags_to_string(badguys, total_badguys), Vector(col2_x, row4_y), ALIGN_LEFT, LAYER_HUD, Statistics::text_color);
  if (best_stats) {
	int badguys_best = (best_stats->badguys > badguys) ? best_stats->badguys : badguys;
	int total_badguys_best = (best_stats->total_badguys > total_badguys) ? best_stats->total_badguys : total_badguys;
	context.draw_text(Resources::normal_font, frags_to_string(badguys_best, total_badguys_best), Vector(col3_x, row4_y), ALIGN_LEFT, LAYER_HUD, Statistics::text_color);
  }

  context.draw_text(Resources::normal_font, _("Secrets"), Vector(col2_x-16, row5_y), ALIGN_RIGHT, LAYER_HUD, Statistics::header_color);
  context.draw_text(Resources::normal_font, secrets_to_string(secrets, total_secrets), Vector(col2_x, row5_y), ALIGN_LEFT, LAYER_HUD, Statistics::text_color);
  if (best_stats) {
    int secrets_best = (best_stats->secrets > secrets) ? best_stats->secrets : secrets;
    int total_secrets_best = (best_stats->total_secrets > total_secrets) ? best_stats->total_secrets : total_secrets;
    context.draw_text(Resources::normal_font, secrets_to_string(secrets_best, total_secrets_best), Vector(col3_x, row5_y), ALIGN_LEFT, LAYER_HUD, Statistics::text_color);
  }

  context.draw_text(Resources::normal_font, _("Time"), Vector(col2_x-16, row2_y), ALIGN_RIGHT, LAYER_HUD, Statistics::header_color);
  context.draw_text(Resources::normal_font, time_to_string(time), Vector(col2_x, row2_y), ALIGN_LEFT, LAYER_HUD, Statistics::text_color);
  if (best_stats) {
    float time_best = (best_stats->time < time) ? best_stats->time : time;
    context.draw_text(Resources::normal_font, time_to_string(time_best), Vector(col3_x, row2_y), ALIGN_LEFT, LAYER_HUD, Statistics::text_color);
  }
}
예제 #7
0
void
TileMap::draw(DrawingContext& context)
{
  // skip draw if current opacity is 0.0
  if (current_alpha == 0.0) return;

  context.push_transform();
  if(draw_target != DrawingContext::NORMAL) {
    context.push_target();
    context.set_target(draw_target);
  }

  if(drawing_effect != 0) context.set_drawing_effect(drawing_effect);
  if(current_alpha != 1.0) context.set_alpha(current_alpha);

  /* Force the translation to be an integer so that the tiles appear sharper.
   * For consistency (i.e., to avoid 1-pixel gaps), this needs to be done even
   * for solid tilemaps that are guaranteed to have speed 1.
   * FIXME Force integer translation for all graphics, not just tilemaps. */
  float trans_x = roundf(context.get_translation().x);
  float trans_y = roundf(context.get_translation().y);
  context.set_translation(Vector(int(trans_x * speed_x),
                                 int(trans_y * speed_y)));

  Rectf draw_rect = Rectf(context.get_translation(),
        context.get_translation() + Vector(SCREEN_WIDTH, SCREEN_HEIGHT));
  Rect t_draw_rect = get_tiles_overlapping(draw_rect);

  // Make sure the tilemap is within draw view
  if (t_draw_rect.is_valid()) {
    Vector start = get_tile_position(t_draw_rect.left, t_draw_rect.top);

    Vector pos;
    int tx, ty;

    for(pos.x = start.x, tx = t_draw_rect.left; tx < t_draw_rect.right; pos.x += 32, ++tx) {
      for(pos.y = start.y, ty = t_draw_rect.top; ty < t_draw_rect.bottom; pos.y += 32, ++ty) {
        int index = ty*width + tx;
        assert (index >= 0);
        assert (index < (width * height));

        if (tiles[index] == 0) continue;
        const Tile* tile = tileset->get(tiles[index]);
        assert(tile != 0);

        tile->draw(context, pos, z_pos, current_tint);
      } /* for (pos y) */
    } /* for (pos x) */

    /* Make sure that tiles with images larger than 32x32 that overlap
     * the draw rect will be drawn, even if their tile position does
     * not fall within the draw rect. */
    static const int EXTENDING_TILES = 32;
    int ex_left = std::max(0, t_draw_rect.left-EXTENDING_TILES);
    int ex_top = std::max(0, t_draw_rect.top-EXTENDING_TILES);
    Vector ex_start = get_tile_position(ex_left, ex_top);

    for (pos.x = start.x, tx = t_draw_rect.left; tx < t_draw_rect.right; pos.x += 32, ++tx) {
      for (pos.y = ex_start.y, ty = ex_top; ty < t_draw_rect.top; pos.y += 32, ++ty) {
        int index = ty*width + tx;
        assert (index >= 0);
        assert (index < (width * height));

        if (tiles[index] == 0) continue;
        const Tile* tile = tileset->get(tiles[index]);
        assert(tile != 0);

        SurfacePtr image = tile->get_current_image();
        if (image) {
          int h = image->get_height();
          if (h <= 32) continue;

          if (pos.y + h > start.y)
            tile->draw(context, pos, z_pos, current_tint);
        }
      }
    }

    for (pos.x = ex_start.x, tx = ex_left; tx < t_draw_rect.right; pos.x += 32, ++tx) {
      for(pos.y = ex_start.y, ty = ex_top; ty < t_draw_rect.bottom; pos.y += 32, ++ty) {
        int index = ty*width + tx;
        assert (index >= 0);
        assert (index < (width * height));

        if (tiles[index] == 0) continue;
        const Tile* tile = tileset->get(tiles[index]);
        assert(tile != 0);

        SurfacePtr image = tile->get_current_image();
        if (image) {
          int w = image->get_width();
          int h = image->get_height();
          if (w <= 32 && h <= 32) continue;

          if (pos.x + w > start.x && pos.y + h > start.y)
            tile->draw(context, pos, z_pos, current_tint);
        }
      }
    }
  }

  if(draw_target != DrawingContext::NORMAL) {
    context.pop_target();
  }
  context.pop_transform();
}
예제 #8
0
void
SpriteData::parse_action(const ReaderMapping& lisp, const std::string& basedir)
{
  auto action = std::unique_ptr<Action>(new Action);

  if(!lisp.get("name", action->name)) {
    if(!actions.empty())
      throw std::runtime_error(
        "If there are more than one action, they need names!");
  }

  std::vector<float> hitbox;
  if (lisp.get("hitbox", hitbox)) {
    switch(hitbox.size()) {
      case 4:
        action->hitbox_h = hitbox[3];
        action->hitbox_w = hitbox[2];

        //fall-through
      case 2:
        action->y_offset = hitbox[1];
        action->x_offset = hitbox[0];
        break;

      default:
        throw std::runtime_error("hitbox should specify 2/4 coordinates");
    }
  }
  lisp.get("z-order", action->z_order);
  lisp.get("fps", action->fps);

  std::string mirror_action;
  if (lisp.get("mirror-action", mirror_action)) {
    const Action* act_tmp = get_action(mirror_action);
    if(act_tmp == NULL) {
      std::ostringstream msg;
      msg << "Could not mirror action. Action not found: \"" << mirror_action << "\"\n"
          << "Mirror actions must be defined after the real one!";
      throw std::runtime_error(msg.str());
    } else {
      float max_w = 0;
      float max_h = 0;
      for(int i = 0; static_cast<unsigned int>(i) < act_tmp->surfaces.size(); i++) {
        SurfacePtr surface = act_tmp->surfaces[i]->clone();
        surface->hflip();
        max_w = std::max(max_w, (float) surface->get_width());
        max_h = std::max(max_h, (float) surface->get_height());
        action->surfaces.push_back(surface);
      }
      if (action->hitbox_w < 1) action->hitbox_w = max_w - action->x_offset;
      if (action->hitbox_h < 1) action->hitbox_h = max_h - action->y_offset;
    }
  } else { // Load images
    std::vector<std::string> images;
    if(!lisp.get("images", images)) {
      std::stringstream msg;
      msg << "Sprite '" << name << "' contains no images in action '"
          << action->name << "'.";
      throw std::runtime_error(msg.str());
    } else {
      float max_w = 0;
      float max_h = 0;
      for(std::vector<std::string>::size_type i = 0; i < images.size(); i++) {
        SurfacePtr surface = Surface::create(basedir + images[i]);
        max_w = std::max(max_w, (float) surface->get_width());
        max_h = std::max(max_h, (float) surface->get_height());
        action->surfaces.push_back(surface);
      }
      if (action->hitbox_w < 1) action->hitbox_w = max_w - action->x_offset;
      if (action->hitbox_h < 1) action->hitbox_h = max_h - action->y_offset;
    }
  }
  actions[action->name] = std::move(action);
}