summaryrefslogtreecommitdiff
path: root/asteroids.c
diff options
context:
space:
mode:
Diffstat (limited to 'asteroids.c')
-rw-r--r--asteroids.c199
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);