summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLeo Tenenbaum <leonardomtenenbaum@gmail.com>2018-03-23 00:00:50 -0400
committerLeo Tenenbaum <leonardomtenenbaum@gmail.com>2018-03-23 00:00:50 -0400
commit5e54af301b2b99e8479da3195ef30d0f8ec19227 (patch)
tree0647a605126d94cc914345c587512cf7a9b59dc3 /src
parentbedd7a371cc4649b95dc09bafa1c7ee23a4affb6 (diff)
Initial commit
Diffstat (limited to 'src')
-rw-r--r--src/Color.cpp32
-rw-r--r--src/Color.h18
-rw-r--r--src/Qualum.cpp280
-rw-r--r--src/Qualum.h37
-rw-r--r--src/Rendering.cpp5
-rw-r--r--src/Rendering.h16
-rw-r--r--src/main.cpp124
7 files changed, 512 insertions, 0 deletions
diff --git a/src/Color.cpp b/src/Color.cpp
new file mode 100644
index 0000000..b612315
--- /dev/null
+++ b/src/Color.cpp
@@ -0,0 +1,32 @@
+
+#include "Color.h"
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+unsigned Colors::colors[] = {0x888888, 0xFF0000, 0x0000FF, 0x00FF00,
+ 0x660099, 0xFFFF00, 0x00FFFF, 0xFF8800};
+char* Colors::color_names[] = {"GA", "RE", "BL", "GE", "PU", "YE", "CY", "OR", NULL};
+
+Color Colors::read_color(char* s)
+{
+ for (int i = 0; Colors::color_names[i]; i++)
+ if (!strcmp(Colors::color_names[i], s))
+ return (Color) i;
+ fprintf(stderr, "Error - Color not found: %s\n", s);
+ exit(1);
+}
+
+unsigned Colors::get_color(Color c)
+{
+ // Color to 0xAABBCC format
+ return colors[(int)c];
+}
+
+void Colors::to_rgb(Color c, unsigned char* r, unsigned char* g, unsigned char* b)
+{
+ unsigned c_int = get_color(c);
+ *r = c_int >> 16;
+ *g = (c_int >> 8) % 256;
+ *b = c_int % 256;
+} \ No newline at end of file
diff --git a/src/Color.h b/src/Color.h
new file mode 100644
index 0000000..0f67023
--- /dev/null
+++ b/src/Color.h
@@ -0,0 +1,18 @@
+
+#ifndef COLOR_H
+#define COLOR_H
+
+enum class Color { GRAY, RED, BLUE, GREEN, PURPLE, YELLOW, CYAN, ORANGE };
+
+class Colors {
+public:
+ static Color read_color(char* s);
+ static void to_rgb(Color c, unsigned char* r, unsigned char* g, unsigned char* b);
+private:
+ static unsigned get_color(Color c);
+ static unsigned colors[];
+ static char* color_names[];
+};
+
+#endif /* COLOR_H */
+
diff --git a/src/Qualum.cpp b/src/Qualum.cpp
new file mode 100644
index 0000000..02327e8
--- /dev/null
+++ b/src/Qualum.cpp
@@ -0,0 +1,280 @@
+#include "Qualum.h"
+#include "Rendering.h"
+#include "Color.h"
+#include <SDL.h>
+#include <vector>
+#include <iostream>
+
+int Qualum::locations[Rendering::GRID_HEIGHT][Rendering::GRID_WIDTH];
+std::vector<Qualum*> Qualum::qualums;
+int Qualum::iterations = 0;
+
+void Qualum::initialize()
+{
+ for (int i = 0; i < Rendering::GRID_HEIGHT; i++)
+ {
+ for (int j = 0; j < Rendering::GRID_WIDTH; j++)
+ {
+ locations[i][j] = -1;
+ }
+ }
+}
+
+Qualum::Qualum(int x_, int y_, Color color_, int sx, int sy): x(x_), y(y_), color(color_), speedx(sx), speedy(sy) {
+ index = Qualum::qualums.size();
+ can_collide = true;
+ delayed = 0;
+ Qualum::qualums.push_back(this);
+}
+
+Qualum* Qualum::create_qualum(int x, int y, Color color, int sx, int sy)
+{
+ // printf("Position: %d,%d Color: %d Speed: %d,%d\n", x, y, (int)color, sx, sy);
+ Qualum* newq = (Qualum*)calloc(1,sizeof(Qualum));
+ newq = new Qualum(x, y, color, sx, sy);
+ return newq;
+}
+
+Qualum::~Qualum()
+{
+ if (index >= 0 && index < Qualum::qualums.size())
+ Qualum::qualums[index] = NULL;
+ if (!(x < 0 || y < 0 || x >= Rendering::GRID_WIDTH || y >= Rendering::GRID_HEIGHT)
+ && Qualum::locations[y][x] == index)
+ Qualum::locations[y][x] = -1;
+}
+
+void Qualum::destroy()
+{
+ // Destroy this qualum
+ /*printf("%p; ", Qualum::qualums[index]);
+ printf("Destroying ");
+ debug();
+ printf("\n");
+ */
+ delete this;
+}
+
+void Qualum::render(SDL_Renderer* renderer)
+{
+ unsigned char r;
+ unsigned char g;
+ unsigned char b;
+ Colors::to_rgb(color, &r, &g, &b);
+ SDL_SetRenderDrawColor(renderer, r, g, b, 255);
+ SDL_Rect rect = {x*Rendering::RENDER_SCALE, y*Rendering::RENDER_SCALE,
+ Rendering::RENDER_SCALE, Rendering::RENDER_SCALE};
+ SDL_RenderFillRect(renderer, &rect);
+}
+
+void Qualum::render_all(SDL_Renderer* renderer)
+{
+ for (Qualum* qualum: qualums)
+ {
+ if (qualum != NULL)
+ qualum->render(renderer);
+ }
+}
+
+void Qualum::two_perpendiculars(int speedx, int speedy, int* speedx1, int* speedy1, int* speedx2, int* speedy2)
+{
+ // [speedx1 speedy1] is [speedx speedy] turned 90d left, and [speedx2 speedy2] is it turned 90d right
+ if (speedx1 != NULL && speedy1 != NULL)
+ {
+ *speedx1 = speedy;
+ *speedy1 = -speedx;
+ }
+ if (speedx2 != NULL && speedy2 != NULL)
+ {
+ *speedx2 = -speedy;
+ *speedy2 = speedx;
+ }
+}
+
+void Qualum::debug()
+{
+ printf("(%d: %p) Color: %d; Position: %d,%d; Speed: %d,%d", index, Qualum::qualums[index], (int)color, x, y, speedx, speedy);
+}
+
+void Qualum::collide_with(Qualum* q)
+{
+ /*
+ printf("Collision: ");
+ debug();
+ printf(" and ");
+ q->debug();
+ printf("\n");
+ */
+ if (!can_collide || !q->can_collide)
+ {
+ return;
+ }
+ if (q->color == Color::RED && color == Color::RED) // Destroy
+ {
+ destroy();
+ q->destroy();
+ return;
+ }
+ if (color == Color::RED)
+ {
+ q->destroy();
+ return;
+ }
+ if (q->color == Color::RED)
+ {
+ q->collide_with(this);
+ return;
+ }
+
+ if (color == Color::CYAN)
+ {
+ q->delayed = 1;
+ q->can_collide = false;
+ return;
+ }
+ if (q->color == Color::CYAN)
+ {
+ q->collide_with(this);
+ return;
+ }
+ if (color == Color::ORANGE)
+ {
+ q->delayed = 16;
+ q->can_collide = false;
+ return;
+ }
+ if (q->color == Color::ORANGE)
+ {
+ q->collide_with(this);
+ return;
+ }
+
+ if (color == Color::GRAY) // Turn
+ {
+ Qualum::two_perpendiculars(q->speedx, q->speedy, &q->speedx, &q->speedy, NULL, NULL);
+ if (q->color == Color::GRAY)
+ Qualum::two_perpendiculars(speedx, speedy, &speedx, &speedy, NULL, NULL);
+ return;
+ }
+ if (q->color == Color::GRAY)
+ {
+ q->collide_with(this);
+ return;
+ }
+
+ if ((color == Color::GREEN || color == Color::BLUE)
+ && (q->color == Color::GREEN || q->color == Color::BLUE)) // NAND - Green=True, Blue=False
+ {
+ Color out = !((color == Color::GREEN) && (q->color == Color::GREEN)) ?
+ Color::GREEN : Color::BLUE;
+ Qualum::create_qualum(x, y, out, speedx + q->speedx, speedy + q->speedy);
+ destroy();
+ q->destroy();
+ return;
+ }
+
+ if (color == Color::PURPLE && q->color == Color::PURPLE)
+ {
+ destroy();
+ q->destroy();
+ return;
+ }
+ if (color == Color::PURPLE)
+ {
+ Qualum* newq1 = Qualum::create_qualum(x, y, q->color, 0, 0);
+ Qualum* newq2 = Qualum::create_qualum(x, y, q->color, 0, 0);
+ Qualum::two_perpendiculars(q->speedx, q->speedy, &newq1->speedx, &newq1->speedy, &newq2->speedx, &newq2->speedy);
+ q->destroy();
+ return;
+ }
+ if (q->color == Color::PURPLE)
+ {
+ q->collide_with(this);
+ return;
+ }
+
+ if (color == Color::YELLOW) // Stop
+ {
+ x -= speedx; // Reverse any movement
+ y -= speedy;
+
+ q->x -= q->speedx;
+ q->y -= q->speedy;
+
+ q->speedx = 0;
+ q->speedy = 0;
+
+ speedx = 0;
+ speedy = 0;
+ return;
+ }
+
+ if (q->color == Color::YELLOW)
+ {
+ q->collide_with(this);
+ return;
+ }
+}
+
+void Qualum::update()
+{
+ /*
+ printf("Updating ");
+ debug();
+ printf("\n");
+ */
+ if (x < 0 || y < 0 || x >= Rendering::GRID_WIDTH || y >= Rendering::GRID_HEIGHT)
+ {
+ destroy();
+ return;
+ }
+ if (Qualum::locations[y][x] == index)
+ Qualum::locations[y][x] = -1;
+ if (delayed)
+ {
+ delayed--;
+ }
+ else
+ {
+ x += speedx;
+ y += speedy;
+ if (!can_collide)
+ {
+ can_collide = true;
+ }
+ }
+ if (x < 0 || y < 0 || x >= Rendering::GRID_WIDTH || y >= Rendering::GRID_HEIGHT)
+ {
+ destroy();
+ return;
+ }
+
+ if (Qualum::locations[y][x] == -1)
+ {
+ Qualum::locations[y][x] = index;
+ }
+ else
+ {
+ collide_with(Qualum::qualums[Qualum::locations[y][x]]);
+ }
+}
+
+void Qualum::update_all(bool should_update)
+{
+ /*// Ideally, this code should not be necessary:
+ for (int y = 0; y < Rendering::GRID_HEIGHT; y++)
+ for (int x = 0; x < Rendering::GRID_WIDTH; x++)
+ Qualum::locations[y][x] = -1;
+ */
+ if (!should_update)
+ return;
+ Qualum::iterations++;
+ int size = qualums.size();
+ for (int i = 0; i < size; i++)
+ {
+ if (qualums[i] != nullptr)
+ {
+ qualums[i]->update();
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Qualum.h b/src/Qualum.h
new file mode 100644
index 0000000..49a92b2
--- /dev/null
+++ b/src/Qualum.h
@@ -0,0 +1,37 @@
+#ifndef QUALUM_H
+#define QUALUM_H
+
+#include <vector>
+#include <SDL.h>
+#include "Color.h"
+#include "Rendering.h"
+
+class Qualum {
+public:
+ Qualum(int x, int y, Color color, int sx, int sy);
+ ~Qualum();
+ static Qualum* create_qualum(int x, int y, Color color, int sx, int sy);
+ void render(SDL_Renderer* renderer);
+ void update();
+ static std::vector<Qualum*> qualums;
+ static void render_all(SDL_Renderer* renderer);
+ static void update_all(bool should_update);
+ static void initialize();
+ static int iterations;
+private:
+ static int locations[Rendering::GRID_HEIGHT][Rendering::GRID_WIDTH];
+ static void two_perpendiculars(int speedx, int speedy, int* speedx1, int* speedy1, int* speedx2, int* speedy2);
+ static void combine_speeds(int speedx1, int speedy1, int speedx2, int speedy2, int* speedx, int* speedy);
+ void collide_with(Qualum* q);
+ void debug();
+ void destroy();
+ int x, y, index;
+ int speedx, speedy;
+ int delayed;
+ bool can_collide;
+ Color color;
+
+};
+
+#endif /* QUALUM_H */
+
diff --git a/src/Rendering.cpp b/src/Rendering.cpp
new file mode 100644
index 0000000..542c679
--- /dev/null
+++ b/src/Rendering.cpp
@@ -0,0 +1,5 @@
+#include "Rendering.h"
+
+int Rendering::RENDER_SCALE = 3;
+int Rendering::WIDTH = GRID_WIDTH * RENDER_SCALE;
+int Rendering::HEIGHT = GRID_HEIGHT * RENDER_SCALE;
diff --git a/src/Rendering.h b/src/Rendering.h
new file mode 100644
index 0000000..fcc147b
--- /dev/null
+++ b/src/Rendering.h
@@ -0,0 +1,16 @@
+#ifndef RENDERING_H
+#define RENDERING_H
+
+class Rendering {
+public:
+ static int RENDER_SCALE;
+ static const int GRID_WIDTH = 400;
+ static const int GRID_HEIGHT = 300;
+ static int WIDTH;
+ static int HEIGHT;
+private:
+
+};
+
+#endif /* RENDERING_H */
+
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..d96441f
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,124 @@
+#include <iostream>
+#include <vector>
+
+#include "SDL.h"
+#include "Qualum.h"
+#include "Rendering.h"
+#include "Color.h"
+
+SDL_Window* window;
+
+float TIME_SCALE = 4.0f;
+
+void quit()
+{
+ SDL_DestroyWindow(window);
+ SDL_Quit();
+}
+
+void read_file(char* filename, int x, int y, int speedx, int speedy)
+{
+ // Create the qualums from the given file
+ // Increasing their positions by (x,y) and their speeds by (speedx, speedy)
+ FILE* input_file = fopen(filename, "r"); // Skip first line
+ if (!input_file)
+ {
+ fprintf(stderr, "File not found: %s\n", filename);
+ exit(1);
+ }
+ char* buffer = (char*)malloc(4096);
+ fgets(buffer, 4096, input_file);
+
+ int xrel, yrel, speedxrel, speedyrel; // Read input file
+ char* color_str = (char*) malloc(4096);
+ char* include_filename = (char*) malloc(4096); // File name for includes
+
+ while (fgets(buffer, 4096, input_file))
+ {
+ int i;
+ for (i = 0; i < strlen(buffer); i++)
+ if (buffer[i] == '#')
+ break;
+ buffer[i] = 0;
+ if (sscanf(buffer, "%d %d %d %d %s", &xrel, &yrel, &speedxrel, &speedyrel, color_str) > 0)
+ {
+ if (color_str[0] == '!') // Include
+ {
+ int c;
+ for (c = 0; color_str[c+1]; c++) // Remove !
+ include_filename[c] = color_str[c+1];
+ include_filename[c] = 0;
+ read_file(include_filename, x + xrel, y + yrel, speedx + speedxrel, speedy + speedyrel);
+ }
+ else // Color
+ {
+ Color color = Colors::read_color(color_str);
+ Qualum::create_qualum(x + xrel, y + yrel, color, speedx + speedxrel, speedy + speedyrel);
+ }
+ }
+ }
+}
+
+int main(int argc, char** argv)
+{
+ if (argc < 2)
+ {
+ fprintf(stderr, "Error: No input file provided.\n");
+ return 1;
+ }
+
+ Qualum::initialize();
+ window = SDL_CreateWindow("Qualums", SDL_WINDOWPOS_UNDEFINED,
+ SDL_WINDOWPOS_UNDEFINED, Rendering::WIDTH, Rendering::HEIGHT,
+ SDL_WINDOW_SHOWN);
+ SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
+
+ SDL_Event event;
+ bool will_quit = false;
+
+ read_file(argv[1], 0, 0, 0, 0);
+
+ int i = 0, last_printed = -1;
+ while (!will_quit)
+ {
+ i++;
+ if (Qualum::iterations != last_printed)
+ {
+ printf("%d\n", Qualum::iterations);
+ last_printed = Qualum::iterations;
+ }
+ SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
+ SDL_RenderClear(renderer);
+ Qualum::update_all(i % ((int)(300/TIME_SCALE)) == 0);
+ Qualum::render_all(renderer);
+ SDL_RenderPresent(renderer);
+ while (SDL_PollEvent(&event))
+ {
+ switch (event.type)
+ {
+ case SDL_QUIT:
+ will_quit = true;
+ break;
+ case SDL_KEYDOWN:
+ if (event.key.keysym.sym >= SDLK_0 && event.key.keysym.sym <= SDLK_9)
+ {
+ TIME_SCALE = (float)(event.key.keysym.sym - SDLK_0);
+ break;
+ }
+ switch (event.key.keysym.sym)
+ {
+ case SDLK_SPACE:
+ Qualum::update_all(true);
+ break;
+ case SDLK_ESCAPE:
+ will_quit = true;
+ break;
+ }
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+