ReC98/th01/main/bullet/laser_s.cpp

165 lines
3.6 KiB
C++

extern "C" {
#include "platform.h"
#include "pc98.h"
#include "planar.h"
#include "master.hpp"
#include "th01/sprites/laser_s.h"
#include "th01/hardware/egc.h"
#include "th01/hardware/graph.h"
#include "th01/hardware/input.hpp"
#include "th01/main/playfld.hpp"
#include "th01/main/player/player.hpp"
#include "th01/main/bullet/laser_s.hpp"
}
void CShootoutLaser::spawn(
screen_x_t _origin_left,
vram_y_t _origin_y,
screen_x_t _target_left,
vram_y_t _target_y,
int speed_multiplied_by_8,
unsigned char _col,
int _moveout_at_age,
int w
)
{
if(alive) {
return;
}
origin_left.v = to_laser_pixel(_origin_left);
origin_y.v = to_laser_pixel(_origin_y);
ray_start_left.v = origin_left.v;
ray_start_y.v = origin_y.v;
target_left = _target_left;
target_y = _target_y;
unknown = -256;
unsigned char angle = iatan2(
(_target_y - _origin_y), (_target_left - _origin_left)
);
step_x.v = Cos8(angle);
step_y.v = Sin8(angle);
velocity_x.v = ((speed_multiplied_by_8 * step_x.v) >> 3);
velocity_y.v = ((speed_multiplied_by_8 * step_y.v) >> 3);
ray_extend_speed = (speed_multiplied_by_8 / 8);
w--;
width_cel = w;
alive = true;
damaging = true;
moveout_at_age = _moveout_at_age;
age = 0;
col = _col;
ray_moveout_speed = ray_extend_speed;
ray_length = 0;
}
void CShootoutLaser::hittest_and_render(void)
{
screen_x_t left = ray_i_left.to_pixel();
vram_y_t y = ray_i_y.to_pixel();
unsigned int i;
vram_offset_t vram_offset;
int preshift = (width_cel * PRESHIFT);
dots16_t dots = 0;
unsigned int pixel_count;
if(put_flag) {
pixel_count = ray_length;
grcg_setcolor_rmw(col);
} else {
pixel_count = ray_moveout_speed;
}
for(i = 0; i < pixel_count; i++) {
if(
((left >> 3) != ray_i_left.to_vram_byte_amount()) ||
(y != ray_i_y.to_pixel())
) {
if(put_flag) {
vram_offset = vram_offset_shift(left, y);
grcg_put(vram_offset, dots, 16);
dots = 0;
if(!player_invincible && damaging) {
if(
(y > (player_top + 8)) &&
((player_left + ((PLAYER_W / 8) * 1)) <= left) &&
((player_left + ((PLAYER_W / 8) * 6)) > left)
) {
done = true;
}
}
}
left = ray_i_left.to_pixel();
y = ray_i_y.to_pixel();
if(
(left > (PLAYFIELD_RIGHT - 2)) ||
(left < PLAYFIELD_LEFT) ||
(y < PLAYFIELD_TOP) ||
(y > (PLAYFIELD_BOTTOM - 1))
) {
break;
}
}
// MODDERS: Should just be
// sSHOOTOUT_LASER[preshift][(ray_i_left.to_pixel()...)].
// (Or actually, how about throwing away that sprite altogether?)
dots |= sSHOOTOUT_LASER[0][
preshift + (ray_i_left.to_pixel() & (BYTE_DOTS - 1))
];
if(put_flag == SL_RAY_UNPUT) {
egc_copy_rect_1_to_0_16(
ray_i_left.to_pixel(),
ray_i_y.to_pixel(),
(sizeof(dots) * BYTE_DOTS),
1
);
}
ray_i_left.v += step_x.v;
ray_i_y.v += step_y.v;
}
if(put_flag) {
grcg_off_func();
}
}
void CShootoutLaser::update_hittest_and_render(void)
{
if(!alive) {
return;
}
if(age >= moveout_at_age) {
ray_i_left.v = ray_start_left.v;
ray_i_y.v = ray_start_y.v;
put_flag = SL_RAY_UNPUT;
hittest_and_render();
// hittest_and_render() has conveniently advanced [ray_i_*] by
// [ray_moveout_speed]...
ray_start_left.v = ray_i_left.v;
ray_start_y.v = ray_i_y.v;
if(
(ray_start_left.v >= to_laser_pixel(PLAYFIELD_RIGHT)) ||
(ray_start_left.v < to_laser_pixel(PLAYFIELD_LEFT)) ||
(ray_start_y.v < to_laser_pixel(PLAYFIELD_TOP)) ||
(ray_start_y.v >= to_laser_pixel(PLAYFIELD_BOTTOM))
) {
alive = false;
return;
}
} else {
ray_length += ray_extend_speed;
}
age++;
ray_i_left.v = ray_start_left.v;
ray_i_y.v = ray_start_y.v;
put_flag = SL_RAY_PUT;
hittest_and_render();
}