Last active
July 8, 2026 07:21
-
-
Save elamhut/21fed18483148eb753eca33bf38a4da7 to your computer and use it in GitHub Desktop.
Ryan Fleury's example code for Fat Structs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| typedef struct Entity Entity; | |
| struct Entity | |
| { | |
| // NOTE(rjf): Properties/Generation | |
| u64 properties[(EntityProperty_MAX+63)/64]; | |
| u64 generation; | |
| String8 tag; | |
| // NOTE(rjf): Tree Data | |
| Entity *parent; | |
| Entity *next; | |
| Entity *prev; | |
| Entity *first_child; | |
| Entity *last_child; | |
| // NOTE(rjf): Timed Removal | |
| f32 seconds_to_removal; | |
| // NOTE(rjf): General Rendering Info | |
| Vec4 inverse_tint; // Additive inverse to zero-initialize to full opacity + white. | |
| f32 hurt_transition; | |
| // NOTE(rjf): Sprite | |
| R_Texture *sprite_texture; | |
| Rect2D sprite_source; | |
| f32 sprite_tilt; | |
| // NOTE(rjf): Rendered Item | |
| ItemHandle render_item; | |
| f32 render_item_tilt; | |
| // NOTE(rjf): Rendered Equip Slot | |
| EntityHandle render_equip_slot_entity; | |
| EquipSlot render_equip_slot; | |
| f32 render_equip_slot_tilt; | |
| // NOTE(rjf): Velocity Bob | |
| Vec3 velocity_bob_vector; | |
| f32 velocity_bob_size; | |
| f32 velocity_bob_speed_factor; | |
| f32 velocity_bob_sin_pos; | |
| f32 velocity_bob_transition; | |
| // NOTE(rjf): Time Bob | |
| Vec3 time_bob_vector; | |
| f32 time_bob_size; | |
| f32 time_bob_speed_factor; | |
| f32 time_bob_sin_pos; | |
| // NOTE(rjf): Time Squish | |
| f32 time_squish_size; | |
| f32 time_squish_speed_factor; | |
| f32 time_squish_sin_pos; | |
| // NOTE(rjf): Position, Physics, Size info | |
| Vec3 position; | |
| Body body; | |
| Vec3 offset_from_parent; | |
| Vec3 position_snap; | |
| Vec3 position_snap_target; | |
| f32 position_snap_rate; | |
| f32 position_snap_decay_rate; | |
| // NOTE(rjf): Material Properties | |
| f32 heat; | |
| // NOTE(rjf): Particle Generation | |
| ParticleGenParameters particle_gen; | |
| f32 seconds_to_next_particle_generation; | |
| // NOTE(rjf): Hit-Particle Info | |
| ParticleKind hit_particle_kind; | |
| // NOTE(rjf): Trigger | |
| Trigger trigger; | |
| // NOTE(rjf): Inventory/Equipment | |
| u64 item_count; | |
| Item *first_item; | |
| Item *last_item; | |
| Item *equips[EquipSlot_MAX]; | |
| }; | |
| // NOTE(rjf): Basic Type Conversions | |
| internal String8 StringFromTriggerKind(TriggerKind kind); | |
| // NOTE(rjf): Entity Introspection | |
| internal Entity *RootFromEntity(Entity *entity); | |
| internal Entity *ChildFromTag(Entity *parent, String8 tag); | |
| internal Vec3 PositionFromEntity(Entity *entity); | |
| internal Vec3 VelocityFromEntity(Entity *entity); | |
| internal f32 MassFromEntity(Entity *entity); | |
| internal Vec4 TintFromEntity(Entity *entity); | |
| internal f32 SquishFromEntity(Entity *entity); | |
| internal void SnapEntityPosition(Entity *entity, Vec3 offset, f32 rate, f32 decay_rate); | |
| internal b32 EntityHasProperty(Entity *entity, EntityProperty property); | |
| // NOTE(rjf): Entity Constructor Helpers | |
| internal Entity *SetEntityProperty(Entity *entity, EntityProperty property); | |
| internal Entity *RemoveEntityProperty(Entity *entity, EntityProperty property); | |
| internal Entity *SetEntityBody(Entity *entity, Body body); | |
| internal Entity *SetEntityTimedRemoval(Entity *entity, f32 seconds); | |
| internal Entity *SetEntitySprite(Entity *entity, R_Texture *texture, Rect2D source, f32 tilt); | |
| internal Entity *SetEntityRenderItem(Entity *entity, ItemHandle item, f32 tilt); | |
| internal Entity *SetEntityRenderEquipSlot(Entity *entity, EntityHandle equip_entity, EquipSlot slot, f32 tilt); | |
| internal Entity *SetEntityVelocityBob(Entity *entity, Vec3 bob_vector, f32 bob_size, f32 bob_speed); | |
| internal Entity *SetEntityTimeBob(Entity *entity, Vec3 bob_vector, f32 bob_size, f32 bob_speed); | |
| internal Entity *SetEntityTimeSquish(Entity *entity, f32 squish_size, f32 squish_speed); | |
| internal Entity *SetEntityParticleGeneration(Entity *entity, ParticleGenParameters params); | |
| internal Entity *SetEntityTrigger(Entity *entity, TriggerKind kind, Input input, Shape shape, ItemKind item_kind, Item *item, EntityHandle source_entity, AttackFlags attack_flags); | |
| internal Entity *SetEntityTrigger_Container(Entity *entity, TriggerKind kind, Input input, Shape shape); | |
| internal Entity *SetEntityTrigger_Hit(Entity *entity, Shape shape, AttackFlags attack_flags); | |
| internal Entity *SetEntityTrigger_ItemKind(Entity *entity, Input input, Shape shape, ItemKind item_kind, EntityHandle source_entity); | |
| internal Entity *SetEntityTrigger_Item(Entity *entity, Input input, Shape shape, Item *item, EntityHandle source_entity); | |
| internal Entity *SetEntityHitParticles(Entity *entity, ParticleKind kind); | |
| internal Entity *TagEntity(Entity *entity, String8 string); | |
| internal void PushEntityChild(Entity *parent, Entity *child, Vec3 offset); | |
| // NOTE(rjf): Handles | |
| internal EntityHandle NullEntityHandle(void); | |
| internal b32 EntityHandleIsNull(EntityHandle handle); | |
| internal EntityHandle HandleFromEntityIndexAndGeneration(u64 index, u64 generation); | |
| internal u64 EntityIndexFromHandle(EntityHandle handle); | |
| // NOTE(rjf): Items | |
| internal void PushEntityItem(Entity *entity, Item *item); | |
| internal void InsertEntityItem(Entity *entity, Item *item, Item *prev_item); | |
| internal void RemoveEntityItem(Entity *entity, Item *item); | |
| internal void EquipEntityItem(Entity *entity, EquipSlot slot, Item *item); | |
| internal Entity * | |
| G_MakeHumanoid(Vec3 position, | |
| int head_style, | |
| int hand_style, | |
| int body_style, | |
| int hair_style, | |
| int hair_color, | |
| ParticleKind bleed_style) | |
| { | |
| Rect2D head_source = ArtSource(ArtAnnotation_Heads, R2D(16*head_style, 0, 16, 16)); | |
| Rect2D hand_source = ArtSource(ArtAnnotation_Hands, R2D(16*hand_style, 0, 16, 16)); | |
| Rect2D body_source = ArtSource(ArtAnnotation_Bodies, R2D(16*body_style, 0, 16, 16)); | |
| Rect2D hair_source = ArtSource(ArtAnnotation_Hair, R2D(16*hair_style, | |
| 16*hair_color, | |
| 16, 16)); | |
| Entity *base = G_AllocateEntity(); | |
| base->position = position; | |
| SetEntityProperty(base, EntityProperty_AllowTriggers); | |
| SetEntityBody(base, MakeBody(MakeShape(ShapeKind_Sphere, V3(0.5f)), 0.8f, 0.2f)); | |
| Entity *body = G_AllocateEntity(); | |
| { | |
| SetEntitySprite(body, &game-;>art, body_source, 1.f); | |
| SetEntityProperty(body, EntityProperty_AllowTriggers); | |
| SetEntityVelocityBob(body, V3(0, 0, 1), 0.02f, 1.f); | |
| SetEntityHitParticles(body, bleed_style); | |
| PushEntityChild(base, body, V3(0, +0.f, 0.f)); | |
| } | |
| Entity *head = G_AllocateEntity(); | |
| { | |
| TagEntity(head, S8Lit("Head")); | |
| SetEntitySprite(head, &game-;>art, head_source, 0.8f); | |
| SetEntityVelocityBob(head, V3(0, 0, 1), 0.02f, 1.f); | |
| SetEntityTimeBob(head, V3(0, 0, 1), 0.02f, 4.f); | |
| SetEntityProperty(head, EntityProperty_SnapOnHit); | |
| SetEntityHitParticles(head, bleed_style); | |
| PushEntityChild(body, head, V3(0, 0.05f, 0.6f)); | |
| } | |
| Entity *hair = G_AllocateEntity(); | |
| { | |
| SetEntitySprite(hair, &game-;>art, hair_source, 0.8f); | |
| PushEntityChild(head, hair, V3(0, 0, 0)); | |
| } | |
| Entity *head_equip = G_AllocateEntity(); | |
| { | |
| TagEntity(head_equip, S8Lit("Head Equip")); | |
| SetEntityRenderEquipSlot(head_equip, G_HandleFromEntity(base), EquipSlot_Head, 0.8f); | |
| PushEntityChild(head, head_equip, V3(0, 0.01f, 0.01f)); | |
| } | |
| Entity *left_hand = G_AllocateEntity(); | |
| { | |
| TagEntity(left_hand, S8Lit("Left Hand")); | |
| SetEntitySprite(left_hand, &game-;>art, hand_source, 1.f); | |
| SetEntityVelocityBob(left_hand, V3(0, 1, 0), 0.1f, 0.5f); | |
| SetEntityTimeBob(left_hand, V3(0, 0, -1), 0.015f, 4.f); | |
| SetEntityProperty(left_hand, EntityProperty_SnapOnHit); | |
| SetEntityHitParticles(left_hand, bleed_style); | |
| PushEntityChild(body, left_hand, V3(-0.3f, 0.01f, 0)); | |
| } | |
| Entity *left_hand_equip = G_AllocateEntity(); | |
| { | |
| TagEntity(left_hand_equip, S8Lit("Left Hand Equip")); | |
| SetEntityRenderEquipSlot(left_hand_equip, G_HandleFromEntity(base), EquipSlot_LeftHand, 0.5f); | |
| PushEntityChild(left_hand, left_hand_equip, V3(0, 0.2f, 0.1f)); | |
| } | |
| Entity *right_hand = G_AllocateEntity(); | |
| { | |
| TagEntity(right_hand, S8Lit("Right Hand")); | |
| SetEntitySprite(right_hand, &game-;>art, hand_source, 1.f); | |
| SetEntityVelocityBob(right_hand, V3(0, -1, 0), 0.1f, 0.5f); | |
| SetEntityTimeBob(right_hand, V3(0, 0, -1), 0.015f, 4.f); | |
| SetEntityProperty(right_hand, EntityProperty_SnapOnHit); | |
| SetEntityHitParticles(right_hand, bleed_style); | |
| PushEntityChild(body, right_hand, V3(+0.3f, 0.01f, 0)); | |
| } | |
| Entity *right_hand_equip = G_AllocateEntity(); | |
| { | |
| TagEntity(right_hand_equip, S8Lit("Right Hand Equip")); | |
| SetEntityRenderEquipSlot(right_hand_equip, G_HandleFromEntity(base), EquipSlot_RightHand, 0.5f); | |
| PushEntityChild(right_hand, right_hand_equip, V3(0, 0.2f, 0.1f)); | |
| } | |
| return base; | |
| } | |
| internal Entity * | |
| G_MakeSkeleton(Vec3 position) | |
| { | |
| return G_MakeHumanoid(position, 4, 4, 0, 0, 0, ParticleKind_Bone); | |
| } | |
| internal Entity * | |
| G_MakeMage(Vec3 position) | |
| { | |
| return G_MakeHumanoid(position, 5, 5, 2, 0, 0, ParticleKind_Blood); | |
| } | |
| internal Entity * | |
| G_MakeJelly(Vec3 position) | |
| { | |
| Entity *base = G_AllocateEntity(); | |
| base->position = position; | |
| SetEntityProperty(base, EntityProperty_AllowTriggers); | |
| SetEntityBody(base, MakeBody(MakeShape(ShapeKind_Sphere, V3(0.4f)), 0.9f, 1.f)); | |
| SetEntitySprite(base, &game-;>art, ArtSource(ArtAnnotation_Heads, R2D(48, 0, 16, 16)), 0.8f); | |
| SetEntityTimeSquish(base, 0.05f, 3.f); | |
| SetEntityTrigger_Hit(base, ScaleShape(base->body.shape, 1.1f), AttackFlag_Clobber); | |
| SetEntityHitParticles(base, ParticleKind_Jelly); | |
| return base; | |
| } | |
| internal Entity * | |
| G_MakeItemCollectible(Vec3 position, ItemKind item_kind) | |
| { | |
| Entity *base = G_AllocateEntity(); | |
| base->position = position; | |
| SetEntityBody(base, MakeBody(MakeShape(ShapeKind_Sphere, V3(0.5f)), 0.f, 0.2f)); | |
| SetEntitySprite(base, &game-;>art, | |
| ArtSource(ArtAnnotation_Items, item_kind_metadata[item_kind].source), | |
| 0.4f); | |
| SetEntityTimeBob(base, V3(0, 0, 1), 0.2f, 3.f); | |
| SetEntityTrigger_ItemKind(base, 0, ScaleShape(base->body.shape, 1.1f), item_kind, NullEntityHandle()); | |
| SetEntityProperty(base, EntityProperty_DieOnTrigger); | |
| return base; | |
| } | |
| internal Entity * | |
| G_MakeItemCollectibleFromItem(Vec3 position, Item *item, Entity *source_entity) | |
| { | |
| Entity *base = G_AllocateEntity(); | |
| base->position = position; | |
| SetEntityBody(base, MakeBody(MakeShape(ShapeKind_Sphere, V3(0.5f)), 0.2f, 0.2f)); | |
| SetEntityRenderItem(base, HandleFromItem(item), 0.4f); | |
| SetEntityTimeBob(base, V3(0, 0, 1), 0.2f, 3.f); | |
| SetEntityTrigger_Item(base, 0, ScaleShape(base->body.shape, 1.1f), item, G_HandleFromEntity(source_entity)); | |
| SetEntityProperty(base, EntityProperty_DieOnTrigger); | |
| RemoveEntityItem(item->entity, item); | |
| PushEntityItem(base, item); | |
| return base; | |
| } | |
| internal Entity * | |
| G_MakeTreeLeaf(f32 height, b32 big) | |
| { | |
| Entity *entity = G_AllocateEntity(); | |
| SetEntityProperty(entity, EntityProperty_SnapOnHit); | |
| SetEntityHitParticles(entity, ParticleKind_Leaf); | |
| f32 tilt = 0.3f; | |
| if(big) | |
| { | |
| SetEntitySprite(entity, &game-;>art, | |
| ArtSource(ArtAnnotation_Trees, R2D(16, 0, 32, 32)), | |
| tilt); | |
| } | |
| else | |
| { | |
| SetEntitySprite(entity, &game-;>art, | |
| ArtSource(ArtAnnotation_Trees, R2D(48+16*((int)RandomF32(0, 4)), 0, 16, 16)), | |
| tilt); | |
| } | |
| SetEntityTimeBob(entity, V3(1, 0, 0), 0.1f, 0.25f+RandomF32(-0.08f, +0.08f)); | |
| if(height < 1.f) | |
| { | |
| int number_of_children = (int)RandomF32(0, 4); | |
| for(int i = 0; i < number_of_children; i += 1) | |
| { | |
| Entity *sub_leaf = G_MakeTreeLeaf(height+0.5f, 0); | |
| PushEntityChild(entity, sub_leaf, V3(RandomF32(-0.6f, +0.6f), | |
| RandomF32(-0.6f, +0.6f)-0.01f, | |
| 0.3f)); | |
| } | |
| } | |
| return entity; | |
| } | |
| internal Entity * | |
| G_MakeTree(Vec3 position) | |
| { | |
| Entity *base = G_AllocateEntity(); | |
| base->position = position; | |
| SetEntityProperty(base, EntityProperty_Static); | |
| SetEntityProperty(base, EntityProperty_AllowTriggers); | |
| SetEntityHitParticles(base, ParticleKind_Wood); | |
| SetEntityBody(base, MakeBody(MakeShape(ShapeKind_Sphere, V3(0.5f)), INFINITY, 0.2f)); | |
| Entity *stump = G_AllocateEntity(); | |
| SetEntitySprite(stump, &game-;>art, ArtSource(ArtAnnotation_Trees, R2D(0, 0, 16, 32)), 0.7f); | |
| int number_of_big_leaves = (int)RandomF32(2, 6); | |
| for(int i = 0; i < number_of_big_leaves; i += 1) | |
| { | |
| PushEntityChild(stump, G_MakeTreeLeaf(0.f, 1), V3(RandomF32(-1.f, +1.f), | |
| RandomF32(-1.f, +1.f)-0.2f, | |
| 1.2f)); | |
| } | |
| PushEntityChild(base, stump, V3(0, 0, 0.3f)); | |
| return base; | |
| } | |
| internal Entity * | |
| G_MakeCampFire(Vec3 position) | |
| { | |
| Entity *base = G_AllocateEntity(); | |
| base->position = position; | |
| SetEntityBody(base, MakeBody(MakeShape(ShapeKind_Sphere, V3(0.5f)), 4.f, 0.2f)); | |
| SetEntitySprite(base, &game-;>art, ArtSource(ArtAnnotation_Props, R2D(0, 0, 16, 16)), 0.4f); | |
| G_SetEntityOnFire(base, -1.f); | |
| SetEntityProperty(base, EntityProperty_AllowTriggers); | |
| return base; | |
| } | |
| internal Entity * | |
| G_MakeWorkbenchLeg(void) | |
| { | |
| Entity *leg = G_AllocateEntity(); | |
| SetEntityBody(leg, MakeBody(MakeShape(ShapeKind_Sphere, V3(0.5f)), 0.f, 0.2f)); | |
| SetEntitySprite(leg, &game-;>art, ArtSource(ArtAnnotation_Props, R2D(16, 0, 16, 16)), 0.8f); | |
| SetEntityProperty(leg, EntityProperty_Static); | |
| return leg; | |
| } | |
| internal Entity * | |
| G_MakeWorkbench(Vec3 position) | |
| { | |
| Entity *base = G_AllocateEntity(); | |
| base->position = position; | |
| SetEntityBody(base, MakeBody(MakeShape(ShapeKind_Cuboid, V3(1.3f, 0.3f, 0.5f)), INFINITY, 0.8f)); | |
| SetEntityTrigger_Container(base, TriggerKind_Craft, Input_Interact, | |
| ScaleShape(base->body.shape, 1.2f)); | |
| SetEntityProperty(base, EntityProperty_Static); | |
| Entity *table = G_AllocateEntity(); | |
| { | |
| SetEntitySprite(table, &game-;>art, ArtSource(ArtAnnotation_Props, R2D(32, 0, 48, 16)), 0.3f); | |
| PushEntityChild(table, G_MakeWorkbenchLeg(), V3(-1.3f, -0.3f, -0.4f)); | |
| PushEntityChild(table, G_MakeWorkbenchLeg(), V3(+1.3f, -0.3f, -0.4f)); | |
| PushEntityChild(table, G_MakeWorkbenchLeg(), V3(-1.3f, +0.3f, -0.6f)); | |
| PushEntityChild(table, G_MakeWorkbenchLeg(), V3(+1.3f, +0.3f, -0.6f)); | |
| PushEntityChild(base, table, V3(0, 0, 0.1f)); | |
| } | |
| Entity *saw = G_AllocateEntity(); | |
| SetEntitySprite(saw, &game-;>art, ArtSource(ArtAnnotation_Props, R2D(80, 0, 16, 16)), 0.4f); | |
| PushEntityChild(table, saw, V3(-1.f, 0.2f, +0.2f)); | |
| Entity *hammer = G_AllocateEntity(); | |
| SetEntitySprite(hammer, &game-;>art, ArtSource(ArtAnnotation_Props, R2D(96, 0, 16, 16)), 0.4f); | |
| PushEntityChild(table, hammer, V3(+1.f, 0.2f, +0.2f)); | |
| Entity *page1 = G_AllocateEntity(); | |
| SetEntitySprite(page1, &game-;>art, ArtSource(ArtAnnotation_Props, R2D(112, 0, 16, 16)), 0.2f); | |
| PushEntityChild(table, page1, V3(-0.3f, -0.1f, +0.2f)); | |
| Entity *page2 = G_AllocateEntity(); | |
| SetEntitySprite(page2, &game-;>art, ArtSource(ArtAnnotation_Props, R2D(128, 0, 16, 16)), 0.2f); | |
| PushEntityChild(table, page2, V3(+0.1f, 0.2f, +0.2f)); | |
| return base; | |
| } | |
| internal Entity * | |
| G_MakeChest(Vec3 position) | |
| { | |
| Entity *base = G_AllocateEntity(); | |
| base->position = position; | |
| SetEntityBody(base, MakeBody(MakeShape(ShapeKind_Cuboid, V3(0.5f, 0.5f, 0.5f)), 4.f, 0.f)); | |
| SetEntityHitParticles(base, ParticleKind_Wood); | |
| SetEntitySprite(base, &game-;>art, ArtSource(ArtAnnotation_Props, R2D(144, 0, 32, 16)), 0.5f); | |
| SetEntityProperty(base, EntityProperty_AllowTriggers); | |
| SetEntityTrigger_Container(base, TriggerKind_Open, Input_Interact, ScaleShape(base->body.shape, 1.5f)); | |
| Entity *cover = G_AllocateEntity(); | |
| SetEntityHitParticles(cover, ParticleKind_Wood); | |
| SetEntitySprite(cover, &game-;>art, ArtSource(ArtAnnotation_Props, R2D(176, 0, 32, 16)), 0.3f); | |
| PushEntityChild(base, cover, V3(0, 0, 0.3f)); | |
| return base; | |
| } | |
| internal Entity * | |
| G_MakeHitBox(Shape shape, f32 seconds, AttackFlags attack_flags) | |
| { | |
| Entity *box = G_AllocateEntity(); | |
| SetEntityTrigger_Hit(box, shape, attack_flags); | |
| SetEntityTimedRemoval(box, seconds); | |
| SetEntityProperty(box, EntityProperty_DieOnTrigger); | |
| return box; | |
| } | |
| internal Entity * | |
| G_MakeProjectile(Vec3 position, Vec3 velocity, f32 duration) | |
| { | |
| Entity *p = G_AllocateEntity(); | |
| p->position = position; | |
| SetEntityBody(p, MakeBody(MakeShape(ShapeKind_Sphere, V3(0.3f)), 0.8f, 1.f)); | |
| ApplyImpulseToBody(&p-;>body, velocity); | |
| SetEntityTimedRemoval(p, duration); | |
| return p; | |
| } | |
| internal void | |
| G_RenderEntity(Entity *entity) | |
| { | |
| Vec3 p = PositionFromEntity(entity); | |
| Vec4 tint = TintFromEntity(entity); | |
| if(EntityHasProperty(entity, EntityProperty_RenderSprite)) | |
| { | |
| R_Texture *texture = entity->sprite_texture; | |
| Rect2D source = entity->sprite_source; | |
| f32 tilt = entity->sprite_tilt; | |
| f32 squish = SquishFromEntity(entity); | |
| RenderSprite(p, source, texture, tint, tilt, squish); | |
| } | |
| if(EntityHasProperty(entity, EntityProperty_RenderItem)) | |
| { | |
| Item *item = ItemFromHandle(entity->render_item); | |
| if(item != 0) | |
| { | |
| Matrix4x4 xform = MakeMatrix4x4(1.f); | |
| xform = Multiply4x4(Rotate4x4(-90*entity->render_item_tilt, V3(1, 0, 0)), xform); | |
| xform = Multiply4x4(Translate4x4(p), xform); | |
| RenderItem(item, xform); | |
| } | |
| } | |
| if(EntityHasProperty(entity, EntityProperty_RenderEquipSlot)) | |
| { | |
| Entity *equip_entity = G_EntityFromHandle(entity->render_equip_slot_entity); | |
| if(equip_entity != 0) | |
| { | |
| Item *item = equip_entity->equips[entity->render_equip_slot]; | |
| if(item != 0) | |
| { | |
| Matrix4x4 xform = MakeMatrix4x4(1.f); | |
| //xform = Multiply4x4(Rotate4x4(-20.f, V3(0, 0, 1)), xform); | |
| xform = Multiply4x4(Rotate4x4(-90*entity->render_equip_slot_tilt, V3(1, 0, 0)), xform); | |
| xform = Multiply4x4(Translate4x4(p), xform); | |
| RenderItem(item, xform); | |
| } | |
| } | |
| } | |
| } | |
| // simple snippet from particle generation implementation... | |
| if(EntityHasProperty(entity, EntityProperty_GenerateParticles)) | |
| { | |
| ParticleGenParameters *params = &entity-;>particle_gen; | |
| entity->seconds_to_next_particle_generation -= APP_DT(); | |
| if(entity->seconds_to_next_particle_generation <= 0.f) | |
| { | |
| entity->seconds_to_next_particle_generation = params->seconds_between_generations; | |
| Vec3 entity_p = PositionFromEntity(entity); | |
| for(u16 i = 0; i < params->particles_per_generation; i += 1) | |
| { | |
| Vec3 position = | |
| { | |
| entity_p.x + params->position_variance.x * RandomF32(-1.f, 1.f), | |
| entity_p.y + params->position_variance.y * RandomF32(-1.f, 1.f), | |
| entity_p.z + params->position_variance.z * RandomF32(-1.f, 1.f), | |
| }; | |
| Vec3 velocity = | |
| { | |
| params->velocity_weight_vector.x + params->velocity_variance.x * RandomF32(-1.f, 1.f), | |
| params->velocity_weight_vector.y + params->velocity_variance.y * RandomF32(-1.f, 1.f), | |
| params->velocity_weight_vector.z + params->velocity_variance.z * RandomF32(-1.f, 1.f), | |
| }; | |
| G_PushParticle(params->kind, position, velocity, 1.f + params->life_variance * RandomF32(-1.f, 1.f)); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment