/*
* Seven Kingdoms: Ancient Adversaries
*
* Copyright 1997,1998 Enlight Software Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
// Filename : OLIGHTN.CPP
// Description : Lightning class
// Ownership : Gilbert
#include
#include
#include
#include
#include
#include
#include
//------------ Define constant ----------//
#define PI 3.141592654
#define CORELIGHTNCOLOR (VGA_GRAY+15)
#define INLIGHTNCOLOR (VGA_GRAY+13)
#define OUTLIGHTNCOLOR (VGA_GRAY+10)
//--------- Define static class vars --------//
int Lightning::bound_x1 = ZOOM_X1+4;
int Lightning::bound_y1 = ZOOM_Y1-4;
int Lightning::bound_x2 = ZOOM_X2-4;
int Lightning::bound_y2 = ZOOM_Y2-4;
//---------- Declare static functions ----------//
static double sqr(double x);
//-------- Begin of static function Lightning::dist ----------//
double Lightning::dist(double dx, double dy)
{
return sqrt( dx*dx + dy*dy);
}
//-------- End of static function Lightning::dist ----------//
//-------- Begin of static function Lightning::set_clip ----------//
void Lightning::set_clip(int x1, int y1, int x2, int y2)
{
bound_x1 = x1;
bound_x2 = x2;
bound_y1 = y1;
bound_y2 = y2;
}
//-------- End of static function Lightning::set_clip ----------//
//-------- Begin of function Lightning::~Lightning ----------//
Lightning::~Lightning()
{
}
//-------- End of function Lightning::~Lightning ----------//
//-------- Begin of function Lightning::rand_seed ----------//
unsigned Lightning::rand_seed()
{
#define MULTIPLIER 0x015a4e35L
#define INCREMENT 1
seed = MULTIPLIER * seed + INCREMENT;
return seed;
}
//-------- End of function Lightning::rand_seed ----------//
//-------- Begin of function Lightning::init ----------//
void Lightning::init(double fromX, double fromY, double toX, double toY,
char energy)
{
x = fromX;
y = fromY;
destx = toX;
desty = toY;
energy_level = energy;
v = 6.0;
expect_steps = (int)( dist(desty-y, destx-x) / v * 1.2);
if( expect_steps < 2 )
expect_steps = 2;
steps = 0;
a0 = a = 8.0;
r0 = r = 8.0 * a;
wide = PI / 4;
seed = (unsigned)(fromX + fromY + toX + toY) | 1;
(void) rand_seed();
}
//-------- End of function Lightning::init ----------//
//-------- Begin of function Lightning::goal ----------//
// return TRUE if the point is very near destination
int Lightning::goal()
{
return( dist(destx-x, desty-y) < v );
}
//-------- End of function Lightning::goal ----------//
//-------- Begin of function Lightning::update_parameter ----------//
void Lightning::update_parameter()
{
double progress = (double) steps / expect_steps;
if( progress > 1)
progress = 1;
// a = a0; // constant
r = r0 * (1-progress);
wide = 0.25 * ( 1 + progress ) * PI;
}
//-------- End of function Lightning::update_parameter ----------//
//-------- Begin of function Lightning::move_particle ----------//
void Lightning::move_particle()
{
// determine attraction
double attractionDist = dist(destx-x, desty-y);
if( attractionDist < v)
return;
double aX = a * (destx-x) / attractionDist;
double aY = a * (desty-y) / attractionDist;
// determine random component
double attractionAngle = atan2( desty-y, destx-x);
double randomAngle = ((rand_seed() & 255)/128.0-1.0)*wide+ attractionAngle;
double rX = r * cos(randomAngle);
double rY = r * sin(randomAngle);
// total
double tX = aX + rX;
double tY = aY + rY;
double distt = dist(tX, tY);
// move x and y, along tX, tY but the magnitude is v
if( distt > 0)
{
x += v * tX / distt;
y += v * tY / distt;
}
steps ++;
update_parameter();
}
//-------- End of function Lightning::move_particle ----------//
//-------- Begin of function Lightning::draw_step ----------//
void Lightning::draw_step(VgaBuf *vgabuf)
{
int prex, prey;
if(!goal() )
{
prex = (int) x;
prey = (int) y;
move_particle();
// BUGHERE: ignore if clipped, currently
if( energy_level > 4)
{
if( prex >= bound_x1+2 && (int)x >= bound_x1+2 &&
prex <= bound_x2-2 && (int)x <= bound_x2-2 &&
prey >= bound_y1+2 && (int)y >= bound_y1+2 &&
prey <= bound_y2-2 && (int)y <= bound_y2-2 )
{
vgabuf->line(prex+2, prey, (int) x+2, (int) y, OUTLIGHTNCOLOR);
vgabuf->line(prex, prey+2, (int) x, (int) y+2, OUTLIGHTNCOLOR);
vgabuf->line(prex-2, prey, (int) x-2, (int) y, OUTLIGHTNCOLOR);
vgabuf->line(prex, prey-2, (int) x, (int) y-2, OUTLIGHTNCOLOR);
vgabuf->line(prex+1, prey, (int) x+1, (int) y, INLIGHTNCOLOR);
vgabuf->line(prex, prey+1, (int) x, (int) y+1, INLIGHTNCOLOR);
vgabuf->line(prex-1, prey, (int) x-1, (int) y, INLIGHTNCOLOR);
vgabuf->line(prex, prey-1, (int) x, (int) y-1, INLIGHTNCOLOR);
vgabuf->line(prex, prey, (int) x, (int) y, CORELIGHTNCOLOR);
}
}
else if( energy_level > 2)
{
if( prex >= bound_x1+1 && (int)x >= bound_x1+1 &&
prex <= bound_x2-1 && (int)x <= bound_x2-1 &&
prey >= bound_y1+1 && (int)y >= bound_y1+1 &&
prey <= bound_y2-1 && (int)y <= bound_y2-1 )
{
vgabuf->line(prex+1, prey, (int) x+1, (int) y, OUTLIGHTNCOLOR);
vgabuf->line(prex, prey+1, (int) x, (int) y+1, OUTLIGHTNCOLOR);
vgabuf->line(prex, prey, (int) x, (int) y, INLIGHTNCOLOR);
}
}
else
{
if( prex >= bound_x1 && (int)x >= bound_x1 &&
prex <= bound_x2 && (int)x <= bound_x2 &&
prey >= bound_y1 && (int)y >= bound_y1 &&
prey <= bound_y2 && (int)y <= bound_y2 )
{
vgabuf->line(prex, prey, (int) x, (int) y, OUTLIGHTNCOLOR);
}
}
}
}
//-------- End of function Lightning::draw_step ----------//
//-------- Begin of function Lightning::draw_whole ----------//
void Lightning::draw_whole(VgaBuf *vgabuf)
{
int prex, prey;
while(!goal() )
{
prex = (int) x;
prey = (int) y;
move_particle();
// ignore clipping, currently
if( energy_level > 4)
{
if( prex >= bound_x1+2 && (int)x >= bound_x1+2 &&
prex <= bound_x2-2 && (int)x <= bound_x2-2 &&
prey >= bound_y1+2 && (int)y >= bound_y1+2 &&
prey <= bound_y2-2 && (int)y <= bound_y2-2 )
{
vgabuf->line(prex+2, prey, (int) x+2, (int) y, OUTLIGHTNCOLOR);
vgabuf->line(prex, prey+2, (int) x, (int) y+2, OUTLIGHTNCOLOR);
vgabuf->line(prex-2, prey, (int) x-2, (int) y, OUTLIGHTNCOLOR);
vgabuf->line(prex, prey-2, (int) x, (int) y-2, OUTLIGHTNCOLOR);
vgabuf->line(prex+1, prey, (int) x+1, (int) y, INLIGHTNCOLOR);
vgabuf->line(prex, prey+1, (int) x, (int) y+1, INLIGHTNCOLOR);
vgabuf->line(prex-1, prey, (int) x-1, (int) y, INLIGHTNCOLOR);
vgabuf->line(prex, prey-1, (int) x, (int) y-1, INLIGHTNCOLOR);
vgabuf->line(prex, prey, (int) x, (int) y, CORELIGHTNCOLOR);
}
}
else if( energy_level > 2)
{
if( prex >= bound_x1+1 && (int)x >= bound_x1+1 &&
prex <= bound_x2-1 && (int)x <= bound_x2-1 &&
prey >= bound_y1+1 && (int)y >= bound_y1+1 &&
prey <= bound_y2-1 && (int)y <= bound_y2-1 )
{
vgabuf->line(prex+1, prey, (int) x+1, (int) y, OUTLIGHTNCOLOR);
vgabuf->line(prex, prey+1, (int) x, (int) y+1, OUTLIGHTNCOLOR);
vgabuf->line(prex, prey, (int) x, (int) y, INLIGHTNCOLOR);
}
}
else
{
if( prex >= bound_x1 && (int)x >= bound_x1 &&
prex <= bound_x2 && (int)x <= bound_x2 &&
prey >= bound_y1 && (int)y >= bound_y1 &&
prey <= bound_y2 && (int)y <= bound_y2 )
{
vgabuf->line(prex, prey, (int) x, (int) y, OUTLIGHTNCOLOR);
}
}
}
}
//-------- End of function Lightning::draw_whole ----------//
//-------- Begin of function Lightning::progress ----------//
double Lightning::progress()
{
if(goal())
return 1;
else
return (double) steps / expect_steps;
}
//-------- End of function Lightning::progress ----------//
//-------- Begin of function Lightning::draw_section ----------//
void Lightning::draw_section(VgaBuf *vgabuf, double portion)
{
while( progress() < ( portion< 1.0 ? portion : 1.0 ) )
draw_step(vgabuf);
}
//-------- End of function Lightning::draw_section ----------//
//-------- Begin of static function sqr ----------//
static double sqr(double x)
{
return x*x;
}
//-------- End of static function sqr ----------//