/*
* Copyright 2023, Ali Arya
* Anyone Can Code: Algorithmic Thinking
* Example 6.8c
*/

#include "Main.h"

#define SCREEN_W 640
#define SCREEN_H 480
#define NUM_PARTICLES 20

class GameObject
{
	int x;
	int y;
	SDLX_Bitmap* shape;
	int visible;
	int vy;
	int vx;
public:
	GameObject()
	{
		shape = NULL;
		x = y = vx = vy = 0;
		visible = 100;
	}
	void Init(int xx, int yy)
	{
		x = xx;
		y = yy;
		visible = 100;
	}
	void Init(SDLX_Bitmap* bmp, int xx, int yy, int v)
	{
		shape = bmp;
		x = xx;
		y = yy;
		if (v >= 0 && v <= 100)
			visible = v;
	}
	void Move(bool random=false)
	{
		if (random)
		{
			x += rand() % 5 - 2;
			y += rand() % 5 - 2;
		}
		else
		{
			x += vx;
			y += vy;
		}
	}
	void Move(int dx, int dy)
	{
		x += dx;
		y += dy;
	}
	void Draw()
	{
		SDLX_DrawBitmap(shape, x, y, visible);
	}
	int GetVisible()
	{
		return visible;
	}
	void SetVisible(int v)
	{
		if (v >= 0 && v <= 100)
			visible = v;
	}
	int GetX()
	{
		return x;
	}
	int GetY()
	{
		return y;
	}
};
class ParticleSystem
{
	GameObject particles[NUM_PARTICLES];
	GameObject source;
	SDLX_Bitmap* source_shape;
	SDLX_Bitmap* particle_shape;
public:
	ParticleSystem()
	{
		//we can't do any SDL/SDLX functions yet
		//this constructor is called before Game constructor, so SDLX_Init() is not called yet
		source_shape = NULL;
		particle_shape = NULL;
	}
	void Init()
	{
		//second parameter asks ot use a mask to not show certain color (background)
		source_shape = SDLX_LoadBitmap("Player.bmp", true);
		//default color mask is white
		//if we want to use a different one, we can pass hat to the LoadBitmap function
		SDLX_Color mask_color;
		mask_color.r = mask_color.g = mask_color.b = mask_color.a = 255;
		particle_shape = SDLX_LoadBitmap("Prize.bmp", true, &mask_color);
		//show source in the middle of screen
		source.Init(source_shape, SCREEN_W / 2, SCREEN_H / 2, 100);
		//prepare particles but don't show yet
		for (int i = 0; i < NUM_PARTICLES; i++)
		{
			particles[i].Init(particle_shape, SCREEN_W / 2, SCREEN_H / 2, rand()%100);
		}
	}
	void Update(int dx, int dy)
	{
		//move source
		source.Move(dx,dy);
		//update particles
		for (int i = 0; i < NUM_PARTICLES; i++)
		{
			particles[i].Move(true); //random move
			int v = particles[i].GetVisible();
			v--;
			particles[i].SetVisible(v);
			if (v <= 0)
			{
				particles[i].Init(source.GetX(), source.GetY());
				particles[i].SetVisible(100);
			}
		}
	}
	void Draw()
	{
		for (int i = 0; i < NUM_PARTICLES; i++)
			particles[i].Draw();
		source.Draw();
	}
};
class Game
{
	SDLX_Bitmap* map;
	ParticleSystem ps;
	bool quit;
	bool left;
	bool right;
	bool up;
	bool down;
public:
	Game()	//same as Init()
	{
		//init SDL library and graphics window
		SDLX_Init("Simple 2D Game", 640, 480, true);

		//background
		map = SDLX_LoadBitmap("map.bmp");

		//particle system
		ps.Init();

		//control variables
		quit = false;
		down = up = right = left = false;
	}
	void Update()
	{
		SDLX_Event e;
		if (SDLX_PollEvent(&e))
		{
			if (e.type == SDL_KEYDOWN)
			{
				if (e.keycode == SDLK_ESCAPE)
					quit = true;
				//update source
				if (e.keycode == SDLK_RIGHT)
					right = true;
				if (e.keycode == SDLK_LEFT)
					left = true;
				if (e.keycode == SDLK_UP)
					up = true;
				if (e.keycode == SDLK_DOWN)
					down = true;
			}
			if (e.type == SDL_KEYUP)
			{
				if (e.keycode == SDLK_RIGHT)
					right = false;
				if (e.keycode == SDLK_LEFT)
					left = false;
				if (e.keycode == SDLK_UP)
					up = false;
				if (e.keycode == SDLK_DOWN)
					down = false;
			}
		}

		//update particle system
		int dx = 0;
		if (right)
			dx += 3;
		if (left)
			dx -= 3;
		int dy = 0;
		if (up)
			dy -= 3;
		if (down)
			dy += 3;
		ps.Update(dx, dy);
	}
	void Draw()
	{
		SDLX_DrawBitmap(map,0,0);
		ps.Draw();
		SDLX_Render();
	}
	void Run()
	{
		while (!quit)
		{
			Update();
			Draw();
			SDLX_Delay(1);
		}
	}
};

int main(int argc, char* argv[])
{
	Game game;
	game.Run();
	return 0;
}