diff options
-rw-r--r-- | asteroids.c | 199 |
1 files changed, 138 insertions, 61 deletions
diff --git a/asteroids.c b/asteroids.c index f353db9..33876f0 100644 --- a/asteroids.c +++ b/asteroids.c @@ -4,20 +4,21 @@ #include <math.h> #include <time.h> - -const int width = 800; -const int height = 800; +const int width = 2650; +const int height = 1440; const int fps = 60; const Color bg = BLACK; const Color fg = GREEN; +const float THRUST = 0.04f; +const float RUDDER = 0.05f; const float NOSE = PI/8; const int LENGTH = 36; -const float THRUST = 0.1; const int SPAWN_RATE = 10*60; const float S_SPEED = 4.0f; -const int LAZER_LENGTH = 8; +const int LAZER_LENGTH = 3; +const int MAX_SIZE=5; typedef struct B { Vector2 pos; @@ -25,16 +26,18 @@ typedef struct B { int size; } Asteroid, Bullet; -Vector2 sky[256]; -Asteroid asteroids[64]; -Bullet bullets[8]; +Vector2 sky[512]; +Asteroid asteroids[128]; +Bullet bullets[16]; -Vector2 pos = {(float) height / 2, (float) width / 2}; -Vector2 vel = {0.0f, 0.0f}; -float angle = 0; +bool alive = 1; +Vector2 pos; +Vector2 vel; +float angle; int l = 0; + int clamp(Vector2 *vec) { if (vec->x > width+LENGTH) vec->x -= width+LENGTH; if (vec->x < -LENGTH) vec->x += width+LENGTH*2; @@ -82,8 +85,8 @@ int drawPlayer() { int shoot() { Vector2 position = pos; Vector2 velocity = (Vector2){ - S_SPEED * sin(angle), - S_SPEED * cos(angle) + vel.x + S_SPEED * sin(angle), + vel.y + S_SPEED * cos(angle) }; int i = 0; @@ -102,11 +105,14 @@ int addAsteroid(Vector2 position, Vector2 velocity, int size) { int i = 0; while (i < sizeof(asteroids) / sizeof(Asteroid)) { if (asteroids[i].size == 0) { + asteroids[i].pos.x = position.x; asteroids[i].pos.y = position.y; asteroids[i].vel.x = velocity.x; asteroids[i].vel.y = velocity.y; asteroids[i].size = size; + + return 0; } i++; @@ -116,67 +122,123 @@ int addAsteroid(Vector2 position, Vector2 velocity, int size) { int spawnAsteroid() { Vector2 s,v; - if (rand() % 2 == 0) { - s = (Vector2){0, rand() % height}; + if (rand()%2) { + if (rand()%2) s = (Vector2){0, rand() % height}; + else s = (Vector2){width, rand() % height}; } else { - s = (Vector2){rand() % width, 0}; + if (rand()%2) s = (Vector2){rand() % width, 0}; + else s = (Vector2){rand() % width, height}; } float n = -sqrt(pow(s.x - (width/2), 2) + pow(s.y - (height/2), 2)); - float m = (float)(rand() % 4 + 1); + float m = (float)(rand() % 7 + 1); v = (Vector2){ (s.x-(width/2)) / n, (s.y-(height/2)) / n }; - addAsteroid(s, v, (rand()%4)+1); + addAsteroid(s, v, (rand()%MAX_SIZE)+1); } int breakAsteroid(int i) { asteroids[i].size -= 1; if (asteroids[i].size > 0) { - double m = magnitude(&asteroids[i].vel)*0.5d; + // split the velocity in 2, adding a bit extra from the lazer + double m = (magnitude(&asteroids[i].vel) + 0.3d*S_SPEED)*0.5d; randVec(&asteroids[i].vel, m); + int s = pow(2, asteroids[i].size + 1); addAsteroid( - asteroids[i].pos, + (Vector2){asteroids[i].pos.x - s, asteroids[i].pos.y - s}, (Vector2){-asteroids[i].vel.x, -asteroids[i].vel.y}, asteroids[i].size ); + asteroids[i].pos.x += s; + asteroids[i].pos.y += s; } } +int collideAsteroids(Asteroid *a, Asteroid *b) { + + int aa = pow(pow(2, a->size+1), 2); + int ba = pow(pow(2, b->size+1), 2); + int ta = aa+ba; + + const int x = a->pos.x - b->pos.x; + const int y = a->pos.y - b->pos.y; + const int d = x * x + y * y; + + const double u1 = (a->vel.x * x + a->vel.y * y) / d; // a to b + const double u2 = (x * a->vel.y - y * a->vel.x) / d; // adjust a along tangent + const double u3 = (b->vel.x * x + b->vel.y * y) / d; // from b to a + const double u4 = (x * b->vel.y - y * b->vel.x) / d; // adjust b along tangent + + // adjust to work with different masses; + const double vu3 = ((aa - ba) / ta) * u1 + (2 * ba) / ta * u3; + const double vu1 = ((ba - aa) / ta) * u3 + (2 * aa) / ta * u1; + + // set new velocity + b->vel.x = x * vu1 - y * u4; + b->vel.y = y * vu1 + x * u4; + a->vel.x = x * vu3 - y * u2; + a->vel.y = y * vu3 + x * u2; +} + +int reset() { + for (int i = 0; i < 256; i++) { + sky[i] = (Vector2){rand() % width, rand() % height}; + } + for (int i=0; i < sizeof(asteroids) / sizeof(Asteroid); i++) { + asteroids[i] = (Asteroid){(Vector2){0,0}, (Vector2){0,0}, 0}; + } + for (int i=0; i < sizeof(bullets) / sizeof(Bullet); i++) { + bullets[i] = (Bullet){(Vector2){0,0}, (Vector2){0,0}, 0}; + } + for (int i = 0; i < (rand()%10) + 3; i++) { + spawnAsteroid(); + } + alive = 1; + pos = (Vector2){(float) width / 2, (float) height / 2}; + vel = (Vector2){0.0f, 0.0f}; + angle = 0; +} + int draw() { - if (IsKeyDown(KEY_RIGHT)) angle -= 0.1f; - if (IsKeyDown(KEY_LEFT)) angle += 0.1f; + BeginDrawing(); + ClearBackground(BLACK); - if (IsKeyDown(KEY_UP)) { - vel.x += sin(angle) * THRUST; - vel.y += cos(angle) * THRUST; + for (int i = 0; i < 256; i++) { + DrawPixelV(sky[i], fg); } + if (alive) { + if (IsKeyDown(KEY_RIGHT)) angle -= RUDDER; + if (IsKeyDown(KEY_LEFT)) angle += RUDDER; + + if (IsKeyDown(KEY_UP)) { + vel.x += sin(angle) * THRUST; + vel.y += cos(angle) * THRUST; + } + + pos.x += vel.x; + pos.y += vel.y; + clamp(&pos); + drawPlayer(); + } + if (IsKeyDown(KEY_SPACE)) { - if (l == 0) { - shoot(); + if (!l) { l = 1; + if (alive) shoot(); + else { + reset(); + return 0; + } } } else { l = 0; } - - pos.x += vel.x; - pos.y += vel.y; - clamp(&pos); - if (rand() % SPAWN_RATE == 0) { spawnAsteroid(); } - - BeginDrawing(); - ClearBackground(BLACK); - - for (int i = 0; i < 256; i++) { - DrawPixelV(sky[i], fg); - } - drawPlayer(); for (int i=0; i < sizeof(bullets) / sizeof(Bullet); i++) { Bullet *b = &bullets[i]; @@ -196,20 +258,48 @@ int draw() { break; } } + if (CheckCollisionPointTriangle(b->pos, pos, wingpos(1), wingpos(-1))) { + alive = 0; + } } } for (int i=0; i < sizeof(asteroids) / sizeof(Asteroid); i++) { - if (asteroids[i].size > 0) { + Asteroid *asteroid = &asteroids[i]; + if (asteroid->size > 0) { + int csize = pow(2, asteroid->size + 1); DrawCircleLines( - asteroids[i].pos.x, - asteroids[i].pos.y, - pow(2, asteroids[i].size + 1), + + asteroid->pos.x, + asteroid->pos.y, + csize, fg ); - asteroids[i].pos.x += asteroids[i].vel.x; - asteroids[i].pos.y += asteroids[i].vel.y; - clamp(&asteroids[i].pos); + + for (int j=0; j < sizeof(asteroids) / sizeof(Asteroid); j++) { + if (i!=j) { + Asteroid *other = &asteroids[j]; + if (CheckCollisionCircles(asteroid->pos, pow(2, asteroid->size + 1), + other->pos, pow(2, other->size + 1))) { + collideAsteroids(asteroid, other); + break; + } + } + } + + // Doesnt necessarily catch all collision cases :/ + if ( + CheckCollisionPointCircle(pos, asteroid->pos, csize) + || CheckCollisionPointCircle(wingpos(-1), asteroid->pos, csize) + || CheckCollisionPointCircle(wingpos(1), asteroid->pos, csize) + || CheckCollisionPointTriangle(asteroid->pos, pos, wingpos(1), wingpos(2)) + ) { + alive = 0; + } + + asteroid->pos.x += asteroid->vel.x; + asteroid->pos.y += asteroid->vel.y; + clamp(&asteroid->pos); } } EndDrawing(); @@ -217,20 +307,7 @@ int draw() { int main() { srand(time(0)); - - for (int i = 0; i < 256; i++) { - sky[i] = (Vector2){rand() % width, rand() % height}; - } - for (int i=0; i < sizeof(asteroids) / sizeof(Asteroid); i++) { - asteroids[i] = (Asteroid){(Vector2){0,0}, (Vector2){0,0}, 0}; - } - for (int i=0; i < sizeof(bullets) / sizeof(bullets); i++) { - bullets[i] = (Bullet){(Vector2){0,0}, (Vector2){0,0}, 0}; - } - for (int i = 1; i < rand()%10; i++) { - spawnAsteroid(); - } - + reset(); InitWindow(width, height, "game"); Vector2 m = GetMonitorPosition(1); |