[RELEASE] u22-v03

This version is submitted to U22 breau.
This commit is contained in:
2020-09-14 00:00:00 +00:00
parent 360595de37
commit 84c3a02b9a
357 changed files with 29223 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
add_library(loscene
context.c
game.c
scene.c
title.c
)
target_link_libraries(loscene
msgpackc
glyphas
jukebox
math
memory
mpkutil
locommon
loentity
loground
loplayer
loresource
loshader
loworld
)

127
core/loscene/context.c Normal file
View File

@@ -0,0 +1,127 @@
#include "./context.h"
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "util/glyphas/context.h"
#include "util/jukebox/mixer.h"
#include "util/math/algorithm.h"
#include "util/math/vector.h"
#include "util/memory/memory.h"
#include "core/locommon/input.h"
#include "core/locommon/ticker.h"
#include "core/loresource/set.h"
#include "core/loshader/set.h"
#include "./game.h"
#include "./param.h"
#include "./scene.h"
#include "./title.h"
struct loscene_context_t {
glyphas_context_t glyphas;
jukebox_mixer_t* mixer;
locommon_ticker_t ticker;
loresource_set_t resources;
loshader_set_t shaders;
loscene_t* scene;
loscene_param_t param;
};
#define loscene_context_mixer_reserve_ 256
static const jukebox_format_t loscene_context_mixer_format_ = {
.sample_rate = 48000,
.channels = 2,
};
static loscene_t* loscene_context_create_start_scene_(loscene_context_t* ctx) {
assert(ctx != NULL);
/* Unless the context is deleted, scenes can hold a pointer to ctx->param. */
if (ctx->param.skip_title) {
return loscene_game_new(
&ctx->param, &ctx->resources, &ctx->shaders, &ctx->ticker, true);
}
return loscene_title_new(
&ctx->param, &ctx->resources, &ctx->shaders, &ctx->ticker);
}
loscene_context_t* loscene_context_new(const loscene_param_t* param) {
assert(param != NULL);
loscene_context_t* ctx = memory_new(sizeof(*ctx));
*ctx = (typeof(*ctx)) {
.param = *param,
};
glyphas_context_initialize(&ctx->glyphas);
ctx->mixer = jukebox_mixer_new(
&loscene_context_mixer_format_, loscene_context_mixer_reserve_);
locommon_ticker_initialize(&ctx->ticker, 0);
loresource_set_initialize(
&ctx->resources,
ctx->mixer,
&loscene_context_mixer_format_,
LORESOURCE_LANGUAGE_JP);
loshader_set_initialize(
&ctx->shaders,
param->width,
param->height,
&param->dpi,
param->max_msaa);
ctx->scene = loscene_context_create_start_scene_(ctx);
return ctx;
}
void loscene_context_delete(loscene_context_t* ctx) {
if (ctx == NULL) return;
/* Firstly delete the mixer working in other thread. */
jukebox_mixer_delete(ctx->mixer);
loscene_delete(ctx->scene);
loshader_set_deinitialize(&ctx->shaders);
loresource_set_deinitialize(&ctx->resources);
locommon_ticker_deinitialize(&ctx->ticker);
glyphas_context_deinitialize(&ctx->glyphas);
memory_delete(ctx);
}
bool loscene_context_update(
loscene_context_t* ctx, const locommon_input_t* input, uint64_t uptime) {
assert(ctx != NULL);
assert(input != NULL);
locommon_ticker_tick(&ctx->ticker, uptime);
loscene_t* s = loscene_update(ctx->scene, input);
if (s != ctx->scene) {
loscene_delete(ctx->scene);
ctx->scene = s;
}
return ctx->scene != NULL;
}
void loscene_context_draw(loscene_context_t* ctx) {
assert(ctx != NULL);
loscene_draw(ctx->scene);
}

35
core/loscene/context.h Normal file
View File

@@ -0,0 +1,35 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include "util/math/vector.h"
#include "core/locommon/input.h"
#include "./param.h"
struct loscene_context_t;
typedef struct loscene_context_t loscene_context_t;
loscene_context_t* /* OWNERSHIP */
loscene_context_new(
const loscene_param_t* param
);
void
loscene_context_delete(
loscene_context_t* ctx /* OWNERSHIP */
);
bool
loscene_context_update(
loscene_context_t* ctx,
const locommon_input_t* input,
uint64_t uptime
);
void
loscene_context_draw(
loscene_context_t* ctx
);

