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