169 lines
4.0 KiB
C
169 lines
4.0 KiB
C
#include "comp/entity.h"
|
|
#include "comp/physical.h"
|
|
#include "comp/particle.h"
|
|
#include "anim.h"
|
|
#include "geometry.h"
|
|
#include "util.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->bound_to_entity = false;
|
|
p->x = target_p->x;
|
|
p->y = target_p->y;
|
|
p->z = fix(0.5);
|
|
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->bound_to_entity = false;
|
|
p->x = target_p->x;
|
|
p->y = target_p->y;
|
|
p->z = 0;
|
|
p->age = 0;
|
|
|
|
return e;
|
|
}
|
|
|
|
entity_t *particle_make_buff(entity_t *target, int color)
|
|
{
|
|
entity_t *e = entity_make(particle);
|
|
particle_t *p = getcomp(e, particle);
|
|
|
|
p->type = PARTICLE_BUFF;
|
|
p->plane = CEILING;
|
|
p->bound_to_entity = true;
|
|
p->bound_entity = target;
|
|
p->z = fix(0.5);
|
|
p->age = 0;
|
|
|
|
p->BUFF.color = color;
|
|
|
|
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)
|
|
{
|
|
font_damage_print(x, y, p->DAMAGE.color, DTEXT_CENTER, DTEXT_MIDDLE,
|
|
p->DAMAGE.damage);
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
static bool buff_update(particle_t *p, GUNUSED fixed_t dt)
|
|
{
|
|
int total_ms = 0;
|
|
anim_frame_t const *frame = anims_item_buff.start[0];
|
|
while(frame) {
|
|
total_ms += frame->duration;
|
|
frame = frame->next;
|
|
}
|
|
|
|
return p->age >= total_ms;
|
|
}
|
|
|
|
static void buff_render(int x, int y, particle_t const *p)
|
|
{
|
|
int ms = p->age;
|
|
anim_frame_t const *frame = anims_item_buff.start[0];
|
|
while(frame && ms > frame->duration) {
|
|
ms -= frame->duration;
|
|
frame = frame->next;
|
|
}
|
|
if(!frame)
|
|
return;
|
|
|
|
/* Find black and white in the palette */
|
|
int black_index = -1;
|
|
int white_index = -1;
|
|
for(int i = 0; i < frame->sheet->color_count; i++) {
|
|
if(black_index == -1 && frame->sheet->palette[i] == 0x0000)
|
|
black_index = i;
|
|
if(white_index == -1 && frame->sheet->palette[i] == 0xffff)
|
|
white_index = i;
|
|
}
|
|
|
|
/* Render while swapping black for p->BUFF.color */
|
|
frame->sheet->palette[black_index] = p->BUFF.color;
|
|
frame->sheet->palette[white_index] = ~((~p->BUFF.color & 0xf7de) >> 1);
|
|
|
|
dsubimage_p4(x - frame->cx, y - frame->cy, frame->sheet,
|
|
frame->x, frame->y, frame->w, frame->h, DIMAGE_NONE);
|
|
|
|
frame->sheet->palette[black_index] = 0x0000;
|
|
frame->sheet->palette[white_index] = 0xffff;
|
|
}
|
|
|
|
//---
|
|
// 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);
|
|
if(p->type == PARTICLE_BUFF)
|
|
return buff_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);
|
|
if(p->type == PARTICLE_BUFF)
|
|
return buff_render(x, y, p);
|
|
}
|