about summary refs log tree commit diff stats
path: root/data/maps/the_revitalized/rooms/Too Room.txtpb
blob: 819c3cfbb26f26c2032e15b37ba76c9c92f2f2a0 (plain) (blame)
1
2
3
4
5
6
7
8
name: "Too Room"
panels {
  name: "TOO"
  path: "Panels/panel_6"
  clue: "too"
  answer: "two"
  symbols: ZERO
}
nt.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
#include "animation_system.h"
#include <fstream>
#include <string>
#include <list>
#include "game.h"
#include "vector.h"
#include "util.h"

void AnimationSystem::initSprite(int spriteId, std::string_view filename) {
  std::ifstream datafile(filename.data());
  if (!datafile.is_open()) {
    throw std::invalid_argument(std::string("Could not find sprite datafile: ") + std::string(filename));
  }

  Sprite& sprite = game_.getSprite(spriteId);
  sprite.isAnimated = true;

  char ch;
  std::string line;

  datafile >> sprite.spritesheet;

  std::string framefilename;
  datafile >> framefilename;

  std::ifstream framefile(framefilename);
  if (!framefile.is_open()) {
    throw std::invalid_argument("Could not find frame datafile: " + framefilename);
  }

  vec2i cellSize;
  framefile >> cellSize.w();
  framefile >> ch; //,
  framefile >> cellSize.h();
  std::getline(framefile, line); // cell size

  int framesPerRow;
  framefile >> framesPerRow;
  std::getline(framefile, line); // frames per row

  int numFrames;
  framefile >> numFrames;
  std::getline(framefile, line); // frames
  std::getline(framefile, line); // blank

  sprite.frames.clear();
  for (int i=0; i<numFrames; i++) {
    SpriteFrame f;
    framefile >> f.size.w();
    framefile >> ch; //,
    framefile >> f.size.h();
    framefile >> ch; //,
    framefile >> f.center.x();
    framefile >> ch; //,
    framefile >> f.center.y();
    std::getline(framefile, line); // blank

    f.srcRect.x = (i % framesPerRow) * cellSize.w();
    f.srcRect.y = (i / framesPerRow) * cellSize.h();
    f.srcRect.w = f.size.w();
    f.srcRect.h = f.size.h();

    sprite.frames.push_back(std::move(f));
  }

  std::string animLine;
  std::getline(datafile, animLine); // blank
  sprite.animations.clear();
  sprite.nameDirToAnim.clear();
  while (std::getline(datafile, animLine)) {
    std::regex re(R"(([a-z!._]+)\[([a-z_]+)\](%[0-9]+)?: ([0-9,#]+))");
    std::smatch m;
    std::regex_match(animLine, m, re);

    std::string animName = m[1];
    Animation anim;
    auto framestrs = splitStr<std::list<std::string>>(m[4], ",");
    for (const std::string& f : framestrs) {
      int times = 1;
      size_t repeat_it = f.find("#");
      if (repeat_it != std::string::npos) {
        times = std::stoi(f.substr(repeat_it + 1));
      }

      for (int i=0; i<times; i++) {
        anim.frameIndices.push_back(std::stoi(f));
      }
    }

    if (animName.back() == '!') {
      anim.looping = false;
    }

    if (m[3] != "") {
      int frameRate = std::stoi(std::string(m[3]).substr(1));
      switch (frameRate) {
        case 5: anim.timerNum = 0; break;
        case 60: anim.timerNum = 1; break;
        default: throw std::invalid_argument("Invalid frame rate");
      }
    }

    int animId = sprite.animations.size();
    sprite.animations.push_back(std::move(anim));

    Direction dir = directionFromString(std::string(m[2]));
    sprite.nameDirToAnim[animName][dir] = animId;
  }

  updateAnimation(spriteId);
}

void AnimationSystem::tick(double dt) {
  if (game_.isGameplayPaused()) return;

  for (int timerNum = 0; timerNum < animTimers_.size(); timerNum++) {
    Timer& animTimer = animTimers_[timerNum];

    animTimer.accumulate(dt);
    while (animTimer.step()) {
      for (Sprite& sprite : game_.getSprites() | game_.spriteView()) {
        if (sprite.isAnimated &&
            sprite.animations[sprite.animationId].timerNum == timerNum &&
            !sprite.animFinished &&
            !sprite.animPaused) {
          if (sprite.animSlowdown > 1) {
            sprite.animSlowdownProgress++;

            if (sprite.animSlowdownProgress == sprite.animSlowdown) {
              sprite.animSlowdownProgress = 0;
            } else {
              continue;
            }
          }

          sprite.animationFrame++;

          if (sprite.animationFrame >= sprite.animations[sprite.animationId].frameIndices.size()) {
            if (sprite.animations[sprite.animationId].looping) {
              sprite.animationFrame = 0;
            } else {
              sprite.animFinished = true;
              sprite.animationFrame = sprite.animations[sprite.animationId].frameIndices.size() - 1;
            }
          }
        }
      }
    }
  }

  bobbingTimer_.accumulate(dt);
  while (bobbingTimer_.step()) {
    for (Sprite& sprite : game_.getSprites() | game_.spriteView()) {
      if (sprite.isAnimated && sprite.bobbing) {
        if (sprite.bobbingDown) {
          sprite.bobAmount--;
          if (sprite.bobAmount == 0) {
            sprite.bobbingDown = false;
          }
        } else {
          sprite.bobAmount++;
          if (sprite.bobAmount == 4) {
            sprite.bobbingDown = true;
          }
        }
      }
    }
  }
}

void AnimationSystem::setSpriteDirection(int spriteId, Direction dir) {
  Sprite& sprite = game_.getSprite(spriteId);
  if (sprite.dir != dir) {
    sprite.dir = dir;
    updateAnimation(spriteId);
  }
}

void AnimationSystem::setSpriteAnimation(int spriteId, std::string_view name) {
  Sprite& sprite = game_.getSprite(spriteId);
  if (sprite.animationName != name) {
    sprite.animationName = name;
    updateAnimation(spriteId);
  }
}

void AnimationSystem::updateAnimation(int spriteId) {
  Sprite& sprite = game_.getSprite(spriteId);
  sprite.animationId = sprite.nameDirToAnim[sprite.animationName][sprite.dir];
  sprite.animationFrame = 0;
  sprite.animFinished = false;
  sprite.animPaused = false;
  sprite.animSlowdownProgress = 0;
}