void VisualExplodingImage::initFromSurface(const Graphics::Surface *surface) {
	assert(!_surface && !_texture);

	// Decode the XMG
	_surface = new Graphics::Surface();
	_surface->copyFrom(*surface);
	_texture = _gfx->createTexture(_surface);

	// Create an explosion unit for each pixel in the surface
	_units.resize(_surface->w * _surface->h);

	Common::Point explosionCenter(_surface->w / 2, _surface->h / 2);
	Common::Point explosionAmplitude(48, 16);

	uint index = 0;
	for (uint y = 0; y < _surface->h; y++) {
		for (uint x = 0; x < _surface->w; x++, index++) {
			_units[index].setPosition(x, y);
			_units[index].setExplosionSettings(explosionCenter, explosionAmplitude);
			_units[index].setColor(*static_cast<uint32 *>(_surface->getBasePtr(x, y)), _surface->format);
		}
	}
}
int main() {

	Screen screen;
	
	long long previousTime = (long long)Util::getCurrentTimeInMiliseconds();
	long long accumulateTime = 0;
	Keyboard::startListening();
	
	Point f_pos(50,20);
	Color  f_col(255,255,255,255);
	Pixel f_plane(f_pos, f_col);
	propeller.setDrawPosition(145,30);
	
	bird.setPosition(50,20);
	fish.setPosition(50,20);

	roda1.setRadius(10);
	roda1.setCenter(Point(40,50));

	roda2.setRadius(10);
	roda2.setCenter(Point(120,50));
	parasut.setPosition(50,10);
	//plane.setPosition(200,10);
	//plane.fillColor(f_plane);
	//plane.fillPattern(&bird);
	
	ship.setPosition(10,250);
	
	
	
	f_pos.x = 50; f_pos.y = 20;
	Pixel f_ship(f_pos, f_col);
	//ship.fillColor(f_ship);
	
	f_pos.x = ship.getWidth() / 2;
	f_pos.y = ship.getHeight() / 2;
	
	
	ship.fillWithFloodFill(f_pos,&fish);
	

	int ii = 0;

	float speed = 0;
	float initialPercentage = 0;
	
	/* Game Clock */
	while (true) {
		if (accumulateTime>(SECONDS_PER_FRAME)) {
			handleInput();
			
			printf("%c[%d;%df",0x1B,199,99);
			screen.beginBatch();
			
			
			if (isPlane){
			  //planeEx += 0.05f;
			  //meledak.setPosition(meledak.getPosition().x - 2,meledak.getPosition().y - 2);

			
	
			    initialPercentage += 0.07;
			plane.explode(initialPercentage);
				speed += 0.1f;

			propeller.applyGravity((int)speed);

			applyGravity(&parasut,(int)speed);
			screen.draw(&parasut);

			if (!isPlaneGrounded){
				isPlaneGrounded = roda1.applyGravity((int)speed);
				roda2.applyGravity((int)speed);
			}else{
				propeller.setState(0);
				isBanSelesai = !roda1.bounce();
				roda2.bounce();
			}

			usleep(FRAMERATE/4);
			  //screen.draw(&meledak, planeEx);
			  
			  if (isBanSelesai){

			      //screen.beginBatch();
			      //screen.endBatch();

			  	  isPlane = false;
			      //isAftermath = true;

				//gotoxy(1, 10);
			      //printf("\t\tSHIP WIN!\n\n\n\n\n\n\n\n\n\n");
			      isFinish = true;

				  /* TODO:
			         - Animasi pesawat pecah
			         - Kasih Gravity tiap pecahan pesawat biar jatuh:
			           - baling-baling
			           - ban
			           - potongan badan pesawat
			           - pilot keluar dari pesawat pake parasut
			         - Bikin ban mantul-mantul di atas tanah -_-
			      */

			      // gotoxy(10, 10);
			      // printf("SHIP WIN!\n\n\n\n\n\n\n\n\n\n");

			      // exit(0);

			  }
			}

			screen.draw(&plane, isFlipPlane);
			screen.draw(&roda1);
			screen.draw(&roda2);
			

			propeller.draw(&screen);

			if (isShip){
			  shipEx += 0.05f;
			  
			  meledak.setPosition(meledak.getPosition().x - 2,meledak.getPosition().y - 2);
			  screen.draw(&meledak, shipEx);
			  
			  if (shipEx > 2){
			      screen.beginBatch();
			      screen.endBatch();
			      //gotoxy(10, 10);
			      //printf("PLANE WIN!\n\n\n\n\n\n\n\n\n\n");
			      isFinish = true;
			      isShip = false;
			  }
			}else if (!isPlane) screen.draw(&ship, isFlipShip);
			
			// handle peluru
			for (int i = 0; i < 100; i++){
				if (b[i] != NULL){
					Point st = b[i]->getPoint();
					bool arah = b[i]->arah;
					b[i] = bf.create(BulletFactory::LASER);
					
					if (arah == true){ //pesawat yang nembak, pelurunya kebawah
						b[i]->arah = true;
						b[i]->rotate(180);
						b[i]->setPoint(Point(st.x, st.y + 1));
						
						if (st.y > 330) b[i] = NULL;
						
						if (st.x > ship.getPosition().x  - 10 && st.x < ship.getPosition().x + 150 && st.y > 220){	// COLLISION
						    meledak.setPosition(ship.getPosition().x,ship.getPosition().y);
						    isShip = true;
						    b[i] = NULL;
						}
						
					}else{
						b[i]->arah = false;
						b[i]->setPoint(Point(st.x, st.y - 1));
						
						if (st.y < 0) b[i] = NULL;
						
						if (st.x > plane.getPosition().x - 5 && st.x < plane.getPosition().x + 180 && st.y < 40){	// COLLISION
						    meledak.setPosition(plane.getPosition().x,plane.getPosition().y);
						    isPlane = true;
						    b[i] = NULL;

							Point explosionCenter(plane.getWidth()/2,plane.getHeight()/2);

							//Ini harus dipanggil sebelum meledak
							plane.startExplode(explosionCenter);
						}
					}
					if (b[i] != NULL) screen.draw(b[i]);
				}
			}

			if (isAftermath) {
				
			//	speed += 1; // speed untuk gravity pull
			//	isPlaneGrounded = plane.applyGravity(speed); /* Kasih efek gravity, return valuenya bakal 1 kalo object nya udah sampe "tanah" */				
			//	screen.draw(&plane, isFlipPlane); /* Ini buat gambar objek2 yang udah mulai jatoh ke tanah */
			//	usleep(FRAMERATE); // ini buat ngedelay kecepetan refresh frame biar gak terlalu cepet
				initialPercentage += 0.01;
				plane.explode(initialPercentage);

				if(initialPercentage == 1) { // periksa kalo semua objek udah sampe tanah, berarti game nya pindah ke state finish
					isAftermath = false;
					isFinish = true;

					screen.beginBatch();
					screen.draw(&plane, isFlipPlane); // ini buat gambar object2 yang udah berserakan di tanah
					screen.endBatch();

					//gotoxy(10,10);
				//	printf("Ship Wins!\n\n\n\n\n");
				//	gotoxy(40,40);
				//	printf("\n");
				}
			}

			if (isFinish) {
				exit(0);
			}

			screen.endBatch();
			
			while (accumulateTime<(SECONDS_PER_FRAME))
				accumulateTime -= (SECONDS_PER_FRAME);
				
		}
		else {
			long long currentTime = (long long)Util::getCurrentTimeInMiliseconds();
			accumulateTime += (currentTime - previousTime);
			previousTime = currentTime;
		}
	}

	return 0;	
}