home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Desktop Works 1995 - 1996
/
desktopworks1995-1996.iso
/
scrnsave
/
sperm
/
spermplt.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-01-01
|
10KB
|
331 lines
//
// SPERMPLT - swimming sperm plotter
//
// Version 1.0 12/18/92 Copyright (C) 1992 Hutchins Software
// Author: Edward Hutchins &:
//
// The animation guts from a freely distributable X program:
// xsperm.c
// Drew Olbrich, Febrary 1991
// Note -- This code originally served as a demonstration
// of how to do animation under X. The "guts" of the program
// which draws the sperm are consequently located in one huge
// chunk in the update_display() routine, and can be easily
// cut out.
// The animation function wrapped in a NeXTstep View subclass
// by Ali Ozer, May 91
// Very minor changes so this thing works as a screen saver module
// by sam streeper, August 91
// The "oneStep" method computes new locations.
//
// Revisions:
// 12/18/92 ported to Windows as an SPX - Ed.
//
#include <math.h>
#include "sperm.h"
//
// defines
//
// fixed point scale factor
#define VEC_1 (256L)
#define NORM(x) ((INT)((x)/VEC_1))
typedef LONG VECTOR[2];
#define VEC_COPY( y, x ) y[0] = x[0], y[1] = x[1]
#define VEC_ADD( z, x, y ) z[0] = x[0] + y[0], z[1] = x[1] + y[1]
#define VEC_SUB( z, x, y ) z[0] = x[0] - y[0], z[1] = x[1] - y[1]
#define VEC_MULT( x, a ) (x[0] = (x[0] * a) / VEC_1, x[1] = (x[1] * a) / VEC_1)
#define VEC_DIV( x, a ) (x[0] = (x[0] * VEC_1) / a, x[1] = (x[1] * VEC_1) / a)
#define VEC_ADDS( z, x, a, y ) (z[0] = x[0] + (((a)*y[0])/VEC_1), z[1] = x[1] + (((a)*y[1])/VEC_1))
#define VEC_NORM( x ) { LONG _nLen = IntDist( x[0], x[1] ); VEC_DIV( x, _nLen ); }
#define MINRAD (VEC_1 / 10)
#define RADSTEP 2
#define MAXRAD (MINRAD * 6 * RADSTEP)
#define INITRAD (MINRAD * 3 * RADSTEP)
// RandInt(n) returns an integer 0..n-1
#define RandInt(n) (arand( n ))
// degrees scaled to integer math
#define DEGREE_SIZE 256
#define DEGREE_MASK 255
#define DEGREE_MAX 0x4000 // this is now hardcoded into the lookup table...
// faster than MulDiv!
#define MULDEG(x,y) (((x)*(y))/DEGREE_MAX)
// DEG - convert an integer into a degree lookup index
#define DEG(x) ((WORD)(x)&DEGREE_MASK)
//
// imports
//
IMPORT INT nSpermCnt FROM( sperm.c );
IMPORT TRI triBlank FROM( sperm.c );
//
// locals
//
LOCAL DWORD dwSeed;
LOCAL VECTOR x[SPERM_MAX], xPrev[SPERM_MAX];
LOCAL VECTOR v[SPERM_MAX];
LOCAL VECTOR lCenter;
LOCAL LONG lSin[SPERM_MAX];
LOCAL LONG lCos[SPERM_MAX];
LOCAL LONG lVel[SPERM_MAX];
LOCAL LONG lRad;
LOCAL LONG lDir;
GLOBAL INT nCos[DEGREE_SIZE] =
{
16384, 16379, 16364, 16339, 16305, 16260, 16206, 16142,
16069, 15985, 15892, 15790, 15678, 15557, 15426, 15286,
15136, 14978, 14810, 14634, 14449, 14255, 14053, 13842,
13622, 13395, 13159, 12916, 12665, 12406, 12139, 11866,
11585, 11297, 11002, 10701, 10393, 10079, 9759, 9434,
9102, 8765, 8423, 8075, 7723, 7366, 7005, 6639,
6269, 5896, 5519, 5139, 4756, 4369, 3980, 3589,
3196, 2801, 2404, 2005, 1605, 1205, 803, 402,
0, -403, -804, -1206, -1606, -2006, -2405, -2802,
-3197, -3590, -3981, -4370, -4757, -5140, -5520, -5897,
-6270, -6640, -7006, -7367, -7724, -8076, -8424, -8766,
-9103, -9435, -9760, -10080, -10394, -10702, -11003, -11298,
-11586, -11867, -12140, -12407, -12666, -12917, -13160, -13396,
-13623, -13843, -14054, -14256, -14450, -14635, -14811, -14979,
-15137, -15287, -15427, -15558, -15679, -15791, -15893, -15986,
-16070, -16143, -16207, -16261, -16306, -16340, -16365, -16380,
-16384, -16380, -16365, -16340, -16306, -16261, -16207, -16143,
-16070, -15986, -15893, -15791, -15679, -15558, -15427, -15287,
-15137, -14979, -14811, -14635, -14450, -14256, -14054, -13843,
-13623, -13396, -13160, -12917, -12666, -12407, -12140, -11867,
-11586, -11298, -11003, -10702, -10394, -10080, -9760, -9435,
-9103, -8766, -8424, -8076, -7724, -7367, -7006, -6640,
-6270, -5897, -5520, -5140, -4757, -4370, -3981, -3590,
-3197, -2802, -2405, -2006, -1606, -1206, -804, -403,
0, 402, 803, 1205, 1605, 2005, 2404, 2801,
3196, 3589, 3980, 4369, 4756, 5139, 5519, 5896,
6269, 6639, 7005, 7366, 7723, 8075, 8423, 8765,
9102, 9434, 9759, 10079, 10393, 10701, 11002, 11297,
11585, 11866, 12139, 12406, 12665, 12916, 13159, 13395,
13622, 13842, 14053, 14255, 14449, 14634, 14810, 14978,
15136, 15286, 15426, 15557, 15678, 15790, 15892, 15985,
16069, 16142, 16206, 16260, 16305, 16339, 16364, 16379
};
GLOBAL INT nSin[DEGREE_SIZE] =
{
0, 402, 803, 1205, 1605, 2005, 2404, 2801,
3196, 3589, 3980, 4369, 4756, 5139, 5519, 5896,
6269, 6639, 7005, 7366, 7723, 8075, 8423, 8765,
9102, 9434, 9759, 10079, 10393, 10701, 11002, 11297,
11585, 11866, 12139, 12406, 12665, 12916, 13159, 13395,
13622, 13842, 14053, 14255, 14449, 14634, 14810, 14978,
15136, 15286, 15426, 15557, 15678, 15790, 15892, 15985,
16069, 16142, 16206, 16260, 16305, 16339, 16364, 16379,
16383, 16379, 16364, 16339, 16305, 16260, 16206, 16142,
16069, 15985, 15892, 15790, 15678, 15557, 15426, 15286,
15136, 14978, 14810, 14634, 14449, 14255, 14053, 13842,
13622, 13395, 13159, 12916, 12665, 12406, 12139, 11866,
11585, 11297, 11002, 10701, 10393, 10079, 9759, 9434,
9102, 8765, 8423, 8075, 7723, 7366, 7005, 6639,
6269, 5896, 5519, 5139, 4756, 4369, 3980, 3589,
3196, 2801, 2404, 2005, 1605, 1205, 803, 402,
0, -403, -804, -1206, -1606, -2006, -2405, -2802,
-3197, -3590, -3981, -4370, -4757, -5140, -5520, -5897,
-6270, -6640, -7006, -7367, -7724, -8076, -8424, -8766,
-9103, -9435, -9760, -10080, -10394, -10702, -11003, -11298,
-11586, -11867, -12140, -12407, -12666, -12917, -13160, -13396,
-13623, -13843, -14054, -14256, -14450, -14635, -14811, -14979,
-15137, -15287, -15427, -15558, -15679, -15791, -15893, -15986,
-16070, -16143, -16207, -16261, -16306, -16340, -16365, -16380,
-16384, -16380, -16365, -16340, -16306, -16261, -16207, -16143,
-16070, -15986, -15893, -15791, -15679, -15558, -15427, -15287,
-15137, -14979, -14811, -14635, -14450, -14256, -14054, -13843,
-13623, -13396, -13160, -12917, -12666, -12407, -12140, -11867,
-11586, -11298, -11003, -10702, -10394, -10080, -9760, -9435,
-9103, -8766, -8424, -8076, -7724, -7367, -7006, -6640,
-6270, -5897, -5520, -5140, -4757, -4370, -3981, -3590,
-3197, -2802, -2405, -2006, -1606, -1206, -804, -403
};
//
// arand - pseudorandom number from 0 to x-1
//
LONG NEAR PASCAL arand( LONG x )
{
dwSeed = dwSeed * 0x343fd + 0x269ec3;
return( (LONG)((dwSeed >> 8) % x) );
}
//
// IntDist - find an approximate distance
//
LONG NEAR PASCAL IntDist( LONG dx, LONG dy )
{
LONG lDist;
if (dx < 0) dx = -dx;
if (dy < 0) dy = -dy;
lDist = dx + dy - (((dx > dy) ? dy : dx) >> 1);
return( (lDist > 0) ? lDist : 1 );
}
//
// Tri - convert a tri-state into a boolean (unset == random)
//
BOOL NEAR PASCAL Tri( TRI tri )
{
switch (tri)
{
case TRI_FALSE:
return( FALSE );
case TRI_TRUE:
return( TRUE );
default:
return( (BOOL)arand( 2 ) );
}
}
//
// DoEffect - do a special effect
//
VOID NEAR PASCAL DoEffect( INT nVal )
{
INT i;
switch (nVal)
{
case 0:
lDir *= -1;
for (i = 0; i < nSpermCnt; i++)
{
VECTOR y;
VEC_COPY( y, v[i] );
if (lDir < 0) v[i][0] = y[1], v[i][1] = -y[0];
else v[i][0] = -y[1], v[i][1] = y[0];
}
break;
case 1:
for (i = 0; i < nSpermCnt; i++) v[i][0] = -v[i][0];
break;
case 2:
for (i = 0; i < nSpermCnt; i++) v[i][1] = -v[i][1];
break;
case 3:
DoEffect( 1 );
DoEffect( 2 );
break;
case 4:
DoEffect( 0 );
DoEffect( 3 );
case 5:
lRad = lRad * RADSTEP;
if (lRad > MAXRAD) lRad = MAXRAD;
break;
case 6:
lRad = lRad / RADSTEP;
if (lRad < MINRAD) lRad = MINRAD;
break;
default:
break;
}
}
//
// SaverDraw - the main drawing routine
//
VOID FAR PASCAL EXPORT SaverDraw( HWND hwnd, HDC hdc, H