Day 42 complete

Found and fixed bugs with gencpp when generating the vector math stuff.
This commit is contained in:
Edward R. Gonzalez 2023-10-22 21:52:41 -04:00
parent fa28d401ef
commit 4ab64e2c17
30 changed files with 1694 additions and 886 deletions

11
.vscode/launch.json vendored
View File

@ -16,7 +16,16 @@
{
"type":"cppvsdbg",
"request": "launch",
"name" : "Debug handmade engine (post_build) gen msvc",
"name" : "Debug handmade engine gen msvc",
"program": "${workspaceFolder}/build/engine_gen.exe",
"args": [],
"cwd": "${workspaceFolder}/project/engine/gen",
"visualizerFile": "${workspaceFolder}/scripts/gencpp.natvis"
},
{
"type":"cppvsdbg",
"request": "launch",
"name" : "Debug handmade engine (post-build) gen msvc",
"program": "${workspaceFolder}/build/engine_postbuild_gen.exe",
"args": [],
"cwd": "${workspaceFolder}/build",

View File

@ -1,13 +0,0 @@
# Day 25
Him doing replay save states at the platform layer is causing issues for me...
I'm going to most likely end up doing two categories of save states, one for engine level and one for platform level.
The engine level can just store it in the memory struct, and the game memory can just stay where it is.
I want to use the same "save state" slots for both engine and game since there is no need different memory buckets for that. They will at worst case be ofcourse the size of engine's memory block.
So if there is 4, we are looking at 5x the actual memory size. This is fine for now since the engine block is 2 gigs.
Snapshots of of memory are are handled using take and load snapshot functions. They can be used separate from the replay looping functionality.
Replay looping however is dependent on snapshots so if a replay is save/loaded it will use the same snapshot slot of memory to do that state management.
Feels great to be past the platform layer bulk!!!

77
docs/Day 026-40.md Normal file
View File

@ -0,0 +1,77 @@
# Day 27
Definitely feels refreshing to not touch win32.
# Day 30
Tile map stuff is looking alright. Doing my best to not clean-up the code as Casey pleads in the vods.
I would have perferred if he didn't just do one tilemap at a time and instead I would have had the current tile map and surrounding loaded at the same time (He might do this in the future). Since were aren't constrained memory wise like the old machines, we could have those loaded as well and it would make the management of the tilemaps easier (possibly...).
Looking foward to when he introduces a proper vector space for the positioning.
# Day 31
This was really a prepatory day for day 32 so I did some extra stuff...
I setup codebase so now that the build translation unit files have every single file included for that unit explicitly.
I do not (or should not) have nested includes other than from `grime.hpp`
## Side Tracking
I did some refactoring and added `INTELLISENSE_DIRECTIVES` preprocessor conditional blocks throughout the codebase.
I wanted to see if I could get all IDE/Editors I've ever used to support the project without bad errors from parsing failures.
Unfortunately getting Visual Studio and Rider's intellisense to behave was not possible.
This is mostly from how the code is structured across files currently.
I'll have to re-sturcture it down the line to make it more IDE friendly.
10xEditor Needs help with the intellisense directives macros, but otherwise was able to parse everything quite accurately.
VSCode has some failures in few files, they are nearly the same failures as VS2022, however like 10xEditor I saw that it has include awareness beyond a single file's scope!
In fact, if I open all the files, the parser corrects itself (you can close them afterwards). It essentially cached the include graph for the project by doing so for the lifetime of the process.
VS2022 has issues due to it strictly parsing each file, without awareness of whats going on in other files.
(It doesn't build a proper include graph).
Rider just straight up broken, it seems to not work every well with NMake projects.
At least, you can't depend on it to use the external include directories field properly.
It will show errors for all external include symbols.
# Day 32
Vod was more of a pain to follow along than usual...
I updated the scripts to only build each module if it detects changes (just using md5 hash on the files).
# Day 33
I thought the last few vods were not great to follow... That was just training for today.
# Day 34
Casey decided to start offloading tile map definitions to separate files so I took the time to also cleanup some of the organization of the code.
I'm still keeping some cpp files directly included within engine.cpp and win32_platform.cpp for now (instead of their translation unit files). I'll problably wait till much later to offload them.
Making that first baby step for procedural gen, and proper tile_chunk memory felt pretty good after many vods of stumbling.
# Day 36
Just dealing with Casey's "methods" for going about the code exploration...
Loading an image was nice, I got it to render somewhat properly with draw_bitmap but until he does it I kept the bad way hes doing it.
# Day 37
I went ahead and did some extra stuff.
My "hero" is a mojito bmp for now. I'll eventually do something else for it.
I also added incremental build support for the codegen metaprograms.
I originally wanted to make the assets on the fly (just as a break from the code),
but decided to just use his assets as this series is already going to take forever.
I have the assets mapped to an "offical" directory within content, however they'll be naturally ignored on the repo.
# Day 40
Its finally done with this phase of the project.
Looking forward to seeing some vectors after all these days.

View File

@ -1,3 +0,0 @@
# Day 27
Definitely feels refreshing to not touch win32.

View File

@ -1,7 +0,0 @@
# Day 30
Tile map stuff is looking alright. Doing my best to not clean-up the code as Casey pleads in the vods.
I would have perferred if he didn't just do one tilemap at a time and instead I would have had the current tile map and surrounding loaded at the same time (He might do this in the future). Since were aren't constrained memory wise like the old machines, we could have those loaded as well and it would make the management of the tilemaps easier (possibly...).
Looking foward to when he introduces a proper vector space for the positioning.

View File

@ -1,26 +0,0 @@
# Day 31
This was really a prepatory day for day 32 so I did some extra stuff...
I setup codebase so now that the build translation unit files have every single file included for that unit explicitly.
I do not (or should not) have nested includes other than from `grime.hpp`
## Side Tracking
I did some refactoring and added `INTELLISENSE_DIRECTIVES` preprocessor conditional blocks throughout the codebase.
I wanted to see if I could get all IDE/Editors I've ever used to support the project without bad errors from parsing failures.
Unfortunately getting Visual Studio and Rider's intellisense to behave was not possible.
This is mostly from how the code is structured across files currently.
I'll have to re-sturcture it down the line to make it more IDE friendly.
10xEditor Needs help with the intellisense directives macros, but otherwise was able to parse everything quite accurately.
VSCode has some failures in few files, they are nearly the same failures as VS2022, however like 10xEditor I saw that it has include awareness beyond a single file's scope!
In fact, if I open all the files, the parser corrects itself (you can close them afterwards). It essentially cached the include graph for the project by doing so for the lifetime of the process.
VS2022 has issues due to it strictly parsing each file, without awareness of whats going on in other files.
(It doesn't build a proper include graph).
Rider just straight up broken, it seems to not work every well with NMake projects.
At least, you can't depend on it to use the external include directories field properly.
It will show errors for all external include symbols.

View File

@ -1,5 +0,0 @@
# Day 32
Vod was more of a pain to follow along than usual...
I updated the scripts to only build each module if it detects changes (just using md5 hash on the files).

View File

@ -1,3 +0,0 @@
# Day 033
I thought the last few vods were not great to follow... That was just training for today.

View File

@ -1,6 +0,0 @@
# Day 34
Casey decided to start offloading tile map definitions to separate files so I took the time to also cleanup some of the organization of the code.
I'm still keeping some cpp files directly included within engine.cpp and win32_platform.cpp for now (instead of their translation unit files). I'll problably wait till much later to offload them.
Making that first baby step for procedural gen, and proper tile_chunk memory felt pretty good after many vods of stumbling.

View File

@ -1,5 +0,0 @@
# Day 36
Just dealing with Casey's "methods" for going about the code exploration...
Loading an image was nice, I got it to render somewhat properly with draw_bitmap but until he does it I kept the bad way hes doing it.

View File

@ -1,10 +0,0 @@
# Day 37
I went ahead and did some extra stuff.
My "hero" is a mojito bmp for now. I'll eventually do something else for it.
I also added incremental build support for the codegen metaprograms.
I originally wanted to make the assets on the fly (just as a break from the code),
but decided to just use his assets as this series is already going to take forever.
I have the assets mapped to an "offical" directory within content, however they'll be naturally ignored on the repo.

View File

@ -1,18 +0,0 @@
# Day 39
My `draw_bitmap` proc has been already setup to have the position specified
from the assumped position of the center of the image.
Its how I'm used to anchoring images by default so thats why I decided to go with it.
Casey however is using the corner however...
and then is doing some offset alignment based on what he sees for the coordinates on GIMP..
I decided to hand calibrate the alignment by eye. Since I already have it centered on X, the `align_x` could
stay zeroed for now and all I needed to do was align_y.
I also did not do the difference using a `tile_map_diff` like he did,
I just returned a tile_map_position and switch the map coodinates to be signed
(which tbh is fine I'll just adjust the math later when I need to).
I'm assuming it won't matter because the tile map setup we currently have is before he revamps the project with proper
vector math data structures, and he might switch to signed coordinates for them in the stream.

8
docs/Day 042.md Normal file
View File

@ -0,0 +1,8 @@
# Day 42
I decided to generate the vectors since I wanted f32 and s32 vectors. However, I didn't want to use templates.
I ended up messing aroudn with templates a bit for the `Zero(type)` macro which is just an alt for `type {}`.
Pattern is useful for other constant inits though (if I want to do it that way...)
Found bugs in gencpp which was nice!
Compressing the code with vector abstraction was nice, hopefuly these pixel will soon as well...

View File

@ -0,0 +1,310 @@
#include "platform/compiler_ignores.hpp"
#if GEN_TIME
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
#define GEN_IMPLEMENTATION
#define GEN_BENCHMARK
#define GEN_ENFORCE_STRONG_CODE_TYPES
#include "dependencies/gen.hpp"
#undef ccast
#undef pcast
#undef rcast
#undef scast
#undef do_once
#undef do_once_start
#undef do_once_end
using namespace gen;
#include "platform/platform_module.hpp"
#include "platform/grime.hpp"
#include "platform/macros.hpp"
#include "platform/types.hpp"
#include "platform/strings.hpp"
#include "platform/platform.hpp"
constexpr StrC fname_vec_header = txt("vectors.hpp");
constexpr char const* vec2_ops = stringize(
template<>
constexpr <type> tmpl_zero< <type> >() {
return { 0, 0 };
}
inline
<type> abs( <type> v ) {
<type> result {
abs( v.x ),
abs( v.y )
};
return result;
}
inline
<type> operator - ( <type> v ) {
<type> result {
- v.x,
- v.y
};
return result;
}
inline
<type> operator + ( <type> a, <type> b ) {
<type> result {
a.x + b.x,
a.y + b.y
};
return result;
}
inline
<type> operator - ( <type> a, <type> b ) {
<type> result {
a.x - b.x,
a.y - b.y
};
return result;
}
inline
<type> operator * ( <type> v, <unit_type> s ) {
<type> result {
v.x * s,
v.y * s
};
return result;
}
inline
<type> operator / ( <type> v, <unit_type> s ) {
<type> result {
v.x / s,
v.y / s
};
return result;
}
inline
<type>& operator += ( <type>& a, <type> b ) {
a.x += b.x;
a.y += b.y;
return a;
}
inline
<type>& operator -= ( <type>& a, <type> b ) {
a.x -= b.x;
a.y -= b.y;
return a;
}
inline
<type>& operator *= ( <type>& v, <unit_type> s ) {
v.x *= s;
v.y *= s;
return v;
}
inline
<type>& operator /= ( <type>& v, <unit_type> s ) {
v.x /= s;
v.y /= s;
return v;
}
);
#define gen_vec2( vec_name, type ) gen__vec2( txt( stringize(vec_name) ), txt( stringize(type) ) )
CodeBody gen__vec2( StrC vec_name, StrC type )
{
CodeStruct vec_struct = parse_struct( token_fmt( "type", vec_name, "unit_type", type, stringize(
struct <type>
{
union {
struct {
<unit_type> x;
<unit_type> y;
};
<unit_type> Basis[2];
};
};
)));
CodeBody vec_ops = parse_global_body( token_fmt( "type", vec_name, "unit_type", type, vec2_ops) );
CodeBody vec_def = def_global_body( args(
vec_struct,
fmt_newline,
vec_ops
));
return vec_def;
}
#define gen_phys2( type ) gen__phys2( txt( stringize(type) ) )
Code gen__phys2( StrC type )
{
String t_vec = String::fmt_buf( GlobalAllocator, "Vec2_%s", type.Ptr );
String t_pos = String::fmt_buf( GlobalAllocator, "Pos2_%s", type.Ptr );
String t_dist = String::fmt_buf( GlobalAllocator, "Dist2_%s", type.Ptr );
String t_vel = String::fmt_buf( GlobalAllocator, "Vel2_%s", type.Ptr );
String t_accel = String::fmt_buf( GlobalAllocator, "Accel2_%s", type.Ptr );
#pragma push_macro("pcast")
#pragma push_macro("rcast")
#undef pcast
#undef rcast
Code result = parse_global_body( token_fmt(
"unit_type", (StrC)type,
"vec_type", (StrC)t_vec,
"pos_type", (StrC)t_pos,
"dist_type", (StrC)t_dist,
"vel_type", (StrC)t_vel,
"accel_type", (StrC)t_accel,
stringize(
struct <pos_type> {
union {
struct {
<unit_type> x;
<unit_type> y;
};
<unit_type> Basis[2];
};
operator <vec_type>() {
return * rcast(<vec_type>*, this);
}
};
using <dist_type> = <unit_type>;
inline
<dist_type> distance( <pos_type> a, <pos_type> b ) {
<unit_type> x = b.x - a.x;
<unit_type> y = b.y - a.y;
<dist_type> result = sqrt( x * x + y * y );
return result;
}
struct <vel_type> {
union {
struct {
<unit_type> x;
<unit_type> y;
};
<unit_type> Basis[2];
};
operator <vec_type>() {
return * rcast(<vec_type>*, this);
}
};
inline
<vel_type> velocity( <pos_type> a, <pos_type> b ) {
<vec_type> result = b - a;
return pcast(<vel_type>, result);
}
inline
<pos_type>& operator +=(<pos_type>& pos, const <vel_type>& vel) {
pos.x += vel.x;
pos.y += vel.y;
return pos;
}
inline
<vel_type>& operator *= ( <vel_type>& v, <unit_type> s ) {
v.x *= s;
v.y *= s;
return v;
}
struct <accel_type> {
union {
struct {
<unit_type> x;
<unit_type> y;
};
<unit_type> Basis[2];
};
operator <vec_type>() {
return * rcast(<vec_type>*, this);
}
};
inline
<accel_type> acceleration( <vel_type> a, <vel_type> b ) {
<vec_type> result = b - a;
return pcast(<accel_type>, result);
}
)));
return result;
#pragma pop_macro("rcast")
#pragma pop_macro("pcast")
}
int gen_main()
{
gen::init();
log_fmt("Generating code for Handmade Hero: Engine Module\n");
CodeComment cmt_gen_notice = def_comment( txt("This was generated by project/codegen/engine_gen.cpp") );
Builder vec_header = Builder::open(fname_vec_header);
{
vec_header.print( cmt_gen_notice );
vec_header.print( pragma_once );
vec_header.print_fmt( "#if INTELLISENSE_DIRECTIVES" );
vec_header.print( fmt_newline );
vec_header.print( def_include( txt("engine_module.hpp") ));
vec_header.print( def_include( txt("platform.hpp") ));
vec_header.print( preprocess_endif );
vec_header.print( fmt_newline );
CodeUsing using_vec2 = parse_using( code( using Vec2 = Vec2_f32; ));
CodeUsing using_vec2i = parse_using( code( using Vec2i = Vec2_s32; ));
vec_header.print( gen_vec2( Vec2_f32, f32) );
vec_header.print( gen_vec2( Vec2_s32, s32) );
vec_header.print( using_vec2 );
vec_header.print( using_vec2i );
CodeUsing using_vec3 = parse_using( code( using Vec2 = Vec3_f32; ));
CodeUsing using_vec3i = parse_using( code( using Vec2i = Vec3_f32; ));
// vec_header.print( using_vec3 );
vec_header.write();
}
Builder physics_header = Builder::open( txt("physics.hpp") );
{
physics_header.print( cmt_gen_notice );
physics_header.print( pragma_once );
physics_header.print_fmt( "#if INTELLISENSE_DIRECTIVES" );
physics_header.print( fmt_newline );
physics_header.print( def_include( txt("vectors.hpp") ));
physics_header.print( preprocess_endif );
physics_header.print( fmt_newline );
physics_header.print( gen_phys2( f32 ) );
physics_header.print( gen_phys2( s32 ) );
physics_header.print( parse_global_body( code(
using Pos2 = Pos2_f32;
using Dist2 = Dist2_f32;
using Vel2 = Vel2_f32;
using Accel2 = Accel2_f32;
using Pos2i = Pos2_s32;
using Dist2i = Dist2_s32;
using Vel2i = Vel2_s32;
using Accel2i = Accel2_s32;
)));
physics_header.write();
}
log_fmt("Generaton finished for Handmade Hero: Engine Module\n\n");
// gen::deinit();
return 0;
}
#endif

View File

@ -15,14 +15,20 @@
#undef do_once_end
using namespace gen;
#include <math.h>
#include "platform/platform_module.hpp"
#include "platform/grime.hpp"
#include "platform/macros.hpp"
#include "platform/generics.hpp"
#include "platform/types.hpp"
#include "platform/intrinsics.hpp"
#include "platform/strings.hpp"
#include "platform/platform.hpp"
#include "engine/engine_module.hpp"
#include "engine/gen/vectors.hpp"
#include "engine/gen/physics.hpp"
#include "engine/input.hpp"
#include "engine/tile_map.hpp"
#include "engine/engine.hpp"
@ -65,7 +71,7 @@ void get_symbols_from_module_table( FileContents symbol_table, Array<String> sym
int gen_main()
{
gen::init();
log_fmt("Generating code for Handmade Hero: Engine Module\n");
log_fmt("Generating code for Handmade Hero: Engine Module (Post-Build)\n");
FileContents symbol_table = file_read_contents( GlobalAllocator, true, fname_handmade_engine_symbols );
@ -103,7 +109,7 @@ int gen_main()
builder.write();
#pragma pop_macro("str_ascii")
log_fmt("Generaton finished for Handmade Hero: Engine Module\n\n");
log_fmt("Generaton finished for Handmade Hero: Engine Module (Post-Build)\n\n");
// gen::deinit();
return 0;
}

View File

@ -3931,8 +3931,8 @@ struct AST
operator CodeVar();
#pragma endregion Member Functions
constexpr static int ArrSpecs_Cap =
( AST_POD_Size - sizeof( AST* ) * 3 - sizeof( Parser::Token* ) - sizeof( AST* ) - sizeof( StringCached ) - sizeof( CodeT ) - sizeof( ModuleFlag ) - sizeof( int ) )
constexpr static int ArrSpecs_Cap = ( AST_POD_Size - sizeof( AST* ) * 3 - sizeof( Parser::Token* ) - sizeof( AST* ) - sizeof( StringCached )
- sizeof( CodeT ) - sizeof( ModuleFlag ) - sizeof( int ) )
/ sizeof( int )
- 1; // -1 for 4 extra bytes
@ -13569,7 +13569,10 @@ String AST::to_string()
if ( bitfield_is_equal( u32, ModuleFlags, ModuleFlag::Export ) )
result.append( "export " );
if ( Params )
result.append_fmt( "template< %S >\n%S", Params->to_string(), Declaration->to_string() );
else
result.append_fmt( "template<>\n%S", Declaration->to_string() );
}
break;
@ -14696,6 +14699,11 @@ internal void define_constants()
#endif
#undef def_constant_code_type
#define def_constant_spec( Type_, ... ) \
spec_##Type_ = def_specifiers( num_args( __VA_ARGS__ ), __VA_ARGS__ ); \
spec_##Type_.set_global();
#pragma push_macro( "forceinline" )
#pragma push_macro( "global" )
#pragma push_macro( "internal" )
@ -14706,11 +14714,6 @@ internal void define_constants()
#undef internal
#undef local_persist
#undef neverinline
#define def_constant_spec( Type_, ... ) \
spec_##Type_ = def_specifiers( num_args( __VA_ARGS__ ), __VA_ARGS__ ); \
spec_##Type_.set_global();
def_constant_spec( const, ESpecifier::Const );
def_constant_spec( consteval, ESpecifier::Consteval );
def_constant_spec( constexpr, ESpecifier::Constexpr );
@ -15005,13 +15008,13 @@ OpValidateResult operator__validate( OperatorT op, CodeParam params_code, CodeTy
}
#define check_param_eq_ret() \
if ( ! is_member_symbol && params_code->ValueType != ret_type ) \
if ( ! is_member_symbol && ! params_code->ValueType.is_equal( ret_type ) ) \
{ \
log_failure( \
"gen_def_operator: operator%s requires first parameter to equal return type\n" \
"gen::def_operator: operator%s requires first parameter to equal return type\n" \
"param types: %s\n" \
"return type: %s", \
to_str( op ), \
to_str( op ).Ptr, \
params_code.debug_str(), \
ret_type.debug_str() \
); \
@ -15905,6 +15908,7 @@ ModuleFlag mflags
CodeOperator result = ( CodeOperator )make_code();
result->Name = get_cached_string( { str_len( name ), name } );
result->ModuleFlags = mflags;
result->Op = op;
if ( body )
{
@ -18323,6 +18327,18 @@ namespace Parser
if ( left )
move_forward();
if ( current == '=' )
{
token.Length++;
token.IsAssign = true;
// token.Flags |= TokFlags::Assignment;
// token.Type = TokType::Assign_Multiply;
if ( left )
move_forward();
}
goto FoundToken;
}
case ';' :
@ -18518,7 +18534,14 @@ namespace Parser
if ( left )
{
if ( current == '/' )
if ( current == '=' )
{
// token.Type = TokeType::Assign_Divide;
move_forward();
token.Length++;
token.IsAssign = true;
}
else if ( current == '/' )
{
token.Type = TokType::Comment;
token.Length = 2;
@ -20302,7 +20325,8 @@ internal CodeOperator parse_operator_after_ret_type( ModuleFlag mflags, CodeAttr
eat( TokType::Decl_Operator );
if ( ! left && currtok.Type != TokType::Operator && currtok.Type != TokType::Star && currtok.Type != TokType::Ampersand && currtok.Type != TokType::Ampersand_DBL )
if ( ! left && currtok.Type != TokType::Operator && currtok.Type != TokType::Star && currtok.Type != TokType::Ampersand
&& currtok.Type != TokType::Ampersand_DBL )
{
log_failure( "Expected operator after 'operator' keyword\n%s", Context.to_string() );
Context.pop();
@ -20319,7 +20343,7 @@ internal CodeOperator parse_operator_after_ret_type( ModuleFlag mflags, CodeAttr
if ( currtok.Text[ 1 ] == '=' )
op = Assign_Add;
if ( currtok.Text[ 1 ] == '+' )
else if ( currtok.Text[ 1 ] == '+' )
op = Increment;
else
@ -20339,7 +20363,7 @@ internal CodeOperator parse_operator_after_ret_type( ModuleFlag mflags, CodeAttr
break;
}
if ( currtok.Text[ 1 ] == '=' )
else if ( currtok.Text[ 1 ] == '=' )
op = Assign_Subtract;
else
@ -20691,6 +20715,12 @@ internal inline CodeParam parse_params( bool use_template_capture )
Context.pop();
return { nullptr };
}
else if ( check( TokType::Operator ) && currtok.Text[ 0 ] == '>' )
{
eat( TokType::Operator );
Context.pop();
return { nullptr };
}
CodeType type = { nullptr };
Code value = { nullptr };
@ -22227,7 +22257,8 @@ internal CodeType parse_type( bool* typedef_is_function )
}
// All kinds of nonsense can makeup a type signature, first we check for a in-place definition of a class, enum, or struct
if ( currtok.Type == TokType::Decl_Class || currtok.Type == TokType::Decl_Enum || currtok.Type == TokType::Decl_Struct || currtok.Type == TokType::Decl_Union )
if ( currtok.Type == TokType::Decl_Class || currtok.Type == TokType::Decl_Enum || currtok.Type == TokType::Decl_Struct
|| currtok.Type == TokType::Decl_Union )
{
name = currtok;
eat( currtok.Type );

View File

@ -188,26 +188,23 @@ void output_sound( EngineState* state, AudioBuffer* sound_buffer, GetSoundSample
internal
void draw_rectangle( OffscreenBuffer* buffer
, f32 min_x, f32 min_y
, f32 max_x, f32 max_y
, Vec2 min, Vec2 max
, f32 red, f32 green, f32 blue )
{
s32 min_x_32 = round( min_x );
s32 min_y_32 = round( min_y );
s32 max_x_32 = round( max_x );
s32 max_y_32 = round( max_y );
Vec2i min_rounded { round(min.x), round(min.y) };
Vec2i max_rounded { round(max.x), round(max.y) };
s32 buffer_width = buffer->width;
s32 buffer_height = buffer->height;
s32 width = buffer->width;
s32 height = buffer->height;
if ( min_x_32 < 0 )
min_x_32 = 0;
if ( min_y_32 < 0 )
min_y_32 = 0;
if ( max_x_32 > buffer_width )
max_x_32 = buffer_width;
if ( max_y_32 > buffer_height )
max_y_32 = buffer_height;
if ( min_rounded.x < 0 )
min_rounded.x = 0;
if ( min_rounded.y < 0 )
min_rounded.y = 0;
if ( max_rounded.x > width )
max_rounded.x = width;
if ( max_rounded.y > height )
max_rounded.y = height;
s32 red_32 = round( 255.f * red );
s32 green_32 = round( 255.f * green );
@ -220,14 +217,14 @@ void draw_rectangle( OffscreenBuffer* buffer
// Start with the pixel on the top left corner of the rectangle
u8* row = rcast(u8*, buffer->memory )
+ min_x_32 * buffer->bytes_per_pixel
+ min_y_32 * buffer->pitch;
+ min_rounded.x * buffer->bytes_per_pixel
+ min_rounded.y * buffer->pitch;
for ( s32 y = min_y_32; y < max_y_32; ++ y )
for ( s32 y = min_rounded.y; y < max_rounded.y; ++ y )
{
s32* pixel_32 = rcast(s32*, row);
for ( s32 x = min_x_32; x < max_x_32; ++ x )
for ( s32 x = min_rounded.x; x < max_rounded.x; ++ x )
{
*pixel_32 = color;
pixel_32++;
@ -237,45 +234,46 @@ void draw_rectangle( OffscreenBuffer* buffer
}
internal
void draw_bitmap( OffscreenBuffer* buffer
, f32 pos_x, f32 pos_y
, Bitmap* bitmap )
void draw_bitmap( OffscreenBuffer* buffer, Vec2 pos, Bitmap* bitmap )
{
s32 half_width = bitmap->width / 2;
s32 half_height = bitmap->height / 2;
s32 min_x = round( pos_x ) - half_width;
s32 min_y = round( pos_y ) - half_height;
s32 max_x = round( pos_x ) + half_width;
s32 max_y = round( pos_y ) + half_height;
Vec2i pos_rounded { round(pos.x), round(pos.y) };
Vec2i bmp_half_size { bitmap->width / 2, bitmap->height / 2 };
Vec2i min = pos_rounded - bmp_half_size;
Vec2i max = pos_rounded + bmp_half_size;
s32 bmp_offset_x = min_x < 0 ? min_x * -1 : 0;
u32 bmp_offset_y = min_y < 0 ? bitmap->height + min_y - 1 : bitmap->height - 1;
s32 max_x = round( pos.x ) + half_width;
s32 max_y = round( pos.y ) + half_height;
s32 buffer_width = buffer->width;
s32 buffer_height = buffer->height;
s32 bmp_offset_x = min.x < 0 ? min.x * -1 : 0;
u32 bmp_offset_y = min.y < 0 ? bitmap->height + min.y - 1 : bitmap->height - 1;
if ( min_x < 0 )
min_x = 0;
if ( min_y < 0 )
min_y = 0;
if ( max_x > buffer_width )
max_x = buffer_width;
if ( max_y > buffer_height )
max_y = buffer_height;
s32 width = buffer->width;
s32 height = buffer->height;
if ( min.x < 0 )
min.x = 0;
if ( min.y < 0 )
min.y = 0;
if ( max.x > width )
max.x = width;
if ( max.y > height )
max.y = height;
// Start with the pixel on the top left corner of the rectangle
u8* dst_row = rcast(u8*, buffer->memory )
+ min_x * buffer->bytes_per_pixel
+ min_y * buffer->pitch;
+ min.x * buffer->bytes_per_pixel
+ min.y * buffer->pitch;
u32* src_row = bitmap->pixels + bitmap->width * bmp_offset_y;
for ( s32 y = min_y; y < max_y; ++ y )
for ( s32 y = min.y; y < max.y; ++ y )
{
u32* dst = rcast(u32*, dst_row);
u32* src = src_row + bmp_offset_x;
for ( s32 x = min_x; x < max_x; ++ x )
for ( s32 x = min.x; x < max.x; ++ x )
{
#define extract( pixel, shift ) (( *pixel >> shift ) & 0xFF)
f32 alpha = scast(f32, extract(src, 24)) / 255.f;
@ -305,16 +303,22 @@ void draw_bitmap( OffscreenBuffer* buffer
}
inline
void draw_debug_point(OffscreenBuffer* back_buffer, World* world, TileMapPosition pos, f32 red, f32 green, f32 blue)
void draw_debug_point(OffscreenBuffer* back_buffer, World* world, TileMapPos pos, f32 red, f32 green, f32 blue)
{
TileMap* tile_map = world->tile_map;
draw_rectangle(back_buffer,
pos.x * world->tile_meters_to_pixels + world->tile_lower_left_x + scast(f32, pos.tile_x * world->tile_size_in_pixels),
pos.y * world->tile_meters_to_pixels + world->tile_lower_left_y + scast(f32, pos.tile_y * world->tile_size_in_pixels),
(pos.x + 0.1f) * world->tile_meters_to_pixels + world->tile_lower_left_x + scast(f32, pos.tile_x * world->tile_size_in_pixels),
(pos.y + 0.1f) * world->tile_meters_to_pixels + world->tile_lower_left_y + scast(f32, pos.tile_y * world->tile_size_in_pixels),
red, green, blue);
Vec2 min {
pos.rel_pos.x * world->tile_meters_to_pixels + world->tile_lower_left_x + scast(f32, pos.tile_x * world->tile_size_in_pixels),
pos.rel_pos.y * world->tile_meters_to_pixels + world->tile_lower_left_y + scast(f32, pos.tile_y * world->tile_size_in_pixels)
};
Vec2 max {
(pos.rel_pos.x + 0.1f) * world->tile_meters_to_pixels + world->tile_lower_left_x + scast(f32, pos.tile_x * world->tile_size_in_pixels),
(pos.rel_pos.y + 0.1f) * world->tile_meters_to_pixels + world->tile_lower_left_y + scast(f32, pos.tile_y * world->tile_size_in_pixels)
};
draw_rectangle(back_buffer
, min, max
, red, green, blue);
}
internal
@ -704,8 +708,8 @@ void startup( OffscreenBuffer* back_buffer, Memory* memory, platform::ModuleAPI*
hh::PlayerState* player = & game_state->player_state;
player->position.tile_x = 4;
player->position.tile_y = 4;
player->position.x = 0.f;
player->position.y = 0.f;
player->position.rel_pos.x = 0.f;
player->position.rel_pos.y = 0.f;
player->mid_jump = false;
player->jump_time = 0.f;
@ -862,9 +866,6 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back
hh::GameState* game_state = rcast( hh::GameState*, state->game_memory.persistent );
hh::PlayerState* player = & game_state->player_state;
f32 x_offset_f = scast(f32, state->x_offset);
f32 y_offset_f = scast(f32, state->y_offset);
World* world = state->world;
TileMap* tile_map = world->tile_map;
@ -887,53 +888,64 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back
move_speed = 24.f;
}
f32 new_player_pos_x = player->position.x;
f32 new_player_pos_y = player->position.y;
Pos2_f32 new_player_pos = { player->position.rel_pos.x, player->position.rel_pos.y };
b32 moved_x = player_actions.player_x_move_analog != 0 || player_actions.player_x_move_digital != 0;
b32 moved_y = player_actions.player_y_move_analog != 0 || player_actions.player_y_move_digital != 0;
Vel2_f32 player_move_vel = {};
if ( player_actions.player_x_move_analog || player_actions.player_y_move_analog )
{
new_player_pos_x += scast(f32, player_actions.player_x_move_analog * delta_time * move_speed);
new_player_pos_y += scast(f32, player_actions.player_y_move_analog * delta_time * move_speed);
player_move_vel.x = scast(f32, player_actions.player_x_move_analog * delta_time * move_speed);
player_move_vel.y = scast(f32, player_actions.player_y_move_analog * delta_time * move_speed);
}
else
{
new_player_pos_x += scast(f32, player_actions.player_x_move_digital) * delta_time * move_speed;
new_player_pos_y += scast(f32, player_actions.player_y_move_digital) * delta_time * move_speed;
player_move_vel.x = scast(f32, player_actions.player_x_move_digital) * delta_time * move_speed;
player_move_vel.y = scast(f32, player_actions.player_y_move_digital) * delta_time * move_speed;
}
new_player_pos_y += sinf( player->jump_time * TAU ) * 10.f * delta_time;
if ( moved_x && moved_y )
{
player_move_vel *= (f32)0.707106781187f;
}
new_player_pos += player_move_vel;
new_player_pos.y -= sinf( player->jump_time * TAU ) * 10.f * delta_time;
b32 valid_new_pos = true;
{
TileMapPosition test_pos = {
new_player_pos_x, new_player_pos_y,
TileMapPos test_pos = {
new_player_pos.x, new_player_pos.y,
player->position.tile_x, player->position.tile_y, player->position.tile_z
};
test_pos = recannonicalize_position( tile_map, test_pos );
// TODO(Ed) : Need a delta-function that auto-reconnonicalizes.
TileMapPosition test_pos_nw {
new_player_pos_x - player_half_width, new_player_pos_y + player_quarter_height,
TileMapPos test_pos_nw {
new_player_pos.x - player_half_width, new_player_pos.y + player_quarter_height,
player->position.tile_x, player->position.tile_y, player->position.tile_z
};
test_pos_nw = recannonicalize_position( tile_map, test_pos_nw );
valid_new_pos &= TileMap_is_point_empty( tile_map, test_pos_nw );
TileMapPosition test_pos_ne {
new_player_pos_x + player_half_width, new_player_pos_y + player_quarter_height,
TileMapPos test_pos_ne {
new_player_pos.x + player_half_width, new_player_pos.y + player_quarter_height,
player->position.tile_x, player->position.tile_y, player->position.tile_z
};
test_pos_ne = recannonicalize_position( tile_map, test_pos_ne );
valid_new_pos &= TileMap_is_point_empty( tile_map, test_pos_ne );
TileMapPosition test_pos_sw {
new_player_pos_x - player_half_width, new_player_pos_y,
TileMapPos test_pos_sw {
new_player_pos.x - player_half_width, new_player_pos.y,
player->position.tile_x, player->position.tile_y, player->position.tile_z
};
test_pos_sw = recannonicalize_position( tile_map, test_pos_sw );
valid_new_pos &= TileMap_is_point_empty( tile_map, test_pos_sw );
TileMapPosition test_pos_se {
new_player_pos_x + player_half_width, new_player_pos_y,
TileMapPos test_pos_se {
new_player_pos.x + player_half_width, new_player_pos.y,
player->position.tile_x, player->position.tile_y, player->position.tile_z
};
test_pos_se = recannonicalize_position( tile_map, test_pos_se );
@ -942,8 +954,8 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back
if ( valid_new_pos )
{
TileMapPosition new_pos = {
new_player_pos_x, new_player_pos_y,
TileMapPos new_pos = {
new_player_pos.x, new_player_pos.y,
player->position.tile_x, player->position.tile_y, player->position.tile_z
};
new_pos = recannonicalize_position( tile_map, new_pos );
@ -999,7 +1011,7 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back
player->mid_jump = true;
}
TileMapPosition player_to_camera = subtract( player->position, game_state->camera_pos );
TileMapPos player_to_camera = subtract( player->position, game_state->camera_pos );
game_state->camera_pos.tile_z = player->position.tile_z;
@ -1022,25 +1034,20 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back
}
Vec2 screen_center {
scast(f32, back_buffer->width) * 0.5f,
scast(f32, back_buffer->height) * 0.5f
};
draw_rectangle( back_buffer
, 0.f, 0.f
, scast(f32, back_buffer->width), scast(f32, back_buffer->height)
, Zero(Vec2)
, { scast(f32, back_buffer->width), scast(f32, back_buffer->height) }
, 1.f, 0.24f, 0.24f );
draw_bitmap( back_buffer
, scast(f32, back_buffer->width) / 2.f, scast(f32, back_buffer->height) / 2.f
, & game_state->test_bg
);
draw_bitmap( back_buffer
, scast(f32, back_buffer->width) / 2.f, scast(f32, back_buffer->height) / 2.f
, & game_state->test_bg_hh
);
draw_bitmap( back_buffer, screen_center, & game_state->test_bg );
draw_bitmap( back_buffer, screen_center, & game_state->test_bg_hh );
// Screen Camera
f32 screen_center_x = 0.5f * scast(f32, back_buffer->width);
f32 screen_center_y = 0.5f * scast(f32, back_buffer->height);
for ( s32 relative_row = -10; relative_row < +10; ++ relative_row )
{
for ( s32 relative_col = -20; relative_col < +20; ++ relative_col )
@ -1080,17 +1087,16 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back
color[2] = 0.3f;
}
f32 center_x = screen_center_x + scast(f32, relative_col) * tile_size_in_pixels - game_state->camera_pos.x * world->tile_meters_to_pixels;
f32 center_y = screen_center_y - scast(f32, relative_row) * tile_size_in_pixels + game_state->camera_pos.y * world->tile_meters_to_pixels;
f32 min_x = center_x - tile_size_in_pixels * 0.5f;
f32 min_y = center_y - tile_size_in_pixels * 0.5f;
f32 max_x = center_x + tile_size_in_pixels * 0.5f;
f32 max_y = center_y + tile_size_in_pixels * 0.5f;
Vec2 tile_pixel_size = { tile_size_in_pixels * 0.5f, tile_size_in_pixels * 0.5f };
Vec2 center {
screen_center.x + scast(f32, relative_col) * tile_size_in_pixels - game_state->camera_pos.rel_pos.x * world->tile_meters_to_pixels,
screen_center.y - scast(f32, relative_row) * tile_size_in_pixels + game_state->camera_pos.rel_pos.y * world->tile_meters_to_pixels
};
Vec2 min = center - tile_pixel_size;
Vec2 max = center + tile_pixel_size;
draw_rectangle( back_buffer
, min_x, min_y
, max_x, max_y
, min, max
, color[0], color[1], color[2] );
}
}
@ -1118,38 +1124,44 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back
f32 player_green = 0.7f;
f32 player_blue = 0.3f;
TileMapPosition player_to_camera = subtract( player->position, game_state->camera_pos );
TileMapPos player_to_camera = subtract( player->position, game_state->camera_pos );
f32 offcenter_amount_x = player_to_camera.x + scast(f32, player_to_camera.tile_x) * world->tile_map->tile_size_in_meters;
f32 offcenter_amount_y = player_to_camera.y + scast(f32, player_to_camera.tile_y) * world->tile_map->tile_size_in_meters;
offcenter_amount_x *= world->tile_meters_to_pixels;
offcenter_amount_y *= world->tile_meters_to_pixels * -1;
f32 player_ground_pos_x = screen_center_x + offcenter_amount_x;
f32 player_ground_pos_y = screen_center_y + offcenter_amount_y;
Vec2 player_to_screenspace {
player_to_camera.rel_pos.x + scast(f32, player_to_camera.tile_x) * world->tile_map->tile_size_in_meters,
-1 * (player_to_camera.rel_pos.y + scast(f32, player_to_camera.tile_y) * world->tile_map->tile_size_in_meters)
};
Vec2 player_ground_pos = screen_center + player_to_screenspace * world->tile_meters_to_pixels;
hh::HeroBitmaps* hero_bitmaps = & game_state->hero_bitmaps[game_state->hero_direction];
#if 1
Vec2 player_collision_min {
player_ground_pos.x - player_half_width * world->tile_meters_to_pixels,
player_ground_pos.y - player->height * world->tile_meters_to_pixels,
};
Vec2 player_collision_max {
player_ground_pos.x + player_half_width * world->tile_meters_to_pixels,
player_ground_pos.y
};
draw_rectangle( back_buffer
, player_ground_pos_x - player_half_width * world->tile_meters_to_pixels, player_ground_pos_y - player->height * world->tile_meters_to_pixels
, player_ground_pos_x + player_half_width * world->tile_meters_to_pixels, player_ground_pos_y
, player_collision_min, player_collision_max
, player_red, player_green, player_blue );
#endif
draw_bitmap( back_buffer
, player_ground_pos_x, player_ground_pos_y - scast(f32, hero_bitmaps->align_y)
, { player_ground_pos.x, player_ground_pos.y - scast(f32, hero_bitmaps->align_y) }
, & hero_bitmaps->torso );
draw_bitmap( back_buffer
, player_ground_pos_x, player_ground_pos_y - scast(f32, hero_bitmaps->align_y)
, { player_ground_pos.x, player_ground_pos.y - scast(f32, hero_bitmaps->align_y) }
, & hero_bitmaps->cape );
#if 0
#if 1
draw_bitmap( back_buffer
, player_ground_pos_x, player_ground_pos_y - 45.f
, { player_ground_pos.x, player_ground_pos.y - 125.f }
, & game_state->mojito_head );
#else
draw_bitmap( back_buffer
, player_ground_pos_x, player_ground_pos_y - scast(f32, hero_bitmaps->align_y)
, { player_ground_pos.x, player_ground_pos.y - scast(f32, hero_bitmaps->align_y) }
, & hero_bitmaps->head );
#endif
@ -1158,17 +1170,18 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back
{
f32 snapshot_percent_x = ((state->auto_snapshot_timer / state->auto_snapshot_interval)) * (f32)back_buffer->width / 4.f;
draw_rectangle( back_buffer
, 0.f, 0.f
, snapshot_percent_x, 10.f
, Zero(Vec2)
, { snapshot_percent_x, 10.f }
, 0.f, 0.15f, 0.35f );
}
#if Build_Development
if ( memory->replay_mode == ReplayMode_Record )
{
// TODO(Ed) : We're prob going to need a better indicator for recording...
draw_rectangle( back_buffer
, player->position.x + 50.f, player->position.y - 50.f
, player->position.x + 10.f, player->position.y + 40.f
, { player->position.rel_pos.x + 50.f, player->position.rel_pos.y - 50.f }
, { player->position.rel_pos.x + 10.f, player->position.rel_pos.y + 40.f }
, 1.f, 1.f, 1.f );
}
#endif
@ -1177,8 +1190,8 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back
if ( 0 )
{
draw_rectangle( back_buffer
, (f32)input->controllers[0].mouse->X.end, (f32)input->controllers[0].mouse->Y.end
, (f32)input->controllers[0].mouse->X.end + 10.f, (f32)input->controllers[0].mouse->Y.end + 10.f
, { (f32)input->controllers[0].mouse->X.end, (f32)input->controllers[0].mouse->Y.end }
, { (f32)input->controllers[0].mouse->X.end + 10.f, (f32)input->controllers[0].mouse->Y.end + 10.f }
, 1.f, 1.f, 0.f );
}

View File

@ -6,6 +6,8 @@
#if INTELLISENSE_DIRECTIVES
#include "platform/platform.hpp"
#include "gen/vectors.hpp"
#include "gen/physics.hpp"
#include "engine_module.hpp"
#include "tile_map.hpp"
#endif

View File

@ -0,0 +1,200 @@
// This was generated by project/codegen/engine_gen.cpp
#pragma once
#if INTELLISENSE_DIRECTIVES
#include "vectors.hpp"
#endif
struct Pos2_f32
{
union
{
struct
{
f32 x;
f32 y;
};
f32 Basis[ 2 ];
};
operator Vec2_f32()
{
return *rcast( Vec2_f32*, this );
}
};
using Dist2_f32 = f32;
inline Dist2_f32 distance( Pos2_f32 a, Pos2_f32 b )
{
f32 x = b.x - a.x;
f32 y = b.y - a.y;
Dist2_f32 result = sqrt( x * x + y * y );
return result;
}
struct Vel2_f32
{
union
{
struct
{
f32 x;
f32 y;
};
f32 Basis[ 2 ];
};
operator Vec2_f32()
{
return *rcast( Vec2_f32*, this );
}
};
inline Vel2_f32 velocity( Pos2_f32 a, Pos2_f32 b )
{
Vec2_f32 result = b - a;
return pcast( Vel2_f32, result );
}
inline Pos2_f32& operator+=( Pos2_f32& pos, Vel2_f32 const& vel )
{
pos.x += vel.x;
pos.y += vel.y;
return pos;
}
inline Vel2_f32& operator*=( Vel2_f32& v, f32 s )
{
v.x *= s;
v.y *= s;
return v;
}
struct Accel2_f32
{
union
{
struct
{
f32 x;
f32 y;
};
f32 Basis[ 2 ];
};
operator Vec2_f32()
{
return *rcast( Vec2_f32*, this );
}
};
inline Accel2_f32 acceleration( Vel2_f32 a, Vel2_f32 b )
{
Vec2_f32 result = b - a;
return pcast( Accel2_f32, result );
}
struct Pos2_s32
{
union
{
struct
{
s32 x;
s32 y;
};
s32 Basis[ 2 ];
};
operator Vec2_s32()
{
return *rcast( Vec2_s32*, this );
}
};
using Dist2_s32 = s32;
inline Dist2_s32 distance( Pos2_s32 a, Pos2_s32 b )
{
s32 x = b.x - a.x;
s32 y = b.y - a.y;
Dist2_s32 result = sqrt( x * x + y * y );
return result;
}
struct Vel2_s32
{
union
{
struct
{
s32 x;
s32 y;
};
s32 Basis[ 2 ];
};
operator Vec2_s32()
{
return *rcast( Vec2_s32*, this );
}
};
inline Vel2_s32 velocity( Pos2_s32 a, Pos2_s32 b )
{
Vec2_s32 result = b - a;
return pcast( Vel2_s32, result );
}
inline Pos2_s32& operator+=( Pos2_s32& pos, Vel2_s32 const& vel )
{
pos.x += vel.x;
pos.y += vel.y;
return pos;
}
inline Vel2_s32& operator*=( Vel2_s32& v, s32 s )
{
v.x *= s;
v.y *= s;
return v;
}
struct Accel2_s32
{
union
{
struct
{
s32 x;
s32 y;
};
s32 Basis[ 2 ];
};
operator Vec2_s32()
{
return *rcast( Vec2_s32*, this );
}
};
inline Accel2_s32 acceleration( Vel2_s32 a, Vel2_s32 b )
{
Vec2_s32 result = b - a;
return pcast( Accel2_s32, result );
}
using Pos2 = Pos2_f32;
using Dist2 = Dist2_f32;
using Vel2 = Vel2_f32;
using Accel2 = Accel2_f32;
using Pos2i = Pos2_s32;
using Dist2i = Dist2_s32;
using Vel2i = Vel2_s32;
using Accel2i = Accel2_s32;

View File

@ -0,0 +1,177 @@
// This was generated by project/codegen/engine_gen.cpp
#pragma once
#if INTELLISENSE_DIRECTIVES
#include "engine_module.hpp"
#include "platform.hpp"
#endif
struct Vec2_f32
{
union
{
struct
{
f32 x;
f32 y;
};
f32 Basis[ 2 ];
};
};
template<>
constexpr Vec2_f32 tmpl_zero< Vec2_f32 >()
{
return { 0, 0 };
}
inline Vec2_f32 abs( Vec2_f32 v )
{
Vec2_f32 result { abs( v.x ), abs( v.y ) };
return result;
}
inline Vec2_f32 operator-( Vec2_f32 v )
{
Vec2_f32 result { -v.x, -v.y };
return result;
}
inline Vec2_f32 operator+( Vec2_f32 a, Vec2_f32 b )
{
Vec2_f32 result { a.x + b.x, a.y + b.y };
return result;
}
inline Vec2_f32 operator-( Vec2_f32 a, Vec2_f32 b )
{
Vec2_f32 result { a.x - b.x, a.y - b.y };
return result;
}
inline Vec2_f32 operator*( Vec2_f32 v, f32 s )
{
Vec2_f32 result { v.x * s, v.y * s };
return result;
}
inline Vec2_f32 operator/( Vec2_f32 v, f32 s )
{
Vec2_f32 result { v.x / s, v.y / s };
return result;
}
inline Vec2_f32& operator+=( Vec2_f32& a, Vec2_f32 b )
{
a.x += b.x;
a.y += b.y;
return a;
}
inline Vec2_f32& operator-=( Vec2_f32& a, Vec2_f32 b )
{
a.x -= b.x;
a.y -= b.y;
return a;
}
inline Vec2_f32& operator*=( Vec2_f32& v, f32 s )
{
v.x *= s;
v.y *= s;
return v;
}
inline Vec2_f32& operator/=( Vec2_f32& v, f32 s )
{
v.x /= s;
v.y /= s;
return v;
}
struct Vec2_s32
{
union
{
struct
{
s32 x;
s32 y;
};
s32 Basis[ 2 ];
};
};
template<>
constexpr Vec2_s32 tmpl_zero< Vec2_s32 >()
{
return { 0, 0 };
}
inline Vec2_s32 abs( Vec2_s32 v )
{
Vec2_s32 result { abs( v.x ), abs( v.y ) };
return result;
}
inline Vec2_s32 operator-( Vec2_s32 v )
{
Vec2_s32 result { -v.x, -v.y };
return result;
}
inline Vec2_s32 operator+( Vec2_s32 a, Vec2_s32 b )
{
Vec2_s32 result { a.x + b.x, a.y + b.y };
return result;
}
inline Vec2_s32 operator-( Vec2_s32 a, Vec2_s32 b )
{
Vec2_s32 result { a.x - b.x, a.y - b.y };
return result;
}
inline Vec2_s32 operator*( Vec2_s32 v, s32 s )
{
Vec2_s32 result { v.x * s, v.y * s };
return result;
}
inline Vec2_s32 operator/( Vec2_s32 v, s32 s )
{
Vec2_s32 result { v.x / s, v.y / s };
return result;
}
inline Vec2_s32& operator+=( Vec2_s32& a, Vec2_s32 b )
{
a.x += b.x;
a.y += b.y;
return a;
}
inline Vec2_s32& operator-=( Vec2_s32& a, Vec2_s32 b )
{
a.x -= b.x;
a.y -= b.y;
return a;
}
inline Vec2_s32& operator*=( Vec2_s32& v, s32 s )
{
v.x *= s;
v.y *= s;
return v;
}
inline Vec2_s32& operator/=( Vec2_s32& v, s32 s )
{
v.x /= s;
v.y /= s;
return v;
}
using Vec2 = Vec2_f32;
using Vec2i = Vec2_s32;

View File

@ -5,11 +5,11 @@
NS_ENGINE_BEGIN
inline
TileMapPosition subtract( TileMapPosition pos_a, TileMapPosition pos_b )
TileMapPos subtract( TileMapPos pos_a, TileMapPos pos_b )
{
TileMapPosition result {
pos_a.x - pos_b.x,
pos_a.y - pos_b.y,
TileMapPos result {
pos_a.rel_pos - pos_b.rel_pos,
pos_a.tile_x - pos_b.tile_x,
pos_a.tile_y - pos_b.tile_y,
@ -42,13 +42,13 @@ void cannonicalize_coord( TileMap* tile_map, s32* tile_coord, f32* pos_coord )
// TODO(Ed) : Consider moving (Casey wants to)
inline
TileMapPosition recannonicalize_position( TileMap* tile_map, TileMapPosition pos )
TileMapPos recannonicalize_position( TileMap* tile_map, TileMapPos pos )
{
assert( tile_map != nullptr );
TileMapPosition result = pos;
cannonicalize_coord( tile_map, & result.tile_x, & result.x );
cannonicalize_coord( tile_map, & result.tile_y, & result.y );
TileMapPos result = pos;
cannonicalize_coord( tile_map, & result.tile_x, & result.rel_pos.x );
cannonicalize_coord( tile_map, & result.tile_y, & result.rel_pos.y );
return result;
}
@ -109,11 +109,11 @@ TileChunkPosition get_tile_chunk_position_for( TileMap* tile_map, u32 abs_tile_x
}
inline
u32 TileMap_get_tile_value( TileMap* tile_map, u32 tile_x, u32 tile_y, u32 tile_z )
u32 TileMap_get_tile_value( TileMap* tile_map, s32 tile_x, s32 tile_y, s32 tile_z )
{
assert( tile_map != nullptr );
u32 value = 0;
s32 value = 0;
TileChunkPosition chunk_pos = get_tile_chunk_position_for( tile_map, tile_x, tile_y, tile_z );
TileChunk* chunk = TileMap_get_chunk( tile_map, chunk_pos.tile_chunk_x, chunk_pos.tile_chunk_y, chunk_pos.tile_chunk_z );
@ -124,14 +124,14 @@ u32 TileMap_get_tile_value( TileMap* tile_map, u32 tile_x, u32 tile_y, u32 tile_
}
inline
u32 TileMap_get_tile_value( TileMap* tile_map, TileMapPosition position )
u32 TileMap_get_tile_value( TileMap* tile_map, TileMapPos position )
{
u32 value = TileMap_get_tile_value( tile_map, position.tile_x, position.tile_y, position.tile_z );
return value;
}
internal
b32 TileMap_is_point_empty( TileMap* tile_map, TileMapPosition position )
b32 TileMap_is_point_empty( TileMap* tile_map, TileMapPos position )
{
assert( tile_map != nullptr );
@ -168,7 +168,7 @@ void TileMap_set_tile_value( MemoryArena* arena, TileMap* tile_map, s32 abs_tile
internal
b32 TileMap_are_on_same_tile( TileMapPosition* pos_a, TileMapPosition* pos_b )
b32 TileMap_are_on_same_tile( TileMapPos* pos_a, TileMapPos* pos_b )
{
b32 result =
pos_a->tile_x == pos_b->tile_x

View File

@ -50,11 +50,10 @@ struct TileMap
TileChunk* chunks;
};
struct TileMapPosition
struct TileMapPos
{
// Note(Ed) : Relative position from tile center.
f32 x;
f32 y;
Vec2 rel_pos;
// "World-relative (x, y), AKA: Absolute Position
// Fixed point tile locations.

View File

@ -74,7 +74,7 @@ struct PlayerState
f32 width;
f32 height;
engine::TileMapPosition position;
engine::TileMapPos position;
b32 mid_jump;
f32 jump_time;
@ -124,7 +124,7 @@ struct GameState
Bitmap test_bg_hh;
engine::TileMapPosition camera_pos;
engine::TileMapPos camera_pos;
EHeroBitmapsDirection hero_direction;
HeroBitmaps hero_bitmaps[4];

View File

@ -19,6 +19,8 @@ Handmade Engine Translation Unit
#include "platform/platform.hpp"
#include "engine_module.hpp"
#include "gen/vectors.hpp"
#include "gen/physics.hpp"
#include "input.hpp"
#include "tile_map.hpp"
#include "engine.hpp"

View File

@ -20,6 +20,8 @@ Handmade Win32 Platform Translation Unit
// Engine layer headers
#include "engine/engine_module.hpp"
#include "engine/gen/vectors.hpp"
#include "engine/gen/physics.hpp"
#include "engine/input.hpp"
#include "engine/tile_map.hpp"
#include "engine/engine.hpp"

View File

@ -14,6 +14,7 @@
#pragma warning( disable: 4711 ) // Support automatic inline expansion
#pragma warning( disable: 4710 ) // Support automatic inline expansion
#pragma warning( disable: 4805 ) // Support comparisons of s32 to bool.
#pragma warning( disable: 5246 ) // Support for initialization of subobject without braces.
#endif
#ifdef __clang__

View File

@ -8,3 +8,7 @@ void swap( Type& a, Type& b )
a = b;
b = temp;
}
#define Zero( type ) tmpl_zero<type>()
template< class Type >
constexpr Type tmpl_zero();

View File

@ -7,11 +7,43 @@
// TODO(Ed) : Convert all of these to platform-efficient versions
//inline
//s32 abs( s32 value )
//{
// return ;
//}
inline
f32 abs( f32 value )
{
return fabsf(value);
}
inline
f32 sqrt( f32 value )
{
return sqrtf(value);
}
inline
s32 sqrt(s32 value) {
if (value < 0) {
return -1;
}
if (value == 0 || value == 1) {
return value;
}
// Initial guess for the square root
s32 current_estimate = value;
s32 reciprocal_estimate = 1;
// Second estimate based on the reciprocal of our current guess
// Tolerance level for convergence
const s32 tolerance = 1;
while (current_estimate - reciprocal_estimate > tolerance) {
current_estimate = (current_estimate + reciprocal_estimate) / 2;
reciprocal_estimate = value / current_estimate;
}
return current_estimate;
}
inline
s32 floor( f32 value )

View File

@ -188,6 +188,44 @@ else {
function build-engine
{
$unit = Join-Path $path_codegen 'engine_gen.cpp'
$should_build = (check-FileForChanges $unit) -eq $true
if ( $should_build )
{
$executable = Join-Path $path_build 'engine_gen.exe'
$compiler_args = @()
$compiler_args += ( $flag_define + 'GEN_TIME' )
$linker_args = @(
$flag_link_win_subsystem_console
)
$build_result = build-simple $path_build $includes $compiler_args $linker_args $unit $executable
if ( $build_result -eq $false ) {
return $false
}
Push-Location $path_engine_gen
$time_taken = Measure-Command {
& $executable 2>&1 | ForEach-Object {
write-host `t $_ -ForegroundColor Green
}
}
Pop-Location
push-location $path_scripts
$include = @(
'*.cpp'
'*.hpp'
)
format-cpp $path_engine_gen $include
pop-location
}
else {
write-host "No changes detected in engine gen, skipping build" -ForegroundColor Yellow
}
$should_build = check-ModuleForChanges $path_engine
if ( $should_build -eq $false ) {
write-host "No changes detected in engine module, skipping build" -ForegroundColor Yellow
@ -318,13 +356,6 @@ function build-engine
$should_build = (check-FileForChanges $unit) -eq $true
if ( $should_build )
{
# Delete old PDBs
$pdb_files = Get-ChildItem -Path $path_build -Filter "engine_postbuild_gen_*.pdb"
foreach ($file in $pdb_files) {
Remove-Item -Path $file.FullName -Force
if ($verbose) { Write-Host "Deleted $file" -ForegroundColor Green }
}
$compiler_args = @()
$compiler_args += ( $flag_define + 'GEN_TIME' )