Files
ZSNES/zsnes/src/effects/water.c
2003-11-01 21:33:26 +00:00

400 lines
7.4 KiB
C

/*
Copyright (C) 1997-2003 ZSNES Team ( zsknight@zsnes.com / _demo_@zsnes.com )
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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef __LINUX__
#include "../gblhdr.h"
#else
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <memory.h>
#include <time.h>
#include <string.h>
#endif
#include "fixsin.h"
extern char *vidbuffer;
#define SCRW 288
#define SCRH 224
static unsigned char vscr[SCRW*SCRH];
static int Height[2][SCRW*SCRH];
extern char NetPlayNoMore;
/* static void DrawWaterNoLight(int *ptr); */
static void DrawWaterWithLight(int *ptr,int light);
static void SineBlob(int x, int y, int radius, int height, int page);
static void CalcWater(int *nptr,int *optr,int density);
//static int x,y;
static int ox=80,oy=60;
static int xang,yang;
static int density=5;
static int Hpage=0;
static int mode=0x0001;
static int offset;
static int pheight=400;
static int radius=30;
extern char GUIEffect;
void DrawWater(void)
{
// tslast=tscurrent;
// tscurrent=time(NULL);
/*
if (NetPlayNoMore == 1)
{
DrawWaterNoLight(Height[Hpage]);
}
else
{
DrawWaterWithLight(Height[Hpage],1);
}
*/
#if 0
DrawWaterNoLight(Height[Hpage]);
#else
DrawWaterWithLight(Height[Hpage],1);
#endif
if (GUIEffect==2) { mode=0x0001; }
else { mode = 0x0004; }
if(mode&2) // && (tscurrent-tslast))
{
int x,y;
x=rand()%(SCRW-2)+1;
y=rand()%(SCRH-2)+1;
Height[Hpage][y*SCRW+x]=rand()%(pheight<<2);
}
/* the surfer */
if(mode&1)
{
int x,y;
x = (SCRW/2)
+ ((((FSin( (xang* 65) >>8) >>8)
* (FSin( (xang*349) >>8) >>8))
* ((SCRW-8)/2)) >> 16);
y = (SCRH/2)
+ ((((FSin( (yang*377) >>8) >>8)
*(FSin( (yang* 84) >>8) >>8))
* ((SCRH-8)/2)) >> 16);
xang += 13;
yang += 12;
if(mode & 0x4000)
{
offset = (oy+y)/2*SCRW + (ox+x)/2;
Height[Hpage][offset] = pheight;
Height[Hpage][offset + 1] =
Height[Hpage][offset - 1] =
Height[Hpage][offset + SCRW] =
Height[Hpage][offset - SCRW] = pheight >> 1;
offset = y*SCRW + x;
Height[Hpage][offset] = pheight<<1;
Height[Hpage][offset + 1] =
Height[Hpage][offset - 1] =
Height[Hpage][offset + SCRW] =
Height[Hpage][offset - SCRW] = pheight;
}
else
{
SineBlob((ox+x)/2, (oy+y)/2, 3, -1200, Hpage);
SineBlob(x, y, 4, -2000, Hpage);
}
ox = x;
oy = y;
}
if(mode&4)
{
int x,y;
srand(time(0));
if(rand()%14 == 7)
{
/*
if(mode & 0x4000)
// HeightBlob(-1, -1, radius/2, pheight, Hpage);
else
*/
x=rand()%(SCRW-2)+1;
y=rand()%(SCRH-2)+1;
SineBlob(x, y, radius, -pheight*6, Hpage);
}
}
CalcWater(Height[Hpage^1], Height[Hpage], density);
Hpage ^= 1; /* flip flop */
}
#if 0
void DrawWaterNoLight(int *ptr)
{
int dx,dy;
int x,y;
int c;
int p;
int offset = SCRW+1;
if(ptr == NULL)
{
return;
}
for(y=((SCRH-1)*SCRW); offset < y; offset+=2)
{
for(x = offset+SCRW-2;offset<x;offset++)
{
dx=ptr[offset]-ptr[offset+1];
dy=ptr[offset]-ptr[offset+SCRW];
p=offset+SCRW*(dy>>3)+(dx>>3);
/* if(p>(SCRH*SCRW))
{
for(;p<(SCRH*SCRW);p-=SCRW);
}
if(p<0)
{
for(;p>0;p+=SCRW);
}
*/
if(p >= (SCRW*SCRH) )
{
p=(SCRW*SCRH)-1;
}
else
{
if(p < 0)
{
p=0;
}
}
c=vidbuffer[p];
(c<1) ? c=1 : (c > 31) ? c=31 : 0;
vscr[offset]=c;
offset++;
dx=ptr[offset]-ptr[offset+1];
dy=ptr[offset]-ptr[offset+SCRW];
p=offset+SCRW*(dy>>3)+(dx>>3);
/*
if(p>(SCRH*SCRW))
{
for(;p<(SCRH*SCRW);p-=SCRW);
}
if(p<0)
{
for(;p>=0;p+=SCRW);
}
*/
if(p >= (SCRW*SCRH) )
{
p=(SCRW*SCRH)-1;
}
else
{
if(p < 0)
{
p=0;
}
}
c=vidbuffer[p];
(c<1) ? c=1 : (c > 31) ? c=31 : 0;
vscr[offset]=c;
}
}
memcpy( vidbuffer,vscr,SCRW*SCRH);
// frames++;
}
#endif
void DrawWaterWithLight(int *ptr,int light)
{
int dx,dy;
int x,y;
int c;
int p;
int offset = SCRW+1;
if(ptr == NULL)
{
return;
}
for(y=((SCRH-1)*SCRW); offset < y; offset+=2)
{
for(x = offset+SCRW-2;offset<x;offset++)
{
dx=ptr[offset]-ptr[offset+1];
dy=ptr[offset]-ptr[offset+SCRW];
p=offset+SCRW*(dy>>3)+(dx>>3);
if (p>(SCRH*SCRW)) p = (p % SCRW) + ((SCRH-((p - (SCRH*SCRW)) / SCRW)) * SCRW);
if (p<0) p = (SCRW + (p % SCRW)) + abs(p / SCRW) * SCRW;
/*
if(p >= (SCRW*SCRH) )
{
p=(SCRW*SCRH)-1;
}
else
{
if(p < 0)
{
p=0;
}
}
*/
c=vidbuffer[p];
c-=(dx>>light);
(c<1) ? c=1 : (c > 31) ? c=31 : 0;
vscr[offset]=c;
offset++;
dx=ptr[offset]-ptr[offset+1];
dy=ptr[offset]-ptr[offset+SCRW];
p=offset+SCRW*(dy>>3)+(dx>>3);
if (p>(SCRH*SCRW)) p = (p % SCRW) + ((SCRH-((p - (SCRH*SCRW)) / SCRW)) * SCRW);
if (p<0) p = (SCRW + (p % SCRW)) + abs(p / SCRW) * SCRW;
/*
if(p >= (SCRW*SCRH) )
{
p=(SCRW*SCRH)-1;
}
else
{
if(p < 0)
{
p=0;
}
}
*/
c=vidbuffer[p];
c-=(dx>>light);
(c<1) ? c=1 : (c > 31) ? c=31 : 0;
vscr[offset]=c;
}
}
memcpy( vidbuffer,vscr,SCRW*SCRH);
// memcpy( VGLDisplay->Bitmap,vscr,SCRW*SCRH);
// frames++;
}
void CalcWater(int *nptr,int *optr,int density)
{
int newh;
int count = SCRW+1;
int x,y;
for(y = (SCRH-1) * SCRW;count<y;count+=2)
{
for(x = count+SCRW-2;count<x;count++)
{
newh = ((optr[count+SCRW]
+optr[count-SCRW]
+optr[count+1]
+optr[count-1]
+optr[count-SCRW-1]
+optr[count-SCRW+1]
+optr[count+SCRW-1]
+optr[count+SCRW+1]
) >> 2)
- nptr[count];
nptr[count] = newh - (newh >> density);
}
}
}
void SineBlob(int x, int y, int radius, int height, int page)
{
int cx, cy;
int left,top,right,bottom;
int square, dist;
int radsquare = radius * radius;
float length = (1024.0f/(float)radius)*(1024.0f/(float)radius);
if(x<0) x = 1+radius+ rand()%(SCRW-2*radius-1);
if(y<0) y = 1+radius+ rand()%(SCRH-2*radius-1);
// radsquare = (radius*radius) << 8;
radsquare = (radius*radius);
/*
if (NetPlayNoMore == 1)
{
radsquare = (radius*radius);
}
else
{
radsquare = (radius*radius) << 8;
height /= 8;
}
*/
radsquare = (radius*radius);
height /= 8;
left=-radius; right = radius;
top=-radius; bottom = radius;
// Perform edge clipping...
if(x - radius < 1) left -= (x-radius-1);
if(y - radius < 1) top -= (y-radius-1);
if(x + radius > SCRW-1) right -= (x+radius-SCRW+1);
if(y + radius > SCRH-1) bottom-= (y+radius-SCRH+1);
for(cy = top; cy < bottom; cy++)
{
for(cx = left; cx < right; cx++)
{
square = cy*cy + cx*cx;
if(square < radsquare)
{
dist = (int) sqrt(square*length);
Height[page][SCRW*(cy+y) + cx+x]
+= (int)((FCos(dist)+0xffff)*(height)) >> 19;
}
}
}
}