Initial source commit
53
gamma256/prototypes/screenCompress/Makefile
Normal file
|
@ -0,0 +1,53 @@
|
|||
|
||||
|
||||
ROOT_PATH = ../../..
|
||||
|
||||
COMPILE = g++ -g -I${ROOT_PATH} -c
|
||||
LINK = g++ -I${ROOT_PATH}
|
||||
|
||||
|
||||
|
||||
MINOR_GEMS_SOURCES = \
|
||||
${ROOT_PATH}/minorGems/io/file/linux/PathLinux.cpp \
|
||||
#${ROOT_PATH}/minorGems/graphics/linux/ScreenGraphicsLinux.cpp \
|
||||
#${ROOT_PATH}/minorGems/system/win32/ThreadWin32.cpp \
|
||||
#${ROOT_PATH}/minorGems/system/linux/ThreadLinux.cpp \
|
||||
|
||||
MINOR_GEMS_OBJECTS = ${MINOR_GEMS_SOURCES:.cpp=.o}
|
||||
|
||||
LIBRARIES = -lSDL
|
||||
|
||||
|
||||
all: screenCompress tileSet.tga characterSprite.tga
|
||||
|
||||
screenCompress: screenCompress.o landscape.o ${MINOR_GEMS_OBJECTS}
|
||||
${LINK} -o screenCompress screenCompress.o landscape.o ${MINOR_GEMS_OBJECTS} ${LIBRARIES}
|
||||
|
||||
|
||||
sdlTest: sdlTest.o
|
||||
${LINK} -o sdlTest sdlTest.o ${MINOR_GEMS_OBJECTS} ${LIBRARIES} -lSDLmain
|
||||
|
||||
|
||||
screenCompress.o: screenCompress.cpp landscape.h
|
||||
|
||||
landscape.o: landscape.cpp landscape.h
|
||||
|
||||
tileSet.tga: tileSet.png
|
||||
convert tileSet.png tileSet.tga
|
||||
|
||||
characterSprite.tga: characterSprite.png
|
||||
convert characterSprite.png characterSprite.tga
|
||||
|
||||
|
||||
#
|
||||
# Generic:
|
||||
#
|
||||
# Map all .cpp C++ and C files into .o object files
|
||||
#
|
||||
# $@ represents the name.o file
|
||||
# $< represents the name.cpp file
|
||||
#
|
||||
.cpp.o:
|
||||
${COMPILE} -o $@ $<
|
||||
.c.o:
|
||||
${COMPILE} -o $@ $<
|
BIN
gamma256/prototypes/screenCompress/characterSprite.png
Normal file
After Width: | Height: | Size: 311 B |
BIN
gamma256/prototypes/screenCompress/characterSprite.tga
Normal file
After Width: | Height: | Size: 1.7 KiB |
1
gamma256/prototypes/screenCompress/compile
Executable file
|
@ -0,0 +1 @@
|
|||
g++ -I../../.. -o screenCompress screenCompress.cpp ../../../minorGems/graphics/linux/ScreenGraphicsLinux.cpp ../../../minorGems/io/file/linux/PathLinux.cpp landscape.o -lSDL
|
442
gamma256/prototypes/screenCompress/landscape.cpp
Normal file
|
@ -0,0 +1,442 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2006-September-26 Jason Rohrer
|
||||
* Switched to cosine interpolation.
|
||||
* Added optimizations discovered with profiler. Reduced running time by 18%.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "landscape.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "minorGems/util/SimpleVector.h"
|
||||
|
||||
|
||||
|
||||
double landscape( double inX, double inY, double inT,
|
||||
double inBaseFrequency, double inRoughness,
|
||||
int inDetail ) {
|
||||
|
||||
if( inDetail < 0 ) {
|
||||
return 0.0;
|
||||
}
|
||||
else {
|
||||
// frequency of octave
|
||||
double frequency = inBaseFrequency * pow( 2, inDetail );
|
||||
double amplitude = pow( inRoughness, inDetail );
|
||||
return amplitude * noise4d( inX * frequency,
|
||||
inY * frequency,
|
||||
// index different planes of noise
|
||||
inDetail,
|
||||
inT )
|
||||
+ landscape( inX, inY, inT, inBaseFrequency, inRoughness,
|
||||
inDetail - 1 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
double variableRoughnessLandscape( double inX, double inY, double inT,
|
||||
double inBaseFrequency,
|
||||
double inRoughnessChangeFrequency,
|
||||
double inMinRoughness,
|
||||
double inMaxRoughness,
|
||||
int inDetail ) {
|
||||
|
||||
double roughnessFreqX = inX * inRoughnessChangeFrequency;
|
||||
double roughnessFreqY = inY * inRoughnessChangeFrequency;
|
||||
|
||||
// use low-frequency noise 4d to select landscape roughness
|
||||
// between 0 and 1
|
||||
double roughness =
|
||||
( noise4d( 6, roughnessFreqX, roughnessFreqY, inT ) + 1 ) / 2;
|
||||
|
||||
// move roughness into specified range
|
||||
roughness =
|
||||
roughness * ( inMaxRoughness - inMinRoughness ) +
|
||||
inMinRoughness;
|
||||
|
||||
return landscape( inX, inY, inT, inBaseFrequency, roughness, inDetail );
|
||||
}
|
||||
|
||||
|
||||
|
||||
int getRandomPoints( double inStartX, double inEndX,
|
||||
double inStartY, double inEndY,
|
||||
double inT,
|
||||
double inSampleStepSize,
|
||||
double inDensity,
|
||||
double **outXCoordinates,
|
||||
double **outYCoordinates ) {
|
||||
|
||||
SimpleVector<double> *xCoordinates = new SimpleVector<double>();
|
||||
SimpleVector<double> *yCoordinates = new SimpleVector<double>();
|
||||
|
||||
// discretize startX and start Y so that sample grid for differently-placed
|
||||
// windows always meshes
|
||||
// use ceil to ensure that starting points are always inside the
|
||||
// inStart/inEnd bounds
|
||||
double discretizedStartX =
|
||||
inSampleStepSize * ceil( inStartX / inSampleStepSize );
|
||||
double discretizedStartY =
|
||||
inSampleStepSize * ceil( inStartY / inSampleStepSize );
|
||||
|
||||
// put a point wherever we have a zero-crossing
|
||||
double lastSample = 1;
|
||||
|
||||
for( double x=discretizedStartX; x<=inEndX; x+=inSampleStepSize ) {
|
||||
for( double y=discretizedStartY; y<=inEndY; y+=inSampleStepSize ) {
|
||||
double landscapeSample =
|
||||
variableRoughnessLandscape(
|
||||
30 * x + 1000, 30 * y + 1000, inT + 1000,
|
||||
0.01, 0.001, 0.25, 0.65, 0 );
|
||||
|
||||
// shift landscape up to reduce chance of zero-crossing
|
||||
landscapeSample = (1-inDensity) * 0.5 + 0.5 + landscapeSample ;
|
||||
|
||||
if( landscapeSample < 0 &&
|
||||
lastSample >= 0 ||
|
||||
landscapeSample >= 0 &&
|
||||
landscapeSample < 0 ) {
|
||||
|
||||
// sign change
|
||||
|
||||
// hit
|
||||
xCoordinates->push_back( x );
|
||||
yCoordinates->push_back( y );
|
||||
}
|
||||
|
||||
lastSample = landscapeSample;
|
||||
}
|
||||
}
|
||||
|
||||
*outXCoordinates = xCoordinates->getElementArray();
|
||||
*outYCoordinates = yCoordinates->getElementArray();
|
||||
|
||||
int numPoints = xCoordinates->size();
|
||||
|
||||
delete xCoordinates;
|
||||
delete yCoordinates;
|
||||
|
||||
return numPoints;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Computes a 32-bit random number.
|
||||
* Use linear congruential method.
|
||||
*
|
||||
* @param inSeed the seed to use.
|
||||
*/
|
||||
// this is the readable version of the funcion
|
||||
// it has been turned into a set of macros below
|
||||
inline unsigned long random32_readable( unsigned long inSeed ) {
|
||||
// this is the true hot-spot of the entire landscape function
|
||||
// thus, optimization is warranted.
|
||||
|
||||
// multiplier = 3141592621
|
||||
// use hex to avoid warnings
|
||||
//unsigned long multiplier = 0xBB40E62D;
|
||||
//unsigned long increment = 1;
|
||||
|
||||
// better:
|
||||
// unsigned long multiplier = 196314165
|
||||
// unsigned long increment = 907633515
|
||||
|
||||
// this will automatically be mod-ed by 2^32 because of the limit
|
||||
// of the unsigned long type
|
||||
// return multiplier * inSeed + increment;
|
||||
//return 0xBB40E62D * inSeed + 1;
|
||||
//return 196314165 * inSeed + 907633515;
|
||||
|
||||
//int n = ( inSeed << 13 ) ^ inSeed;
|
||||
//return n * (n * n * 15731 + 789221) + 1376312589;
|
||||
|
||||
//const unsigned long Num1 = (inSeed * 0xFEA09B9DLU) + 1;
|
||||
//const unsigned long Num2 = ((inSeed * 0xB89C8895LU) + 1) >> 16;
|
||||
//return Num1 ^ Num2;
|
||||
|
||||
/*
|
||||
unsigned int rseed=(inSeed*15064013)^(inSeed*99991+604322121)^(inSeed*45120321)^(inSeed*5034121+13);
|
||||
|
||||
const unsigned long Num1 = (inSeed * 0xFEA09B9DLU) + 1;
|
||||
|
||||
const unsigned long Num2 = ((inSeed * 0xB89C8895LU) + 1) >> 16;
|
||||
|
||||
rseed *= Num1 ^ Num2;
|
||||
|
||||
return rseed;
|
||||
*/
|
||||
|
||||
const unsigned long Num1 = (inSeed * 0xFEA09B9DLU) + 1;
|
||||
const unsigned long Num2 = ((inSeed^Num1) * 0x9C129511LU) + 1;
|
||||
const unsigned long Num3 = (inSeed * 0x2512CFB8LU) + 1;
|
||||
const unsigned long Num4 = ((inSeed^Num3) * 0xB89C8895LU) + 1;
|
||||
const unsigned long Num5 = (inSeed * 0x6BF962C1LU) + 1;
|
||||
const unsigned long Num6 = ((inSeed^Num5) * 0x4BF962C1LU) + 1;
|
||||
|
||||
return Num2 ^ (Num4 >> 11) ^ (Num6 >> 22);
|
||||
}
|
||||
|
||||
|
||||
// faster as a set of macros
|
||||
#define Num1( inSeed ) \
|
||||
( ( inSeed * 0xFEA09B9DLU ) + 1 )
|
||||
|
||||
#define Num2( inSeed ) \
|
||||
( ( ( inSeed ^ Num1( inSeed ) ) * 0x9C129511LU ) + 1 )
|
||||
|
||||
#define Num3( inSeed ) \
|
||||
( ( inSeed * 0x2512CFB8LU ) + 1 )
|
||||
|
||||
#define Num4( inSeed ) \
|
||||
( ( ( inSeed ^ Num3( inSeed ) ) * 0xB89C8895LU ) + 1 )
|
||||
|
||||
#define Num5( inSeed ) \
|
||||
( ( inSeed * 0x6BF962C1LU ) + 1 )
|
||||
|
||||
#define Num6( inSeed ) \
|
||||
( ( ( inSeed ^ Num5( inSeed ) ) * 0x4BF962C1LU ) + 1 )
|
||||
|
||||
#define random32( inSeed ) \
|
||||
( Num2( inSeed ) ^ (Num4( inSeed ) >> 11) ^ (Num6( inSeed ) >> 22) )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define invMaxIntAsDouble 2.32830643708e-10
|
||||
// 1/(x/2) = 2*(1/x)
|
||||
//double invHalfMaxIntAsDouble = 2 * invMaxIntAsDouble;
|
||||
// 2.32830643708e-10
|
||||
//+ 2.32830643708e-10
|
||||
//-------------------
|
||||
// 4.65661287416e-10
|
||||
#define invHalfMaxIntAsDouble 4.65661287416e-10
|
||||
|
||||
|
||||
|
||||
#define mixFour( x, y, z, t ) ( x ^ (y * 57) ^ (z * 131) ^ (t * 2383) )
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Maps 4d integer coordinates into a [-1..1] noise space.
|
||||
*
|
||||
* @param x, y, z, t the 4d coordinates.
|
||||
*
|
||||
* @return a random value in the range [-1..1]
|
||||
*/
|
||||
// keep readable version around for reference
|
||||
// it has been replaced by a macro below
|
||||
inline double noise4dInt32_readable( unsigned long x,
|
||||
unsigned long y,
|
||||
unsigned long z,
|
||||
unsigned long t ) {
|
||||
|
||||
|
||||
//double maxIntAsDouble = 4294967295.0;
|
||||
|
||||
// modular addition automatic
|
||||
// multiply x, y, z, and t by distinct primes to
|
||||
// avoid correllations.
|
||||
// using xor ( ^ ) here seems to avoid correllations that show
|
||||
// up when using addition.
|
||||
|
||||
// mix x, y, z, and t
|
||||
unsigned long randomSeed =
|
||||
x ^
|
||||
y * 57 ^
|
||||
z * 131 ^
|
||||
t * 2383;
|
||||
|
||||
// a random value between 0 and max unsigned long
|
||||
unsigned long randomValue = random32( randomSeed );
|
||||
|
||||
// a random value between 0 and 2
|
||||
double zeroTwoValue = randomValue * invHalfMaxIntAsDouble;
|
||||
|
||||
// a random value between -1 and 1
|
||||
return zeroTwoValue - 1;
|
||||
}
|
||||
|
||||
|
||||
// noise4dInt32 function call itself was the slowest spot in code
|
||||
// (found with profiler)
|
||||
// turn into a set of macros
|
||||
|
||||
// matches original parameter format
|
||||
#define noise4dInt32( x, y, z, t ) \
|
||||
random32( mixFour( x, y, z, t ) ) \
|
||||
* invHalfMaxIntAsDouble - 1
|
||||
|
||||
// problem: now that random32 is a macro, we are passing the unevaluated
|
||||
// expression, ( x ^ (y * 57) ^ (z * 131) ^ (t * 2383) ), down into it.
|
||||
// it is being evaluated 6 times within the depths of the random32 macro
|
||||
|
||||
// thus, we need to provide a new format where the caller can precompute
|
||||
// the mix for us. This is even faster.
|
||||
#define noise1dInt32( precomputedMix ) \
|
||||
random32( precomputedMix ) \
|
||||
* invHalfMaxIntAsDouble - 1
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* The following functions (blendNoiseNd) do 4d linear interpolation
|
||||
* one dimension at a time.
|
||||
*
|
||||
* The end result is 8 calls to blendNoise1d (and 16 calls to noise4dInt32).
|
||||
*
|
||||
* This method was inspired by the functional implementations---I am
|
||||
* decomposing a complicated problem into sub-problems that are easier
|
||||
* to solve.
|
||||
*/
|
||||
|
||||
|
||||
// faster than f * b + (1-f) * a
|
||||
// one less multiply
|
||||
#define linearInterpolation( t, a, b ) ( a + t * ( b - a ) )
|
||||
|
||||
|
||||
/**
|
||||
* Blends 4d discrete (integer-parameter) noise function along one dimension
|
||||
* with 3 fixed integer parameters.
|
||||
*/
|
||||
inline double blendNoise1d( double x,
|
||||
unsigned long y,
|
||||
unsigned long z,
|
||||
unsigned long t ) {
|
||||
|
||||
double floorX = floor( x );
|
||||
unsigned long floorIntX = (unsigned long)floorX;
|
||||
|
||||
if( floorX == x ) {
|
||||
unsigned long precomputedMix = mixFour( floorIntX, y, z, t );
|
||||
|
||||
return noise1dInt32( precomputedMix );
|
||||
}
|
||||
else {
|
||||
unsigned long ceilIntX = floorIntX + 1;
|
||||
|
||||
// cosine interpolation
|
||||
// from http://freespace.virgin.net/hugo.elias/models/m_perlin.htm
|
||||
double ft = ( x - floorX ) * M_PI;
|
||||
double f = ( 1 - cos( ft ) ) * .5;
|
||||
|
||||
|
||||
// need to pre-store intermediate values because noise4dInt32 is a
|
||||
// macro
|
||||
// thus, we end up calling the noise1dInt32 function instead
|
||||
|
||||
unsigned long precomputedMix = mixFour( floorIntX, y, z, t );
|
||||
double valueAtFloor = noise1dInt32( precomputedMix );
|
||||
|
||||
precomputedMix = mixFour( ceilIntX, y, z, t );
|
||||
double valueAtCeiling = noise1dInt32( precomputedMix );
|
||||
|
||||
return linearInterpolation( f, valueAtFloor, valueAtCeiling );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Blends 4d discrete (integer-parameter) noise function along 2 dimensions
|
||||
* with 2 fixed integer parameters.
|
||||
*/
|
||||
double blendNoise2d( double x,
|
||||
double y,
|
||||
unsigned long z,
|
||||
unsigned long t ) {
|
||||
|
||||
double floorY = floor( y );
|
||||
unsigned long floorIntY = (unsigned long)floorY;
|
||||
|
||||
if( floorY == y ) {
|
||||
return blendNoise1d( x, floorIntY, z, t );
|
||||
}
|
||||
else {
|
||||
unsigned long ceilIntY = floorIntY + 1;
|
||||
|
||||
// cosine interpolation
|
||||
// from http://freespace.virgin.net/hugo.elias/models/m_perlin.htm
|
||||
double ft = ( y - floorY ) * M_PI;
|
||||
double f = ( 1 - cos( ft ) ) * .5;
|
||||
|
||||
return ( f ) * blendNoise1d( x, ceilIntY, z, t ) +
|
||||
( 1 - f ) * blendNoise1d( x, floorIntY, z, t );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Blends 4d discrete (integer-parameter) noise function along 3 dimensions
|
||||
* with 1 fixed integer parameters.
|
||||
*/
|
||||
double blendNoise3d( double x,
|
||||
double y,
|
||||
double z,
|
||||
unsigned long t ) {
|
||||
|
||||
double floorZ = floor( z );
|
||||
unsigned long floorIntZ = (unsigned long)floorZ;
|
||||
|
||||
if( floorZ == z ) {
|
||||
return blendNoise2d( x, y, floorIntZ, t );
|
||||
}
|
||||
else {
|
||||
unsigned long ceilIntZ = floorIntZ + 1;
|
||||
|
||||
// cosine interpolation
|
||||
// from http://freespace.virgin.net/hugo.elias/models/m_perlin.htm
|
||||
double ft = ( z - floorZ ) * M_PI;
|
||||
double f = ( 1 - cos( ft ) ) * .5;
|
||||
|
||||
return ( f ) * blendNoise2d( x, y, ceilIntZ, t ) +
|
||||
( 1 - f ) * blendNoise2d( x, y, floorIntZ, t );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Blends 4d discrete (integer-parameter) noise function along 4 dimensions.
|
||||
*/
|
||||
double noise4d( double x,
|
||||
double y,
|
||||
double z,
|
||||
double t ) {
|
||||
|
||||
double floorT = floor( t );
|
||||
unsigned long floorIntT = (unsigned long)floorT;
|
||||
|
||||
if( floorT == t ) {
|
||||
return blendNoise3d( x, y, z, floorIntT );
|
||||
}
|
||||
else {
|
||||
unsigned long ceilIntT = floorIntT + 1;
|
||||
|
||||
// cosine interpolation
|
||||
// from http://freespace.virgin.net/hugo.elias/models/m_perlin.htm
|
||||
double ft = ( t - floorT ) * M_PI;
|
||||
double f = ( 1 - cos( ft ) ) * .5;
|
||||
|
||||
return ( f ) * blendNoise3d( x, y, z, ceilIntT ) +
|
||||
( 1 - f ) * blendNoise3d( x, y, z, floorIntT );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
97
gamma256/prototypes/screenCompress/landscape.h
Normal file
|
@ -0,0 +1,97 @@
|
|||
|
||||
|
||||
|
||||
#ifndef LANDSCAPE_INCLUDED
|
||||
#define LANDSCAPE_INCLUDED
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets height samples from an "infinite" fractal landscape.
|
||||
* The landscape can change over time by varying t.
|
||||
*
|
||||
* @param x the x coordinate of the sample.
|
||||
* @param y the y coordinate of the sample.
|
||||
* @param t the time of the sample.
|
||||
* @param baseFrequency the frequency to use for the lowest detail component.
|
||||
* @param inRoughness the roughness of the landscape (how much high frequencies
|
||||
* are factored in). Should be in the range [0..1] with 0 making a very
|
||||
* smooth landscape and 1 making a very rough landscape.
|
||||
* @param detail the detail level. Larger numbers result in more
|
||||
* detail. Defaults to 10.
|
||||
*
|
||||
* @return the height of the landscape at the sample point/time.
|
||||
*/
|
||||
double landscape( double inX, double inY, double inT,
|
||||
double inBaseFrequency, double inRoughness,
|
||||
int inDetail = 10 );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Samples height of a landscape that varies in roughness over the xy plane.
|
||||
*
|
||||
* @params same as for landscape, except:
|
||||
* @param inRoughnessChangeFrequency the rate at which roughness changes
|
||||
* over space. Should, in general, be less than inBaseFrequency.
|
||||
* @param inMinRoughness the minimum roughness value, in the range [0..1].
|
||||
* @param inMaxRoughness the maximum roughness value, in the range [0..1].
|
||||
*
|
||||
* @return same as for landscape.
|
||||
*/
|
||||
double variableRoughnessLandscape( double inX, double inY, double inT,
|
||||
double inBaseFrequency,
|
||||
double inRoughnessChangeFrequency,
|
||||
double inMinRoughness,
|
||||
double inMaxRoughness,
|
||||
int inDetail );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Computes linearly-blended random values in the range [-1..1] from a
|
||||
* 4d parameterized noise space.
|
||||
*
|
||||
* @param x, y, z, t the 4d floating-point coordinates.
|
||||
*
|
||||
* @return a blended random value in the range [-1..1].
|
||||
*/
|
||||
double noise4d( double x,
|
||||
double y,
|
||||
double z,
|
||||
double t );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets a set of randomly-chosen (though stable) points in a given
|
||||
* region of the landscape.
|
||||
*
|
||||
* @param inStartX, inEndX the x region.
|
||||
* @param inStartY, inEndY the y region.
|
||||
* @param inT the time.
|
||||
* @param inSampleStepSize the step size in the sample grid.
|
||||
* Higher values are faster but result in sparser distributions of points.
|
||||
* @param inDensity the density of points, in the range [0,1].
|
||||
* @param outXCoordinates pointer to where array of x coordinates should
|
||||
* be returned. Array must be destroyed by caller.
|
||||
* @param outYCoordinates pointer to where array of x coordinates should
|
||||
* be returned. Array must be destroyed by caller.
|
||||
*
|
||||
* @return the number of points (the length of outXCoordinates).
|
||||
*/
|
||||
int getRandomPoints( double inStartX, double inEndX,
|
||||
double inStartY, double inEndY,
|
||||
double inT,
|
||||
double inSampleStepSize,
|
||||
double inDensity,
|
||||
double **outXCoordinates,
|
||||
double **outYCoordinates );
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
BIN
gamma256/prototypes/screenCompress/mapTile.tga
Normal file
After Width: | Height: | Size: 236 B |
798
gamma256/prototypes/screenCompress/screenCompress.cpp
Normal file
|
@ -0,0 +1,798 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2007-September-25 Jason Rohrer
|
||||
* Created.
|
||||
*/
|
||||
|
||||
#include "landscape.h"
|
||||
|
||||
#include "minorGems/graphics/Image.h"
|
||||
#include "minorGems/graphics/converters/TGAImageConverter.h"
|
||||
|
||||
#include "minorGems/io/file/File.h"
|
||||
|
||||
#include "minorGems/io/file/FileInputStream.h"
|
||||
|
||||
// #include "minorGems/system/Thread.h"
|
||||
|
||||
|
||||
#include <math.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
// for memcpy
|
||||
#include <string.h>
|
||||
|
||||
|
||||
|
||||
// size of game image
|
||||
int width = 100;
|
||||
int height = 16;
|
||||
|
||||
// size of screen
|
||||
int screenWidth = 640;
|
||||
int screenHeight = 480;
|
||||
|
||||
// blow-up factor when projecting game onto screen
|
||||
int blowUpFactor = 6;
|
||||
//int blowUpFactor = 1;
|
||||
|
||||
|
||||
char fullScreen = false;
|
||||
|
||||
double timeDelta = -0.1;
|
||||
//double timeDelta = -0.0;
|
||||
|
||||
|
||||
int mainFunction();
|
||||
|
||||
|
||||
|
||||
// must do this to prevent WinMain linker errors on win32
|
||||
int main() {
|
||||
mainFunction();
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
|
||||
// the joystick to read from, or NULL if there's no available joystick
|
||||
SDL_Joystick *joystick;
|
||||
|
||||
|
||||
|
||||
void catch_int(int sig_num) {
|
||||
printf( "Quiting...\n" );
|
||||
SDL_Quit();
|
||||
exit( 0 );
|
||||
signal( SIGINT, catch_int );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void blowupOntoScreen( Uint32 *inImage, int inWidth, int inHeight,
|
||||
int inBlowFactor, SDL_Surface *inScreen ) {
|
||||
|
||||
int newWidth = inBlowFactor * inWidth;
|
||||
int newHeight = inBlowFactor * inHeight;
|
||||
|
||||
int yOffset = ( inScreen->h - newHeight ) / 2;
|
||||
int xOffset = ( inScreen->w - newWidth ) / 2;
|
||||
|
||||
int endY = yOffset + newHeight;
|
||||
int endX = xOffset + newWidth;
|
||||
|
||||
Uint32 *pixels = (Uint32 *)( inScreen->pixels );
|
||||
|
||||
for( int y=yOffset; y<endY; y++ ) {
|
||||
int imageY = ( y - yOffset ) / inBlowFactor;
|
||||
|
||||
for( int x=xOffset; x<endX; x++ ) {
|
||||
int imageX = ( x - xOffset ) / inBlowFactor;
|
||||
|
||||
pixels[ y * inScreen->w + x ] =
|
||||
inImage[ imageY * inWidth + imageX ];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// values in range 0..1
|
||||
Image *tileImage;
|
||||
int imageW, imageH;
|
||||
|
||||
// dimensions of one tile. TileImage contains 13 tiles, stacked vertically,
|
||||
// with blank lines between tiles
|
||||
int tileW = 8;
|
||||
int tileH = 8;
|
||||
|
||||
|
||||
int numTileSets;
|
||||
|
||||
// how wide the swath of a world is that uses a given tile set
|
||||
int tileSetWorldSpan = 200;
|
||||
// overlap during tile set transition
|
||||
int tileSetWorldOverlap = 50;
|
||||
|
||||
|
||||
|
||||
// optimization (found with profiler)
|
||||
// values in range 0..255
|
||||
double *tileRed;
|
||||
double *tileGreen;
|
||||
double *tileBlue;
|
||||
|
||||
|
||||
Image *spriteImage;
|
||||
int spriteW = 8;
|
||||
int spriteH = 8;
|
||||
|
||||
double *spriteRed;
|
||||
double *spriteGreen;
|
||||
double *spriteBlue;
|
||||
|
||||
int currentSpriteIndex = 2;
|
||||
|
||||
|
||||
|
||||
double playerX, playerY;
|
||||
int playerRadius = spriteW / 2;
|
||||
|
||||
int seed = time( NULL );
|
||||
|
||||
|
||||
|
||||
inline char isBlocked( int inX, int inY ) {
|
||||
// reduce to grid coordinates
|
||||
int gridX = inX / tileW;
|
||||
int gridY = inY / tileH;
|
||||
|
||||
// wall along far left and top
|
||||
if( gridX <=0 || gridY <= 0 ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// make a grid of empty spaces from which blocks can be
|
||||
// removed below to make a maze
|
||||
if( gridX % 2 !=0 && gridY % 2 != 0 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// blocks get denser as y increases
|
||||
double threshold = 1 - gridY / 20.0;
|
||||
|
||||
double randValue = noise4d( gridX, gridY, seed, 0 );
|
||||
return randValue > threshold;
|
||||
}
|
||||
|
||||
|
||||
char isSpriteTransparent( int inSpriteIndex ) {
|
||||
// take transparent color from corner
|
||||
return
|
||||
spriteRed[ inSpriteIndex ] == spriteRed[ 0 ]
|
||||
&&
|
||||
spriteGreen[ inSpriteIndex ] == spriteGreen[ 0 ]
|
||||
&&
|
||||
spriteBlue[ inSpriteIndex ] == spriteBlue[ 0 ];
|
||||
}
|
||||
|
||||
|
||||
|
||||
Uint32 sampleFromWorld( int inX, int inY, double inWeight = 1.0 ) {
|
||||
|
||||
// consider sampling from sprite
|
||||
|
||||
// player position centered on sprint left-to-right
|
||||
int spriteX = (int)( inX - playerX + spriteW / 2 );
|
||||
// player position at sprite's feet
|
||||
int spriteY = (int)( inY - playerY + spriteH - 1);
|
||||
|
||||
|
||||
if( spriteX >= 0 && spriteX < spriteW
|
||||
&&
|
||||
spriteY >= 0 && spriteY < spriteH ) {
|
||||
|
||||
|
||||
int spriteIndex = spriteY * spriteW + spriteX;
|
||||
|
||||
// skip to appropriate sprite fram
|
||||
spriteIndex += currentSpriteIndex * spriteW * ( spriteH + 1 );
|
||||
|
||||
if( !isSpriteTransparent( spriteIndex ) ) {
|
||||
|
||||
unsigned char r =
|
||||
(unsigned char)(
|
||||
inWeight * spriteRed[ spriteIndex ] );
|
||||
|
||||
unsigned char g =
|
||||
(unsigned char)(
|
||||
inWeight * spriteGreen[ spriteIndex ] );
|
||||
|
||||
unsigned char b =
|
||||
(unsigned char)(
|
||||
inWeight * spriteBlue[ spriteIndex ] );
|
||||
|
||||
return r << 16 | g << 8 | b;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int tileIndex;
|
||||
|
||||
if( !isBlocked( inX, inY ) ) {
|
||||
// empty tile
|
||||
tileIndex = 0;
|
||||
}
|
||||
else {
|
||||
int neighborsBlockedBinary = 0;
|
||||
|
||||
if( isBlocked( inX, inY - tileH ) ) {
|
||||
// top
|
||||
neighborsBlockedBinary = neighborsBlockedBinary | 1;
|
||||
}
|
||||
if( isBlocked( inX + tileW, inY ) ) {
|
||||
// right
|
||||
neighborsBlockedBinary = neighborsBlockedBinary | 1 << 1;
|
||||
}
|
||||
if( isBlocked( inX, inY + tileH ) ) {
|
||||
// bottom
|
||||
neighborsBlockedBinary = neighborsBlockedBinary | 1 << 2;
|
||||
}
|
||||
if( isBlocked( inX - tileW, inY ) ) {
|
||||
// left
|
||||
neighborsBlockedBinary = neighborsBlockedBinary | 1 << 3;
|
||||
}
|
||||
|
||||
// skip empty tile, treat as tile index
|
||||
neighborsBlockedBinary += 1;
|
||||
|
||||
tileIndex = neighborsBlockedBinary;
|
||||
}
|
||||
|
||||
|
||||
// pick a tile set
|
||||
int netWorldSpan = tileSetWorldSpan + tileSetWorldOverlap;
|
||||
|
||||
int tileSet = inX / netWorldSpan;
|
||||
int overhang = inX % netWorldSpan;
|
||||
if( inX < 0 ) {
|
||||
// fix to a constant tile set below 0
|
||||
overhang = 0;
|
||||
tileSet = 0;
|
||||
}
|
||||
|
||||
// is there blending with next tile set?
|
||||
int blendTileSet = tileSet + 1;
|
||||
double blendWeight = 0;
|
||||
|
||||
if( overhang > tileSetWorldSpan ) {
|
||||
blendWeight = ( overhang - tileSetWorldSpan ) /
|
||||
(double) tileSetWorldOverlap;
|
||||
}
|
||||
// else 100% blend of our first tile set
|
||||
|
||||
|
||||
tileSet = tileSet % numTileSets;
|
||||
blendTileSet = blendTileSet % numTileSets;
|
||||
|
||||
// make sure not negative
|
||||
if( tileSet < 0 ) {
|
||||
tileSet += numTileSets;
|
||||
}
|
||||
if( blendTileSet < 0 ) {
|
||||
blendTileSet += numTileSets;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// sample from tile image
|
||||
int imageY = inY % tileH;
|
||||
int imageX = inX % tileW;
|
||||
|
||||
|
||||
if( imageX < 0 ) {
|
||||
imageX += tileW;
|
||||
}
|
||||
if( imageY < 0 ) {
|
||||
imageY += tileH;
|
||||
}
|
||||
|
||||
// offset to top left corner of tile
|
||||
int tileImageOffset = tileIndex * ( tileH + 1 ) * imageW
|
||||
+ tileSet * (tileW + 1);
|
||||
int blendTileImageOffset = tileIndex * ( tileH + 1 ) * imageW
|
||||
+ blendTileSet * (tileW + 1);
|
||||
|
||||
|
||||
int imageIndex = tileImageOffset + imageY * imageW + imageX;
|
||||
int blendImageIndex = blendTileImageOffset + imageY * imageW + imageX;
|
||||
|
||||
unsigned char r =
|
||||
(unsigned char)(
|
||||
inWeight * (
|
||||
(1-blendWeight) * tileRed[ imageIndex ] +
|
||||
blendWeight * tileRed[ blendImageIndex ] ) );
|
||||
|
||||
unsigned char g =
|
||||
(unsigned char)(
|
||||
inWeight * (
|
||||
(1-blendWeight) * tileGreen[ imageIndex ] +
|
||||
blendWeight * tileGreen[ blendImageIndex ] ) );
|
||||
|
||||
unsigned char b =
|
||||
(unsigned char)(
|
||||
inWeight * (
|
||||
(1-blendWeight) * tileBlue[ imageIndex ] +
|
||||
blendWeight * tileBlue[ blendImageIndex ] ) );
|
||||
|
||||
|
||||
return r << 16 | g << 8 | b;
|
||||
}
|
||||
|
||||
|
||||
|
||||
char getKeyDown( int inKeyCode ) {
|
||||
SDL_PumpEvents();
|
||||
Uint8 *keys = SDL_GetKeyState( NULL );
|
||||
return keys[ inKeyCode ] == SDL_PRESSED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
char getHatDown( Uint8 inHatPosition ) {
|
||||
if( joystick == NULL ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_JoystickUpdate();
|
||||
|
||||
Uint8 hatPosition = SDL_JoystickGetHat( joystick, 1 );
|
||||
|
||||
if( hatPosition & inHatPosition ) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Image *readTGA( char *inFileName ) {
|
||||
File tileFile( NULL, inFileName );
|
||||
FileInputStream tileStream( &tileFile );
|
||||
|
||||
TGAImageConverter converter;
|
||||
|
||||
return converter.deformatImage( &tileStream );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int mainFunction() {
|
||||
|
||||
// let catch_int handle interrupt (^c)
|
||||
signal( SIGINT, catch_int );
|
||||
|
||||
|
||||
// read in map tile
|
||||
tileImage = readTGA( "tileSet.tga" );
|
||||
|
||||
imageW = tileImage->getWidth();
|
||||
imageH = tileImage->getHeight();
|
||||
|
||||
numTileSets = (imageW + 1) / (tileW + 1);
|
||||
|
||||
|
||||
int imagePixelCount = imageW * imageH;
|
||||
|
||||
tileRed = new double[ imagePixelCount ];
|
||||
tileGreen = new double[ imagePixelCount ];
|
||||
tileBlue = new double[ imagePixelCount ];
|
||||
|
||||
for( int i=0; i<imagePixelCount; i++ ) {
|
||||
tileRed[i] = 255 * tileImage->getChannel(0)[ i ];
|
||||
tileGreen[i] = 255 * tileImage->getChannel(1)[ i ];
|
||||
tileBlue[i] = 255 * tileImage->getChannel(2)[ i ];
|
||||
}
|
||||
|
||||
|
||||
// read in map tile
|
||||
spriteImage = readTGA( "characterSprite.tga" );
|
||||
|
||||
imagePixelCount = spriteImage->getWidth() * spriteImage->getHeight();
|
||||
|
||||
spriteRed = new double[ imagePixelCount ];
|
||||
spriteGreen = new double[ imagePixelCount ];
|
||||
spriteBlue = new double[ imagePixelCount ];
|
||||
|
||||
for( int i=0; i<imagePixelCount; i++ ) {
|
||||
spriteRed[i] = 255 * spriteImage->getChannel(0)[ i ];
|
||||
spriteGreen[i] = 255 * spriteImage->getChannel(1)[ i ];
|
||||
spriteBlue[i] = 255 * spriteImage->getChannel(2)[ i ];
|
||||
}
|
||||
|
||||
|
||||
|
||||
if( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_JOYSTICK |
|
||||
SDL_INIT_NOPARACHUTE ) < 0 ) {
|
||||
printf( "Couldn't initialize SDL: %s\n", SDL_GetError() );
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_ShowCursor( SDL_DISABLE );
|
||||
|
||||
Uint32 flags = SDL_HWSURFACE | SDL_DOUBLEBUF;
|
||||
if( fullScreen ) {
|
||||
flags = flags | SDL_FULLSCREEN;
|
||||
}
|
||||
|
||||
|
||||
SDL_Surface *screen = SDL_SetVideoMode( screenWidth, screenHeight,
|
||||
32,
|
||||
flags );
|
||||
|
||||
if ( screen == NULL ) {
|
||||
printf( "Couldn't set %dx%dx32 video mode: %s\n", screenWidth,
|
||||
screenHeight,
|
||||
SDL_GetError() );
|
||||
return-1;
|
||||
}
|
||||
|
||||
// try to open joystick
|
||||
int numJoysticks = SDL_NumJoysticks();
|
||||
printf( "Found %d joysticks\n", numJoysticks );
|
||||
|
||||
if( numJoysticks > 0 ) {
|
||||
// open first one by default
|
||||
joystick = SDL_JoystickOpen( 1 );
|
||||
|
||||
if( joystick == NULL ) {
|
||||
printf( "Couldn't open joystick 1: %s\n", SDL_GetError() );
|
||||
}
|
||||
int numHats = SDL_JoystickNumHats( joystick );
|
||||
|
||||
if( numHats <= 0 ) {
|
||||
printf( "No d-pad found on joystick\n" );
|
||||
SDL_JoystickClose( joystick );
|
||||
joystick = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
joystick = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Uint32 *pixels = (Uint32 *)( screen->pixels );
|
||||
|
||||
Uint32 *gameImage = new Uint32[ width * height ];
|
||||
|
||||
|
||||
// first, fill the whole thing with black
|
||||
SDL_FillRect(screen, NULL, 0x00000000);
|
||||
|
||||
// small area in center that we actually draw in, black around it
|
||||
int yOffset = ( screenHeight - height * blowUpFactor ) / 2;
|
||||
int xOffset = ( screenWidth - width * blowUpFactor ) / 2;
|
||||
|
||||
|
||||
double dX = 0;
|
||||
double dY = 0;
|
||||
|
||||
int frameCount = 0;
|
||||
unsigned long startTime = time( NULL );
|
||||
|
||||
char done = false;
|
||||
|
||||
double maxWorldX = 0;
|
||||
double minWorldX = 0;
|
||||
|
||||
|
||||
// start player position
|
||||
playerX = tileW;
|
||||
//playerX = 0;
|
||||
dX = tileW;
|
||||
playerY = 0 + height/2;
|
||||
dY = 0;
|
||||
|
||||
while( !done ) {
|
||||
|
||||
char someBlocksDrawn = false;
|
||||
|
||||
for( int y=0; y<height; y++ ) {
|
||||
for( int x=0; x<width; x++ ) {
|
||||
|
||||
// offset into center
|
||||
int gameImageIndex = y * width + x;
|
||||
|
||||
|
||||
|
||||
//int worldX = (int)( pow( x / 2.0, 1.4 ) );
|
||||
|
||||
// compression based on distance of pixel column from player
|
||||
double trueDistanceFromPlayer = dX + x - playerX;
|
||||
double maxDistance = width - 1;
|
||||
|
||||
// cap it so that we don't force tan into infinity below
|
||||
double cappedDistanceFromPlayer = trueDistanceFromPlayer;
|
||||
if( cappedDistanceFromPlayer > maxDistance ) {
|
||||
cappedDistanceFromPlayer = maxDistance;
|
||||
}
|
||||
if( cappedDistanceFromPlayer < -maxDistance ) {
|
||||
cappedDistanceFromPlayer = -maxDistance;
|
||||
}
|
||||
|
||||
// the world position we will sample from
|
||||
double worldX = x;
|
||||
|
||||
// zone around player where no x compression happens
|
||||
int noCompressZone = 10;
|
||||
|
||||
|
||||
if( trueDistanceFromPlayer > noCompressZone ) {
|
||||
|
||||
worldX =
|
||||
x +
|
||||
//(width/8) *
|
||||
// use true distance as a factor so that compression
|
||||
// continues at constant rate after we pass capped
|
||||
// distance
|
||||
// otherwise, compression stops after capped distance
|
||||
// Still... constant rate looks weird, so avoid
|
||||
// it by not letting it pass capped distance
|
||||
trueDistanceFromPlayer / 2 *
|
||||
( pow( tan( ( ( cappedDistanceFromPlayer -
|
||||
noCompressZone ) /
|
||||
(double)( width - noCompressZone ) ) *
|
||||
M_PI / 2 ), 2) );
|
||||
/*
|
||||
trueDistanceFromPlayer / 2 *
|
||||
( tan( ( cappedDistanceFromPlayer /
|
||||
(double)( width - 0.5 ) ) * M_PI / 2 ) );
|
||||
*/
|
||||
// simpler formula
|
||||
// actually, this does not approach 0 as
|
||||
// cappedDistanceFromPlayer approaches 0, so use tan
|
||||
// instead
|
||||
// ( trueDistanceFromPlayer / 2 ) * 100
|
||||
// / pow( ( width - cappedDistanceFromPlayer ), 1.6 );
|
||||
}
|
||||
else if( trueDistanceFromPlayer < - noCompressZone ) {
|
||||
worldX =
|
||||
x +
|
||||
//(width/8) *
|
||||
trueDistanceFromPlayer / 2 *
|
||||
( pow( tan( ( ( - cappedDistanceFromPlayer -
|
||||
noCompressZone ) /
|
||||
(double)( width - noCompressZone ) ) *
|
||||
M_PI / 2 ), 2) );
|
||||
/*
|
||||
trueDistanceFromPlayer / 2 *
|
||||
( tan( ( - cappedDistanceFromPlayer /
|
||||
(double)( width - 0.5 ) ) * M_PI / 2 ) );
|
||||
*/
|
||||
//( trueDistanceFromPlayer / 2 ) * 50
|
||||
/// ( width + cappedDistanceFromPlayer );
|
||||
}
|
||||
else {
|
||||
// inside no-compresison zone
|
||||
worldX = x;
|
||||
}
|
||||
|
||||
|
||||
//int worldX = x;
|
||||
|
||||
worldX += dX;
|
||||
|
||||
if( worldX > maxWorldX ) {
|
||||
maxWorldX = worldX;
|
||||
}
|
||||
if( worldX < minWorldX ) {
|
||||
minWorldX = worldX;
|
||||
}
|
||||
|
||||
|
||||
int worldY = (int)floor( y + dY );
|
||||
|
||||
|
||||
// linear interpolation of two samples for worldX
|
||||
int intWorldX = (int)floor( worldX );
|
||||
|
||||
double bWeight = worldX - intWorldX;
|
||||
double aWeight = 1 - bWeight;
|
||||
|
||||
|
||||
Uint32 sampleA =
|
||||
sampleFromWorld( intWorldX, worldY, aWeight );
|
||||
Uint32 sampleB =
|
||||
sampleFromWorld( intWorldX + 1, worldY, bWeight );
|
||||
|
||||
|
||||
|
||||
Uint32 combined = sampleB + sampleA;
|
||||
|
||||
|
||||
gameImage[ y * width + x ] = combined;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// check if we need to lock the screen
|
||||
if( SDL_MUSTLOCK( screen ) ) {
|
||||
if( SDL_LockSurface( screen ) < 0 ) {
|
||||
printf( "Couldn't lock screen: %s\n", SDL_GetError() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
blowupOntoScreen( gameImage, width, height, blowUpFactor, screen );
|
||||
|
||||
|
||||
// unlock the screen if necessary
|
||||
if ( SDL_MUSTLOCK(screen) ) {
|
||||
SDL_UnlockSurface(screen);
|
||||
}
|
||||
|
||||
if( ( screen->flags & SDL_DOUBLEBUF ) == SDL_DOUBLEBUF ) {
|
||||
// need to flip buffer
|
||||
SDL_Flip( screen );
|
||||
printf( "double\n" );
|
||||
|
||||
}
|
||||
else {
|
||||
// just update center
|
||||
//SDL_UpdateRect( screen, yOffset, xOffset, width, height );
|
||||
SDL_Flip( screen );
|
||||
}
|
||||
|
||||
int moveDelta = 1;
|
||||
if( getKeyDown( SDLK_LEFT ) || getHatDown( SDL_HAT_LEFT ) ) {
|
||||
if( currentSpriteIndex == 6 ) {
|
||||
currentSpriteIndex = 7;
|
||||
}
|
||||
else {
|
||||
currentSpriteIndex = 6;
|
||||
}
|
||||
|
||||
if( !isBlocked( (int)( playerX - moveDelta ), (int)playerY ) ) {
|
||||
|
||||
playerX -= moveDelta;
|
||||
|
||||
if( playerX < 0 ) {
|
||||
// undo
|
||||
playerX += moveDelta;
|
||||
}
|
||||
else {
|
||||
// update screen position
|
||||
dX -= moveDelta;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( getKeyDown( SDLK_RIGHT ) || getHatDown( SDL_HAT_RIGHT )) {
|
||||
if( currentSpriteIndex == 2 ) {
|
||||
currentSpriteIndex = 3;
|
||||
}
|
||||
else {
|
||||
currentSpriteIndex = 2;
|
||||
}
|
||||
|
||||
if( !isBlocked( (int)( playerX + moveDelta ), (int)playerY ) ) {
|
||||
|
||||
dX += moveDelta;
|
||||
|
||||
playerX += moveDelta;
|
||||
}
|
||||
}
|
||||
else if( getKeyDown( SDLK_UP ) || getHatDown( SDL_HAT_UP ) ) {
|
||||
if( currentSpriteIndex == 0 ) {
|
||||
currentSpriteIndex = 1;
|
||||
}
|
||||
else {
|
||||
currentSpriteIndex = 0;
|
||||
}
|
||||
|
||||
if( !isBlocked( (int)playerX, (int)( playerY - moveDelta ) ) ) {
|
||||
|
||||
playerY -= moveDelta;
|
||||
|
||||
if( playerY < 0 ) {
|
||||
// undo
|
||||
playerY += moveDelta;
|
||||
}
|
||||
else {
|
||||
// update screen position
|
||||
dY -= moveDelta;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( getKeyDown( SDLK_DOWN ) || getHatDown( SDL_HAT_DOWN )) {
|
||||
if( currentSpriteIndex == 4 ) {
|
||||
currentSpriteIndex = 5;
|
||||
}
|
||||
else {
|
||||
currentSpriteIndex = 4;
|
||||
}
|
||||
|
||||
if( !isBlocked( (int)playerX, (int)( playerY + moveDelta ) ) ) {
|
||||
|
||||
dY += moveDelta;
|
||||
|
||||
playerY += moveDelta;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// check for events to quit
|
||||
SDL_Event event;
|
||||
while( SDL_PollEvent(&event) ) {
|
||||
switch( event.type ) {
|
||||
case SDL_KEYDOWN:
|
||||
switch( event.key.keysym.sym ) {
|
||||
case SDLK_q:
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SDL_QUIT:
|
||||
done = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//t +=0.25;
|
||||
frameCount ++;
|
||||
|
||||
// player position on screen inches forward
|
||||
dX += timeDelta;
|
||||
//dX -= 1;
|
||||
// stop after player has gone off right end of screen
|
||||
if( playerX - dX > width ) {
|
||||
dX = playerX - width;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
unsigned long netTime = time( NULL ) - startTime;
|
||||
double frameRate = frameCount / (double)netTime;
|
||||
|
||||
printf( "Max world x = %f\n", maxWorldX );
|
||||
printf( "Min world x = %f\n", minWorldX );
|
||||
|
||||
printf( "Frame rate = %f fps (%d frames)\n", frameRate, frameCount );
|
||||
fflush( stdout );
|
||||
|
||||
|
||||
|
||||
delete tileImage;
|
||||
delete [] tileRed;
|
||||
delete [] tileGreen;
|
||||
delete [] tileBlue;
|
||||
|
||||
|
||||
delete spriteImage;
|
||||
delete [] spriteRed;
|
||||
delete [] spriteGreen;
|
||||
delete [] spriteBlue;
|
||||
|
||||
|
||||
if( joystick != NULL ) {
|
||||
SDL_JoystickClose( joystick );
|
||||
}
|
||||
|
||||
SDL_Quit();
|
||||
}
|
110
gamma256/prototypes/screenCompress/sdlTest.cpp
Normal file
|
@ -0,0 +1,110 @@
|
|||
// FIXME:
|
||||
// why does this end up with a blank, white screen after 5 seconds
|
||||
// while the demo code (testsprite) works fine?
|
||||
// Does it only happen on win32
|
||||
|
||||
|
||||
|
||||
#include <math.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// for memcpy
|
||||
#include <string.h>
|
||||
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
void catch_int(int sig_num) {
|
||||
printf( "Quiting...\n" );
|
||||
//currentStep = numSteps;
|
||||
exit( 0 );
|
||||
signal( SIGINT, catch_int );
|
||||
}
|
||||
|
||||
|
||||
// if SDL.h is included before our main function, the linker complains
|
||||
// about missing WinMain
|
||||
// This fixes it
|
||||
int mainFunction();
|
||||
|
||||
int main() {
|
||||
mainFunction();
|
||||
}
|
||||
|
||||
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
|
||||
int mainFunction() {
|
||||
|
||||
|
||||
// let catch_int handle interrupt (^c)
|
||||
signal( SIGINT, catch_int );
|
||||
|
||||
int w = 640;
|
||||
int h = 480;
|
||||
|
||||
if( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE ) < 0 ) {
|
||||
printf( "Couldn't initialize SDL: %s\n", SDL_GetError() );
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_Surface *screen = SDL_SetVideoMode( w, h,
|
||||
32,
|
||||
SDL_SWSURFACE );
|
||||
|
||||
if ( screen == NULL ) {
|
||||
printf( "Couldn't set %dx%dx32 video mode: %s\n", w, h,
|
||||
SDL_GetError() );
|
||||
return-1;
|
||||
}
|
||||
|
||||
Uint32 *buffer = (Uint32 *)( screen->pixels );
|
||||
|
||||
char white = false;
|
||||
|
||||
char done = false;
|
||||
|
||||
while( !done ) {
|
||||
if( white ) {
|
||||
SDL_FillRect(screen, NULL, 0x00FFFFFF);
|
||||
}
|
||||
else {
|
||||
SDL_FillRect(screen, NULL, 0x00000000);
|
||||
}
|
||||
/*
|
||||
for( int y=0; y<h; y++ ) {
|
||||
for( int x=0; x<w; x++ ) {
|
||||
|
||||
|
||||
if( white ) {
|
||||
buffer[ y * w + x ] = 0x00FFFFFF;
|
||||
}
|
||||
else {
|
||||
buffer[ y * w + x ] = 0x00000000;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
white = ! white;
|
||||
//SDL_UpdateRect( screen, 0, 0, w, h );
|
||||
SDL_Flip( screen );
|
||||
|
||||
// check for events to quit
|
||||
SDL_Event event;
|
||||
while ( SDL_PollEvent(&event) ) {
|
||||
switch (event.type) {
|
||||
case SDL_KEYDOWN:
|
||||
/* Any keypress quits the app... */
|
||||
case SDL_QUIT:
|
||||
done = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
BIN
gamma256/prototypes/screenCompress/tileSet.png
Normal file
After Width: | Height: | Size: 831 B |
BIN
gamma256/prototypes/screenCompress/tileSet.tga
Normal file
After Width: | Height: | Size: 7.6 KiB |
BIN
gamma256/prototypes/screenCompress/tileTemplate.png
Normal file
After Width: | Height: | Size: 207 B |
BIN
gamma256/prototypes/screenCompress/tileTemplate.tga
Normal file
After Width: | Height: | Size: 3.6 KiB |