434 lines
12 KiB
C++
434 lines
12 KiB
C++
#include "math/float_types.hpp"
|
|
#include "math/transform.hpp"
|
|
|
|
#include "platform/graphics_primitive.hpp"
|
|
#include "platform/font.hpp"
|
|
#include "platform/emulator_detected.hpp"
|
|
|
|
#include "demo/lizard/main.hpp"
|
|
#include "demo/lizard/levels.hpp"
|
|
|
|
#include "texture/igh25_box_top_32.data.h"
|
|
|
|
#include "xm_player/playlist.hpp"
|
|
|
|
#include "assert.h"
|
|
|
|
extern float alpha_mul;
|
|
|
|
const int lizard_walking_frames[] = {
|
|
texture::offset::walking_frame0000,
|
|
texture::offset::walking_frame0001,
|
|
texture::offset::walking_frame0002,
|
|
texture::offset::walking_frame0003,
|
|
texture::offset::walking_frame0004,
|
|
texture::offset::walking_frame0005,
|
|
texture::offset::walking_frame0006,
|
|
};
|
|
const int lizard_walking_frames_count = (sizeof (lizard_walking_frames)) / (sizeof (lizard_walking_frames[0]));
|
|
|
|
const int lizard_turning_frames[] = {
|
|
texture::offset::turning_frame0000,
|
|
texture::offset::turning_frame0001,
|
|
texture::offset::turning_frame0002,
|
|
texture::offset::turning_frame0003,
|
|
texture::offset::turning_frame0004,
|
|
texture::offset::turning_frame0005,
|
|
texture::offset::turning_frame0006,
|
|
};
|
|
const int lizard_turning_frames_count = (sizeof (lizard_turning_frames)) / (sizeof (lizard_turning_frames[0]));
|
|
|
|
int last_drawn_frame;
|
|
|
|
namespace demo {
|
|
static inline void print_mat4x4(const mat4x4& mat)
|
|
{
|
|
for (int i = 0; i < 4; i++) {
|
|
printf("%f %f %f %f\n", mat[i][0], mat[i][1], mat[i][2], mat[i][3]);
|
|
}
|
|
}
|
|
|
|
world::platform * find_end_platform(world::level& level)
|
|
{
|
|
float end_x = 81;
|
|
float end_z = 212;
|
|
for (int i = 0; i < level.platforms_length; i++) {
|
|
world::platform * p = &level.platforms[i];
|
|
if (p->position.x == end_x && p->position.z == end_z) {
|
|
return p;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
mat4x4 lizard::init()
|
|
{
|
|
platform_touch_count = 0;
|
|
|
|
vx = -pi / 3.5;
|
|
vy = -pi / 8;
|
|
|
|
current_level = &demo::igh25_map1_level;
|
|
|
|
world::table_build(*current_level);
|
|
end_platform = find_end_platform(*current_level);
|
|
|
|
lizard_position = {2.5, 1, 2.5};
|
|
//lizard_position = {218.5, 0, 65.5};
|
|
//lizard_position = {81, 100, 212};
|
|
lizard_velocity = {0, 0, 0};
|
|
|
|
if (1 || !emulator_detected) {
|
|
emulator_detected_hud_frames = 60 * 30;
|
|
playlist::next();
|
|
} else {
|
|
emulator_detected_hud_frames = 0;
|
|
}
|
|
|
|
return view_trans;
|
|
}
|
|
|
|
static float sign(float n)
|
|
{
|
|
if (n > 0)
|
|
return 1;
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
void lizard::update()
|
|
{
|
|
lizard_rotation *= 0.8;
|
|
|
|
lizard_turning_frame += lizard_rotation * 5;
|
|
|
|
lizard_heading += lizard_rotation;
|
|
|
|
if (abs(lizard_velocity.x) > 0.10)
|
|
lizard_velocity.x = 0.10 * sign(lizard_velocity.x);
|
|
if (abs(lizard_velocity.y) > 0.20)
|
|
lizard_velocity.y = 0.20 * sign(lizard_velocity.y);
|
|
if (abs(lizard_velocity.z) > 0.10)
|
|
lizard_velocity.z = 0.10 * sign(lizard_velocity.z);
|
|
|
|
lizard_velocity.x *= 0.8;
|
|
lizard_velocity.y *= 0.99;
|
|
lizard_velocity.z *= 0.8;
|
|
|
|
vec2 frame_velocity = vec2(lizard_velocity.x, lizard_velocity.z);
|
|
lizard_walking_frame += magnitude(frame_velocity) * 5;
|
|
|
|
world::platform * p = lizard_collide();
|
|
collided = (p != nullptr);
|
|
if (!collided) {
|
|
lizard_velocity.y -= 0.01;
|
|
} else {
|
|
if (p->touched == false) {
|
|
platform_touch_count += 1;
|
|
last_platform1 = last_platform;
|
|
last_platform = p;
|
|
}
|
|
|
|
p->touched = true;
|
|
//lizard_position.y -= -lizard_velocity.y;
|
|
float pp = p->position.y + p->scale.y * 0.5;
|
|
//lizard_velocity.y *= 0.1;
|
|
lizard_position.y = pp + 0.5;
|
|
}
|
|
|
|
lizard_position.x += lizard_velocity.x;
|
|
lizard_position.y += lizard_velocity.y;
|
|
lizard_position.z += lizard_velocity.z;
|
|
|
|
view_trans
|
|
= translate(vec3(0, 0, 3))
|
|
* rotate_x(vy)
|
|
* rotate_y(vx)
|
|
* translate(-lizard_position);
|
|
}
|
|
|
|
void lizard::y()
|
|
{
|
|
lizard_velocity = {0, 0, 0};
|
|
if (last_platform1 == nullptr) {
|
|
lizard_position = {2.5, 1, 2.5};
|
|
} else {
|
|
lizard_position = last_platform1->position;
|
|
lizard_position.y += 0.5;
|
|
if (last_platform->touched == true)
|
|
platform_touch_count -= 1;
|
|
last_platform->touched = false;
|
|
last_platform = last_platform1;
|
|
}
|
|
}
|
|
|
|
void lizard::a()
|
|
{
|
|
//lizard_velocity.y -= 0.01;
|
|
if (collided) {
|
|
lizard_velocity.y = 30;
|
|
}
|
|
}
|
|
|
|
void lizard::start()
|
|
{
|
|
}
|
|
|
|
void lizard::ra()
|
|
{
|
|
vx += 0.01f;
|
|
}
|
|
|
|
void lizard::la()
|
|
{
|
|
vx -= 0.01f;
|
|
}
|
|
|
|
void lizard::ua()
|
|
{
|
|
vy += 0.01f;
|
|
}
|
|
|
|
void lizard::da()
|
|
{
|
|
vy -= 0.01f;
|
|
}
|
|
|
|
void lizard::x()
|
|
{
|
|
//lizard_rotation += pi * (1.0f / 160);
|
|
}
|
|
|
|
void lizard::b()
|
|
{
|
|
//lizard_rotation -= pi * (1.0f / 160);
|
|
}
|
|
|
|
void lizard::analog(float dl, float dr, float dx, float dy)
|
|
{
|
|
//float forward = (dr - dl) * -0.001f;
|
|
//alpha_mul += forward;
|
|
float forward = (dr - dl) * -0.1f;
|
|
//vx += forward * 0.5f;
|
|
|
|
lizard_velocity.x += -cos(lizard_heading) * forward;
|
|
lizard_velocity.z += sin(lizard_heading) * forward;
|
|
|
|
lizard_rotation += -dx * 0.03f;
|
|
|
|
//vy += dy * 0.03f;
|
|
//vx += dx * 0.03f;
|
|
}
|
|
|
|
world::platform * lizard::lizard_collide()
|
|
{
|
|
world::platform * p = world::table_lookup(lizard_position.x, lizard_position.z);
|
|
if (p == nullptr)
|
|
return nullptr;
|
|
|
|
float ym = lizard_position.y - 0.5;
|
|
float yp = lizard_position.y + 0.5;
|
|
|
|
float pm = p->position.y - p->scale.y * 0.5;
|
|
float pp = p->position.y + p->scale.y * 0.5;
|
|
|
|
if (ym < pp && yp > pm)
|
|
return p;
|
|
else
|
|
return nullptr;
|
|
}
|
|
|
|
const char * emulator_speech[] = {
|
|
"This counterfeit Dreamcast failed a",
|
|
"CORE rasterization test.",
|
|
"",
|
|
"Dreamcast emulator behavior is highly",
|
|
"divergent from genuine Sega Dreamcast",
|
|
"hardware.",
|
|
"",
|
|
"Some emulator authors deliberately",
|
|
"choose to forgo accuracy, and instead ",
|
|
"develop a distinct and unrelated",
|
|
"fantasy-platform."
|
|
};
|
|
const int emulator_speech_lines = (sizeof (emulator_speech)) / (sizeof (emulator_speech[0]));
|
|
|
|
void lizard::draw_hud(ta_parameter_writer& writer)
|
|
{
|
|
const int framebuffer_width_2 = framebuffer::framebuffer.px_width >> 1;
|
|
const int framebuffer_height_2 = framebuffer::framebuffer.px_height >> 1;
|
|
vec3 center_p = vec3(0, 5, 10);
|
|
|
|
font::ter_u12n.global(writer);
|
|
{
|
|
const int title_length = 12;
|
|
const int title_width_2 = (font::ter_u12n.hori_advance * title_length) >> 1;
|
|
const int x = framebuffer_width_2 - title_width_2;
|
|
center_p.x = x;
|
|
//font::ter_u12n.draw_string(writer, center_p, "demo: lizard", 0xffffffff);
|
|
}
|
|
//center_p.y += font::ter_u12n.height;
|
|
{
|
|
const int title_length = 46;
|
|
const int title_width_2 = (font::ter_u12n.hori_advance * title_length) >> 1;
|
|
const int x = framebuffer_width_2 - title_width_2;
|
|
center_p.x = x;
|
|
font::ter_u12n.draw_string(writer, center_p, "objective: find and touch the glowing platform", 0xffffffff);
|
|
}
|
|
|
|
vec3 status_p = vec3(10, framebuffer::framebuffer.px_height - 24, 10);
|
|
font::ter_u12n.draw_string(writer, status_p, "score:", 0xffffffff);
|
|
//font::ter_u12n.draw_float(writer, status_p, (float)last_drawn_frame, 0xffffffff, 10);
|
|
status_p.x += font::ter_u12n.hori_advance * 7;
|
|
font::ter_u12n.draw_int(writer, status_p, (float)platform_touch_count, 0xffffffff, 4);
|
|
|
|
const int height_2 = (font::ter_u32n.height * (emulator_speech_lines + 2)) >> 1;
|
|
const int y = framebuffer_height_2 - height_2;
|
|
vec3 center_e = vec3(8, y, 10);
|
|
if (emulator_detected_hud_frames < 60 * 30) {
|
|
font::ter_u32n.global(writer);;
|
|
for (int i = 0; i < emulator_speech_lines; i++) {
|
|
font::ter_u32n.draw_string(writer, center_e, emulator_speech[i], 0xffffffff);
|
|
font::ter_u32n.draw_string(writer, {center_e.x + 2, center_e.y + 0, center_e.z - 1}, emulator_speech[i], 0x00000000);
|
|
font::ter_u32n.draw_string(writer, {center_e.x - 2, center_e.y + 0, center_e.z - 1}, emulator_speech[i], 0x00000000);
|
|
font::ter_u32n.draw_string(writer, {center_e.x + 0, center_e.y + 2, center_e.z - 1}, emulator_speech[i], 0x00000000);
|
|
font::ter_u32n.draw_string(writer, {center_e.x + 0, center_e.y - 2, center_e.z - 1}, emulator_speech[i], 0x00000000);
|
|
center_e.y += font::ter_u32n.height;
|
|
}
|
|
center_e.y += font::ter_u32n.height;
|
|
int timeout = 30 - (emulator_detected_hud_frames / 60);
|
|
font::ter_u32n.draw_int(writer, center_e, timeout, 0xffffffff, 0);
|
|
emulator_detected_hud_frames += 1;
|
|
if (emulator_detected_hud_frames >= 60 * 30) {
|
|
playlist::next();
|
|
}
|
|
} else if (end_platform != nullptr && end_platform->touched) {
|
|
font::ter_u32n.global(writer);
|
|
const int title_length = 18;
|
|
const int title_width_2 = (font::ter_u12n.hori_advance * title_length) >> 1;
|
|
const int x = framebuffer_width_2 - title_width_2;
|
|
center_e.x = x;
|
|
|
|
const char * s = "objective complete";
|
|
font::ter_u32n.draw_string(writer, center_e, s, 0xffffffff);
|
|
font::ter_u32n.draw_string(writer, {center_e.x + 2, center_e.y + 0, center_e.z - 1}, s, 0x00000000);
|
|
font::ter_u32n.draw_string(writer, {center_e.x - 2, center_e.y + 0, center_e.z - 1}, s, 0x00000000);
|
|
font::ter_u32n.draw_string(writer, {center_e.x + 0, center_e.y + 2, center_e.z - 1}, s, 0x00000000);
|
|
font::ter_u32n.draw_string(writer, {center_e.x + 0, center_e.y - 2, center_e.z - 1}, s, 0x00000000);
|
|
}
|
|
}
|
|
|
|
void lizard::draw_platform(ta_parameter_writer& writer, const mat4x4& trans, const world::platform * p)
|
|
{
|
|
mat4x4 t
|
|
= trans
|
|
* translate(p->position)
|
|
* scale(p->scale);
|
|
|
|
float intensity_offset;
|
|
vec3 base_color;
|
|
if (p == end_platform) {
|
|
base_color = vec3(0.5, 1, 0.5);
|
|
intensity_offset = sin(end_platform_tick * 0.1f) * 0.4f + 0.5f;
|
|
end_platform_tick += 1;
|
|
} else if (p->touched) {
|
|
intensity_offset = 0.5;
|
|
base_color = vec3(1, 1, 1);
|
|
} else {
|
|
intensity_offset = 0;
|
|
base_color = vec3(1, 0.5, 0.5);
|
|
}
|
|
|
|
draw_textured_cube(writer,
|
|
t,
|
|
p->scale,
|
|
texture::cube_type_1,
|
|
base_color,
|
|
intensity_offset);
|
|
}
|
|
|
|
void lizard::draw_lizard(ta_parameter_writer& writer, const mat4x4& trans)
|
|
{
|
|
mat4x4 t
|
|
= trans
|
|
* translate(lizard_position)
|
|
* rotate_y(lizard_heading);
|
|
|
|
/*
|
|
draw_icosphere(writer,
|
|
t,
|
|
vec3(1, 0.5, 0));
|
|
*/
|
|
if (abs(lizard_rotation) > 0.01) {
|
|
int frame = ((int)lizard_turning_frame) % lizard_turning_frames_count;
|
|
if (frame < 0)
|
|
frame = lizard_turning_frames_count + frame;
|
|
last_drawn_frame = frame;
|
|
|
|
draw_textured_voxel(writer,
|
|
t,
|
|
lizard_turning_frames[frame]);
|
|
} else {
|
|
int frame = ((int)lizard_walking_frame) % lizard_walking_frames_count;
|
|
if (frame < 0)
|
|
frame = lizard_walking_frames_count + frame;
|
|
last_drawn_frame = frame;
|
|
|
|
draw_textured_voxel(writer,
|
|
t,
|
|
lizard_walking_frames[frame]);
|
|
}
|
|
}
|
|
|
|
void lizard::draw_cover(ta_parameter_writer& writer, const mat4x4& trans)
|
|
{
|
|
mat4x4 t
|
|
= trans
|
|
* translate(lizard_position)
|
|
* scale(1000.f);
|
|
|
|
int texture_offset = playlist::playlist[playlist::state.playlist_ix].cover_ix;
|
|
if (cover_ix_transition >= 1.0) {
|
|
if (texture_offset != last_cover_texture_offset) {
|
|
cover_ix_transition = 0.0;
|
|
}
|
|
} else {
|
|
cover_ix_transition += 0.001f;
|
|
if (cover_ix_transition >= 1.0) {
|
|
last_cover_texture_offset = texture_offset;
|
|
}
|
|
}
|
|
draw_textured_cube2(writer, t, last_cover_texture_offset, texture_offset, cover_ix_transition);
|
|
}
|
|
|
|
void lizard::draw(ta_parameter_writer& writer, const mat4x4& _)
|
|
{
|
|
// punch through
|
|
const mat4x4& trans = view_trans;
|
|
|
|
draw_hud(writer);
|
|
draw_lizard(writer, trans);
|
|
|
|
writer.append<ta_global_parameter::end_of_list>() =
|
|
ta_global_parameter::end_of_list(para_control::para_type::end_of_list);
|
|
|
|
// translucent
|
|
|
|
draw_cover(writer, trans);
|
|
|
|
writer.append<ta_global_parameter::end_of_list>() =
|
|
ta_global_parameter::end_of_list(para_control::para_type::end_of_list);
|
|
|
|
// opaque
|
|
|
|
//draw_axis(writer, trans * translate(lizard_position));
|
|
|
|
for (int i = 0; i < current_level->platforms_length; i++) {
|
|
draw_platform(writer, trans, ¤t_level->platforms[i]);
|
|
}
|
|
|
|
writer.append<ta_global_parameter::end_of_list>() =
|
|
ta_global_parameter::end_of_list(para_control::para_type::end_of_list);
|
|
}
|
|
}
|