diff options
| -rw-r--r-- | main.c | 102 | 
1 files changed, 62 insertions, 40 deletions
| @@ -26,6 +26,28 @@ typedef struct {  	int alive;  } Projectile; +typedef struct { +	float *mask; +	int width; +	int height; +	int updated; +} Terrain; + +void PaintTerrain(Terrain *t, float x, float y, float color, float size) { +	for (int j = y - size; j < y + size; j++) { +		for (int i = x - size; i < x + size; i++) { +			float dj = y - j; +			float di = x - i; +			if (i > 0 && i < t->width && j > 0 && j < t->height +					&& dj * dj + di * di <= size * size / 2) { +				size_t index = i + j * t->width; +				t->mask[index] = color; +			} +		} +	} +	t->updated = 1; +} +  static inline double GetCurrentTimestamp() {  	return (double) SDL_GetTicks64() / 1000.0;  } @@ -53,41 +75,31 @@ SDL_Texture *CreateTiledTexture(SDL_Renderer *context, const char *filename, int  	return texture;  } -void PaintMask(float *mask, int width, int height, float x, float y, float color, float size) { -	for (int j = y - size; j < y + size; j++) { -		for (int i = x - size; i < x + size; i++) { -			float dj = y - j; -			float di = x - i; -			if (i > 0 && i < width && j > 0 && j < height -					&& dj * dj + di * di <= size * size / 2) { -				size_t index = i + j * width; -				mask[index] = color; -			} -		} -	} -} -  void GameMain(SDL_Renderer *context) {  	SDL_Texture *background = CreateTiledTexture(context, "background.bmp", WINDOW_W, WINDOW_H);  	SDL_Texture *foreground = CreateTiledTexture(context, "foreground.bmp", WINDOW_W, WINDOW_H);  	SDL_SetTextureBlendMode(foreground, SDL_BLENDMODE_MOD); -	SDL_Texture *terrain = SDL_CreateTexture(context, +	SDL_Texture *terrain_texture = SDL_CreateTexture(context,  			SDL_PIXELFORMAT_RGBA8888,  			SDL_TEXTUREACCESS_TARGET,  			WINDOW_W, WINDOW_H); -	SDL_SetTextureBlendMode(terrain, SDL_BLENDMODE_BLEND); +	SDL_SetTextureBlendMode(terrain_texture, SDL_BLENDMODE_BLEND);  	SDL_Texture *mask_texture = SDL_CreateTexture(context,  			SDL_PIXELFORMAT_RGBA8888,  			SDL_TEXTUREACCESS_STREAMING,  			WINDOW_W, WINDOW_H); -	float *mask = calloc(WINDOW_W * WINDOW_H, sizeof(float)); +	Terrain terrain = {0}; +	terrain.width = WINDOW_W; +	terrain.height = WINDOW_H; +	terrain.mask = calloc(WINDOW_W * WINDOW_H, sizeof(float));  	for (int i = 0; i < 100 * WINDOW_W; i++) { -		mask[i] = 1.0; +		terrain.mask[i] = 1.0;  	} +	terrain.updated = 1;  	Cannon player = {0};  	player.x = 100; @@ -100,15 +112,12 @@ void GameMain(SDL_Renderer *context) {  	int exit = 0;  	while (!exit) { -		double new_t = GetCurrentTimestamp(); -		double dt = (new_t - old_t) * 10; -		old_t = new_t; -  		SDL_Event event;  		while (SDL_PollEvent(&event)) {  			if (event.type == SDL_QUIT) {  				exit = 1; -			} else if (event.type == SDL_KEYDOWN && event.key.state == SDL_PRESSED && event.key.keysym.sym == SDLK_SPACE && !projectile.alive) { +			} else if (event.type == SDL_KEYDOWN && event.key.state == SDL_PRESSED && +					event.key.keysym.sym == SDLK_SPACE && !projectile.alive) {  				projectile.alive = 1;  				projectile.x = player.x;  				projectile.y = player.y; @@ -116,13 +125,20 @@ void GameMain(SDL_Renderer *context) {  				projectile.vx = cos(player.angle) * player.power;  			}  		} +		int simulation_frames = 10; +		while (simulation_frames > 0) { +			simulation_frames--; +		double new_t = GetCurrentTimestamp(); +		double dt = (new_t - old_t); +		old_t = new_t; +  		int mouse_x, mouse_y;  		Uint32 mouse_state = SDL_GetMouseState(&mouse_x, &mouse_y);  		float size = 20;  		if (mouse_state & SDL_BUTTON_LMASK) { -			PaintMask(mask, WINDOW_W, WINDOW_H, mouse_x, WINDOW_H - mouse_y, 1.0, size); +			PaintTerrain(&terrain, mouse_x, WINDOW_H - mouse_y, 1.0, size);  		} else if (mouse_state & SDL_BUTTON_RMASK) { -			PaintMask(mask, WINDOW_W, WINDOW_H, mouse_x, WINDOW_H - mouse_y, 0.0, size); +			PaintTerrain(&terrain, mouse_x, WINDOW_H - mouse_y, 0.0, size);  		}  		const Uint8 *keys = SDL_GetKeyboardState(0); @@ -136,6 +152,7 @@ void GameMain(SDL_Renderer *context) {  			player.angle += PI / 180 * dt;  		}  		if (keys[SDL_SCANCODE_S] && player.angle > 0) { +  			player.angle -= PI / 180 * dt;  		} @@ -143,11 +160,11 @@ void GameMain(SDL_Renderer *context) {  			player.y  = WINDOW_H - 1;  			player.vy = 0;  		} -		if (mask[(int)player.x + (int)player.y * WINDOW_W] == 0.0 && +		if (terrain.mask[(int)player.x + (int)player.y * WINDOW_W] == 0.0 &&  				player.y >= 0) {  			player.y += player.vy * dt;  			player.vy += GRAVITY * dt; -			while (mask[(int)player.x + (int)player.y * WINDOW_W] != 0.0) { +			while (terrain.mask[(int)player.x + (int)player.y * WINDOW_W] != 0.0) {  				player.y += 1;  				player.vy = 0;  			} @@ -156,45 +173,50 @@ void GameMain(SDL_Renderer *context) {  		if (projectile.alive) {  			if (projectile.y >= 0 && projectile.y < WINDOW_H &&  					projectile.x >= 0 && projectile.x < WINDOW_W && -					mask[(int)projectile.x + (int)projectile.y * WINDOW_W] == 0.0) { +					terrain.mask[(int)projectile.x + (int)projectile.y * WINDOW_W] == 0.0) {  				projectile.x += projectile.vx * dt;  				projectile.y += projectile.vy * dt;  				projectile.vy += GRAVITY * dt;  			} else {  				projectile.alive = 0; -				PaintMask(mask, WINDOW_W, WINDOW_H, projectile.x, projectile.y, 0.0, 40); +				PaintTerrain(&terrain, projectile.x, projectile.y, 0.0, 40);  			}  		} -		void *pixels; -		int pitch; -		SDL_LockTexture(mask_texture, 0, &pixels, &pitch); -		Uint32 *p = (Uint32 *) pixels; -		for (int j = 0; j < WINDOW_H; j++) { -			for (int i = 0; i < WINDOW_W; i++) { -				p[i + j * WINDOW_W] = mask[i + (WINDOW_H - j) * WINDOW_W] ? 0xffffffff : 0x00000000; +		if (terrain.updated) { +			void *pixels; +			int pitch; +			SDL_LockTexture(mask_texture, 0, &pixels, &pitch); +			Uint32 *p = (Uint32 *) pixels; +			for (int j = 0; j < WINDOW_H; j++) { +				for (int i = 0; i < WINDOW_W; i++) { +					p[i + j * WINDOW_W] = terrain.mask[i + (WINDOW_H - j) * WINDOW_W] ? 0xffffffff : 0x00000000; +				}  			} +			SDL_UnlockTexture(mask_texture); +			terrain.updated = 0; +		}  		} -		SDL_UnlockTexture(mask_texture);  		SDL_SetRenderDrawColor(context, 40, 40, 40, 255);  		SDL_RenderClear(context);  		SDL_RenderCopy(context, background, 0, 0); -		SDL_SetRenderTarget(context, terrain); +		SDL_SetRenderTarget(context, terrain_texture);  		SDL_SetRenderDrawColor(context, 0, 0, 0, 0);  		SDL_RenderClear(context);  		SDL_RenderCopy(context, mask_texture, 0, 0);  		SDL_RenderCopy(context, foreground, 0, 0);  		SDL_SetRenderTarget(context, 0); -		SDL_RenderCopy(context, terrain, 0, 0); +		SDL_RenderCopy(context, terrain_texture, 0, 0);  		SDL_SetRenderDrawColor(context, 255, 0, 0, 255);  		SDL_Rect player_rect = {player.x - 5, WINDOW_H - player.y - 10, 10, 10 };  		SDL_RenderFillRect(context, &player_rect); -		SDL_RenderDrawLine(context, player.x, WINDOW_H - player.y, player.x + cos(player.angle) * 100, WINDOW_H - player.y - sin(player.angle) * 100); +		SDL_RenderDrawLine(context, player.x, WINDOW_H - player.y,  +				player.x + cos(player.angle) * 100, WINDOW_H - player.y - sin(player.angle) * 100);  		if (projectile.alive) {  			SDL_SetRenderDrawColor(context, 0, 255, 0, 255); | 
