diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Color.cpp | 32 | ||||
-rw-r--r-- | src/Color.h | 18 | ||||
-rw-r--r-- | src/Qualum.cpp | 280 | ||||
-rw-r--r-- | src/Qualum.h | 37 | ||||
-rw-r--r-- | src/Rendering.cpp | 5 | ||||
-rw-r--r-- | src/Rendering.h | 16 | ||||
-rw-r--r-- | src/main.cpp | 124 |
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; +} + |