summary refs log tree commit diff stats
path: root/src/animation_system.cpp
blob: cf34066ef6a12d764e196b5b7d35c90967bab4a9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#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, Renderer& renderer) {
  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;

  std::string imagename;
  datafile >> imagename;
  sprite.textureId = renderer.loadImageFromFile(imagename);

  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

  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
  while (std::getline(datafile, animLine)) {
    std::regex re(R"(([a-z]+)\[([a-z_]+)\]: ([0-9,]+))");
    std::smatch m;
    std::regex_match(animLine, m, re);

    std::vector<int> frames;
    auto framestrs = splitStr<std::list<std::string>>(m[3], ",");
    for (const std::string& f : framestrs) {
      frames.push_back(std::stoi(f));
    }

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

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

  updateAnimation(spriteId);
}

void AnimationSystem::tick(double dt) {
  animTimer_.accumulate(dt);
  while (animTimer_.step()) {
    for (Sprite& sprite : game_.getSprites() | game_.spriteView()) {
      if (sprite.isAnimated) {
        sprite.animationFrame++;
        if (sprite.animationFrame >= sprite.animations[sprite.animationId].size()) {
          sprite.animationFrame = 0;
        }
      }
    }
  }
}

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;
}