Chris Dick
/
Gameduino_collision_demo
Collision demo for the Gameduino
main.cpp@1:614d0042c0d5, 2012-12-21 (annotated)
- Committer:
- TheChrisyd
- Date:
- Fri Dec 21 13:50:18 2012 +0000
- Revision:
- 1:614d0042c0d5
- Parent:
- 0:deb284e70ca5
updated Gameduino library
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
TheChrisyd | 0:deb284e70ca5 | 1 | |
TheChrisyd | 0:deb284e70ca5 | 2 | #include "shield.h" |
TheChrisyd | 0:deb284e70ca5 | 3 | #include "mbed.h" |
TheChrisyd | 0:deb284e70ca5 | 4 | #include "GD.h" |
TheChrisyd | 0:deb284e70ca5 | 5 | SPI spimain(ARD_MOSI, ARD_MISO, ARD_SCK); // mosi, miso, sclk |
TheChrisyd | 0:deb284e70ca5 | 6 | GDClass GD(ARD_MOSI, ARD_MISO, ARD_SCK, ARD_D9, USBTX, USBRX) ; |
TheChrisyd | 0:deb284e70ca5 | 7 | |
TheChrisyd | 0:deb284e70ca5 | 8 | void readn(int *dst, unsigned int addr, int c) { |
TheChrisyd | 0:deb284e70ca5 | 9 | GD.__start(addr); |
TheChrisyd | 0:deb284e70ca5 | 10 | while (c--) |
TheChrisyd | 0:deb284e70ca5 | 11 | *dst++ = spimain.write(0); |
TheChrisyd | 0:deb284e70ca5 | 12 | GD.__end(); |
TheChrisyd | 0:deb284e70ca5 | 13 | } |
TheChrisyd | 0:deb284e70ca5 | 14 | |
TheChrisyd | 0:deb284e70ca5 | 15 | #define NBALLS 80 |
TheChrisyd | 0:deb284e70ca5 | 16 | |
TheChrisyd | 0:deb284e70ca5 | 17 | static int coll[NBALLS]; |
TheChrisyd | 0:deb284e70ca5 | 18 | static void load_coll() { |
TheChrisyd | 0:deb284e70ca5 | 19 | while (GD.rd(VBLANK) == 0) // Wait until vblank |
TheChrisyd | 0:deb284e70ca5 | 20 | ; |
TheChrisyd | 0:deb284e70ca5 | 21 | while (GD.rd(VBLANK) == 1) // Wait until display |
TheChrisyd | 0:deb284e70ca5 | 22 | ; |
TheChrisyd | 0:deb284e70ca5 | 23 | while (GD.rd(VBLANK) == 0) // Wait until vblank |
TheChrisyd | 0:deb284e70ca5 | 24 | ; |
TheChrisyd | 0:deb284e70ca5 | 25 | readn(coll, COLLISION, NBALLS); |
TheChrisyd | 0:deb284e70ca5 | 26 | } |
TheChrisyd | 0:deb284e70ca5 | 27 | |
TheChrisyd | 0:deb284e70ca5 | 28 | struct ball { |
TheChrisyd | 0:deb284e70ca5 | 29 | int x, y; |
TheChrisyd | 0:deb284e70ca5 | 30 | signed char vx, vy; |
TheChrisyd | 0:deb284e70ca5 | 31 | int lasthit; |
TheChrisyd | 0:deb284e70ca5 | 32 | }; |
TheChrisyd | 0:deb284e70ca5 | 33 | |
TheChrisyd | 0:deb284e70ca5 | 34 | static struct ball balls[NBALLS]; |
TheChrisyd | 0:deb284e70ca5 | 35 | |
TheChrisyd | 0:deb284e70ca5 | 36 | #include "stone_wall_texture.h" // texture from 3dmd.net project |
TheChrisyd | 0:deb284e70ca5 | 37 | #include "sphere.h" |
TheChrisyd | 0:deb284e70ca5 | 38 | |
TheChrisyd | 0:deb284e70ca5 | 39 | static void plot_balls() { |
TheChrisyd | 0:deb284e70ca5 | 40 | int i; |
TheChrisyd | 0:deb284e70ca5 | 41 | for (i = 0; i < NBALLS; i++) |
TheChrisyd | 0:deb284e70ca5 | 42 | GD.sprite(i, balls[i].x >> 4, balls[i].y >> 4, 0, 0, 0); |
TheChrisyd | 0:deb284e70ca5 | 43 | } |
TheChrisyd | 0:deb284e70ca5 | 44 | |
TheChrisyd | 0:deb284e70ca5 | 45 | // Place all balls so that none collide. Do this by placing all at |
TheChrisyd | 0:deb284e70ca5 | 46 | // random, then moving until there are no collisions |
TheChrisyd | 0:deb284e70ca5 | 47 | |
TheChrisyd | 0:deb284e70ca5 | 48 | static int anycolliding() { |
TheChrisyd | 0:deb284e70ca5 | 49 | plot_balls(); |
TheChrisyd | 0:deb284e70ca5 | 50 | load_coll(); |
TheChrisyd | 0:deb284e70ca5 | 51 | int i; |
TheChrisyd | 0:deb284e70ca5 | 52 | for (i = 0; i < NBALLS; i++) |
TheChrisyd | 0:deb284e70ca5 | 53 | if (coll[i] != 0xff) |
TheChrisyd | 0:deb284e70ca5 | 54 | return 1; |
TheChrisyd | 0:deb284e70ca5 | 55 | return 0; |
TheChrisyd | 0:deb284e70ca5 | 56 | } |
TheChrisyd | 0:deb284e70ca5 | 57 | |
TheChrisyd | 0:deb284e70ca5 | 58 | static void place_balls() { |
TheChrisyd | 0:deb284e70ca5 | 59 | int i; |
TheChrisyd | 0:deb284e70ca5 | 60 | for (i = 0; i < NBALLS; i++) { |
TheChrisyd | 0:deb284e70ca5 | 61 | balls[i].x = (2 + rand()%380) << 4; |
TheChrisyd | 0:deb284e70ca5 | 62 | balls[i].y = (2 + rand()%280) << 4; |
TheChrisyd | 0:deb284e70ca5 | 63 | balls[i].vx = (rand()%256)-128; |
TheChrisyd | 0:deb284e70ca5 | 64 | balls[i].vy = (rand()%256)-128; |
TheChrisyd | 0:deb284e70ca5 | 65 | balls[i].lasthit = 255; |
TheChrisyd | 0:deb284e70ca5 | 66 | } |
TheChrisyd | 0:deb284e70ca5 | 67 | while (anycolliding()) { |
TheChrisyd | 0:deb284e70ca5 | 68 | for (i = 0; i < NBALLS; i++) { |
TheChrisyd | 0:deb284e70ca5 | 69 | if (coll[i] != 0xff) { |
TheChrisyd | 0:deb284e70ca5 | 70 | balls[i].x = (2 + (rand()%380)) << 4; |
TheChrisyd | 0:deb284e70ca5 | 71 | balls[i].y = (2 + (rand()%280)) << 4; |
TheChrisyd | 0:deb284e70ca5 | 72 | } |
TheChrisyd | 0:deb284e70ca5 | 73 | } |
TheChrisyd | 0:deb284e70ca5 | 74 | } |
TheChrisyd | 0:deb284e70ca5 | 75 | } |
TheChrisyd | 0:deb284e70ca5 | 76 | |
TheChrisyd | 0:deb284e70ca5 | 77 | void setup() { |
TheChrisyd | 0:deb284e70ca5 | 78 | int i; |
TheChrisyd | 0:deb284e70ca5 | 79 | |
TheChrisyd | 0:deb284e70ca5 | 80 | GD.begin(); |
TheChrisyd | 0:deb284e70ca5 | 81 | |
TheChrisyd | 0:deb284e70ca5 | 82 | GD.wr(JK_MODE, 0); |
TheChrisyd | 0:deb284e70ca5 | 83 | |
TheChrisyd | 0:deb284e70ca5 | 84 | GD.copy(RAM_CHR, stone_wall_texture_chr, sizeof(stone_wall_texture_chr)); |
TheChrisyd | 0:deb284e70ca5 | 85 | GD.copy(RAM_PAL, stone_wall_texture_pal, sizeof(stone_wall_texture_pal)); |
TheChrisyd | 0:deb284e70ca5 | 86 | for (i = 0; i < 4096; i++) |
TheChrisyd | 0:deb284e70ca5 | 87 | GD.wr(RAM_PIC + i, (i & 15) + ((i >> 6) << 4)); |
TheChrisyd | 0:deb284e70ca5 | 88 | |
TheChrisyd | 0:deb284e70ca5 | 89 | GD.copy(RAM_SPRIMG, sphere_img, sizeof(sphere_img)); |
TheChrisyd | 0:deb284e70ca5 | 90 | GD.copy(RAM_SPRPAL, sphere_pal, sizeof(sphere_pal)); |
TheChrisyd | 0:deb284e70ca5 | 91 | |
TheChrisyd | 0:deb284e70ca5 | 92 | for (i = 0; i < 256; i++) |
TheChrisyd | 0:deb284e70ca5 | 93 | GD.sprite(i, 400, 400, 0, 0, 0); |
TheChrisyd | 0:deb284e70ca5 | 94 | |
TheChrisyd | 0:deb284e70ca5 | 95 | place_balls(); |
TheChrisyd | 0:deb284e70ca5 | 96 | } |
TheChrisyd | 0:deb284e70ca5 | 97 | |
TheChrisyd | 0:deb284e70ca5 | 98 | |
TheChrisyd | 0:deb284e70ca5 | 99 | float dot(float x1, float y1, float x2, float y2) { |
TheChrisyd | 0:deb284e70ca5 | 100 | return (x1 * x2) + (y1 * y2); |
TheChrisyd | 0:deb284e70ca5 | 101 | } |
TheChrisyd | 0:deb284e70ca5 | 102 | |
TheChrisyd | 0:deb284e70ca5 | 103 | // Collide ball a with ball b, compute new velocities. |
TheChrisyd | 0:deb284e70ca5 | 104 | // Algorithm from |
TheChrisyd | 0:deb284e70ca5 | 105 | // http://stackoverflow.com/questions/345838/ball-to-ball-collision-detection-and-handling |
TheChrisyd | 0:deb284e70ca5 | 106 | |
TheChrisyd | 0:deb284e70ca5 | 107 | void collide(struct ball *a, struct ball *b) { |
TheChrisyd | 0:deb284e70ca5 | 108 | float collision_x, collision_y; |
TheChrisyd | 0:deb284e70ca5 | 109 | |
TheChrisyd | 0:deb284e70ca5 | 110 | collision_x = a->x - b->x; |
TheChrisyd | 0:deb284e70ca5 | 111 | collision_y = a->y - b->y; |
TheChrisyd | 0:deb284e70ca5 | 112 | float distance = sqrt(collision_x * collision_x + collision_y * collision_y); |
TheChrisyd | 0:deb284e70ca5 | 113 | float rdistance = 1.0 / distance; |
TheChrisyd | 0:deb284e70ca5 | 114 | collision_x *= rdistance; |
TheChrisyd | 0:deb284e70ca5 | 115 | collision_y *= rdistance; |
TheChrisyd | 0:deb284e70ca5 | 116 | float aci = dot(a->vx, a->vy, collision_x, collision_y); |
TheChrisyd | 0:deb284e70ca5 | 117 | float bci = dot(b->vx, b->vy, collision_x, collision_y); |
TheChrisyd | 0:deb284e70ca5 | 118 | float acf = bci; |
TheChrisyd | 0:deb284e70ca5 | 119 | float bcf = aci; |
TheChrisyd | 0:deb284e70ca5 | 120 | a->vx += int((acf - aci) * collision_x); |
TheChrisyd | 0:deb284e70ca5 | 121 | a->vy += int((acf - aci) * collision_y); |
TheChrisyd | 0:deb284e70ca5 | 122 | b->vx += int((bcf - bci) * collision_x); |
TheChrisyd | 0:deb284e70ca5 | 123 | b->vy += int((bcf - bci) * collision_y); |
TheChrisyd | 0:deb284e70ca5 | 124 | } |
TheChrisyd | 0:deb284e70ca5 | 125 | |
TheChrisyd | 0:deb284e70ca5 | 126 | #define LWALL (0 << 4) |
TheChrisyd | 0:deb284e70ca5 | 127 | #define RWALL (384 << 4) |
TheChrisyd | 0:deb284e70ca5 | 128 | #define TWALL (0 << 4) |
TheChrisyd | 0:deb284e70ca5 | 129 | #define BWALL (284 << 4) |
TheChrisyd | 0:deb284e70ca5 | 130 | |
TheChrisyd | 0:deb284e70ca5 | 131 | static int timer; |
TheChrisyd | 0:deb284e70ca5 | 132 | int main() { |
TheChrisyd | 0:deb284e70ca5 | 133 | setup(); |
TheChrisyd | 0:deb284e70ca5 | 134 | while (1) { |
TheChrisyd | 0:deb284e70ca5 | 135 | int i; |
TheChrisyd | 0:deb284e70ca5 | 136 | |
TheChrisyd | 0:deb284e70ca5 | 137 | plot_balls(); |
TheChrisyd | 0:deb284e70ca5 | 138 | |
TheChrisyd | 0:deb284e70ca5 | 139 | load_coll(); |
TheChrisyd | 0:deb284e70ca5 | 140 | |
TheChrisyd | 0:deb284e70ca5 | 141 | struct ball *pb; |
TheChrisyd | 0:deb284e70ca5 | 142 | |
TheChrisyd | 0:deb284e70ca5 | 143 | for (i = NBALLS, pb = balls; i--; pb++, i) { |
TheChrisyd | 0:deb284e70ca5 | 144 | if ((pb->x <= LWALL)) { |
TheChrisyd | 0:deb284e70ca5 | 145 | pb->x = LWALL; |
TheChrisyd | 0:deb284e70ca5 | 146 | pb->vx = -pb->vx; |
TheChrisyd | 0:deb284e70ca5 | 147 | } |
TheChrisyd | 0:deb284e70ca5 | 148 | if ((pb->x >= RWALL)) { |
TheChrisyd | 0:deb284e70ca5 | 149 | pb->x = RWALL; |
TheChrisyd | 0:deb284e70ca5 | 150 | pb->vx = -pb->vx; |
TheChrisyd | 0:deb284e70ca5 | 151 | } |
TheChrisyd | 0:deb284e70ca5 | 152 | if ((pb->y <= TWALL)) { |
TheChrisyd | 0:deb284e70ca5 | 153 | pb->y = TWALL; |
TheChrisyd | 0:deb284e70ca5 | 154 | pb->vy = -pb->vy; |
TheChrisyd | 0:deb284e70ca5 | 155 | } |
TheChrisyd | 0:deb284e70ca5 | 156 | if ((pb->y >= BWALL)) { |
TheChrisyd | 0:deb284e70ca5 | 157 | pb->y = BWALL; |
TheChrisyd | 0:deb284e70ca5 | 158 | pb->vy = -pb->vy; |
TheChrisyd | 0:deb284e70ca5 | 159 | } |
TheChrisyd | 0:deb284e70ca5 | 160 | } |
TheChrisyd | 0:deb284e70ca5 | 161 | for (i = 1; i < NBALLS; i++) { |
TheChrisyd | 0:deb284e70ca5 | 162 | int other = coll[i]; |
TheChrisyd | 0:deb284e70ca5 | 163 | if ((balls[i].lasthit != other) && other != 0xff) { |
TheChrisyd | 0:deb284e70ca5 | 164 | collide(&balls[i], &balls[other]); |
TheChrisyd | 0:deb284e70ca5 | 165 | } |
TheChrisyd | 0:deb284e70ca5 | 166 | balls[i].lasthit = other; |
TheChrisyd | 0:deb284e70ca5 | 167 | } |
TheChrisyd | 0:deb284e70ca5 | 168 | for (i = NBALLS, pb = balls; i--; pb++, i) { |
TheChrisyd | 0:deb284e70ca5 | 169 | pb->x += pb->vx; |
TheChrisyd | 0:deb284e70ca5 | 170 | pb->y += pb->vy; |
TheChrisyd | 0:deb284e70ca5 | 171 | } |
TheChrisyd | 0:deb284e70ca5 | 172 | if (++timer == 2000) { |
TheChrisyd | 0:deb284e70ca5 | 173 | place_balls(); |
TheChrisyd | 0:deb284e70ca5 | 174 | wait_ms(1000); |
TheChrisyd | 0:deb284e70ca5 | 175 | timer = 0; |
TheChrisyd | 0:deb284e70ca5 | 176 | } |
TheChrisyd | 0:deb284e70ca5 | 177 | } |
TheChrisyd | 0:deb284e70ca5 | 178 | } |