[update] Implemented animations for scene transition.
This commit is contained in:
parent
b94b9f823e
commit
06fc93a2c4
@ -1,13 +1,20 @@
|
|||||||
/// License: MIT
|
/// License: MIT
|
||||||
module sj.SelectScene;
|
module sj.SelectScene;
|
||||||
|
|
||||||
|
import std.math,
|
||||||
|
std.variant;
|
||||||
|
|
||||||
import derelict.sfml2.audio;
|
import derelict.sfml2.audio;
|
||||||
|
|
||||||
|
import gl4d;
|
||||||
|
|
||||||
import sj.KeyInput,
|
import sj.KeyInput,
|
||||||
sj.LobbyWorld,
|
sj.LobbyWorld,
|
||||||
sj.ProgramSet,
|
sj.ProgramSet,
|
||||||
sj.SceneInterface,
|
sj.SceneInterface,
|
||||||
sj.TitleScene,
|
sj.TitleScene,
|
||||||
|
sj.util.Animation,
|
||||||
|
sj.util.Easing,
|
||||||
sj.util.audio;
|
sj.util.audio;
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -20,6 +27,9 @@ class SelectScene : SceneInterface {
|
|||||||
|
|
||||||
sound_ = sfSound_create();
|
sound_ = sfSound_create();
|
||||||
soundres_.Load();
|
soundres_.Load();
|
||||||
|
|
||||||
|
first_state_ = new FirstSetupState(this);
|
||||||
|
status_ = first_state_;
|
||||||
}
|
}
|
||||||
~this() {
|
~this() {
|
||||||
sfSound_destroy(sound_);
|
sfSound_destroy(sound_);
|
||||||
@ -33,13 +43,19 @@ class SelectScene : SceneInterface {
|
|||||||
|
|
||||||
///
|
///
|
||||||
void Initialize() {
|
void Initialize() {
|
||||||
|
first_state_.Initialize();
|
||||||
|
status_ = first_state_;
|
||||||
}
|
}
|
||||||
override SceneInterface Update(KeyInput input) {
|
override SceneInterface Update(KeyInput input) {
|
||||||
if (input.up) {
|
SceneInterface next_scene = this;
|
||||||
title_scene_.Initialize();
|
AbstractSceneState next_state;
|
||||||
return title_scene_;
|
|
||||||
}
|
status_.Update(input).visit!(
|
||||||
return this;
|
(SceneInterface scene) { next_scene = scene; },
|
||||||
|
(AbstractSceneState state) { next_state = state; }
|
||||||
|
);
|
||||||
|
status_ = next_state;
|
||||||
|
return next_scene;
|
||||||
}
|
}
|
||||||
override void Draw() {
|
override void Draw() {
|
||||||
lobby_.Draw();
|
lobby_.Draw();
|
||||||
@ -67,4 +83,111 @@ class SelectScene : SceneInterface {
|
|||||||
sfSound* sound_;
|
sfSound* sound_;
|
||||||
|
|
||||||
SoundResources soundres_;
|
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
|
/// License: MIT
|
||||||
module sj.TitleScene;
|
module sj.TitleScene;
|
||||||
|
|
||||||
import std.math;
|
import std.conv,
|
||||||
|
std.math;
|
||||||
|
|
||||||
import gl4d;
|
import gl4d;
|
||||||
|
|
||||||
@ -10,7 +11,9 @@ import sj.KeyInput,
|
|||||||
sj.ProgramSet,
|
sj.ProgramSet,
|
||||||
sj.SelectScene,
|
sj.SelectScene,
|
||||||
sj.SceneInterface,
|
sj.SceneInterface,
|
||||||
sj.TitleTextProgram;
|
sj.TitleTextProgram,
|
||||||
|
sj.util.Animation,
|
||||||
|
sj.util.Easing;
|
||||||
|
|
||||||
///
|
///
|
||||||
class TitleScene : SceneInterface {
|
class TitleScene : SceneInterface {
|
||||||
@ -23,10 +26,35 @@ class TitleScene : SceneInterface {
|
|||||||
return m;
|
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) {
|
this(LobbyWorld lobby, ProgramSet program) {
|
||||||
lobby_ = lobby;
|
lobby_ = lobby;
|
||||||
title_ = program.Get!TitleTextProgram;
|
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() {
|
void Initialize() {
|
||||||
lobby_.view.pos = vec3(0, -0.15, -1);
|
anime_ = Animation(AnimationFrame);
|
||||||
lobby_.view.target = vec3(0, -0.15, 0);
|
|
||||||
lobby_.view.up = vec3(0, 1, 0);
|
|
||||||
|
|
||||||
lobby_.background.inner_color = vec4(0.9, 0.9, 0.9, 1);
|
bg_inner_ease_ = Easing!vec4(lobby_.background.inner_color, BgInnerColor);
|
||||||
lobby_.background.outer_color = vec4(-0.1, -0.1, -0.1, 1);
|
bg_outer_ease_ = Easing!vec4(lobby_.background.outer_color, BgOuterColor);
|
||||||
|
|
||||||
lobby_.light_pos = vec3(0, 9, -1);
|
cube_interval_ease_ = Easing!float(lobby_.cube_interval, CubeInterval);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
override SceneInterface Update(KeyInput input) {
|
override SceneInterface Update(KeyInput input) {
|
||||||
|
const ratio = anime_.Update();
|
||||||
|
|
||||||
lobby_.cube_matrix.rotation += vec3(PI/600, PI/600, PI/600);
|
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) {
|
if (input.down) {
|
||||||
select_scene_.Initialize();
|
select_scene_.Initialize();
|
||||||
return select_scene_;
|
return select_scene_;
|
||||||
@ -63,7 +89,8 @@ class TitleScene : SceneInterface {
|
|||||||
}
|
}
|
||||||
override void Draw() {
|
override void Draw() {
|
||||||
lobby_.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:
|
private:
|
||||||
@ -73,5 +100,9 @@ class TitleScene : SceneInterface {
|
|||||||
|
|
||||||
TitleTextProgram title_;
|
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