Line data Source code
1 : #include "rendersystem.h"
2 :
3 : #include "game.h"
4 :
5 5 : RenderSystem::RenderSystem(Game& game) : game_(game), randomArray2D_(64, 64, 0) {
6 20485 : for (int& v : randomArray2D_.data()) {
7 20480 : v = randInt(0, INT32_MAX);
8 : }
9 5 : }
10 :
11 5 : void RenderSystem::update() {
12 5 : const int slowBy = 2;
13 : static int slowDown = 0;
14 5 : bool updateAnimation = slowDown++ >= slowBy;
15 5 : if (updateAnimation)
16 1 : slowDown = 0;
17 :
18 5 : tick_++;
19 :
20 502 : for (auto& sprite : game_.sprites.values()) {
21 497 : if (updateAnimation) {
22 103 : if (sprite.animated) {
23 83 : sprite.frameCounter++;
24 83 : if (sprite.frameCounter >= sprite.frameRate && !sprite.frames.empty()) {
25 44 : sprite.frame = (sprite.frame + 1) % sprite.frames.size();
26 44 : sprite.frameCounter = 0;
27 : }
28 : }
29 :
30 103 : if (sprite.flashTimer > 0) {
31 0 : sprite.flashTimer--;
32 : }
33 : }
34 : }
35 5 : }
36 :
37 5 : void RenderSystem::render() {
38 5 : game_.window.clear();
39 :
40 5 : const recti& b = game_.worldBounds;
41 :
42 30 : auto renderLayer = [&](RenderLayer layer) {
43 4499 : for (const auto& sprite : game_.sprites.values()) {
44 2982 : if (sprite.renderLayer == layer) {
45 497 : vec2i p = sprite.position;
46 497 : if (game_.onScreen(p) && b.contains(p)) {
47 495 : vec2i sc = game_.screenCoord(p);
48 495 : bool flash = sprite.flashTimer > 0;
49 1485 : game_.window.set(sc.x, sc.y, sprite.frames[sprite.frame],
50 990 : flash ? TB_WHITE : sprite.fg, sprite.bg);
51 : }
52 : }
53 : }
54 35 : };
55 :
56 5 : renderGround();
57 :
58 : // Ground sprites
59 15 : for (auto layer : {RenderLayer::Ground, RenderLayer::GroundCover}) {
60 10 : renderLayer(layer);
61 : }
62 :
63 5 : renderOcean();
64 :
65 : // Remaining sprites
66 40 : for (auto layer :
67 5 : {RenderLayer::Particles, RenderLayer::MobBelow, RenderLayer::Mob, RenderLayer::MobAbove}) {
68 20 : renderLayer(layer);
69 : }
70 5 : }
71 :
72 5 : void RenderSystem::renderGround() {
73 5 : const vec2i ws{game_.window.width(), game_.window.height()};
74 5 : const recti& b = game_.worldBounds;
75 :
76 645 : for (int y = 0; y < ws.y; y++) {
77 164480 : for (int x = 0; x < ws.x; x++) {
78 163840 : vec2i p = game_.worldCoord({x, y});
79 163840 : if (game_.onScreen(p) && b.contains(p)) {
80 30720 : game_.window.set(x, y, game_.groundTile(p), TB_WHITE, TB_BLACK);
81 : }
82 : }
83 : }
84 5 : }
85 :
86 5 : void RenderSystem::renderOcean() {
87 5 : const vec2i ws{game_.window.width(), game_.window.height()};
88 5 : const recti& b = game_.worldBounds;
89 :
90 : // Maps a coordinate to a random int
91 135840 : auto hash = [&](vec2i p) -> size_t {
92 271680 : auto mod = [](int x, int m) {
93 271680 : if (x >= 0)
94 136590 : return x % m;
95 : else
96 135090 : return m - 1 - (-x % m);
97 : };
98 407520 : int px = mod(p.x + tick_ / 32, randomArray2D_.width());
99 271680 : int py = mod(p.y - tick_ / 256, randomArray2D_.height());
100 135840 : return randomArray2D_(px, py);
101 5 : };
102 :
103 : // Main mass
104 645 : for (int y = 0; y < ws.y; y++) {
105 164480 : for (int x = 0; x < ws.x; x++) {
106 163840 : vec2i p = game_.worldCoord({x, y});
107 163840 : if (game_.onScreen(p) && !b.contains(p)) {
108 133120 : char c = hash(p) % 16 == 0 ? '~' : ' ';
109 133120 : game_.window.set(x, y, c, TB_WHITE, TB_BLUE);
110 : }
111 : }
112 : }
113 :
114 : // Edges
115 15 : for (bool fg : {false, true}) {
116 10 : int tick = fg ? tick_ + 50 : tick_;
117 :
118 30 : for (int yEdge : {-1, 1}) {
119 20 : int y = (yEdge == -1) ? (b.top - b.height + 1) : b.top;
120 2580 : for (int x = b.left; x < b.left + b.width; x++) {
121 2560 : double mag = cos(tick * 0.03);
122 2560 : int depth = 1 + (int)(2 + 2 * mag * sin(tick * 0.01 + x * 0.1));
123 8980 : for (int dy = 0; dy < depth; dy++) {
124 6420 : vec2i p{x, y - dy * yEdge};
125 6420 : vec2i sc = game_.screenCoord(p);
126 6420 : if (game_.onScreen(p)) {
127 6420 : if (fg) {
128 3220 : char c = (dy == depth - 1) ? '~' : hash(p) % 4 == 0 ? '~' : ' ';
129 3220 : game_.window.set(sc.x, sc.y, c, TB_WHITE, TB_BLUE);
130 : } else {
131 3200 : game_.window.set(sc.x, sc.y, '~', TB_BLUE, TB_BLACK);
132 : }
133 : }
134 : }
135 : }
136 : }
137 :
138 30 : for (int xEdge : {-1, 1}) {
139 20 : int x = (xEdge == -1) ? b.left : (b.left + b.width - 1);
140 980 : for (int y = b.top - b.height + 1; y <= b.top; y++) {
141 960 : double mag = cos(tick * 0.03);
142 960 : int depth = 1 + (int)(2 + 2 * mag * sin(tick * 0.01 + y * 0.1));
143 3440 : for (int dx = 0; dx < depth; dx++) {
144 2480 : vec2i p{x - dx * xEdge, y};
145 2480 : vec2i sc = game_.screenCoord(p);
146 2480 : if (game_.onScreen(p)) {
147 2480 : if (fg) {
148 1260 : char c = (dx == depth - 1) ? '~' : hash(p) % 4 == 0 ? '~' : ' ';
149 1260 : game_.window.set(sc.x, sc.y, c, TB_WHITE, TB_BLUE);
150 : } else {
151 1220 : game_.window.set(sc.x, sc.y, '~', TB_BLUE, TB_BLACK);
152 : }
153 : }
154 : }
155 : }
156 : }
157 : }
158 5 : }
|