class CameraConfig
{
public:
- // 0 = No, 1 = Fix, 2 = Mario/Yoshi, 3 = Kirby, 4 = inverse rubber
+ // 0 = No, 1 = Fix, 2 = Mario/Yoshi, 3 = Kirby
int ymode;
+ // as above, 4 = super metroid like
int xmode;
float kirby_rectsize_x;
float kirby_rectsize_y;
float dirchange_time;
// edge_x
float edge_x;
+ // when too change from noscroll mode back to lookahead left/right mode
+ // set to <= 0 to disable noscroll mode
float sensitive_x;
float clamp_y;
float clamp_x;
+ float dynamic_speed_sm;
+
CameraConfig() {
xmode = 1;
ymode = 1;
sensitive_x = 1.f/4.f;
dynamic_max_speed_x = 1.0;
dirchange_time = 0.2f;
+ dynamic_speed_sm = 1.0f;
}
void load(const std::string& filename)
camconfig->get("kirby-rectsize-y", kirby_rectsize_y);
camconfig->get("edge-x", edge_x);
camconfig->get("sensitive-x", sensitive_x);
+ camconfig->get("dynamic-speed-sm", dynamic_speed_sm);
}
};
Camera::Camera(Sector* newsector, std::string name)
- : mode(NORMAL), sector(newsector), lookahead_mode(LOOKAHEAD_NONE)
+ : mode(NORMAL), sector(newsector), lookahead_mode(LOOKAHEAD_NONE),
+ lookahead_pos(0)
{
this->name = name;
config = new CameraConfig();
return;
/****** Vertical Scrolling part ******/
+ int xmode = config.xmode;
int ymode = config.ymode;
if(player->is_dying() || sector->get_height() == 19*32) {
ymode = 0;
}
+ if(player->is_dying())
+ xmode = 0;
if(ymode == 1) {
translation.y = player_pos.y - SCREEN_HEIGHT * config.target_y;
if(ymode == 3) {
float halfsize = config.kirby_rectsize_y * 0.5f;
translation.y = clamp(translation.y,
- player_pos.y - SCREEN_HEIGHT * (0.5f - halfsize),
- player_pos.y - SCREEN_HEIGHT * (0.5f + halfsize));
+ player_pos.y - SCREEN_HEIGHT * (0.5f + halfsize),
+ player_pos.y - SCREEN_HEIGHT * (0.5f - halfsize));
}
if(ymode == 4) {
// TODO...
if(ymode != 0 && config.clamp_y > 0) {
translation.y = clamp(translation.y,
- player_pos.y - SCREEN_HEIGHT * config.clamp_y,
- player_pos.y - SCREEN_HEIGHT * (1-config.clamp_y));
+ player_pos.y - SCREEN_HEIGHT * (1-config.clamp_y),
+ player_pos.y - SCREEN_HEIGHT * config.clamp_y);
}
/****** Horizontal scrolling part *******/
- if(config.xmode == 1) {
+ if(xmode == 1) {
translation.x = player_pos.x - SCREEN_WIDTH * config.target_x;
}
- if(config.xmode == 2) {
+ if(xmode == 2) {
// our camera is either in leftscrolling, rightscrolling or
// nonscrollingmode.
//
else if (player->dir == ::LEFT) walkDirection = LOOKAHEAD_LEFT;
else walkDirection = LOOKAHEAD_RIGHT;
- float LEFTEND = SCREEN_WIDTH * config.sensitive_x;
- float RIGHTEND = SCREEN_WIDTH * (1-config.sensitive_x);
+ float LEFTEND, RIGHTEND;
+ if(config.sensitive_x > 0) {
+ LEFTEND = SCREEN_WIDTH * config.sensitive_x;
+ RIGHTEND = SCREEN_WIDTH * (1-config.sensitive_x);
+ } else {
+ LEFTEND = SCREEN_WIDTH;
+ RIGHTEND = 0;
+ }
- /* if we're undecided then look if we crossed the left or right "sensitive"
- * area */
if(lookahead_mode == LOOKAHEAD_NONE) {
+ /* if we're undecided then look if we crossed the left or right
+ * "sensitive" area */
if(player_pos.x < translation.x + LEFTEND) {
lookahead_mode = LOOKAHEAD_LEFT;
} else if(player_pos.x > translation.x + RIGHTEND) {
lookahead_mode = LOOKAHEAD_RIGHT;
}
+ /* at the ends of a level it's obvious which way we will go */
+ if(player_pos.x < SCREEN_WIDTH*0.5) {
+ lookahead_mode = LOOKAHEAD_RIGHT;
+ } else if(player_pos.x >= sector->get_width() - SCREEN_WIDTH*0.5) {
+ lookahead_mode = LOOKAHEAD_LEFT;
+ }
+
changetime = -1;
} else if(lookahead_mode != walkDirection) {
/* player changed direction while camera was scrolling...
player_pos.x < translation.x + LEFTEND) {
lookahead_mode = LOOKAHEAD_LEFT;
} else {
- printf("abortscroll\n");
lookahead_mode = LOOKAHEAD_NONE;
}
}
// calculate our scroll target depending on scroll mode
float target_x;
if(lookahead_mode == LOOKAHEAD_LEFT)
- target_x = player->get_bbox().get_middle().x - RIGHTEND;
+ target_x = player_pos.x - RIGHTEND;
else if(lookahead_mode == LOOKAHEAD_RIGHT)
- target_x = player->get_bbox().get_middle().x - LEFTEND;
+ target_x = player_pos.x - LEFTEND;
else
target_x = translation.x;
// apply scrolling
translation.x -= speed_x * elapsed_time;
}
- if(config.xmode == 3) {
+ if(xmode == 3) {
float halfsize = config.kirby_rectsize_x * 0.5f;
translation.x = clamp(translation.x,
- player_pos.x - SCREEN_WIDTH * (0.5f - halfsize),
- player_pos.x - SCREEN_WIDTH * (0.5f + halfsize));
+ player_pos.x - SCREEN_WIDTH * (0.5f + halfsize),
+ player_pos.x - SCREEN_WIDTH * (0.5f - halfsize));
}
- if(config.xmode == 4) {
- // TODO...
+ if(xmode == 4) {
+ float LEFTEND = SCREEN_WIDTH * config.edge_x;
+ float RIGHTEND = SCREEN_WIDTH * (1 - config.edge_x);
+
+ if (player_delta.x < -EPSILON) {
+ // walking left
+ lookahead_pos -= player_delta.x * config.dynamic_speed_sm;
+
+ if(lookahead_pos > RIGHTEND) {
+ lookahead_pos = RIGHTEND;
+ }
+ } else if (player_delta.x > EPSILON) {
+ // walking right
+ lookahead_pos -= player_delta.x * config.dynamic_speed_sm;
+ if(lookahead_pos < LEFTEND) {
+ lookahead_pos = LEFTEND;
+ }
+ }
+
+ if(player->peeking_direction() == ::LEFT) {
+ lookahead_pos += config.max_speed_x * elapsed_time * 3.0f;
+ } else if(player->peeking_direction() == ::RIGHT) {
+ lookahead_pos -= config.max_speed_x * elapsed_time * 3.0f;
+ }
+
+ // adjust for level ends
+ if (player_pos.x < LEFTEND) {
+ lookahead_pos = LEFTEND;
+ }
+ if (player_pos.x > sector->get_width() - LEFTEND) {
+ lookahead_pos = RIGHTEND;
+ }
+
+ translation.x = player_pos.x - lookahead_pos;
}
- if(config.xmode != 0 && config.clamp_x > 0) {
+ if(xmode != 0 && config.clamp_x > 0) {
translation.x = clamp(translation.x,
- player_pos.x - SCREEN_WIDTH * config.clamp_x,
- player_pos.x - SCREEN_WIDTH * (1-config.clamp_x));
+ player_pos.x - SCREEN_WIDTH * (1-config.clamp_x),
+ player_pos.x - SCREEN_WIDTH * config.clamp_x);
}
keep_in_bounds(translation);