398
core/loscene/game.c Normal file
View File

@@ -0,0 +1,398 @@
#include "./game.h"
#include <assert.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <GL/glew.h>
#include <msgpack.h>
#include <msgpack/fbuffer.h>
#include "util/math/matrix.h"
#include "util/math/vector.h"
#include "util/memory/memory.h"
#include "util/mpkutil/file.h"
#include "util/mpkutil/get.h"
#include "util/mpkutil/pack.h"
#include "core/lobullet/pool.h"
#include "core/locharacter/pool.h"
#include "core/locommon/counter.h"
#include "core/locommon/ticker.h"
#include "core/loentity/store.h"
#include "core/loground/pool.h"
#include "core/loplayer/camera.h"
#include "core/loplayer/player.h"
#include "core/loresource/set.h"
#include "core/loshader/set.h"
#include "core/loworld/environment.h"
#include "core/loworld/generator.h"
#include "core/loworld/poolset.h"
#include "core/loworld/store.h"
#include "core/loworld/template.h"
#include "core/loworld/view.h"
#include "./param.h"
#include "./scene.h"
#include "./title.h"
typedef struct {
loscene_t header;
const loscene_param_t* param;
const locommon_ticker_t* app_ticker;
loresource_set_t* res;
loshader_set_t* shaders;
uint64_t app_begin_time;
uint64_t begin_time;
locommon_counter_t idgen;
locommon_ticker_t ticker;
loentity_store_t* entities;
loplayer_t player;
loworld_poolset_t pools;
loworld_generator_t* generator;
loworld_store_t* world;
loworld_view_t* view;
loworld_environment_t environment;
/* temporary parameters */
bool updated;
mat4_t proj;
} loscene_game_t;
#define LOSCENE_GAME_MAX_DELTA_TIME 500
#define LOSCENE_GAME_SCALE 4.0f
#define LOSCENE_GAME_ENTITY_STORE_RESERVE 256
#define LOSCENE_GAME_WORLD_STORE_CHUNK_RESERVE 64
#define LOSCENE_GAME_BULLETS_PER_CHUNK 64
#define LOSCENE_GAME_DATA_BASEPATH "./data/"
#define LOSCENE_GAME_DATA_FILE_PATH \
(LOSCENE_GAME_DATA_BASEPATH"game.msgpack")
#define LOSCENE_GAME_WORLD_STORE_BASEPATH \
(LOSCENE_GAME_DATA_BASEPATH"world/")
static void loscene_game_build_projection_matrix_(loscene_game_t* s) {
assert(s != NULL);
static const float chunk_inch = 16;
static const float max_scale = 1/.5f;
float yscale = s->shaders->dpi.y*chunk_inch/s->shaders->resolution.y*2;
float xscale = s->shaders->dpi.x*chunk_inch/s->shaders->resolution.x*2;
if (xscale > max_scale) {
yscale *= max_scale/xscale;
xscale = max_scale;
}
s->proj = mat4_scale(xscale, yscale, 1);
}
static void loscene_game_convert_viewport_pos_to_chunk_pos_(
loscene_game_t* s, locommon_position_t* pos, const vec2_t* vpos) {
assert(s != NULL);
assert(locommon_position_valid(pos));
mat4_t m, inv;
mat4_mul(&m, &s->proj, &s->player.camera.matrix);
mat4_inv(&inv, &m);
vec4_t disp4;
const vec4_t vpos4 = vec4(vpos->x, vpos->y, 0, 1);
mat4_mul_vec4(&disp4, &inv, &vpos4);
vec2_addeq(&pos->fract, &disp4.xy);
locommon_position_reduce(pos);
}
static bool loscene_game_load_(loscene_game_t* scene) {
assert(scene != NULL);
/* ! Please note that world and view objects may be invalid now. ! */
bool ret = false;
msgpack_unpacker unpacker;
if (!msgpack_unpacker_init(&unpacker, 1024)) return false;
msgpack_unpacked unpacked;
msgpack_unpacked_init(&unpacked);
FILE* fp = fopen(LOSCENE_GAME_DATA_FILE_PATH, "rb");
if (fp == NULL) goto FINALIZE;
const bool loaded =
mpkutil_file_unpack_with_unpacker(&unpacked, fp, &unpacker);
fclose(fp);
if (!loaded) goto FINALIZE;
const msgpack_object_map* root = mpkutil_get_map(&unpacked.data);
# define item_(v) mpkutil_get_map_item_by_str(root, v)
if (!loplayer_unpack(&scene->player, item_("player")) ||
!loworld_generator_unpack(scene->generator, item_("generator")) ||
!locommon_ticker_unpack(&scene->ticker, item_("ticker")) ||
!locommon_counter_unpack(&scene->idgen, item_("idgen"))) {
goto FINALIZE;
}
# undef item_
ret = true;
FINALIZE:
msgpack_unpacked_destroy(&unpacked);
msgpack_unpacker_destroy(&unpacker);
scene->begin_time = scene->ticker.time;
return ret;
}
static bool loscene_game_save_(loscene_game_t* scene) {
assert(scene != NULL);
bool ret = true;
loworld_view_flush_store(scene->view);
if (loworld_store_is_error_happened(scene->world)) ret = false;
FILE* fp = fopen(LOSCENE_GAME_DATA_FILE_PATH, "wb");
if (fp == NULL) return false;
msgpack_packer pk;
msgpack_packer_init(&pk, fp, msgpack_fbuffer_write);
msgpack_pack_map(&pk, 4);
mpkutil_pack_str(&pk, "player");
loplayer_pack(&scene->player, &pk);
mpkutil_pack_str(&pk, "generator");
loworld_generator_pack(scene->generator, &pk);
mpkutil_pack_str(&pk, "ticker");
locommon_ticker_pack(&scene->ticker, &pk);
mpkutil_pack_str(&pk, "idgen");
locommon_counter_pack(&scene->idgen, &pk);
fclose(fp);
return ret;
}
static void loscene_game_delete_(loscene_t* scene) {
if (scene == NULL) return;
loscene_game_t* s = (typeof(s)) scene;
if (!loscene_game_save_(s)) {
fprintf(stderr, "failed to save game data\n");
}
loworld_environment_deinitialize(&s->environment);
loworld_view_delete(s->view);
loworld_store_delete(s->world);
loworld_generator_delete(s->generator);
loentity_store_clear(s->entities);
locharacter_pool_delete(s->pools.character);
loplayer_deinitialize(&s->player);
lobullet_pool_delete(s->pools.bullet);
loground_pool_delete(s->pools.ground);
loentity_store_delete(s->entities);
locommon_ticker_deinitialize(&s->ticker);
locommon_counter_deinitialize(&s->idgen);
memory_delete(scene);
}
static loscene_t* loscene_game_update_(
loscene_t* scene, const locommon_input_t* input) {
assert(scene != NULL);
assert(input != NULL);
loscene_game_t* s = (typeof(s)) scene;
s->updated = false;
const uint64_t t = s->app_ticker->time - s->app_begin_time + s->begin_time;
locommon_ticker_tick(&s->ticker, t);
if (s->ticker.delta > LOSCENE_GAME_MAX_DELTA_TIME) {
fprintf(stderr, "1 tick took too long (%"PRId64" ms)\n", s->ticker.delta);
return scene;
}
locommon_position_t cursor = s->player.camera.pos;
loscene_game_convert_viewport_pos_to_chunk_pos_(s, &cursor, &input->cursor);
loplayer_update(&s->player, input, &cursor);
if (loplayer_menu_is_exit_requested(s->player.menu)) {
return loscene_title_new(s->param, s->res, s->shaders, s->app_ticker);
}
loworld_view_look(s->view, &s->player.camera.pos);
loworld_view_update(s->view);
loworld_environment_update(&s->environment);
s->updated = true;
return scene;
}
static void loscene_game_draw_(loscene_t* scene) {
assert(scene != NULL);
loscene_game_t* s = (typeof(s)) scene;
if (!s->updated) return;
const loshader_uniblock_param_t p = {
.proj = s->proj,
.cam = s->player.camera.matrix,
.pos = s->player.camera.pos,
.time = s->ticker.time%60000/1000.0f,
};
loshader_uniblock_update_param(s->shaders->uniblock, &p);
loshader_set_clear_all(s->shaders);
loworld_environment_draw(&s->environment);
loworld_view_draw(s->view);
loplayer_draw(&s->player);
loshader_set_draw_all(s->shaders);
}
static void loscene_game_execute_tests_(
const loscene_game_t* scene, const loscene_param_t* param) {
assert(scene != NULL);
assert(param != NULL);
if (param->test.loworld_poolset_packing) {
loworld_poolset_test_packing(&scene->pools);
}
if (param->test.loplayer_packing) {
loplayer_test_packing(&scene->player);
}
}
loscene_t* loscene_game_new(
const loscene_param_t* param,
loresource_set_t* res,
loshader_set_t* shaders,
const locommon_ticker_t* ticker,
bool load) {
assert(param != NULL);
assert(shaders != NULL);
assert(res != NULL);
assert(ticker != NULL);
loshader_set_drop_cache(shaders);
loscene_game_t* scene = memory_new(sizeof(*scene));
*scene = (typeof(*scene)) {
.header = {
.vtable = {
.delete = loscene_game_delete_,
.update = loscene_game_update_,
.draw = loscene_game_draw_,
},
},
.param = param,
.app_ticker = ticker,
.res = res,
.shaders = shaders,
.app_begin_time = ticker->time,
};
loscene_game_build_projection_matrix_(scene);
locommon_counter_initialize(&scene->idgen, 0);
locommon_ticker_initialize(&scene->ticker, 0);
scene->entities = loentity_store_new(
LOSCENE_GAME_ENTITY_STORE_RESERVE);
scene->pools.ground = loground_pool_new(
scene->shaders->drawer.ground,
&scene->idgen,
LOSCENE_GAME_WORLD_STORE_CHUNK_RESERVE*
LOWORLD_TEMPLATE_MAX_CHARACTERS_PER_CHUNK);
scene->pools.bullet = lobullet_pool_new(
res,
scene->shaders->drawer.bullet,
&scene->idgen,
&scene->ticker,
scene->entities,
LOSCENE_GAME_WORLD_STORE_CHUNK_RESERVE*
LOSCENE_GAME_BULLETS_PER_CHUNK);
loplayer_initialize(
&scene->player,
locommon_counter_count(&scene->idgen), /* = Absolutely 0 */
res,
scene->shaders,
&scene->ticker,
scene->pools.bullet,
scene->entities,
&scene->proj);
scene->player.camera.brightness = param->brightness/1000.f;
scene->pools.character = locharacter_pool_new(
res,
scene->shaders->drawer.character,
&scene->idgen,
&scene->ticker,
scene->pools.bullet,
scene->entities,
&scene->player,
LOSCENE_GAME_WORLD_STORE_CHUNK_RESERVE*
LOWORLD_TEMPLATE_MAX_CHARACTERS_PER_CHUNK);
scene->generator = loworld_generator_new(
&scene->pools,
scene->app_ticker->time*98641 /* = prime number */);
if (load) {
if (!loscene_game_load_(scene)) {
fprintf(stderr, "failed to load game data\n");
}
}
scene->world = loworld_store_new(
&scene->pools,
scene->generator,
LOSCENE_GAME_WORLD_STORE_CHUNK_RESERVE,
LOSCENE_GAME_WORLD_STORE_BASEPATH,
strlen(LOSCENE_GAME_WORLD_STORE_BASEPATH));
scene->view = loworld_view_new(
scene->world,
scene->entities,
&scene->player.camera.pos);
loworld_environment_initialize(
&scene->environment,
res,
scene->shaders,
&scene->ticker,
scene->view,
&scene->player,
&param->environment);
loscene_game_execute_tests_(scene, param);
return &scene->header;
}

