Collision demo for the Gameduino

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 
00002 #include "shield.h"
00003 #include "mbed.h"
00004 #include "GD.h"
00005 SPI spimain(ARD_MOSI, ARD_MISO, ARD_SCK); // mosi, miso, sclk
00006 GDClass GD(ARD_MOSI, ARD_MISO, ARD_SCK, ARD_D9, USBTX, USBRX) ;
00007 
00008 void readn(int *dst, unsigned int addr, int c) {
00009     GD.__start(addr);
00010     while (c--)
00011         *dst++ = spimain.write(0);
00012     GD.__end();
00013 }
00014 
00015 #define NBALLS 80
00016 
00017 static int coll[NBALLS];
00018 static void load_coll() {
00019     while (GD.rd(VBLANK) == 0)  // Wait until vblank
00020         ;
00021     while (GD.rd(VBLANK) == 1)  // Wait until display
00022         ;
00023     while (GD.rd(VBLANK) == 0)  // Wait until vblank
00024         ;
00025     readn(coll, COLLISION, NBALLS);
00026 }
00027 
00028 struct ball {
00029     int x, y;
00030     signed char vx, vy;
00031     int lasthit;
00032 };
00033 
00034 static struct ball balls[NBALLS];
00035 
00036 #include "stone_wall_texture.h" // texture from 3dmd.net project
00037 #include "sphere.h"
00038 
00039 static void plot_balls() {
00040     int i;
00041     for (i = 0; i < NBALLS; i++)
00042         GD.sprite(i, balls[i].x >> 4, balls[i].y >> 4, 0, 0, 0);
00043 }
00044 
00045 // Place all balls so that none collide.  Do this by placing all at
00046 // random, then moving until there are no collisions
00047 
00048 static int anycolliding() {
00049     plot_balls();
00050     load_coll();
00051     int i;
00052     for (i = 0; i < NBALLS; i++)
00053         if (coll[i] != 0xff)
00054             return 1;
00055     return 0;
00056 }
00057 
00058 static void place_balls() {
00059     int i;
00060     for (i = 0; i < NBALLS; i++) {
00061         balls[i].x = (2 + rand()%380) << 4;
00062         balls[i].y = (2 + rand()%280) << 4;
00063         balls[i].vx = (rand()%256)-128;
00064         balls[i].vy = (rand()%256)-128;
00065         balls[i].lasthit = 255;
00066     }
00067     while (anycolliding()) {
00068         for (i = 0; i < NBALLS; i++) {
00069             if (coll[i] != 0xff) {
00070                 balls[i].x = (2 + (rand()%380)) << 4;
00071                 balls[i].y = (2 + (rand()%280)) << 4;
00072             }
00073         }
00074     }
00075 }
00076 
00077 void setup() {
00078     int i;
00079 
00080     GD.begin();
00081 
00082     GD.wr(JK_MODE, 0);
00083 
00084     GD.copy(RAM_CHR, stone_wall_texture_chr, sizeof(stone_wall_texture_chr));
00085     GD.copy(RAM_PAL, stone_wall_texture_pal, sizeof(stone_wall_texture_pal));
00086     for (i = 0; i < 4096; i++)
00087         GD.wr(RAM_PIC + i, (i & 15) + ((i >> 6) << 4));
00088 
00089     GD.copy(RAM_SPRIMG, sphere_img, sizeof(sphere_img));
00090     GD.copy(RAM_SPRPAL, sphere_pal, sizeof(sphere_pal));
00091 
00092     for (i = 0; i < 256; i++)
00093         GD.sprite(i, 400, 400, 0, 0, 0);
00094 
00095     place_balls();
00096 }
00097 
00098 
00099 float dot(float x1, float y1, float x2, float y2) {
00100     return (x1 * x2) + (y1 * y2);
00101 }
00102 
00103 // Collide ball a with ball b, compute new velocities.
00104 // Algorithm from
00105 // http://stackoverflow.com/questions/345838/ball-to-ball-collision-detection-and-handling
00106 
00107 void collide(struct ball *a, struct ball *b) {
00108     float collision_x, collision_y;
00109 
00110     collision_x = a->x - b->x;
00111     collision_y = a->y - b->y;
00112     float distance = sqrt(collision_x * collision_x + collision_y * collision_y);
00113     float rdistance = 1.0 / distance;
00114     collision_x *= rdistance;
00115     collision_y *= rdistance;
00116     float aci = dot(a->vx, a->vy, collision_x, collision_y);
00117     float bci = dot(b->vx, b->vy, collision_x, collision_y);
00118     float acf = bci;
00119     float bcf = aci;
00120     a->vx += int((acf - aci) * collision_x);
00121     a->vy += int((acf - aci) * collision_y);
00122     b->vx += int((bcf - bci) * collision_x);
00123     b->vy += int((bcf - bci) * collision_y);
00124 }
00125 
00126 #define LWALL (0 << 4)
00127 #define RWALL (384 << 4)
00128 #define TWALL (0 << 4)
00129 #define BWALL (284 << 4)
00130 
00131 static int timer;
00132 int main() {
00133     setup();
00134     while (1) {
00135         int i;
00136 
00137         plot_balls();
00138 
00139         load_coll();
00140 
00141         struct ball *pb;
00142 
00143         for (i = NBALLS, pb = balls; i--; pb++, i) {
00144             if ((pb->x <= LWALL)) {
00145                 pb->x = LWALL;
00146                 pb->vx = -pb->vx;
00147             }
00148             if ((pb->x >= RWALL)) {
00149                 pb->x = RWALL;
00150                 pb->vx = -pb->vx;
00151             }
00152             if ((pb->y <= TWALL)) {
00153                 pb->y = TWALL;
00154                 pb->vy = -pb->vy;
00155             }
00156             if ((pb->y >= BWALL)) {
00157                 pb->y = BWALL;
00158                 pb->vy = -pb->vy;
00159             }
00160         }
00161         for (i = 1; i < NBALLS; i++) {
00162             int other = coll[i];
00163             if ((balls[i].lasthit != other) && other != 0xff) {
00164                 collide(&balls[i], &balls[other]);
00165             }
00166             balls[i].lasthit = other;
00167         }
00168         for (i = NBALLS, pb = balls; i--; pb++, i) {
00169             pb->x += pb->vx;
00170             pb->y += pb->vy;
00171         }
00172         if (++timer == 2000) {
00173             place_balls();
00174             wait_ms(1000);
00175             timer = 0;
00176         }
00177     }
00178 }