Exemple #1
0
void WorldStage::SaveMapToFile(RegionalMap *map)
{
	std::stringstream ss;
	const int MAP_WIDTH=80, MAP_HEIGHT=80;

	//Open a file based on map position
	ss << "region." << map->startX/MAP_WIDTH << "." << map->startY/MAP_HEIGHT;
	ALLEGRO_FILE *file = al_fopen(ss.str().c_str(), "w");
	if(file)
	{
		//Write magic number to it and newline
		al_fputs(file, "b272bda9bf0c1cdcba614b5ed99c4d62");
		al_fputs(file, "\n");

		//Write version number and newline
		al_fputs(file, "0\n");

		//Write each tile as a 32le
		for(int y = 0; y < MAP_HEIGHT; y++) for(int x = 0; x < MAP_WIDTH; x++)
		{
			al_fwrite32le(file, map->tile[x][y].materialTypeIndex);
		}

		//Write each actor id as a 32le
		for(auto actorId = map->actorIDs.begin(); actorId != map->actorIDs.end(); actorId++)
		{
			al_fwrite32le(file, (*actorId));
		}


		//Close a file
		al_fclose(file);
	}
}
GameLogic::GameLogic(int Width, int Height, float LogicFPS) {
	Debug = false;
	
	Display = NULL;
    EventQueue = NULL;
    Timer = NULL;
    Bitmap.Logo = NULL;
	Bitmap.Title = NULL;
    Font.Small = NULL;
    Font.Medium = NULL;
    Font.Big = NULL;
    Sound.HitWall = NULL;
    Sound.HitPaddle = NULL;
    Sound.BackgroundMusic = NULL;
    UserDataFile = NULL;
	DisplayWidth = Width;
	DisplayHeight = Height;
	TimerStep = 1.0 / LogicFPS;
    
	bool key[2] = { false, false };
    float alpha = 0;
    float colr = 0;
    float colg = 0;
    float colb = 0;
    int tick = 0;
    int menu = 0;
    int high_score = 0;
    bool restart = true;
    int score = 0, multi = 1, final_score = 1;
    bool game_over, redraw;
    char scoretxt[8] = "";
    char multitxt[4] = "";
    char final_scoretxt[16] = "";
    char hightxt[16] = "";

    // intro screen
    while (1) {
        ALLEGRO_EVENT ev;
        al_wait_for_event(EventQueue, &ev);

        if(ev.type == ALLEGRO_EVENT_TIMER) {
            // trigger redraw
            tick++;
            if(tick < 180) {
                colr = colg = colb = (0.5 * sin( (tick - 90) * ALLEGRO_PI / 180.0) + 0.5);
                alpha = 0;
            }
            else if(tick < 360) {
                alpha = (0.5 * sin( (tick + 90) * ALLEGRO_PI / 180.0) + 0.5);
                colr = colg = colb = 1;
            }
            else if(tick > 450 && tick < 630) {
                colr = colg = colb = alpha = (0.5 * cos( (tick - 90) * ALLEGRO_PI / 180.0) + 0.5);
            }
            else if(tick > 632) {
                break;
            }
            redraw = true;
        }
        else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
            return;
        }
        else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) {
            break;
        }

        if(redraw && al_is_event_queue_empty(EventQueue)) {
            redraw = false;
            al_clear_to_color(al_map_rgb_f(colr,colg,colb));
            al_draw_tinted_bitmap(Bitmap.Logo, al_map_rgba_f(alpha, alpha, alpha, alpha), (DisplayWidth - al_get_bitmap_width(Bitmap.Logo) ) / 2, (DisplayHeight - al_get_bitmap_height(Bitmap.Logo) )/ 2, 0);
            al_flip_display();
        }
    }

    al_flip_display();
    al_clear_to_color(al_map_rgb(0,0,0));

	// load hiscore info
    UserDataFile = al_fopen("assets/hiscore.txt", "r");
    if(UserDataFile) {
        char *line = (char*) malloc (17);
        line = al_fgets(UserDataFile, line, 17);
        high_score = atoi(line);
        free(line);
    }
    else {
        high_score = 0;
    }
	final_score = 0;

    sprintf(hightxt, "High: %d", high_score);
    al_fclose(UserDataFile);

    // main menu loop
    while (1) {
        ALLEGRO_EVENT ev;
        al_wait_for_event(EventQueue, &ev);

        if(ev.type == ALLEGRO_EVENT_TIMER) {
            // trigger redraw
            redraw = true;
        }
        else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
			// exit if the Display is closed
            return;
        }
        else if(ev.type == ALLEGRO_EVENT_MOUSE_AXES || ev.type == ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY) {
            // track mouse movement
			if((ev.mouse.y > 350) && (ev.mouse.y < 388) && (ev.mouse.x > 250) && (ev.mouse.x < 388)) {
				menu = 1;
			}
			else {
				menu = 0;
			}
        }
        else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) {
			// track mouse clicks
			if(menu == 1) {
				break;
			}
        }

        if(redraw && al_is_event_queue_empty(EventQueue)) {
			// process entire queue and only render if the Timer has ticked
            redraw = false;
            al_clear_to_color(al_map_rgb(0,0,0));
			al_draw_bitmap(Bitmap.Title, (DisplayWidth - al_get_bitmap_width(Bitmap.Title) ) / 2, 16, 0);
            al_draw_text(Font.Small, al_map_rgb(128,128,0), DisplayWidth / 2, 250, ALLEGRO_ALIGN_CENTRE, "Version 0.1");
			if(menu == 1) {
				al_draw_text(Font.Medium, al_map_rgb(128,0,0), DisplayWidth / 2, 350, ALLEGRO_ALIGN_CENTRE, "Play Now!");
			}
			else {
				al_draw_text(Font.Medium, al_map_rgb(128,128,0), DisplayWidth / 2, 350, ALLEGRO_ALIGN_CENTRE, "Play Now!");
			}
            al_flip_display();
        }
    }

    // seed rand function
    srand(al_get_time());

    // game wrapper lets us restart the game
    while(restart) {
		// hide the cursor
        //al_hide_mouse_cursor(Display);

		// assume we don't want to play again
        restart = false;
		
		// Base objects
		Ball StarterBall = Ball();
		Paddle StarterPaddle = Paddle(0);
		Paddle StarterPaddle2 = Paddle(DisplayHeight - 8);
		Paddle StarterPaddle3 = Paddle(0, true);
		Paddle StarterPaddle4 = Paddle(DisplayWidth - 8, true);
		        
		// TODO: load the right map

			// set Bitmap.Title
			// set base speed
			// create list of block entities
		

		// Populate entity lists
		// Remove static data when we get map loading done
		for(int i=0; i < 64; i++) {
			Brick SingleBlockyEntity = Brick((i % 16) * 40, 80 + ( (i / 16) * 10), i % 8);
			Bricks.push_back(SingleBlockyEntity);
		}
		Paddles.push_back(StarterPaddle);
		Paddles.push_back(StarterPaddle2);
		Paddles.push_back(StarterPaddle3);
		Paddles.push_back(StarterPaddle4);
		Balls.push_back(StarterBall);

		// save high score if the final score is higher
        if(final_score > high_score) {
            high_score = final_score;
            sprintf (hightxt, "High: %d", high_score);
        }

		// reset score if not a continuation

		// init hud
		
		// force initial draw
		redraw = true;
        
		// reset physics
		game_over = false;

        // main game loop
        while(1) {
            ALLEGRO_EVENT ev;
            al_wait_for_event(EventQueue, &ev);

            if(ev.type == ALLEGRO_EVENT_TIMER) {
                // game logic loop
                if(!game_over) {
					// calculate each ball's new position and check for...
					Path CurrentPath;
					for(int i = 0; i < Balls.size(); i++) {
						CurrentPath = Balls[i].GetPath(TimerStep);

						// distance traveled in axis directions in time delta t
						float NX = Balls[i].Position.DeltaX * TimerStep;
						float NY = Balls[i].Position.DeltaY * TimerStep;
						// new unencombered position
						float NewPositionX = Balls[i].Position.X + NX;
						float NewPositionY = Balls[i].Position.Y + NY;
						ClosestEntity Closest;
						Closest.Magnitude = 10000;
						// look for collisions
						for(int j = 0; j < (int)Bricks.size(); j++) {
							// only check items that haven't been hit in the most recent update
							if (!Bricks[j].HasBeenHit()) {
								Intersection Point = Bricks[j].PathIntersect(CurrentPath);
								if (Point.Type == Intersecting) {
									// mark this hit so we don't check for it again...
									// until the next update frame.
									Bricks[i].Hit = true;
									// see how far the collision is
									float Magnitude = sqrt(pow(Point.X - Balls[i].Position.X, 2) + pow(Point.Y - Balls[i].Position.Y, 2)); 
									if (Magnitude <  Closest.Magnitude) {
										// nab the closest collision so we can handle multiple collisions
										Closest.Magnitude = Magnitude;
										Closest.EntityIndex = j;
										Closest.CollisionPoint = Point;
									}
								}
							}
						}

						if (Closest.CollisionPoint.Type == Intersecting) {
							if(Bricks[Closest.EntityIndex].Harm(Balls[i].CollisionDamage)) {
		
							// TODO: play a sound

							// Update the ball to the point of collision
							Balls[i].Position.X = Closest.CollisionPoint.X;
							Balls[i].Position.Y = Closest.CollisionPoint.Y;

							// Reflect the ball in the appropriate direction
							switch(Closest.CollisionPoint.From) {
							default:
							case Top:
							case Bottom:
								Balls[i].ReflectY();
								break;
							case Left:
							case Right:
								Balls[i].ReflectX();
								break;
							}
		
							/* Find the fraction of DeltaT that had to occur before this collision
							float UnknownT = TimerStep * (Closest.Magnitude / sqrt(pow(NX,2) + pow(NY, 2)));
							// simlulate the ball movement after the collision
							Balls[i].GetPath(TimerStep - UnknownT);
							break;*/
						}

	
						if(NewPositionX > 0.0f && NewPositionX < DisplayWidth - Balls[i].Width && NewPositionY > 0.0f && NewPositionY < DisplayHeight - Balls[i].Height) {
							Balls[i].Live = true;
							Balls[i].Position.X = NewPositionX;
							Balls[i].Position.Y = NewPositionY;
						}
						else {
							Balls[i].Live = false;
						}
					}

					// make sure at least one ball is in play
					if(Balls[0].BallCount < 1) {
						game_over = true;
					}
					}
                }
                else {
                    // end game animation logic
                }
                // trigger a render every tick
				redraw = true;
            }
            else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
                break;
            }
            else if(ev.type == ALLEGRO_EVENT_MOUSE_AXES || ev.type == ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY) {
                if(!game_over) {
                    // update each paddle
					for(int i = 0; i < Paddles.size(); i++) {
						// horizontal clip
						if(Paddles[i].IsHorizontal()) {
							if(ev.mouse.x < (Paddles[i].Width / 2) ) {
								Paddles[i].Position.X = 0;
							}
							else if(ev.mouse.x > DisplayWidth - (Paddles[i].Width / 2) ) {
								Paddles[i].Position.X = DisplayWidth - Paddles[i].Width;
							}
							else {
								Paddles[i].Position.X = ev.mouse.x - (Paddles[i].Width / 2);
							}
						}
						else {
						// vertical clip
							if(ev.mouse.y < (Paddles[i].Height / 2) ) {
								Paddles[i].Position.Y = 0;
							}
							else if(ev.mouse.y > DisplayHeight - (Paddles[i].Height / 2) ) {
								Paddles[i].Position.Y = DisplayHeight - Paddles[i].Height;
							}
							else {
								Paddles[i].Position.Y = ev.mouse.y - (Paddles[i].Height / 2);
							}
						}
					}
                }
                else {
                    // track mouse movement for retry menu logic
                }
            }
            else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) {
                if(game_over) {
                    // track mouse clicks for retry menu logic
                }
				else {
					// Debug
					// add a ball at the current mouse position
				}
            }
            else if(ev.type == ALLEGRO_EVENT_KEY_DOWN) {
                // set keys we are interested in if pressed
                switch(ev.keyboard.keycode) {
                    case ALLEGRO_KEY_ESCAPE:
                        key[KEY_ESC] = true;
                        break;
					case ALLEGRO_KEY_SPACE:
                        key[KEY_SPACE] = true;
                        break;
                }
            }
            else if(ev.type == ALLEGRO_EVENT_KEY_UP) {
                // release keys we are interested in if let go
                switch(ev.keyboard.keycode) {
                    case ALLEGRO_KEY_ESCAPE:
                        key[KEY_ESC] = false;
                        break;
					case ALLEGRO_KEY_SPACE:
                        key[KEY_SPACE] = false;
                        break;
                }
            }

            if(redraw && al_is_event_queue_empty(EventQueue)) {
                //The render loop
                redraw = false;
                if(!game_over) {
					// game play
                    // blank
                    al_clear_to_color(al_map_rgb(128,128,128));
                    
					// render each brick
					for(int i = 0; i < Bricks.size(); i++)
					{
						Bricks[i].Render();
					}

					// render each ball
					for(int i = 0; i < Balls.size(); i++)
					{
						Balls[i].Render();
					}

					// render each paddle
					for(int i = 0; i < Paddles.size(); i++)
					{
						Paddles[i].Render();
					}
					
					// render HUD
					sprintf (scoretxt, "%d", score);
					sprintf (multitxt, "%d", multi);
                    al_draw_text(Font.Medium, al_map_rgb(0,0,0), 8, 8, ALLEGRO_ALIGN_LEFT, "Score");
                    al_draw_text(Font.Medium, al_map_rgb(255,255,255), 128, 8, ALLEGRO_ALIGN_LEFT, scoretxt);
                    al_draw_text(Font.Medium, al_map_rgb(0,0,0), 300, 8, ALLEGRO_ALIGN_LEFT, "x");
                    al_draw_text(Font.Medium, al_map_rgb(255,255,255), 316, 8, ALLEGRO_ALIGN_LEFT, multitxt);
                    al_draw_text(Font.Medium, al_map_rgb(0,0,0), 424, 8, ALLEGRO_ALIGN_LEFT, hightxt);
                }
                else {
					// render retry menu
                    al_clear_to_color(al_map_rgb(128,128,128));
                }
                // always flip Display
                al_flip_display();
            }
        }
    }
    // save high score if the final score is higher
    if(final_score > high_score) {
        high_score = final_score;
    }
    sprintf (hightxt, "%d", high_score);
    // write highscore to file
    UserDataFile = al_fopen("assets/hiscore.txt", "w");
    if(UserDataFile) {
        al_fputs(UserDataFile, hightxt);
        al_fclose(UserDataFile);
    }

	// proper cleanup is important!
    al_destroy_bitmap(Bitmap.Title);
    al_destroy_bitmap(Bitmap.Logo);
    al_destroy_timer(Timer);
    al_destroy_display(Display);
    al_destroy_event_queue(EventQueue);
}
Exemple #3
0
bool ConfigFile::Save( std::string Filename )
{
	ALLEGRO_FILE* fileHnd;
	std::string document;
	bool dataNum;
	std::string* escstr;

	fileHnd = al_fopen( Filename.c_str(), "w" );
	if( fileHnd == 0 )
		return false;

	document.clear();
	for( std::list<ConfigData*>::iterator i = Contents.begin(); i != Contents.end(); i++ )
	{
		ConfigData* cd = (ConfigData*)(*i);
		document.append( cd->Key->c_str() );
		if( cd->IsArray )
		{
			document.append( " [ " );

			bool isFirst = true;
			for( std::vector<std::string*>::iterator s = cd->Contents->begin(); s != cd->Contents->end(); s++ )
			{
				if( isFirst )
					isFirst = false;
				else
					document.append( ", " );

				std::string* cs = (std::string*)(*s);
				dataNum = IsNumber( *cs );
				if( !dataNum )
				{
					document.append( "\"" );
					escstr = EscapeString(*cs);
					document.append( escstr->c_str() );
					delete escstr;
					document.append( "\"" );
				} else {
					document.append( cs->c_str() );
				}
			}

			document.append( " ]\n" );
		} else {
			document.append( " = " );
			dataNum = IsNumber( *cd->Contents->front() );
			if( !dataNum )
			{
				document.append( "\"" );
				escstr = EscapeString(*cd->Contents->front());
				document.append( escstr->c_str() );
				delete escstr;
				document.append( "\"" );
			} else {
				document.append( cd->Contents->front()->c_str() );
			}
			document.append( "\n" );
		}

	}

	al_fputs( fileHnd, document.c_str() );
	al_fclose( fileHnd );
	
	return true;
}