diff --git a/.bin/music/test-60bpm.sj b/.bin/music/test-60bpm.sj index 1b010c4..d076722 100644 --- a/.bin/music/test-60bpm.sj +++ b/.bin/music/test-60bpm.sj @@ -19,7 +19,7 @@ posteffect [0..1] { clip_right := 0.1; } -$repeat i 10 { +$repeat i 1 { $repeat j 20 { circle [$i..$i+2] { color_r := 0.8; diff --git a/src/sj/PlayScene.d b/src/sj/PlayScene.d index c2c5e06..febf414 100644 --- a/src/sj/PlayScene.d +++ b/src/sj/PlayScene.d @@ -39,6 +39,8 @@ class PlayScene : SceneInterface { music_ = music; context_ = context; + score_ = BaseScore; + music_.PlayForGame(); } override SceneInterface Update(KeyInput input) { diff --git a/src/sj/ResultScene.d b/src/sj/ResultScene.d index 82200f7..d856e67 100644 --- a/src/sj/ResultScene.d +++ b/src/sj/ResultScene.d @@ -1,7 +1,10 @@ /// License: MIT module sj.ResultScene; -import std.math; +import std.conv, + std.format, + std.math, + std.random; import gl4d; @@ -11,6 +14,8 @@ import sj.FontSet, sj.Music, sj.ProgramSet, sj.SceneInterface, + sj.Text, + sj.TextProgram, sj.TitleScene, sj.util.Animation, sj.util.Easing; @@ -25,19 +30,57 @@ class ResultScene : SceneInterface { enum CubeLoadingRotationSpeed = vec3(PI/100, PI/10, PI/100); /// enum CubeLoadingInterval = 0.06; + /// + enum BgLoadingInnerColor = vec4(0.4, 0.4, 0.4, 1); + /// + enum BgLoadingOuterColor = vec4(-0.2, -0.2, -0.2, 1); /// enum CubeRotationSpeed = vec3(PI/1000, PI/500, PI/1000); /// enum CubeInterval = 0.005; + /// + enum DescTextScale = vec3(-0.002, 0.002, 0.002); + /// + enum DescTextTranslation = vec3(0, -0.3, 0); + /// + enum DescTextColor = vec4(0.2, 0.2, 0.2, 1); + /// + enum RankTextScale = vec3(-0.002, 0.002, 0.002); + /// + enum RankTextTranslation = vec3(0, -0.5, 0); + /// + enum ScoreTextScale = vec3(-0.002, 0.002, 0.002); + /// + enum ScoreTextTranslation = vec3(0, -0.55, 0); + + /// + enum RankCalculationRatio = 10000; + /// this(LobbyWorld lobby, ProgramSet programs, FontSet fonts) { lobby_ = lobby; programs_ = programs; fonts_ = fonts; + + description_text_ = new Text(programs.Get!TextProgram); + score_text_ = new Text(programs.Get!TextProgram); + rank_text_ = new Text(programs.Get!TextProgram); + + with (description_text_) { + const w = LoadGlyphs(vec2i(256, 32), + "YOUR RANK", vec2i(16, 0), fonts_.gothic); + matrix.scale = DescTextScale; + matrix.translation = + DescTextTranslation + vec3(-w/2*matrix.scale.x, 0, 0); + color = DescTextColor; + } } ~this() { + description_text_.destroy(); + score_text_.destroy(); + rank_text_.destroy(); } /// @@ -55,6 +98,26 @@ class ResultScene : SceneInterface { Easing!float(CubeLoadingInterval, CubeInterval); cube_rotation_speed_ease_ = Easing!vec3(CubeLoadingRotationSpeed, CubeRotationSpeed); + + bg_inner_ease_ = + Easing!vec4(BgLoadingInnerColor, music_.preview.bg_inner_color); + bg_outer_ease_ = + Easing!vec4(BgLoadingOuterColor, music_.preview.bg_outer_color); + + with (score_text_) { + auto w = LoadGlyphs(vec2i(512, 64), + "%d pt".format(score).to!dstring, vec2i(16, 0), fonts_.gothic); + matrix.scale = ScoreTextScale; + matrix.translation = + ScoreTextTranslation + vec3(-w/2 * matrix.scale.x, 0, 0); + } + with (rank_text_) { + auto w = LoadGlyphs(vec2i(512, 128), + GetRankLetter(score), vec2i(100, 0), fonts_.gothic); + matrix.scale = RankTextScale; + matrix.translation = + RankTextTranslation + vec3(-w/2 * matrix.scale.x, 0, 0); + } } override SceneInterface Update(KeyInput input) { const ratio = anime_.Update(); @@ -62,6 +125,9 @@ class ResultScene : SceneInterface { with (lobby_) { cube_matrix.rotation += cube_rotation_speed_ease_.Calculate(ratio); cube_interval = cube_interval_ease_ .Calculate(ratio); + + background.inner_color = bg_inner_ease_.Calculate(ratio); + background.outer_color = bg_outer_ease_.Calculate(ratio); } if (anime_.isFinished && input.down) { title_scene_.Initialize(); @@ -70,10 +136,25 @@ class ResultScene : SceneInterface { return this; } override void Draw() { + const ratio = anime_.ratio; + lobby_.Draw(); + + const view = lobby_.view.Create(); + description_text_.Draw(lobby_.Projection, view); + rank_text_ .Draw(lobby_.Projection, view); + score_text_ .Draw(lobby_.Projection, view); } private: + static dstring GetRankLetter(int score) { + const ratio = score*1f / RankCalculationRatio; + if (ratio < 0.60) return "D"d; + if (ratio < 0.80) return "B"d; + if (ratio < 0.95) return "A"d; + return "S"; + } + TitleScene title_scene_; LobbyWorld lobby_; @@ -84,7 +165,15 @@ class ResultScene : SceneInterface { Music music_; - Animation anime_; + Text description_text_; + Text score_text_; + Text rank_text_; + + Animation anime_; + Easing!vec3 cube_rotation_speed_ease_; Easing!float cube_interval_ease_; + + Easing!vec4 bg_inner_ease_; + Easing!vec4 bg_outer_ease_; } diff --git a/src/sj/util/Animation.d b/src/sj/util/Animation.d index b777b43..839ad98 100644 --- a/src/sj/util/Animation.d +++ b/src/sj/util/Animation.d @@ -12,13 +12,18 @@ struct Animation { } /// float Update() { - return (frame_++ * 1f / frame_count_).clamp(0f, 1f); + scope(exit) ++frame_; + return ratio; } /// @property bool isFinished() const { return frame_ >= frame_count_; } /// + @property float ratio() const { + return (frame_*1f / frame_count_).clamp(0f, 1f); + } + /// @property size_t frame() const { return frame_; }