slopeaccel.cpp (7274B)
1 // Physics slope experiment with lash_game_sprite 2 3 #include "SDL.h" 4 #include "SDL_gfxPrimitives.h" 5 #include "../lash_game_sprite.h" 6 #include <math.h> 7 #include <stdio.h> 8 9 #define SCREEN_WIDTH 800 10 #define SCREEN_HEIGHT 600 11 #define BALL_RADIUS 30 12 #define BPP 32 13 #define FPS 60 14 #define GRAVITY 9.8 15 #define PIXELS_METER 100 16 17 /** 18 * \todo upon landing ball falls below ground and ends up in right bottom corner 19 */ 20 21 int main(int argc, char *argv[]) { 22 23 int i; 24 25 unsigned long frametime; 26 unsigned long lastframetime; 27 float minframetime = 1000 / (float)FPS; 28 int run = 1; 29 int state = 0; 30 31 Lash_Sprite_2D_Simple *sprite; 32 33 SDL_Event event; 34 SDL_Surface *screen; 35 36 SDL_Rect screen_r; 37 //SDL_Rect ball_r; 38 39 uint32_t screen_c; 40 //uint32_t ball_c; 41 //uint32_t slope_c; 42 43 //uint32_t ball_slope_offset_y; 44 float p_ball_force_net; 45 float p_ball_force_norm; 46 float slope_friction; 47 48 float slope_angle; 49 50 uint8_t slope_v_size = 6; 51 Sint16 *slope_v_x; 52 Sint16 *slope_v_y; 53 54 float ballxinit; 55 float ballyinit; 56 57 char debugstring[255]; 58 unsigned int framesrun; 59 unsigned long timestart; 60 float *debugframevels; 61 62 if (argc < 3) { 63 printf("Usage: %s slope_angle_in_degrees ball_mass_in_grammes slope_friction_coeffcient\n", argv[0]); 64 return 1; 65 } 66 67 68 sprite = new Lash_Sprite_2D_Simple(BALL_RADIUS * 2, BALL_RADIUS * 2, 0.f, 0.f); 69 sprite->setMass(atof(argv[2])); 70 71 //radians 72 slope_angle = (atof(argv[1]) * M_PI) / 180; 73 slope_friction = atof(argv[3]); 74 if (!slope_friction) 75 slope_friction = 0.f; 76 77 SDL_Init(SDL_INIT_VIDEO); 78 screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, BPP, SDL_HWSURFACE|SDL_DOUBLEBUF); 79 80 if (screen == NULL) 81 return 1; 82 83 slope_v_x = (Sint16*)malloc(sizeof(Sint16)*slope_v_size); 84 slope_v_y = (Sint16*)malloc(sizeof(Sint16)*slope_v_size); 85 86 if (slope_v_x == NULL || slope_v_y == NULL) 87 return 1; 88 89 debugframevels = (float*)malloc(sizeof(float) * 10000); // should be ample 90 91 screen_r.x = 0; 92 screen_r.y = 0; 93 screen_r.w = SCREEN_WIDTH; 94 screen_r.h = SCREEN_HEIGHT; 95 96 //ball_r.x = 0; 97 //ball_r.y = 0; 98 //ball_r.w = BALL_RADIUS * 2; 99 //ball_r.h = BALL_RADIUS * 2; 100 101 screen_c = SDL_MapRGBA(screen->format, 255, 255, 255, 255); 102 //slope_c = SDL_MapRGBA(screen->format, 0, 0, 255, 255); 103 //ball_c = SDL_MapRGBA(screen->format, 255, 0, 0, 255); 104 105 *slope_v_y = SCREEN_HEIGHT; 106 *(slope_v_y + 1) = (SCREEN_HEIGHT / 2) - ((SCREEN_WIDTH / 4) * tan(slope_angle)); 107 *(slope_v_y + 2) = SCREEN_HEIGHT / 2; 108 *(slope_v_y + 3) = SCREEN_HEIGHT / 2; 109 *(slope_v_y + 4) = (SCREEN_HEIGHT / 2) - ((SCREEN_WIDTH / 4) * tan(slope_angle)); 110 *(slope_v_y + 5) = SCREEN_HEIGHT; 111 112 *slope_v_x = 0; 113 *(slope_v_x + 1) = 0; 114 *(slope_v_x + 2) = SCREEN_WIDTH / 4; 115 *(slope_v_x + 3) = 3 * (SCREEN_WIDTH / 4); 116 *(slope_v_x + 4) = SCREEN_WIDTH; 117 *(slope_v_x + 5) = SCREEN_WIDTH; 118 119 ballxinit = BALL_RADIUS; 120 ballyinit = (BALL_RADIUS / cos(slope_angle)); 121 sprite->setY((int)((tan(slope_angle) * BALL_RADIUS) + *(slope_v_y + 1) - ballyinit)); 122 sprite->setX((int)ballxinit); 123 124 p_ball_force_net = sin(slope_angle) * (GRAVITY * sprite->getMass()); 125 p_ball_force_norm = cos(slope_angle) * (GRAVITY * sprite->getMass()); 126 if (p_ball_force_net < 0.f) 127 p_ball_force_net = 0.f; 128 129 // divide by FPS twice, as it's m/s² 130 sprite->setAcceleration((((p_ball_force_net / sprite->getMass()) * PIXELS_METER) / FPS) / FPS, -slope_angle); 131 // resistance is friction translated to m/s 132 sprite->setResistance(((p_ball_force_norm / sprite->getMass()) * slope_friction) / FPS); 133 134 float tmpav, tmpar; 135 sprite->getAcceleration(&tmpav, &tmpar, 0); 136 printf("FPS: %d\nPixels per meter: %d\nSprite: x %.1fpx, y %.1fpx, mass %.2fkg\nSlope: angle %f, resistance %fm/s, distance %f\nObject force %.2fN, accel: %f m/s/s | %f px/frame, radians %f\n", FPS, PIXELS_METER, sprite->getX(), sprite->getY(), sprite->getMass(), slope_angle, sprite->getResistance(), SCREEN_WIDTH / cos(slope_angle), p_ball_force_net, ((float)p_ball_force_net / sprite->getMass()), tmpav * FPS, tmpar); 137 138 SDL_WM_SetCaption("Slope Physics Test", 0); 139 140 while (run) { 141 142 frametime = SDL_GetTicks(); 143 144 while (SDL_PollEvent(&event)) { 145 switch(event.type) { 146 case SDL_KEYDOWN: 147 if (event.key.keysym.sym == SDLK_ESCAPE) { 148 run = 0; 149 } else if (event.key.keysym.sym == SDLK_SPACE) { 150 sprite->walkRight(); 151 framesrun = 0; 152 timestart = frametime; 153 } else if (event.key.keysym.sym == SDLK_r) { 154 sprite->stop(); 155 sprite->setVel(0.f, 0.f); 156 sprite->setY((int)((tan(slope_angle) * BALL_RADIUS) + *(slope_v_y + 1) - ballyinit)); 157 sprite->setX((int)ballxinit); 158 sprite->setAcceleration((((p_ball_force_net / sprite->getMass()) * PIXELS_METER) / FPS) / FPS, -slope_angle); 159 state = 0; 160 } 161 162 break; 163 } 164 165 } 166 167 if (sprite->isWalking(0)) { 168 169 sprite->move(); 170 171 // enter midfield 172 if (sprite->getX() > SCREEN_WIDTH / 4 && sprite->getX() < 3 * (SCREEN_WIDTH / 4) && state != 1) { 173 sprite->setAcceleration(0.f, sprite->getAccelerationRadians()); 174 sprite->addVel(sprite->getVelY(), M_PI_2); 175 sprite->setY((SCREEN_HEIGHT / 2) - BALL_RADIUS); 176 state = 1; 177 // enter right slope 178 } else if (sprite->getX() > 3 * (SCREEN_WIDTH / 4) && state != 2) { 179 sprite->setVel(sprite->getVel(), slope_angle); 180 sprite->setAcceleration((((p_ball_force_net / sprite->getMass()) * PIXELS_METER) / FPS) / FPS, slope_angle - M_PI); 181 sprite->setY(sprite->getY() + BALL_RADIUS - ballyinit); 182 state = 2; 183 // enter left slope (not from beginning) 184 } else if (sprite->getX() < SCREEN_WIDTH / 4 && state != 0) { 185 sprite->setVel(sprite->getVel(), -slope_angle - M_PI); 186 sprite->setAcceleration((((p_ball_force_net / sprite->getMass()) * PIXELS_METER) / FPS) / FPS, -slope_angle); 187 sprite->setY(sprite->getY() + BALL_RADIUS - ballyinit); 188 state = 0; 189 } 190 191 sprite->accelerate(); 192 193 if (sprite->getY() >= SCREEN_HEIGHT - BALL_RADIUS || sprite->getX() >= SCREEN_WIDTH - BALL_RADIUS || sprite->getVel() == 0.f) { 194 if (sprite->getY() >= SCREEN_HEIGHT - BALL_RADIUS || sprite->getX() >= SCREEN_WIDTH - BALL_RADIUS) { 195 sprite->setX(SCREEN_WIDTH - BALL_RADIUS); 196 } 197 sprite->stop(); 198 printf("End velocity: %f px/frame (%f m/s) after %.2f secs, %d frames. \n---\nVels:\n", *(debugframevels + framesrun - 1), ((*(debugframevels + framesrun - 1) / PIXELS_METER) * FPS), (frametime - timestart) / (float)1000, framesrun); 199 200 if (debugframevels != NULL) { 201 for (i = 0; i < (int)framesrun; i++) { 202 printf("Frame %d: %f\n", i, *(debugframevels+i)); 203 } 204 } 205 } 206 207 if (debugframevels != NULL) 208 *(debugframevels + framesrun) = sprite->getVel(); 209 framesrun++; 210 211 } 212 213 sprintf(debugstring, "Frametime %lu", frametime - lastframetime); 214 SDL_FillRect(screen, &screen_r, screen_c); 215 filledPolygonColor(screen, slope_v_x, slope_v_y, slope_v_size, 0x0000ffff); 216 filledCircleColor(screen, sprite->getXPixels(), sprite->getYPixels(), BALL_RADIUS, 0xff0000ff); 217 stringColor(screen, 10, SCREEN_HEIGHT - 15, debugstring, 0xffffff99); 218 SDL_Flip(screen); 219 220 lastframetime = frametime; 221 222 //if (lastframetime - frametime < minframetime) 223 //SDL_Delay (minframetime - (SDL_GetTicks () - frametime)); 224 SDL_Delay(minframetime); 225 226 227 } 228 229 delete(sprite); 230 SDL_FreeSurface(screen); 231 SDL_Quit(); 232 233 return 0; 234 }