[update] Implemented animations for scene transition.
This commit is contained in:
parent
b94b9f823e
commit
06fc93a2c4
@ -1,13 +1,20 @@
|
||||
/// License: MIT
|
||||
module sj.SelectScene;
|
||||
|
||||
import std.math,
|
||||
std.variant;
|
||||
|
||||
import derelict.sfml2.audio;
|
||||
|
||||
import gl4d;
|
||||
|
||||
import sj.KeyInput,
|
||||
sj.LobbyWorld,
|
||||
sj.ProgramSet,
|
||||
sj.SceneInterface,
|
||||
sj.TitleScene,
|
||||
sj.util.Animation,
|
||||
sj.util.Easing,
|
||||
sj.util.audio;
|
||||
|
||||
///
|
||||
@ -20,6 +27,9 @@ class SelectScene : SceneInterface {
|
||||
|
||||
sound_ = sfSound_create();
|
||||
soundres_.Load();
|
||||
|
||||
first_state_ = new FirstSetupState(this);
|
||||
status_ = first_state_;
|
||||
}
|
||||
~this() {
|
||||
sfSound_destroy(sound_);
|
||||
@ -33,13 +43,19 @@ class SelectScene : SceneInterface {
|
||||
|
||||
///
|
||||
void Initialize() {
|
||||
first_state_.Initialize();
|
||||
status_ = first_state_;
|
||||
}
|
||||
override SceneInterface Update(KeyInput input) {
|
||||
if (input.up) {
|
||||
title_scene_.Initialize();
|
||||
return title_scene_;
|
||||
}
|
||||
return this;
|
||||
SceneInterface next_scene = this;
|
||||
AbstractSceneState next_state;
|
||||
|
||||
status_.Update(input).visit!(
|
||||
(SceneInterface scene) { next_scene = scene; },
|
||||
(AbstractSceneState state) { next_state = state; }
|
||||
);
|
||||
status_ = next_state;
|
||||
return next_scene;
|
||||
}
|
||||
override void Draw() {
|
||||
lobby_.Draw();
|
||||
@ -67,4 +83,111 @@ class SelectScene : SceneInterface {
|
||||
sfSound* sound_;
|
||||
|
||||
SoundResources soundres_;
|
||||
|
||||
FirstSetupState first_state_;
|
||||
|
||||
AbstractSceneState status_;
|
||||
}
|
||||
|
||||
private abstract class AbstractSceneState {
|
||||
public:
|
||||
alias UpdateResult = Algebraic!(AbstractSceneState, SceneInterface);
|
||||
|
||||
this(SelectScene owner) {
|
||||
owner_ = owner;
|
||||
}
|
||||
|
||||
abstract UpdateResult Update(KeyInput input);
|
||||
|
||||
@property SelectScene owner() {
|
||||
return owner_;
|
||||
}
|
||||
|
||||
protected:
|
||||
static UpdateResult CreateResult(SceneInterface s) {
|
||||
return UpdateResult(s);
|
||||
}
|
||||
static UpdateResult CreateResult(AbstractSceneState s) {
|
||||
return UpdateResult(s);
|
||||
}
|
||||
private:
|
||||
SelectScene owner_;
|
||||
}
|
||||
|
||||
private class FirstSetupState : AbstractSceneState {
|
||||
public:
|
||||
this(SelectScene owner) {
|
||||
super(owner);
|
||||
stage_appear_state_ = new StageAppearState(owner);
|
||||
}
|
||||
|
||||
enum AnimeFrames = 30;
|
||||
enum BgInnerColor = vec4(0.8, 0.6, 0.6, 1);
|
||||
enum BgOuterColor = vec4(-0.4, -0.4, -0.4, 1);
|
||||
|
||||
enum CubeRotationSpeed = vec3(0, PI/10, 0);
|
||||
enum CubeInterval = 0.06;
|
||||
|
||||
void Initialize() {
|
||||
anime_ = Animation(AnimeFrames);
|
||||
bg_inner_ease_ = Easing!vec4(owner.lobby_.background.inner_color, BgInnerColor);
|
||||
bg_outer_ease_ = Easing!vec4(owner.lobby_.background.outer_color, BgOuterColor);
|
||||
|
||||
cube_interval_ease_ = Easing!float(owner.lobby_.cube_interval, CubeInterval);
|
||||
}
|
||||
override UpdateResult Update(KeyInput input) {
|
||||
const ratio = anime_.Update();
|
||||
|
||||
owner.lobby_.cube_matrix.rotation += CubeRotationSpeed * (ratio+0.2);
|
||||
owner.lobby_.cube_interval = cube_interval_ease_.Calculate(ratio);
|
||||
|
||||
owner.lobby_.background.inner_color = bg_inner_ease_.Calculate(ratio);
|
||||
owner.lobby_.background.outer_color = bg_outer_ease_.Calculate(ratio);
|
||||
|
||||
if (anime_.isFinished) {
|
||||
stage_appear_state_.Initialize();
|
||||
return CreateResult(stage_appear_state_);
|
||||
}
|
||||
return CreateResult(this);
|
||||
}
|
||||
|
||||
private:
|
||||
StageAppearState stage_appear_state_;
|
||||
|
||||
Animation anime_;
|
||||
|
||||
Easing!vec4 bg_inner_ease_;
|
||||
Easing!vec4 bg_outer_ease_;
|
||||
|
||||
Easing!float cube_interval_ease_;
|
||||
}
|
||||
private class StageAppearState : AbstractSceneState {
|
||||
public:
|
||||
this(SelectScene owner) {
|
||||
super(owner);
|
||||
}
|
||||
|
||||
enum AnimeFrames = 30;
|
||||
enum CubeRotationSpeed = vec3(0, PI/500, 0);
|
||||
|
||||
void Initialize() { // TODO: pass a stage data
|
||||
anime_ = Animation(AnimeFrames);
|
||||
cube_interval_ease_ = Easing!float(owner.lobby_.cube_interval, 0.005);
|
||||
|
||||
sfSound_setBuffer(owner.sound_, owner.soundres_.spotlight);
|
||||
sfSound_play(owner.sound_);
|
||||
}
|
||||
override UpdateResult Update(KeyInput input) {
|
||||
const ratio = anime_.Update();
|
||||
|
||||
owner.lobby_.cube_matrix.rotation += CubeRotationSpeed +
|
||||
(FirstSetupState.CubeRotationSpeed - CubeRotationSpeed) * (1-ratio);
|
||||
owner.lobby_.cube_interval = cube_interval_ease_.Calculate(ratio);
|
||||
return CreateResult(this);
|
||||
}
|
||||
|
||||
private:
|
||||
Animation anime_;
|
||||
|
||||
Easing!float cube_interval_ease_;
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
/// License: MIT
|
||||
module sj.TitleScene;
|
||||
|
||||
import std.math;
|
||||
import std.conv,
|
||||
std.math;
|
||||
|
||||
import gl4d;
|
||||
|
||||
@ -10,7 +11,9 @@ import sj.KeyInput,
|
||||
sj.ProgramSet,
|
||||
sj.SelectScene,
|
||||
sj.SceneInterface,
|
||||
sj.TitleTextProgram;
|
||||
sj.TitleTextProgram,
|
||||
sj.util.Animation,
|
||||
sj.util.Easing;
|
||||
|
||||
///
|
||||
class TitleScene : SceneInterface {
|
||||
@ -23,10 +26,35 @@ class TitleScene : SceneInterface {
|
||||
return m;
|
||||
}();
|
||||
|
||||
///
|
||||
enum AnimationFrame = 30;
|
||||
///
|
||||
enum BgInnerColor = vec4(0.9, 0.9, 0.9, 1);
|
||||
///
|
||||
enum BgOuterColor = vec4(-0.1, -0.1, -0.1, 1);
|
||||
///
|
||||
enum CubeInterval = 0.005;
|
||||
|
||||
///
|
||||
this(LobbyWorld lobby, ProgramSet program) {
|
||||
lobby_ = lobby;
|
||||
title_ = program.Get!TitleTextProgram;
|
||||
|
||||
lobby_.view.pos = vec3(0, -0.15, -1);
|
||||
lobby_.view.target = vec3(0, -0.15, 0);
|
||||
lobby_.view.up = vec3(0, 1, 0);
|
||||
|
||||
lobby_.background.inner_color = BgInnerColor;
|
||||
lobby_.background.outer_color = BgOuterColor;
|
||||
|
||||
lobby_.light_pos = vec3(0, 9, -1);
|
||||
lobby_.cube_material.diffuse_color = vec3(0.1, 0.1, 0.1);
|
||||
lobby_.cube_material.light_color = vec3(1, 0.8, 0.8);
|
||||
lobby_.cube_material.light_power = vec3(100, 100, 100);
|
||||
lobby_.cube_material.ambient_color = vec3(0.2, 0.2, 0.2);
|
||||
lobby_.cube_material.specular_color = vec3(0.5, 0.2, 0.2);
|
||||
|
||||
lobby_.cube_interval = CubeInterval;
|
||||
}
|
||||
|
||||
///
|
||||
@ -36,25 +64,23 @@ class TitleScene : SceneInterface {
|
||||
|
||||
///
|
||||
void Initialize() {
|
||||
lobby_.view.pos = vec3(0, -0.15, -1);
|
||||
lobby_.view.target = vec3(0, -0.15, 0);
|
||||
lobby_.view.up = vec3(0, 1, 0);
|
||||
anime_ = Animation(AnimationFrame);
|
||||
|
||||
lobby_.background.inner_color = vec4(0.9, 0.9, 0.9, 1);
|
||||
lobby_.background.outer_color = vec4(-0.1, -0.1, -0.1, 1);
|
||||
bg_inner_ease_ = Easing!vec4(lobby_.background.inner_color, BgInnerColor);
|
||||
bg_outer_ease_ = Easing!vec4(lobby_.background.outer_color, BgOuterColor);
|
||||
|
||||
lobby_.light_pos = vec3(0, 9, -1);
|
||||
lobby_.cube_material.diffuse_color = vec3(0.1, 0.1, 0.1);
|
||||
lobby_.cube_material.light_color = vec3(1, 0.8, 0.8);
|
||||
lobby_.cube_material.light_power = vec3(100, 100, 100);
|
||||
lobby_.cube_material.ambient_color = vec3(0.2, 0.2, 0.2);
|
||||
lobby_.cube_material.specular_color = vec3(0.5, 0.2, 0.2);
|
||||
|
||||
frame_ = 0;
|
||||
cube_interval_ease_ = Easing!float(lobby_.cube_interval, CubeInterval);
|
||||
}
|
||||
override SceneInterface Update(KeyInput input) {
|
||||
const ratio = anime_.Update();
|
||||
|
||||
lobby_.cube_matrix.rotation += vec3(PI/600, PI/600, PI/600);
|
||||
|
||||
lobby_.background.inner_color = bg_inner_ease_.Calculate(ratio);
|
||||
lobby_.background.outer_color = bg_outer_ease_.Calculate(ratio);
|
||||
|
||||
lobby_.cube_interval = cube_interval_ease_.Calculate(ratio);
|
||||
|
||||
if (input.down) {
|
||||
select_scene_.Initialize();
|
||||
return select_scene_;
|
||||
@ -63,7 +89,8 @@ class TitleScene : SceneInterface {
|
||||
}
|
||||
override void Draw() {
|
||||
lobby_.Draw();
|
||||
title_.Draw(lobby_.Projection, lobby_.view.Create(), TitleMatrix, frame_++);
|
||||
title_.Draw(lobby_.Projection, lobby_.view.Create(), TitleMatrix,
|
||||
(anime_.frame%int.max).to!int);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -73,5 +100,9 @@ class TitleScene : SceneInterface {
|
||||
|
||||
TitleTextProgram title_;
|
||||
|
||||
int frame_;
|
||||
Animation anime_;
|
||||
|
||||
Easing!vec4 bg_inner_ease_;
|
||||
Easing!vec4 bg_outer_ease_;
|
||||
Easing!float cube_interval_ease_;
|
||||
}
|
||||
|
30
src/sj/util/Animation.d
Normal file
30
src/sj/util/Animation.d
Normal file
@ -0,0 +1,30 @@
|
||||
/// License: MIT
|
||||
module sj.util.Animation;
|
||||
|
||||
import std.algorithm;
|
||||
|
||||
///
|
||||
struct Animation {
|
||||
public:
|
||||
///
|
||||
this(size_t frame_count) {
|
||||
frame_count_ = frame_count;
|
||||
}
|
||||
///
|
||||
float Update() {
|
||||
return (frame_++ * 1f / frame_count_).clamp(0f, 1f);
|
||||
}
|
||||
///
|
||||
@property bool isFinished() const {
|
||||
return frame_ >= frame_count_;
|
||||
}
|
||||
///
|
||||
@property size_t frame() const {
|
||||
return frame_;
|
||||
}
|
||||
|
||||
private:
|
||||
size_t frame_count_;
|
||||
|
||||
size_t frame_;
|
||||
}
|
37
src/sj/util/Easing.d
Normal file
37
src/sj/util/Easing.d
Normal file
@ -0,0 +1,37 @@
|
||||
/// License: MIT
|
||||
module sj.util.Easing;
|
||||
|
||||
///
|
||||
enum EasingType {
|
||||
Linear,
|
||||
LinearMountain,
|
||||
}
|
||||
|
||||
///
|
||||
struct Easing(T) {
|
||||
public:
|
||||
///
|
||||
this(T st, T ed, EasingType type = EasingType.Linear) {
|
||||
st_ = st;
|
||||
ed_ = ed;
|
||||
type_ = type;
|
||||
}
|
||||
|
||||
///
|
||||
T Calculate(float t) {
|
||||
final switch (type_) with (EasingType) {
|
||||
case LinearMountain:
|
||||
t = t*2;
|
||||
t = t > 1? 2-t: t;
|
||||
goto case;
|
||||
case Linear:
|
||||
return (ed_ - st_) * t + st_;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
T st_;
|
||||
T ed_;
|
||||
|
||||
EasingType type_;
|
||||
}
|
Reference in New Issue
Block a user