17
core/loscene/game.h Normal file
View File

@@ -0,0 +1,17 @@
#pragma once
#include "core/locommon/ticker.h"
#include "core/loresource/set.h"
#include "core/loshader/set.h"
#include "./param.h"
#include "./scene.h"
loscene_t* /* OWNERSHIP */
loscene_game_new(
const loscene_param_t* param,
loresource_set_t* res,
loshader_set_t* shaders,
const locommon_ticker_t* ticker,
bool load
);

26
core/loscene/param.h Normal file
View File

@@ -0,0 +1,26 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include "util/math/vector.h"
#include "core/loworld/environment.h"
typedef struct {
int32_t width;
int32_t height;
vec2_t dpi;
int32_t max_msaa;
int32_t brightness; /* darkest |0 <- 1000 -> 2000| brightest */
loworld_environment_config_t environment;
bool skip_title;
struct {
bool loworld_poolset_packing;
bool loplayer_packing;
} test;
} loscene_param_t;

28
core/loscene/scene.c Normal file
View File

@@ -0,0 +1,28 @@
#include "./scene.h"
#include <assert.h>
#include <stddef.h>
#include "core/locommon/input.h"
void loscene_delete(loscene_t* scene) {
if (scene == NULL) return;
assert(scene->vtable.delete != NULL);
scene->vtable.delete(scene);
}
loscene_t* loscene_update(loscene_t* scene, const locommon_input_t* input) {
assert(scene != NULL);
assert(input != NULL);
assert(scene->vtable.update != NULL);
return scene->vtable.update(scene, input);
}
void loscene_draw(loscene_t* scene) {
assert(scene != NULL);
assert(scene->vtable.draw != NULL);
scene->vtable.draw(scene);
}

