📄 levels.cpp
字号:
/*************************************************************************
"I Have No Tomatoes"
Copyright (c) 2004, Mika Halttunen
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute
it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must
not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
Mika Halttunen <lsoft@mbnet.fi>
*************************************************************************/
#include <stdio.h>
#include <vector>
#include "SDL.h"
#include "SDL_opengl.h"
#include "mpak.h"
#include "levels.h"
#include "enemy.h"
#include "particle.h"
#include "bonus.h"
#include "bomb.h"
#include "tilemap.h"
#include "timer.h"
#include "special_power.h"
#include "trap.h"
#include "game.h"
#include "bgrounds.h"
#include "mymath.h"
#include "helpers.h"
#include "select_special.h"
#include "comments.h"
#include "soundmusic.h"
#include "texture.h"
using namespace std;
// Number of levels per game
#define NUM_LEVELS 10
// Level list
int level_list[NUM_LEVELS];
// Total number of level files
int num_level_files;
// Level names
static char level_names[NUM_LEVELS][16] = { "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" };
// Current level
int cur_level;
// Level time counter
Uint32 level_time;
// Number of seconds left
int num_seconds_left;
static Uint32 sec_counter;
// Level change interval
const Uint32 level_change_interval = 60 * 1000;
// Is the level begin/end pause active?
int level_pause = 0;
// Return the number of seconds left
float get_level_seconds_left() {
return ((float)level_change_interval/1000.0f - ((float)(SDL_GetTicks() - level_time) / 1000.0f));
}
// Find the levels
void find_levels() {
// Find the levels from the pakfile
num_level_files = 0;
while(1) {
// Check if the file exists
char str[128] = "";
sprintf(str, "MAP%02d.map", num_level_files+1);
FILE *check = pakfile.open_file(str);
if(!check)
// No more levels, break
break;
else {
// There was a level by that name.
fclose(check);
num_level_files++;
}
}
}
// Shuffle the level list
void shuffle_level_list() {
// Shuffle the level files and take NUM_LEVELS amount of levels into the
// level_list array
vector<int> shuffled;
shuffled.clear();
for(int f=0; f<num_level_files; f++)
shuffled.push_back(f);
// Shuffle it
for(unsigned int i = shuffled.size() - 1; i > 0; i--) {
int pos = RAND(0, i - 1);
int swap = shuffled[i];
shuffled[i] = shuffled[pos];
shuffled[pos] = swap;
}
// Take the first NUM_LEVELS levels
for(int j=0; j<NUM_LEVELS; j++)
level_list[j] = shuffled[j];
}
// Shuffle the background list
void shuffle_bground_list() {
vector<int> shuffled;
shuffled.clear();
for(int f=0; f<NUM_BGROUNDS; f++)
shuffled.push_back(f);
// Shuffle it
for(unsigned int i = shuffled.size() - 1; i > 0; i--) {
int pos = RAND(0, i - 1);
int swap = shuffled[i];
shuffled[i] = shuffled[pos];
shuffled[pos] = swap;
}
// Copy the list
for(int j=0; j<NUM_BGROUNDS; j++)
bgrounds[j] = shuffled[j];
}
// Load map by number
void load_map_number(int num) {
char str[128] = "";
sprintf(str, "MAP%02d.map", num+1);
load_map(str);
}
// Load bground by number
void load_bg_number(int num) {
char str[128] = "";
sprintf(str, "bg%02d.jpg", num+1);
// Delete the existing texture and load over it
glDeleteTextures(1, &cur_bground);
glGenTextures(1, &cur_bground);
// Load the background image
load_texture_into(cur_bground, str, "JPG", false, false, true);
}
// Init the levels
void init_levels() {
cur_level = 0;
using_special_power = 0;
special_power_pause = false;
init_special_selection();
// Shuffle the level list and load the first map
shuffle_level_list();
load_map_number(level_list[0]);
level_pause = LEVEL_PAUSE_BEGIN;
// Shuffle the background list and load the first background
shuffle_bground_list();
load_bg_number(bgrounds[0]);
// Make the icons visible
if(two_players) {
show_icon(0);
show_icon(1);
}
// Add the comment
add_comment(COL_DEFAULT, "Press ENTER to begin level %s.", level_names[cur_level]);
// Clear the helpers
wisp.clear();
potatoman.clear();
// Set the bonus system
for(int f=0; f<NUM_ICONS; f++)
icon_menu.count[f] = 0;
next_bonus[BONUS_RED] = RED_POWER_TRAP;
next_bonus[BONUS_GREEN] = GREEN_POWER_WISP;
next_bonus[BONUS_BLUE] = BLUE_POWER_TELEPORT;
bonus_counter[BONUS_RED] = bonus_counter[BONUS_GREEN] = bonus_counter[BONUS_BLUE] = 0;
num_seconds_left = level_change_interval / 1000;
}
// Helper function from player.cpp
void get_random_block_at(int x, int y, int &bx, int &by);
static bool sound_played = false;
static bool comment_added = false;
// Change level.
// Return false if we're finished all the levels.
bool change_level() {
if(level_pause == LEVEL_PAUSE_END) {
level_time--;
if(level_time <= 0) {
// Switch to the next level
if(level_pause == LEVEL_PAUSE_END) {
// Check if we're finished all the levels.
if(cur_level == NUM_LEVELS-1)
return false;
next_level();
}
}
return true;
}
// Check if there's ten seconds left
num_seconds_left = (int)get_level_seconds_left();
if(num_seconds_left == 10 && !comment_added) {
add_comment(COL_DEFAULT, "Ten seconds left.");
comment_added = true;
}
// Check if there's three seconds left
if(num_seconds_left == 3 && !sound_played) {
play_sound(SND_FINISH, false);
sound_played = true;
}
// Advance the level time
Uint32 time = SDL_GetTicks() - level_time;
if(time >= level_change_interval) {
// Level is finished
level_time = 3 * 60;
// Jump the players to the blocks
int bx, by;
if(p1.alive && !p1.dying && !map_solid((int)p1.get_real_x(), (int)p1.get_real_y()) && !p1.jumping && !(using_special_power == 1 && which_special_power == BLUE_POWER_TELEPORT)) {
get_random_block_at((int)p1.get_real_x(), (int)p1.get_real_y(), bx, by);
p1.jump(bx, by, 2.0f, 0.05f);
// Play the jump sound
play_sound(SND_JUMP, false);
}
if(two_players && p2.alive && !p2.dying && !map_solid((int)p2.get_real_x(), (int)p2.get_real_y()) && !p2.jumping && !(using_special_power == 2 && which_special_power == BLUE_POWER_TELEPORT)) {
get_random_block_at((int)p2.get_real_x(), (int)p2.get_real_y(), bx, by);
p2.jump(bx, by, 2.0f, 0.05f);
// Play the jump sound
play_sound(SND_JUMP, false);
}
// Explode the player bombs
if(p1.num_bombs > 0) {
list<BOMB>::iterator b;
for(b = bomblist.begin(); b != bomblist.end(); ++b)
if((*b).owner == 1 && (*b).time > 20)
(*b).time = 20; // Makes the bomb explode soon
}
if(two_players && p2.num_bombs > 0) {
list<BOMB>::iterator b;
for(b = bomblist.begin(); b != bomblist.end(); ++b)
if((*b).owner == 2 && (*b).time > 20)
(*b).time = 20; // Makes the bomb explode soon
}
// Kill all the burning enemies
if(enemylist.size() > 0) {
list<ENEMY>::iterator e;
for(e = enemylist.begin(); e != enemylist.end(); ++e) {
if((*e).burning)
(*e).die();
}
}
// Add the comment
level_pause = LEVEL_PAUSE_END;
add_comment(COL_DEFAULT, "Level finished.");
if(cur_level == NUM_LEVELS-1)
add_comment(COL_DEFAULT, "GAME OVER");
}
return true;
}
// Switch to the next level
void next_level() {
// Proceed to the next level
cur_level++;
if(cur_level >= NUM_LEVELS) {
// We have finished the game.
return;
}
num_seconds_left = level_change_interval / 1000;
game_paused = true;
// Clear stuff
p1.clear();
p2.clear();
clear_enemies();
clear_bombs();
clear_particles();
clear_bonus();
clear_traps();
using_special_power = 0;
special_power_pause = false;
init_special_selection();
// Make the icons visible
if(two_players) {
show_icon(0);
show_icon(1);
}
// Load the level
load_map_number(level_list[cur_level]);
// Load the background
load_bg_number(bgrounds[cur_level]);
// Randomize the location for the wisps and the potato men
if(wisp.alive) {
wisp.pos.x = RANDF(0, MAP_W);
wisp.pos.y = 5.0f;
wisp.pos.z = RANDF(0, MAP_H);
wisp.dir = 0.0f;
wisp.bonus = NULL;
}
if(potatoman.alive) {
int old_counter = potatoman.counter;
create_potatoman();
potatoman.counter = old_counter;
}
// Add the comment
add_comment(COL_DEFAULT, "Press ENTER to begin level %s.", level_names[cur_level]);
level_pause = LEVEL_PAUSE_BEGIN;
start_level_timing();
comment_added = false;
sound_played = false;
game_paused = false;
}
// Start timing the level change
void start_level_timing() {
level_time = SDL_GetTicks();
sec_counter = level_time;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -