diff --git a/README.md b/README.md
index 44840e8..8585ff6 100644
--- a/README.md
+++ b/README.md
@@ -3,9 +3,6 @@
In addtion to having the original features of Flappy Bird, we implemented a brand new way to play the game -- instead of sideviewing the bird, you can view it from the back. There's also day time theme and night time theme.
-
-
-
## Run
1. Clone or download this repository.
diff --git a/flappy-bird.js b/flappy-bird.js
index ba10f7d..3c27a54 100644
--- a/flappy-bird.js
+++ b/flappy-bird.js
@@ -37,7 +37,7 @@ export class Bird extends Scene {
text: new Text_Line( 35 ),
cylinder: new defs.Cylindrical_Tube(150, 300, [[0, 2], [1, 2]]),
capped_cylinder: new defs.Rounded_Capped_Cylinder(150, 300, [[0, 2], [1, 2]]),
-
+
};
this.textures = {
@@ -66,13 +66,13 @@ export class Bird extends Scene {
background: new Material(
new defs.Fake_Bump_Map(1), {
color: hex_color("#000000"),
- ambient: 1,
+ ambient: 1,
texture: this.textures.background,
}),
background_night: new Material(
new defs.Fake_Bump_Map(1), {
color: hex_color("#000000"),
- ambient: 1,
+ ambient: 1,
texture: this.textures.background_night,
}),
game_end: new Material(
@@ -83,8 +83,8 @@ export class Bird extends Scene {
}),
text_image: new Material(
new defs.Textured_Phong(1), {
- ambient: 1,
- diffusivity: 0,
+ ambient: 1,
+ diffusivity: 0,
specularity: 0,
texture: new Texture("assets/text.png"),
}),
@@ -113,6 +113,33 @@ export class Bird extends Scene {
this.score = 0;
this.highest_score = 0;
this.night_theme = false;
+
+
+ this.power_up_active = false;
+ this.power_up_duration = 2; // Duration in seconds
+ this.power_up_timer = 0;
+ this.normal_acceleration = 20; // Normal gravity
+ this.reduced_acceleration = 4; // Reduced gravity when power-up is active
+ this.power_up_position = vec3(0, Math.random() * 10 + 5, 0);
+
+
+ this.last_speed_change_time = 0; // Last time the speed changed
+ this.total_normal_speed_duration = 0; // Total time spent at normal speed
+ this.total_increased_speed_duration = 0;
+
+
+ this.power_up_visible = false;
+ //this.power_up_position = vec3(0, 5, 0);
+ this.power_up_last_activation_time = 0;
+ this.power_up_activation_interval = Math.random() * 10 + 5;
+
+ this.fastforward_active = false;
+ this.fastforward_timer = 0;
+ this.normal_speed = 5;
+
+ this.increased_speed = 6;
+ this.fastforward_position = vec3(Math.random() * 20, Math.random() * 10 + 5, 0);
+
}
make_control_panel() {
@@ -120,6 +147,9 @@ export class Bird extends Scene {
this.click_time = this.t;
this.base_y = this.y;
if (!this.game_start) {
+
+ let adjusted_time = this.total_normal_speed_duration * this.normal_speed + this.total_increased_speed_duration * this.increased_speed;
+
this.game_start_time = this.t + this.starting_distance / this.game_speed;
console.log(this.game_start_time);
}
@@ -142,19 +172,21 @@ export class Bird extends Scene {
this.new_line();
const acceleration_controls = this.control_panel.appendChild(document.createElement("span"));
-
-
-
+
+
+
this.new_line();
const initial_v_y_controls = this.control_panel.appendChild(document.createElement("span"));
-
-
+
+
this.key_triggered_button("Change theme", ["b"], ()=> {
this.night_theme = !this.night_theme;
});
}
+
+
draw_box(context, program_state, model_transform, color) {
this.shapes.cube.draw(context, program_state, model_transform, this.materials.plastic.override({color: color}));
}
@@ -168,9 +200,9 @@ export class Bird extends Scene {
draw_wings(context, program_state, model_transform) {
const left_wing = model_transform.times(Mat4.translation(-0.8, -0.4, -0.4))
- .times(Mat4.scale(0.2, 0.6, 0.8));
+ .times(Mat4.scale(0.2, 0.6, 0.8));
const right_wing = model_transform.times(Mat4.translation(0.8, -0.4, -0.4))
- .times(Mat4.scale(0.2, 0.6, 0.8));
+ .times(Mat4.scale(0.2, 0.6, 0.8));
this.shapes.sun.draw(context, program_state, left_wing, this.materials.plastic.override({color: color(1, 1, 1, 1)}));
this.shapes.sun.draw(context, program_state, right_wing, this.materials.plastic.override({color: color(1, 1, 1, 1)}));
}
@@ -178,9 +210,9 @@ export class Bird extends Scene {
draw_mouth(context, program_state, model_transform) {
const lip_color = hex_color("#FE9800");
const upper_lip = model_transform.times(Mat4.translation(0, 0, 1))
- .times(Mat4.scale(0.8, 0.2, 0.6));
+ .times(Mat4.scale(0.8, 0.2, 0.6));
const lower_lip = model_transform.times(Mat4.translation(0, -0.3, 0.5))
- .times(Mat4.scale(0.7, 0.2, 0.8));
+ .times(Mat4.scale(0.7, 0.2, 0.8));
this.shapes.cube.draw(context, program_state, upper_lip, this.materials.plastic.override({color: lip_color}));
this.shapes.cube.draw(context, program_state, lower_lip, this.materials.plastic.override({color: lip_color}));
}
@@ -190,16 +222,16 @@ export class Bird extends Scene {
const black = hex_color("#000000");
// right eye
const right_bg_transform = model_transform.times(Mat4.translation(-0.75, 0.35, 0.7))
- .times(Mat4.scale(0.2, 0.4, 0.4));
+ .times(Mat4.scale(0.2, 0.4, 0.4));
const right_pupil_transform = model_transform.times(Mat4.translation(-0.8, 0.4, 0.8))
- .times(Mat4.scale(0.2, 0.20, 0.15));
+ .times(Mat4.scale(0.2, 0.20, 0.15));
this.shapes.sun.draw(context, program_state, right_bg_transform, this.materials.plastic.override({color: white}));
this.shapes.sun.draw(context, program_state, right_pupil_transform, this.materials.plastic.override({color: black}));
// left eye
const left_bg_transform = model_transform.times(Mat4.translation(0.75, 0.35, 0.7))
- .times(Mat4.scale(0.2, 0.4, 0.4));
+ .times(Mat4.scale(0.2, 0.4, 0.4));
const left_pupil_transform = model_transform.times(Mat4.translation(0.8, 0.4, 0.8))
- .times(Mat4.scale(0.2, 0.2, 0.15));
+ .times(Mat4.scale(0.2, 0.2, 0.15));
this.shapes.sun.draw(context, program_state, left_bg_transform, this.materials.plastic.override({color: white}));
this.shapes.sun.draw(context, program_state, left_pupil_transform, this.materials.plastic.override({color: black}));
}
@@ -270,7 +302,7 @@ export class Bird extends Scene {
//draw top pipe
const top_pipe_model_transform = model_transform.times(Mat4.translation(0, this.pipe_gap - (9 - pipe_len), i * this.pipe_distance))
- .times(Mat4.rotation(Math.PI, 1, 0, 0));
+ .times(Mat4.rotation(Math.PI, 1, 0, 0));
this.draw_pipe(context, program_state, top_pipe_model_transform, 9 - pipe_len);
this.check_bird_collision(top_pipe_model_transform, bottom_pipe_model_transform, pipe_len);
@@ -365,7 +397,7 @@ export class Bird extends Scene {
draw_ground(context, program_state, model_transform) {
const ground_model_transform = model_transform.times(Mat4.scale(40, 1, 60))
- .times(Mat4.translation(0, -1, 0));
+ .times(Mat4.translation(0, -1, 0));
const green = hex_color(this.night_theme ? "53873d" : "#82C963");
this.shapes.cube.draw(context, program_state, ground_model_transform, this.materials.pure_color.override({color: green}));
}
@@ -377,18 +409,24 @@ export class Bird extends Scene {
const translation_z = type === "r" ? 60: (type === "l" ? -60 : Math.sin(-t/3)*25);
const background_transform = model_transform.times(Mat4.translation(translation_x, 65 - 1 / 5 * this.y, translation_z))
- .times(Mat4.rotation(rotation_angle, 0, 1, 0))
- .times(Mat4.scale(85, 85, 1));
+ .times(Mat4.rotation(rotation_angle, 0, 1, 0))
+ .times(Mat4.scale(85, 85, 1));
this.shapes.square.draw(
context,
program_state,
background_transform,
- this.night_theme ?
- this.materials.background_night :
- this.materials.background,
+ this.night_theme ?
+ this.materials.background_night :
+ this.materials.background,
);
}
-
+ draw_power_up(context, program_state) {
+ // Only draw the power-up if it's visible
+ if (this.power_up_visible) {
+ const power_up_transform = Mat4.translation(...this.power_up_position).times(Mat4.scale(1, 1, 1));
+ this.shapes.sun.draw(context, program_state, power_up_transform, this.materials.pure_color.override({color: color(1, 1, 1, 1)}));
+ }
+ }
draw_all_backgrounds(context, program_state, model_transform, t) {
this.draw_background(context, program_state, model_transform, t, "f");
this.draw_background(context, program_state, model_transform, t, "b");
@@ -398,9 +436,9 @@ export class Bird extends Scene {
draw_score(context, program_state, model_transform) {
const sideview_transform = model_transform.times(Mat4.translation(-3, 25, 5))
- .times(Mat4.rotation(3 * Math.PI / 2, 0, 1, 0));
+ .times(Mat4.rotation(3 * Math.PI / 2, 0, 1, 0));
const backview_transform = model_transform.times(Mat4.translation(-3, 25, 5))
- .times(Matrix.of([-1, 0, 0, 0],[0, 1, 0, 0],[0, 0, 1, 0],[0, 0, 0, 1]));
+ .times(Matrix.of([-1, 0, 0, 0],[0, 1, 0, 0],[0, 0, 1, 0],[0, 0, 0, 1]));
const scoreboard_model_transform = this.sideview ? sideview_transform : backview_transform;
const time_per_pipe = this.pipe_distance / this.game_speed;
@@ -410,7 +448,13 @@ export class Bird extends Scene {
const score_string = "Score: " + this.score.toString();
this.shapes.text.set_string(score_string, context.context);
- this.shapes.text.draw(context, program_state, scoreboard_model_transform, this.materials.text_image);
+ this.shapes.text.draw(context, program_state, scoreboard_model_transform, this.materials.text_image);
+ }
+ check_collision_with_power_up() {
+ // Implement collision detection logic here
+ // Example: Check distance between bird and power-up for simplicity
+ const distance = this.power_up_position.minus(vec3(0, this.y, 0)).norm();
+ return distance < 2; // Assuming a simple radius check for collision
}
@@ -438,16 +482,23 @@ export class Bird extends Scene {
this.update_y(t_after_click);
this.update_angle(t_after_click);
const model_transform = matrix_transform.times(Mat4.translation(0, this.y, 0))
- .times(Mat4.rotation(this.angle, 1, 0, 0));
+ .times(Mat4.rotation(this.angle, 1, 0, 0));
if(!this.game_end) {
this.draw_bird(context, program_state, model_transform);
+
+ // Draw power-up if it's currently visible
+ if (this.power_up_visible) {
+ this.draw_power_up(context, program_state);
+ }
+
+
this.draw_ground(context, program_state, matrix_transform);
this.draw_all_backgrounds(context, program_state, matrix_transform, t);
// draw three sets of pipes, one before the bird, one after the bird, and one with the bird
this.draw_three_sets_of_pipe(context, program_state, matrix_transform, t);
-
+
this.draw_score(context, program_state, matrix_transform);
}
else {
@@ -455,8 +506,8 @@ export class Bird extends Scene {
program_state.set_camera(this.sideview_cam_pos);
this.sideview = true;
this.shapes.square.draw(context, program_state, matrix_transform.times(Mat4.translation(0, 10, 0))
- .times(Mat4.rotation(Math.PI / 2 * 3, 0, 1, 0))
- .times(Mat4.scale(28, 28, 1)), this.materials.game_end);
+ .times(Mat4.rotation(Math.PI / 2 * 3, 0, 1, 0))
+ .times(Mat4.scale(28, 28, 1)), this.materials.game_end);
const score_model_transform = matrix_transform.times(Mat4.translation(-3, 8, -12))
.times(Mat4.rotation(3 * Math.PI / 2, 0, 1, 0));
@@ -465,18 +516,88 @@ export class Bird extends Scene {
this.shapes.text.draw(context, program_state, score_model_transform, this.materials.text_image);
const highscore_model_transform = matrix_transform.times(Mat4.translation(-3, 6, -12))
- .times(Mat4.rotation(3 * Math.PI / 2, 0, 1, 0));
+ .times(Mat4.rotation(3 * Math.PI / 2, 0, 1, 0));
const highscore_string = "Highest score: " + this.highest_score.toString();
this.shapes.text.set_string(highscore_string, context.context);
- this.shapes.text.draw(context, program_state, highscore_model_transform, this.materials.text_image);
-
+ this.shapes.text.draw(context, program_state, highscore_model_transform, this.materials.text_image);
+
const replay_model_transform = matrix_transform.times(Mat4.translation(-3, 4, -12))
- .times(Mat4.rotation(3 * Math.PI / 2, 0, 1, 0));
+ .times(Mat4.rotation(3 * Math.PI / 2, 0, 1, 0));
const replay_string = "Replay with \"n\"";
this.shapes.text.set_string(replay_string, context.context);
- this.shapes.text.draw(context, program_state, replay_model_transform, this.materials.text_image);
+ this.shapes.text.draw(context, program_state, replay_model_transform, this.materials.text_image);
+ }
+
+
+
+
+
+ const time_since_last_activation = program_state.animation_time / 1000 - this.power_up_last_activation_time;
+
+ if (!this.power_up_visible && time_since_last_activation > this.power_up_activation_interval) {
+ // Activate power-up
+ this.power_up_visible = true;
+ this.power_up_position = vec3(0, Math.random() * 10 + 5, 0);
+ this.power_up_activation_interval = Math.random() * 10 + 8; // Reset activation interval
+ }
+
+ // Check for collision with the bird if power-up is visible
+ if (this.power_up_visible && this.check_collision_with_power_up()) {
+ // Collided with power-up
+ this.power_up_visible = false; // Hide power-up
+ this.power_up_last_activation_time = program_state.animation_time / 1000; // Record activation time
+
+ // Set initial and final values for pipe gap
+ const initialPipeGap = 25;
+ const finalPipeGap = 20;
+
+ // Set the duration for increasing the pipe gap
+ const increaseDuration = 5 * 1000; // 5 seconds
+
+ // Set the duration for decreasing the pipe gap
+ const decreaseDuration = 5 * 1000; // 5 seconds
+
+ // Variable to keep track of elapsed time
+ let elapsedTime = 0;
+
+ // Use setInterval to gradually increase the pipe gap
+ const increaseIntervalId = setInterval(() => {
+ // Update the pipe gap by 1 unit
+ this.pipe_gap += 1;
+
+ // Increment the elapsed time
+ elapsedTime += 500; // 0.5 seconds
+
+ // Check if the increase duration has elapsed
+ if (elapsedTime >= increaseDuration) {
+ // Clear the interval for increasing
+ clearInterval(increaseIntervalId);
+
+ // Use setInterval to gradually decrease the pipe gap
+ const decreaseIntervalId = setInterval(() => {
+ // Update the pipe gap by -0.5 units
+ this.pipe_gap -= 0.5;
+
+ // Increment the elapsed time
+ elapsedTime += 500; // 0.5 seconds
+
+ // Check if the decrease duration has elapsed
+ if (elapsedTime >= increaseDuration + decreaseDuration) {
+ // Clear the interval for decreasing
+ clearInterval(decreaseIntervalId);
+
+ // Ensure the pipe gap is set to the final value
+ this.pipe_gap = finalPipeGap;
+ }
+ }, 400); // Update every 0.5 seconds for decreasing
+ }
+ }, 400); // Update every 0.5 seconds for increasing
}
+
+
+
+
const blending_factor = 0.1;
if (!this.sideview) {
// change to back cam position
@@ -490,4 +611,4 @@ export class Bird extends Scene {
program_state.set_camera(transition);
}
}
-}
+}
\ No newline at end of file