43
core/loscene/scene.h Normal file
View File

@@ -0,0 +1,43 @@
#pragma once
#include "core/locommon/input.h"
struct loscene_t;
typedef struct loscene_t loscene_t;
typedef struct {
void
(*delete)(
loscene_t* scene
);
loscene_t*
(*update)(
loscene_t* scene,
const locommon_input_t* input
);
void
(*draw)(
loscene_t* scene
);
} loscene_vtable_t;
struct loscene_t {
loscene_vtable_t vtable;
};
void
loscene_delete(
loscene_t* scene
);
loscene_t*
loscene_update(
loscene_t* scene,
const locommon_input_t* input
);
void
loscene_draw(
loscene_t* scene
);

333
core/loscene/title.c Normal file
View File

@@ -0,0 +1,333 @@
#include "./title.h"
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
#include <GL/glew.h>
#include <msgpack.h>
#include <msgpack/fbuffer.h>
#include "util/chaos/xorshift.h"
#include "util/glyphas/block.h"
#include "util/glyphas/cache.h"
#include "util/jukebox/amp.h"
#include "util/jukebox/decoder.h"
#include "util/math/matrix.h"
#include "util/math/rational.h"
#include "util/math/vector.h"
#include "util/memory/memory.h"
#include "core/locommon/input.h"
#include "core/locommon/position.h"
#include "core/loresource/music.h"
#include "core/loresource/set.h"
#include "core/loresource/text.h"
#include "core/loshader/backwall.h"
#include "core/loshader/fog.h"
#include "core/loshader/menu_text.h"
#include "core/loshader/set.h"
#include "./game.h"
#include "./param.h"
#include "./scene.h"
typedef enum {
LOSCENE_TITLE_STATE_EXPECT_BUTTON_RELEASE,
LOSCENE_TITLE_STATE_EXPECT_BUTTON_PRESS,
LOSCENE_TITLE_STATE_FADING_TO_GAME,
LOSCENE_TITLE_STATE_FADING_TO_EXIT,
} loscene_title_state_t;
typedef struct {
loscene_t header;
const loscene_param_t* param;
loresource_set_t* res;
loshader_set_t* shaders;
const locommon_ticker_t* ticker;
struct {
vec2_t fontsz_large;
vec2_t fontsz_small;
vec2_t fontpx_large;
vec2_t fontpx_small;
} geo;
struct {
glyphas_cache_t* large;
glyphas_cache_t* small;
} font;
struct {
glyphas_block_t* title;
glyphas_block_t* author;
glyphas_block_t* buttons;
} text;
loresource_music_player_t* music;
loscene_title_state_t state;
uint64_t since;
float fade;
} loscene_title_t;
static void loscene_title_calculate_geometry_(loscene_title_t* s) {
assert(s != NULL);
const vec2_t* dpi = &s->shaders->dpi;
const vec2_t* reso = &s->shaders->resolution;
s->geo.fontpx_large = *dpi;
vec2_muleq(&s->geo.fontpx_large, .8f);
s->geo.fontpx_small = *dpi;
vec2_muleq(&s->geo.fontpx_small, .14f);
# define px_to_disp_(v) vec2((v).x/reso->x*2, (v).y/reso->y*2)
s->geo.fontsz_large = px_to_disp_(s->geo.fontpx_large);
s->geo.fontsz_small = px_to_disp_(s->geo.fontpx_small);
# undef px_to_disp_
}
static void loscene_title_create_text_block_(loscene_title_t* s) {
assert(s != NULL);
const char* title = loresource_text_get(s->res->lang, "app_name");
const char* author = loresource_text_get(s->res->lang, "title_authors");
const char* buttons = loresource_text_get(s->res->lang, "title_buttons");
static const vec4_t color = vec4(1, 1, 1, 1);
s->text = (typeof(s->text)) {
.title = glyphas_block_new(
GLYPHAS_ALIGNER_DIRECTION_HORIZONTAL,
-s->geo.fontpx_large.y,
INT32_MAX,
16),
.author = glyphas_block_new(
GLYPHAS_ALIGNER_DIRECTION_HORIZONTAL,
-s->geo.fontpx_small.y,
INT32_MAX,
256),
.buttons = glyphas_block_new(
GLYPHAS_ALIGNER_DIRECTION_HORIZONTAL,
-s->geo.fontpx_small.y,
INT32_MAX,
16),
};
glyphas_block_add_characters(
s->text.title, s->font.large, &color, title, strlen(title));
glyphas_block_add_characters(
s->text.author, s->font.small, &color, author, strlen(author));
glyphas_block_add_characters(
s->text.buttons, s->font.small, &color, buttons, strlen(buttons));
const vec2_t scale = vec2(
2/s->shaders->resolution.x, 2/s->shaders->resolution.y);
glyphas_block_scale(s->text.title, &scale);
glyphas_block_scale(s->text.author, &scale);
glyphas_block_scale(s->text.buttons, &scale);
glyphas_block_set_origin(s->text.title, &vec2(.5f, -.5f));
glyphas_block_set_origin(s->text.author, &vec2(.5f, 0));
glyphas_block_set_origin(s->text.buttons, &vec2(.5f, -1.f));
glyphas_block_translate(
s->text.author, &vec2(0, -s->geo.fontsz_large.y*.7f));
glyphas_block_translate(
s->text.buttons, &vec2(0, -.9f));
}
static void loscene_title_update_uniblock_(loscene_title_t* s) {
assert(s != NULL);
static const uint64_t camspeed = 5000;
const uint64_t chunk = s->ticker->time/camspeed;
const float fract = s->ticker->time%camspeed*1.f/camspeed;
const loshader_uniblock_param_t p = {
.proj = mat4_identity(),
.cam = mat4_identity(),
.pos = locommon_position(chunk, 0, vec2(fract, 0)),
.time = s->ticker->time%60000/1000.0f,
};
loshader_uniblock_update_param(s->shaders->uniblock, &p);
}
static void loscene_title_delete_(loscene_t* scene) {
if (scene == NULL) return;
loscene_title_t* s = (typeof(s)) scene;
glyphas_block_delete(s->text.title);
glyphas_block_delete(s->text.author);
glyphas_block_delete(s->text.buttons);
glyphas_cache_delete(s->font.large);
glyphas_cache_delete(s->font.small);
memory_delete(s);
}
static loscene_t* loscene_title_update_(
loscene_t* scene, const locommon_input_t* input) {
assert(scene != NULL);
assert(input != NULL);
static const uint64_t fadedur = 1500;
loscene_title_t* s = (typeof(s)) scene;
if (s->music == NULL) {
s->music = &s->res->music.title;
jukebox_decoder_play(s->music->decoder, &rational(0, 1), true);
jukebox_amp_change_volume(&s->music->amp, 1, &rational(1, 1));
}
switch (s->state) {
case LOSCENE_TITLE_STATE_EXPECT_BUTTON_RELEASE:
s->fade = 1 - (s->ticker->time - s->since)*1.f / fadedur;
if (s->fade < 0) s->fade = 0;
if (input->buttons == 0 && s->fade <= 0) {
s->state = LOSCENE_TITLE_STATE_EXPECT_BUTTON_PRESS;
}
break;
case LOSCENE_TITLE_STATE_EXPECT_BUTTON_PRESS:
if (input->buttons & LOCOMMON_INPUT_BUTTON_ATTACK) {
jukebox_amp_change_volume(&s->music->amp, 0, &rational(fadedur, 1000));
jukebox_decoder_stop_after(s->music->decoder, &rational(fadedur, 1000));
s->state = LOSCENE_TITLE_STATE_FADING_TO_GAME;
s->since = s->ticker->time;
} else if (input->buttons & LOCOMMON_INPUT_BUTTON_MENU) {
jukebox_amp_change_volume(&s->music->amp, 0, &rational(fadedur, 1000));
jukebox_decoder_stop_after(s->music->decoder, &rational(fadedur, 1000));
s->state = LOSCENE_TITLE_STATE_FADING_TO_EXIT;
s->since = s->ticker->time;
}
break;
case LOSCENE_TITLE_STATE_FADING_TO_GAME:
if (s->since + fadedur < s->ticker->time) {
return loscene_game_new(
s->param, s->res, s->shaders, s->ticker, true /* = load data */);
} else {
s->fade = (s->ticker->time - s->since)*1.f/fadedur;
}
break;
case LOSCENE_TITLE_STATE_FADING_TO_EXIT:
if (s->since + fadedur < s->ticker->time) {
return NULL;
} else {
s->fade = (s->ticker->time - s->since)*1.f/fadedur;
}
break;
}
return scene;
}
static void loscene_title_draw_(loscene_t* scene) {
assert(scene != NULL);
loscene_title_t* s = (typeof(s)) scene;
loscene_title_update_uniblock_(s);
loshader_set_clear_all(s->shaders);
loshader_backwall_drawer_set_param(
s->shaders->drawer.backwall,
&(loshader_backwall_drawer_param_t) {
.type = LOSHADER_BACKWALL_TYPE_JAIL,
.transition = 1,
});
loshader_fog_drawer_set_param(
s->shaders->drawer.fog,
&(loshader_fog_drawer_param_t) {
.type = LOSHADER_FOG_TYPE_WHITE_CLOUD,
.transition = 1,
});
loshader_pixsort_drawer_set_intensity(s->shaders->drawer.pixsort, 0);
loshader_posteffect_drawer_set_param(
s->shaders->drawer.posteffect,
&(loshader_posteffect_drawer_param_t) {
.whole_blur = 1,
.radial_displacement = .05f,
.amnesia_displacement = .1f,
.radial_fade = .5f + s->fade*.3f,
.brightness = s->param->brightness/1000.f,
});
s->shaders->drawer.menu_text.alpha = 1;
loshader_menu_text_drawer_add_block(
&s->shaders->drawer.menu_text, s->text.title);
loshader_menu_text_drawer_add_block(
&s->shaders->drawer.menu_text, s->text.author);
loshader_menu_text_drawer_add_block(
&s->shaders->drawer.menu_text, s->text.buttons);
loshader_cinescope_drawer_set_param(
s->shaders->drawer.cinescope,
&(loshader_cinescope_drawer_param_t) {0});
loshader_set_draw_all(s->shaders);
}
loscene_t* loscene_title_new(
const loscene_param_t* param,
loresource_set_t* res,
loshader_set_t* shaders,
const locommon_ticker_t* ticker) {
assert(param != NULL);
assert(res != NULL);
assert(shaders != NULL);
assert(ticker != NULL);
loshader_set_drop_cache(shaders);
loscene_title_t* scene = memory_new(sizeof(*scene));
*scene = (typeof(*scene)) {
.header = {
.vtable = {
.delete = loscene_title_delete_,
.update = loscene_title_update_,
.draw = loscene_title_draw_,
},
},
.param = param,
.res = res,
.shaders = shaders,
.ticker = ticker,
.state = LOSCENE_TITLE_STATE_EXPECT_BUTTON_RELEASE,
.since = ticker->time,
};
loscene_title_calculate_geometry_(scene);
scene->font = (typeof(scene->font)) {
.large = glyphas_cache_new(
shaders->tex.menu_text,
&res->font.sans,
scene->geo.fontpx_large.x,
scene->geo.fontpx_large.y),
.small = glyphas_cache_new(
shaders->tex.menu_text,
&res->font.sans,
scene->geo.fontpx_small.x,
scene->geo.fontpx_small.y),
};
loscene_title_create_text_block_(scene);
return &scene->header;
}

16
core/loscene/title.h Normal file
View File

@@ -0,0 +1,16 @@
#pragma once
#include "core/locommon/ticker.h"
#include "core/loresource/set.h"
#include "core/loshader/set.h"
#include "./param.h"
#include "./scene.h"
loscene_t* /* OWNERSHIP */
loscene_title_new(
const loscene_param_t* param,
loresource_set_t* res,
loshader_set_t* shaders,
const locommon_ticker_t* ticker
);