RogueLife/src/comp/particle.c

119 lines
2.6 KiB
C

#include "comp/entity.h"
#include "comp/physical.h"
#include "comp/particle.h"
#include "geometry.h"
#include <gint/defs/attributes.h>
#include <gint/display.h>
#include <stdio.h>
entity_t *particle_make_damage(entity_t *target, int damage, int color)
{
entity_t *e = entity_make(particle);
particle_t *p = getcomp(e, particle);
physical_t *target_p = getcomp(target, physical);
p->type = PARTICLE_DAMAGE;
p->plane = CEILING;
p->x = target_p->x;
p->y = target_p->y - fix(0.5);
p->z = 0;
p->age = 0;
p->DAMAGE.damage = damage;
p->DAMAGE.color = color;
return e;
}
entity_t *particle_make_dash(entity_t *target)
{
entity_t *e = entity_make(particle);
particle_t *p = getcomp(e, particle);
physical_t *target_p = getcomp(target, physical);
p->type = PARTICLE_DASH;
p->plane = HORIZONTAL;
p->x = target_p->x;
p->y = target_p->y;
p->z = 0;
p->age = 0;
return e;
}
static bool damage_update(particle_t *p, GUNUSED fixed_t dt)
{
return p->age >= 300;
}
static void damage_render(int x, int y, particle_t const *p)
{
extern bopti_image_t img_font_damage_white;
extern bopti_image_t img_font_damage_red;
bopti_image_t *img = (p->DAMAGE.color == C_RED) ? &img_font_damage_red :
&img_font_damage_white;
int char_w = img->width / 10;
int char_h = img->height;
/* Determine number of characters */
char str[16];
int n = snprintf(str, 16, "%d", p->DAMAGE.damage);
y -= char_h / 2;
x -= (char_w * n + 1) / 2;
for(int i = 0; i < n; i++) {
int offset = (char_w + 1) * (str[i] - '0');
dsubimage(x, y, img, offset, 0, char_w, char_h, DIMAGE_NONE);
x += char_w;
}
}
static bool dash_update(particle_t *p, GUNUSED fixed_t dt)
{
return p->age >= 256;
}
static void dash_render(int x, int y, particle_t const *p)
{
/* 32 * (1 - age/256) */
int radius = 32 - (p->age >> 3);
for(int dx = -5; dx <= +5; dx++)
for(int dy = -5; dy <= +5; dy++) {
if(dx * dx + dy * dy <= radius) {
int index = 396 * (y + dy) + (x + dx);
gint_vram[index] = ~((~gint_vram[index] & 0xf7de) >> 1);
}
}
}
//---
// Generic functions
//---
bool particle_update(particle_t *p, fixed_t dt)
{
p->age += fround(dt * 1000);
if(p->type == PARTICLE_DAMAGE)
return damage_update(p, dt);
if(p->type == PARTICLE_DASH)
return dash_update(p, dt);
return true;
}
void particle_render(int x, int y, particle_t const *p)
{
if(p->type == PARTICLE_DAMAGE)
return damage_render(x, y, p);
if(p->type == PARTICLE_DASH)
return dash_render(x, y, p);
}