liblashgame

Pathfinder and path decision making library for 2D tile game
git clone git://holbrook.no/liblashgame.git
Log | Files | Refs

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 }