# define OLC_PGE_APPLICATION
# include "pixelGameEngine.h"
# include <random>
# include "gameDefines.h"
# include <assert.h>
Meteos * game ;
struct BlockMatchingInfo {
int col ;
int ind ;
int c = - 1 ;
} ;
bool Meteos : : OnUserCreate ( )
{
game = this ;
SPRITES [ " blocks_test.png " ] . Load ( " assets/blocks_test.png " ) ;
std : : random_device rd ; //Will be used to obtain a seed for the random number engine
gen = std : : mt19937 ( rd ( ) ) ; //Standard mersenne_twister_engine seeded with rd()
randBlockPos = std : : uniform_int_distribution < > ( 0 , 9 ) ;
coinFlip = std : : uniform_int_distribution < > ( 0 , 1 ) ;
comboOverlayOffset = std : : uniform_int_distribution < > ( - 16 , 16 ) ;
gameBoard = Board ( { 10 , 14 } , 0.02f , 0.04f , 1.2f , 0.04f , 0.4f , { - 1.f , - 1.5f , - 2.f , - 2.5f , - 4.f } , 1.7f , 2.0f , 0.2f , { 3 , 3 , 1 , 2 , 3 , 0 , 0 , 0 , 0 , 0 } ,
60 * 10 , SPRITES [ " blocks_test.png " ] ) ;
return true ;
}
bool Meteos : : OnUserUpdate ( float fElapsedTime )
{
if ( gameCanRun ) {
accumulatedTime + = fElapsedTime ;
if ( accumulatedTime > = 1 / 60.0f ) {
updateGame ( 1 / 60.0f ) ;
accumulatedTime = 0 ;
}
handleInput ( ) ;
}
drawGame ( fElapsedTime , ! gameCanRun ) ;
return true ;
}
void Meteos : : handleInput ( ) {
if ( GetMouse ( 0 ) . bHeld ) {
int mouseX = ( GetMouseX ( ) - gameBoard . drawOffset . x ) ;
int mouseY = ( GetMouseY ( ) - gameBoard . drawOffset . y ) ;
int mouseCol = mouseX / 12 ;
int mouseRow = mouseY / 12 ;
if ( mouseCol > = 0 & & mouseCol < gameBoard . boardSize . x ) {
for ( int y = 0 ; y < gameBoard . getBlocks ( mouseCol ) . size ( ) ; y + + ) {
Block & b = gameBoard . getBlocks ( mouseCol ) [ y ] ;
if ( b . pos . y / 12 = = mouseRow ) {
SelectedBlockData newData = { mouseCol , y , - 1 } ;
if ( gameBoard . selectedBlock . col ! = - 1 & & mouseCol = = gameBoard . selectedBlock . col ) {
//See if these two can be swapped.
Block & b1 = gameBoard . getBlock ( gameBoard . selectedBlock ) ;
Block & b2 = gameBoard . getBlock ( newData ) ;
int y1 = ( gameBoard . selectedBlock . c ! = - 1 ) ? gameBoard . getBlockClumps ( ) [ gameBoard . selectedBlock . c ] . getBlockPosition ( gameBoard . getBlockClumps ( ) [ gameBoard . selectedBlock . c ] . getBlocks ( ) [ gameBoard . selectedBlock . ind ] ) . y : gameBoard . getBlocks ( gameBoard . selectedBlock . col ) [ gameBoard . selectedBlock . ind ] . pos . y ;
int y2 = ( newData . c ! = - 1 ) ? gameBoard . getBlockClumps ( ) [ newData . c ] . getBlockPosition ( gameBoard . getBlockClumps ( ) [ newData . c ] . getBlocks ( ) [ newData . ind ] ) . y : gameBoard . getBlocks ( newData . col ) [ newData . ind ] . pos . y ;
if ( b1 . pos . x = = b2 . pos . x & & std : : abs ( y1 - y2 ) < = 12 ) {
//Swap the two!
BlockColor tempCol = b1 . col ;
b1 . col = b2 . col ;
b2 . col = tempCol ;
}
}
gameBoard . selectedBlock = newData ;
goto found ;
}
}
for ( int i = 0 ; i < gameBoard . getBlockClumps ( ) . size ( ) ; i + + ) {
BlockClump & c = gameBoard . getBlockClumps ( ) [ i ] ;
for ( int j = 0 ; j < c . getBlocks ( ) . size ( ) ; j + + ) {
Block & b = c . getBlocks ( ) [ j ] ;
if ( b . pos . x / 12 = = mouseCol & & c . getBlockPosition ( b ) . y < = mouseY & & c . getBlockPosition ( b ) . y + 12 > = mouseY ) {
SelectedBlockData newData = { mouseCol , j , i } ;
if ( gameBoard . selectedBlock . col ! = - 1 & & mouseCol = = gameBoard . selectedBlock . col ) {
//See if these two can be swapped.
Block & b1 = gameBoard . getBlock ( gameBoard . selectedBlock ) ;
Block & b2 = gameBoard . getBlock ( newData ) ;
int y1 = ( gameBoard . selectedBlock . c ! = - 1 ) ? gameBoard . getBlockClumps ( ) [ gameBoard . selectedBlock . c ] . getBlockPosition ( gameBoard . getBlockClumps ( ) [ gameBoard . selectedBlock . c ] . getBlocks ( ) [ gameBoard . selectedBlock . ind ] ) . y : gameBoard . getBlocks ( gameBoard . selectedBlock . col ) [ gameBoard . selectedBlock . ind ] . pos . y ;
int y2 = ( newData . c ! = - 1 ) ? gameBoard . getBlockClumps ( ) [ newData . c ] . getBlockPosition ( gameBoard . getBlockClumps ( ) [ newData . c ] . getBlocks ( ) [ newData . ind ] ) . y : gameBoard . getBlocks ( newData . col ) [ newData . ind ] . pos . y ;
if ( b1 . pos . x = = b2 . pos . x & & std : : abs ( y1 - y2 ) < = 12 ) {
//Swap the two!
BlockColor tempCol = b1 . col ;
b1 . col = b2 . col ;
b2 . col = tempCol ;
}
}
gameBoard . selectedBlock = newData ;
goto found ;
}
}
}
found : ;
}
if ( gameBoard . selectedBlock . c = = - 1 & & gameBoard . selectedBlock . col ! = - 1 & & gameBoard . boardSize . y - mouseRow > gameBoard . getBlocks ( gameBoard . selectedBlock . col ) . size ( ) & & gameBoard . getBlocks ( gameBoard . selectedBlock . col ) [ gameBoard . selectedBlock . ind ] . pos . y > 12 ) {
//Fling the block upwards.
BlockClump newClump ;
Block & targetBlock = gameBoard . getBlocks ( gameBoard . selectedBlock . col ) [ gameBoard . selectedBlock . ind ] ;
newClump . y = targetBlock . pos . y - 1 ;
newClump . launchTime = 999999 ;
newClump . vspeed = gameBoard . launchSpd [ 0 ] ;
newClump . flinged = true ;
newClump . addBlock ( gameBoard . selectedBlock . col , targetBlock . col ) ;
gameBoard . addClump ( newClump ) ;
gameBoard . removeBlock ( gameBoard . selectedBlock . col , gameBoard . selectedBlock . ind ) ;
gameBoard . selectedBlock = { - 1 , - 1 , - 1 } ;
}
}
if ( GetMouse ( 0 ) . bReleased ) {
gameBoard . selectedBlock = { - 1 , - 1 , - 1 } ;
}
}
void Meteos : : updateGame ( float fElapsedTime ) {
lastBlockSpawn + = fElapsedTime ;
if ( lastBlockSpawn > = gameBoard . spawnRate ) {
lastBlockSpawn - = gameBoard . spawnRate ;
gameBoard . spawnBlock ( randBlockPos ( gen ) ) ;
}
for ( int i = gameBoard . getBlockClumps ( ) . size ( ) - 1 ; i > = 0 ; i - - ) {
BlockClump & c = gameBoard . getBlockClumps ( ) [ i ] ;
if ( c . launchTime > 0 ) {
c . launchTime - = fElapsedTime ;
} else
if ( c . combo > 0 ) {
c . vspeed + = gameBoard . comboGravity ;
if ( c . vspeed > gameBoard . comboMaxGravity ) {
c . vspeed = gameBoard . comboMaxGravity ;
}
} else {
c . vspeed + = gameBoard . gravity ;
if ( c . vspeed > gameBoard . maxGravity ) {
c . vspeed = gameBoard . maxGravity ;
}
}
if ( c . flinged & & c . y < 12 * 3 ) {
c . flinged = false ;
c . launchTime = 0 ;
}
for ( int j = gameBoard . getBlockClumps ( ) . size ( ) - 1 ; j > = 0 ; j - - ) {
if ( i = = j ) continue ;
BlockClump & c2 = gameBoard . getBlockClumps ( ) [ j ] ;
for ( int k = c2 . getBlocks ( ) . size ( ) - 1 ; k > = 0 ; k - - ) {
Block & b2 = c2 . getBlocks ( ) [ k ] ;
for ( int l = c . getBlocks ( ) . size ( ) - 1 ; l > = 0 ; l - - ) {
Block & b3 = c . getBlocks ( ) [ l ] ;
if ( c2 . getBlockPosition ( b2 ) . x = = c . getBlockPosition ( b3 ) . x & &
c2 . getBlockPosition ( b2 ) . y + 12 > = c . getBlockPosition ( b3 ) . y & &
c2 . getBlockPosition ( b2 ) . y < = c . getBlockPosition ( b3 ) . y + 12 ) {
c . y = ( int ) c . y ;
c2 . y = ( int ) c2 . y ;
if ( c2 . getBlockPosition ( b2 ) . y > c . getBlockPosition ( b3 ) . y ) {
c . y - = 12 - ( c2 . getBlockPosition ( b2 ) . y - c . getBlockPosition ( b3 ) . y ) ;
c . y - = fmod ( c . y - c2 . y , 12 ) ;
if ( fmod ( c2 . y - c . y , 12 ) ! = 0 ) {
std : : cout < < " Difference is not divisible by 12!! Value: " < < fmod ( c2 . y - c . y , 12 ) < < " , " < < c2 . y < < " // " < < c . y < < std : : endl ;
assert ( false ) ;
}
} else {
c2 . y - = 12 - ( c . getBlockPosition ( b3 ) . y - c2 . getBlockPosition ( b2 ) . y ) ;
c2 . y - = fmod ( c . y - c2 . y , 12 ) ;
if ( fmod ( c . y - c2 . y , 12 ) ! = 0 ) {
std : : cout < < " Difference is not divisible by 12!! Value: " < < fmod ( c . y - c2 . y , 12 ) < < " , " < < c . y < < " // " < < c2 . y < < std : : endl ;
assert ( false ) ;
}
}
float influence = ( float ) c . getBlocks ( ) . size ( ) / ( c . getBlocks ( ) . size ( ) + c2 . getBlocks ( ) . size ( ) ) ;
int blockCount = c . getBlocks ( ) . size ( ) ;
int blockCount2 = c2 . getBlocks ( ) . size ( ) ;
//Copy every block from one clump to the other
for ( int m = 0 ; m < c2 . getBlocks ( ) . size ( ) ; m + + ) {
Block & b4 = c2 . getBlocks ( ) [ m ] ;
bool exists = false ;
for ( int n = 0 ; n < c . getBlocks ( ) . size ( ) ; n + + ) {
if ( ( c . getBlocks ( ) [ n ] . pos . x ) / 12 = = ( b4 . pos . x ) / 12 & & ( c . getBlocks ( ) [ n ] . pos . y ) / 12 = = ( c2 . getBlockPosition ( b4 ) . y - c . y ) / 12 ) {
std : : cout < < " WARNING! Block overlapping detected at " < < c . getBlocks ( ) [ n ] . pos < < " ! " < < std : : endl ;
exists = true ;
blockCount - - ;
break ;
}
}
if ( ! exists ) {
c . addBlock ( b4 . pos . x / 12 , ( c2 . getBlockPosition ( b4 ) . y - c . y ) / 12 , b4 . col ) ;
}
}
if ( blockCount + blockCount2 ! = c . getBlocks ( ) . size ( ) ) {
std : : cout < < " Block size is: " < < c . getBlocks ( ) . size ( ) < < " but expected " < < blockCount + blockCount2 < < std : : endl ;
assert ( false ) ;
}
bool overlappingBlocks = false ;
for ( int m = 0 ; m < c . getBlocks ( ) . size ( ) ; m + + ) {
for ( int n = 0 ; n < c . getBlocks ( ) . size ( ) ; n + + ) {
if ( m = = n ) continue ;
if ( c . getBlocks ( ) [ m ] . pos = = c . getBlocks ( ) [ n ] . pos ) {
std : : cout < < " Block overlapping detected at " < < c . getBlocks ( ) [ m ] . pos < < " ! " < < std : : endl ;
overlappingBlocks = true ;
}
}
}
if ( overlappingBlocks ) {
gameCanRun = false ;
return ;
}
if ( overlappingBlocks ) {
std : : cout < < " Block b3 " < < b3 . pos < < " ! " < < std : : endl ;
}
if ( ! c . flinged & & ! c2 . flinged ) {
c . vspeed = std : : min ( c . vspeed , c2 . vspeed ) ;
}
if ( c . flinged | | c2 . flinged ) {
c . launchTime = 0 ;
}
c . flinged = false ;
c2 . flinged = false ;
c . combo = std : : max ( c . combo , c2 . combo ) ;
c . landTime = std : : max ( c . landTime , c2 . landTime ) ;
c . sortBlocks ( ) ;
if ( i > = j ) {
i - - ;
}
gameBoard . removeClump ( j ) ;
goto nextClumpCollisionCheck ;
}
}
}
}
nextClumpCollisionCheck : ;
for ( int j = 0 ; j < c . getBlocks ( ) . size ( ) ; j + + ) {
Block & b = c . getBlocks ( ) [ j ] ;
int col = b . pos . x / 12 ;
for ( int k = 0 ; k < gameBoard . getBlocks ( col ) . size ( ) ; k + + ) {
Block & b2 = gameBoard . getBlocks ( col ) [ k ] ;
if ( c . getBlockPosition ( b ) . y + 12 > = b2 . pos . y & & c . getBlockPosition ( b ) . y < = b2 . pos . y + 12 ) {
c . y - = c . getBlockPosition ( b ) . y + 12 - b2 . pos . y ;
c . vspeed = 0 ;
if ( c . landTime > = gameBoard . landTime ) {
gameBoard . convertClump ( i ) ;
} else {
c . landTime + = fElapsedTime ;
}
goto nextClump ;
}
}
if ( c . getBlockPosition ( b ) . y > = gameBoard . yBottom ) {
c . y - = c . getBlockPosition ( b ) . y - gameBoard . yBottom ;
c . vspeed = 0 ;
if ( c . landTime > = gameBoard . landTime ) {
gameBoard . convertClump ( i ) ;
} else {
c . landTime + = fElapsedTime ;
}
goto nextClump ;
}
}
c . landTime = 0 ;
nextClump : ;
}
for ( int g = 0 ; g < gameBoard . getBlockClumps ( ) . size ( ) ; g + + ) {
BlockClump & c = gameBoard . getBlockClumps ( ) [ g ] ;
std : : vector < BlockMatchingInfo > matchedBlockIDs ;
for ( Block & b : c . getBlocks ( ) ) {
b . addedToLaunchList = false ;
}
for ( int i = 0 ; i < c . getBlocks ( ) . size ( ) ; i + + ) {
Block & b = c . getBlocks ( ) [ i ] ;
std : : vector < BlockMatchingInfo > tempMatchIDsX ;
std : : vector < BlockMatchingInfo > tempMatchIDsY ;
float targetX = b . pos . x ;
float targetY = b . pos . y ;
bool found = false ;
tempMatchIDsX . push_back ( { ( int ) b . pos . x / 12 , i , g } ) ;
tempMatchIDsY . push_back ( { ( int ) b . pos . x / 12 , i , g } ) ;
rightCheck :
float checkX = targetX + 12 ;
float checkY = targetY ;
do {
found = false ;
for ( int j = 0 ; j < c . getBlocks ( ) . size ( ) ; j + + ) {
Block & b2 = c . getBlocks ( ) [ j ] ;
if ( i = = j ) continue ;
if ( b . col = = b2 . col & & b2 . col ! = BlockColor : : LAUNCHED & & b2 . pos . x = = checkX & & b2 . pos . y = = checkY ) {
found = true ;
checkX + = 12 ;
tempMatchIDsX . push_back ( { ( int ) b . pos . x / 12 , j , g } ) ;
goto outerRightCheck ;
}
}
if ( c . landTime > 0 ) {
for ( int h = 0 ; h < gameBoard . getBlockClumps ( ) . size ( ) ; h + + ) {
if ( g = = h ) continue ;
BlockClump & c2 = gameBoard . getBlockClumps ( ) [ h ] ;
if ( c2 . landTime > 0 ) {
for ( int j = 0 ; j < c2 . getBlocks ( ) . size ( ) ; j + + ) {
Block & b2 = c2 . getBlocks ( ) [ j ] ;
if ( b . col = = b2 . col & & b2 . col ! = BlockColor : : LAUNCHED & & b2 . pos . x = = checkX & & b2 . pos . y - c . y = = checkY ) {
found = true ;
checkX + = 12 ;
tempMatchIDsX . push_back ( { ( int ) b2 . pos . x / 12 , j , h } ) ;
goto outerRightCheck ;
}
}
}
}
}
outerRightCheck : ;
} while ( found ) ;
leftCheck :
checkX = targetX - 12 ;
checkY = targetY ;
do {
found = false ;
for ( int j = 0 ; j < c . getBlocks ( ) . size ( ) ; j + + ) {
Block & b2 = c . getBlocks ( ) [ j ] ;
if ( i = = j ) continue ;
if ( b . col = = b2 . col & & b2 . col ! = BlockColor : : LAUNCHED & & b2 . pos . x = = checkX & & b2 . pos . y = = checkY ) {
found = true ;
checkX - = 12 ;
tempMatchIDsX . push_back ( { ( int ) b . pos . x / 12 , j , g } ) ;
goto outerLeftCheck ;
}
}
if ( c . landTime > 0 ) {
for ( int h = 0 ; h < gameBoard . getBlockClumps ( ) . size ( ) ; h + + ) {
if ( g = = h ) continue ;
BlockClump & c2 = gameBoard . getBlockClumps ( ) [ h ] ;
if ( c2 . landTime > 0 ) {
for ( int j = 0 ; j < c2 . getBlocks ( ) . size ( ) ; j + + ) {
Block & b2 = c2 . getBlocks ( ) [ j ] ;
if ( b . col = = b2 . col & & b2 . col ! = BlockColor : : LAUNCHED & & b2 . pos . x = = checkX & & b2 . pos . y - c . y = = checkY ) {
found = true ;
checkX - = 12 ;
tempMatchIDsX . push_back ( { ( int ) b2 . pos . x / 12 , j , h } ) ;
goto outerLeftCheck ;
}
}
}
}
}
outerLeftCheck : ;
} while ( found ) ;
upCheck :
checkX = targetX ;
checkY = targetY - 12 ;
do {
found = false ;
for ( int j = 0 ; j < c . getBlocks ( ) . size ( ) ; j + + ) {
Block & b2 = c . getBlocks ( ) [ j ] ;
if ( i = = j ) continue ;
if ( b . col = = b2 . col & & b2 . col ! = BlockColor : : LAUNCHED & & b2 . pos . x = = checkX & & b2 . pos . y = = checkY ) {
found = true ;
checkY - = 12 ;
tempMatchIDsY . push_back ( { ( int ) b . pos . x / 12 , j , g } ) ;
goto outerUpCheck ;
}
}
if ( c . landTime > 0 ) {
for ( int h = 0 ; h < gameBoard . getBlockClumps ( ) . size ( ) ; h + + ) {
if ( g = = h ) continue ;
BlockClump & c2 = gameBoard . getBlockClumps ( ) [ h ] ;
if ( c2 . landTime > 0 ) {
for ( int j = 0 ; j < c2 . getBlocks ( ) . size ( ) ; j + + ) {
Block & b2 = c2 . getBlocks ( ) [ j ] ;
if ( b . col = = b2 . col & & b2 . col ! = BlockColor : : LAUNCHED & & b2 . pos . x = = checkX & & b2 . pos . y - c . y = = checkY ) {
found = true ;
checkY - = 12 ;
tempMatchIDsY . push_back ( { ( int ) b2 . pos . x / 12 , j , h } ) ;
goto outerUpCheck ;
}
}
}
}
}
outerUpCheck : ;
} while ( found ) ;
downCheck :
checkX = targetX ;
checkY = targetY + 12 ;
do {
found = false ;
for ( int j = 0 ; j < c . getBlocks ( ) . size ( ) ; j + + ) {
Block & b2 = c . getBlocks ( ) [ j ] ;
if ( i = = j ) continue ;
if ( b . col = = b2 . col & & b2 . col ! = BlockColor : : LAUNCHED & & b2 . pos . x = = checkX & & b2 . pos . y = = checkY ) {
found = true ;
checkY + = 12 ;
tempMatchIDsY . push_back ( { ( int ) b . pos . x / 12 , j , g } ) ;
goto outerDownCheck ;
}
}
if ( c . landTime > 0 ) {
for ( int h = 0 ; h < gameBoard . getBlockClumps ( ) . size ( ) ; h + + ) {
if ( g = = h ) continue ;
BlockClump & c2 = gameBoard . getBlockClumps ( ) [ h ] ;
if ( c2 . landTime > 0 ) {
for ( int j = 0 ; j < c2 . getBlocks ( ) . size ( ) ; j + + ) {
Block & b2 = c2 . getBlocks ( ) [ j ] ;
if ( b . col = = b2 . col & & b2 . col ! = BlockColor : : LAUNCHED & & b2 . pos . x = = checkX & & b2 . pos . y - c . y = = checkY ) {
found = true ;
checkY + = 12 ;
tempMatchIDsY . push_back ( { ( int ) b2 . pos . x / 12 , j , h } ) ;
goto outerDownCheck ;
}
}
}
}
}
outerDownCheck : ;
} while ( found ) ;
if ( tempMatchIDsX . size ( ) > 2 | | tempMatchIDsY . size ( ) > 2 ) {
if ( tempMatchIDsX . size ( ) > 2 ) {
for ( BlockMatchingInfo i : tempMatchIDsX ) {
Block & bb = gameBoard . getBlockClumps ( ) [ i . c ] . getBlocks ( ) [ i . ind ] ;
if ( ! bb . addedToLaunchList ) {
bb . addedToLaunchList = true ;
matchedBlockIDs . push_back ( i ) ;
}
}
}
if ( tempMatchIDsY . size ( ) > 2 ) {
for ( BlockMatchingInfo i : tempMatchIDsY ) {
Block & bb = gameBoard . getBlockClumps ( ) [ i . c ] . getBlocks ( ) [ i . ind ] ;
if ( ! bb . addedToLaunchList ) {
bb . addedToLaunchList = true ;
matchedBlockIDs . push_back ( i ) ;
}
}
}
}
}
for ( BlockMatchingInfo i : matchedBlockIDs ) {
if ( g = = i . c ) {
Block & b = gameBoard . getBlockClumps ( ) [ i . c ] . getBlocks ( ) [ i . ind ] ;
b . col = BlockColor : : LAUNCHED ;
} else {
Block & b = gameBoard . getBlockClumps ( ) [ i . c ] . getBlocks ( ) [ i . ind ] ;
if ( ! b . markedForRemoval ) {
b . col = BlockColor : : LAUNCHED ;
c . addBlock ( i . col , ( gameBoard . getBlockClumps ( ) [ i . c ] . getBlockPosition ( b ) . y - c . y ) / 12 , BlockColor : : LAUNCHED ) ;
}
b . col = BlockColor : : LAUNCHED ;
b . markedForRemoval = true ;
}
}
if ( matchedBlockIDs . size ( ) > 0 ) {
c . vspeed = gameBoard . launchSpd [ std : : min ( c . combo , ( int ) gameBoard . launchSpd . size ( ) - 1 ) ] / ( 1 + ( c . getBlocks ( ) . size ( ) * gameBoard . blockWeight ) ) ;
c . launchTime = gameBoard . launchTime ;
c . combo + + ;
vi2d randomOffset = { comboOverlayOffset ( gen ) , comboOverlayOffset ( gen ) } ;
comboDisplayList . push_back ( { c . getBlockPosition ( gameBoard . getBlockClumps ( ) [ matchedBlockIDs [ 0 ] . c ] . getBlocks ( ) [ matchedBlockIDs [ 0 ] . ind ] ) + randomOffset , c . combo } ) ;
//std::cout<<"Combo value is "<<c.combo<<std::endl;
}
}
for ( int g = 0 ; g < gameBoard . getBlockClumps ( ) . size ( ) ; g + + ) {
BlockClump & c = gameBoard . getBlockClumps ( ) [ g ] ;
for ( int i = 0 ; i < c . getBlocks ( ) . size ( ) ; i + + ) {
Block & b = c . getBlocks ( ) [ i ] ;
if ( b . markedForRemoval ) {
c . removeBlock ( i - - ) ;
}
}
}
std : : vector < BlockMatchingInfo > matchedBlockIDs ; //Col followed by index
for ( int i = 0 ; i < gameBoard . boardSize . x ; i + + ) {
for ( Block & b : gameBoard . getBlocks ( i ) ) {
b . addedToLaunchList = false ;
}
for ( int j = 0 ; j < gameBoard . getBlocks ( i ) . size ( ) ; j + + ) {
Block & b = gameBoard . getBlocks ( i ) [ j ] ;
std : : vector < BlockMatchingInfo > tempMatchIDsX ; //Col followed by index
std : : vector < BlockMatchingInfo > tempMatchIDsY ; //Col followed by index
float targetX = b . pos . x ;
float targetY = b . pos . y ;
bool found = false ;
tempMatchIDsX . push_back ( { i , j } ) ;
tempMatchIDsY . push_back ( { i , j } ) ;
rightBoardCheck :
float checkX = 1 ;
float checkY = targetY ;
do {
found = false ;
if ( i + checkX < gameBoard . boardSize . x ) {
for ( int k = 0 ; k < gameBoard . getBlocks ( i + checkX ) . size ( ) ; k + + ) {
Block & b2 = gameBoard . getBlocks ( i + checkX ) [ k ] ;
if ( b . col = = b2 . col & & b2 . col ! = BlockColor : : LAUNCHED & & b2 . pos . x = = b . pos . x + checkX * 12 & & b2 . pos . y = = checkY ) {
found = true ;
tempMatchIDsX . push_back ( { ( int ) ( i + checkX ) , k } ) ;
checkX + + ;
goto outercheck2 ;
}
}
for ( int k = 0 ; k < gameBoard . getBlockClumps ( ) . size ( ) ; k + + ) {
BlockClump & c = gameBoard . getBlockClumps ( ) [ k ] ;
if ( c . landTime > 0 ) {
for ( int l = 0 ; l < c . getBlocks ( ) . size ( ) ; l + + ) {
Block & b2 = c . getBlocks ( ) [ l ] ;
if ( b . col = = b2 . col & & b2 . col ! = BlockColor : : LAUNCHED & & b2 . pos . x = = b . pos . x + checkX * 12 & & c . getBlockPosition ( b2 ) . y = = checkY ) {
found = true ;
tempMatchIDsX . push_back ( { ( int ) ( b2 . pos . x / 12 ) , l , k } ) ;
checkX + + ;
goto outercheck2 ;
}
}
}
}
outercheck2 : ;
}
} while ( found ) ;
leftBoardCheck :
checkX = - 1 ;
checkY = targetY ;
do {
found = false ;
if ( i + checkX > = 0 ) {
for ( int k = 0 ; k < gameBoard . getBlocks ( i + checkX ) . size ( ) ; k + + ) {
Block & b2 = gameBoard . getBlocks ( i + checkX ) [ k ] ;
if ( b . col = = b2 . col & & b2 . col ! = BlockColor : : LAUNCHED & & b2 . pos . x = = b . pos . x + checkX * 12 & & b2 . pos . y = = checkY ) {
found = true ;
tempMatchIDsX . push_back ( { ( int ) ( i + checkX ) , k } ) ;
checkX - - ;
goto outercheck3 ;
}
}
for ( int k = 0 ; k < gameBoard . getBlockClumps ( ) . size ( ) ; k + + ) {
BlockClump & c = gameBoard . getBlockClumps ( ) [ k ] ;
if ( c . landTime > 0 ) {
for ( int l = 0 ; l < c . getBlocks ( ) . size ( ) ; l + + ) {
Block & b2 = c . getBlocks ( ) [ l ] ;
if ( b . col = = b2 . col & & b2 . col ! = BlockColor : : LAUNCHED & & b2 . pos . x = = b . pos . x + checkX * 12 & & c . getBlockPosition ( b2 ) . y = = checkY ) {
found = true ;
tempMatchIDsX . push_back ( { ( int ) ( b2 . pos . x / 12 ) , l , k } ) ;
checkX - - ;
goto outercheck3 ;
}
}
}
}
outercheck3 : ;
}
} while ( found ) ;
upBoardCheck :
checkX = targetX ;
checkY = targetY - 12 ;
do {
found = false ;
for ( int k = 0 ; k < gameBoard . getBlocks ( i ) . size ( ) ; k + + ) {
Block & b2 = gameBoard . getBlocks ( i ) [ k ] ;
if ( j = = k ) continue ;
if ( b . col = = b2 . col & & b2 . col ! = BlockColor : : LAUNCHED & & b2 . pos . x = = checkX & & b2 . pos . y = = checkY ) {
found = true ;
checkY - = 12 ;
tempMatchIDsY . push_back ( { i , k } ) ;
goto outercheck4 ;
}
}
for ( int k = 0 ; k < gameBoard . getBlockClumps ( ) . size ( ) ; k + + ) {
BlockClump & c = gameBoard . getBlockClumps ( ) [ k ] ;
if ( c . landTime > 0 ) {
for ( int l = 0 ; l < c . getBlocks ( ) . size ( ) ; l + + ) {
Block & b2 = c . getBlocks ( ) [ l ] ;
if ( b . col = = b2 . col & & b2 . col ! = BlockColor : : LAUNCHED & & c . getBlockPosition ( b2 ) . x = = checkX & & c . getBlockPosition ( b2 ) . y = = checkY ) {
found = true ;
checkY - = 12 ;
tempMatchIDsY . push_back ( { ( int ) ( b2 . pos . x / 12 ) , l , k } ) ;
goto outercheck4 ;
}
}
}
}
outercheck4 : ;
} while ( found ) ;
downBoardCheck :
checkX = targetX ;
checkY = targetY + 12 ;
do {
found = false ;
for ( int k = 0 ; k < gameBoard . getBlocks ( i ) . size ( ) ; k + + ) {
Block & b2 = gameBoard . getBlocks ( i ) [ k ] ;
if ( j = = k ) continue ;
if ( b . col = = b2 . col & & b2 . col ! = BlockColor : : LAUNCHED & & b2 . pos . x = = checkX & & b2 . pos . y = = checkY ) {
found = true ;
checkY + = 12 ;
tempMatchIDsY . push_back ( { i , k } ) ;
goto outercheck1 ;
}
}
for ( int k = 0 ; k < gameBoard . getBlockClumps ( ) . size ( ) ; k + + ) {
BlockClump & c = gameBoard . getBlockClumps ( ) [ k ] ;
if ( c . landTime > 0 ) {
for ( int l = 0 ; l < c . getBlocks ( ) . size ( ) ; l + + ) {
Block & b2 = c . getBlocks ( ) [ l ] ;
if ( b . col = = b2 . col & & b2 . col ! = BlockColor : : LAUNCHED & & c . getBlockPosition ( b2 ) . x = = checkX & & c . getBlockPosition ( b2 ) . y = = checkY ) {
found = true ;
checkY + = 12 ;
tempMatchIDsY . push_back ( { ( int ) ( b2 . pos . x / 12 ) , l , k } ) ;
goto outercheck1 ;
}
}
}
}
outercheck1 : ;
} while ( found ) ;
if ( tempMatchIDsX . size ( ) > 2 | | tempMatchIDsY . size ( ) > 2 ) {
if ( tempMatchIDsX . size ( ) > 2 ) {
for ( BlockMatchingInfo & info : tempMatchIDsX ) {
if ( info . c ! = - 1 ) {
BlockClump & c = gameBoard . getBlockClumps ( ) [ info . c ] ;
Block & bb = c . getBlocks ( ) [ info . ind ] ;
if ( ! bb . addedToLaunchList ) {
bb . addedToLaunchList = true ;
matchedBlockIDs . push_back ( info ) ;
}
} else {
Block & bb = gameBoard . getBlocks ( info . col ) [ info . ind ] ;
if ( ! bb . addedToLaunchList ) {
bb . addedToLaunchList = true ;
matchedBlockIDs . push_back ( info ) ;
}
}
}
}
if ( tempMatchIDsY . size ( ) > 2 ) {
for ( BlockMatchingInfo & info : tempMatchIDsY ) {
if ( info . c ! = - 1 ) {
BlockClump & c = gameBoard . getBlockClumps ( ) [ info . c ] ;
Block & bb = c . getBlocks ( ) [ info . ind ] ;
if ( ! bb . addedToLaunchList ) {
bb . addedToLaunchList = true ;
matchedBlockIDs . push_back ( info ) ;
}
} else {
Block & bb = gameBoard . getBlocks ( info . col ) [ info . ind ] ;
if ( ! bb . addedToLaunchList ) {
bb . addedToLaunchList = true ;
matchedBlockIDs . push_back ( info ) ;
}
}
}
}
}
}
}
if ( matchedBlockIDs . size ( ) > 0 ) {
BlockClump c ;
bool firstBlock = true ;
vf2d baseBlockPos ;
for ( BlockMatchingInfo & info : matchedBlockIDs ) {
if ( info . c ! = - 1 ) {
Block & b = gameBoard . getBlockClumps ( ) [ info . c ] . getBlocks ( ) [ info . ind ] ;
if ( firstBlock ) {
baseBlockPos = gameBoard . getBlockClumps ( ) [ info . c ] . getBlockPosition ( b ) ;
c . y = baseBlockPos . y - 1 ;
firstBlock = false ;
}
b . col = BlockColor : : LAUNCHED ;
} else {
Block & b = gameBoard . getBlocks ( info . col ) [ info . ind ] ;
if ( firstBlock ) {
baseBlockPos = b . pos ;
c . y = baseBlockPos . y - 1 ;
firstBlock = false ;
}
b . col = BlockColor : : LAUNCHED ;
}
}
for ( BlockMatchingInfo & info : matchedBlockIDs ) {
if ( info . c ! = - 1 ) {
if ( gameBoard . getBlockClumps ( ) [ info . c ] . getBlocks ( ) . size ( ) > 0 ) {
if ( c . combo < gameBoard . getBlockClumps ( ) [ info . c ] . combo ) {
c . combo = gameBoard . getBlockClumps ( ) [ info . c ] . combo ;
}
for ( int i = gameBoard . getBlockClumps ( ) [ info . c ] . getBlocks ( ) . size ( ) - 1 ; i > = 0 ; i - - ) {
Block & b2 = gameBoard . getBlockClumps ( ) [ info . c ] . getBlocks ( ) [ i ] ;
if ( ( int ) fmod ( std : : abs ( std : : round ( gameBoard . getBlockClumps ( ) [ info . c ] . getBlockPosition ( b2 ) . y ) - std : : round ( baseBlockPos . y ) ) , 12 ) ! = 0 ) {
std : : cout < < " Difference is not equal to 0! Value: " < < ( int ) fmod ( std : : abs ( std : : round ( gameBoard . getBlockClumps ( ) [ info . c ] . getBlockPosition ( b2 ) . y ) - std : : round ( baseBlockPos . y ) ) , 12 ) < < " " < < gameBoard . getBlockClumps ( ) [ info . c ] . getBlockPosition ( b2 ) . y < < " // " < < baseBlockPos . y < < std : : endl ;
assert ( false ) ;
}
c . addBlock ( b2 . pos . x / 12 , ( ( int ) gameBoard . getBlockClumps ( ) [ info . c ] . getBlockPosition ( b2 ) . y - ( int ) baseBlockPos . y ) / 12 , b2 . col ) ;
std : : cout < < " Added block @ " < < b2 . pos . x / 12 < < ( ( int ) gameBoard . getBlockClumps ( ) [ info . c ] . getBlockPosition ( b2 ) . y - ( int ) baseBlockPos . y ) / 12 < < std : : endl ;
gameBoard . getBlockClumps ( ) [ info . c ] . removeBlock ( i ) ;
}
} else {
std : : cout < < " Blocks already added elsewhere " < < std : : endl ;
}
} else {
Block & b = gameBoard . getBlocks ( info . col ) [ info . ind ] ;
int yPos = b . pos . y ;
for ( int i = gameBoard . getBlocks ( info . col ) . size ( ) - 1 ; i > = 0 ; i - - ) {
Block & b2 = gameBoard . getBlocks ( info . col ) [ i ] ;
if ( b2 . pos . y < = yPos ) {
if ( ( int ) fmod ( ( int ) b2 . pos . y - ( int ) baseBlockPos . y , 12 ) ! = 0 ) {
std : : cout < < " Difference is not equal to 0! Value: " < < ( int ) fmod ( ( int ) b2 . pos . y - ( int ) baseBlockPos . y , 12 ) < < " " < < b2 . pos . y < < " // " < < baseBlockPos . y < < std : : endl ;
assert ( false ) ;
}
c . addBlock ( info . col , ( ( int ) b2 . pos . y - ( int ) baseBlockPos . y ) / 12 , b2 . col ) ;
std : : cout < < " Added block @ " < < info . col < < ( ( int ) b2 . pos . y - ( int ) baseBlockPos . y ) / 12 < < std : : endl ;
//b2.markedForRemoval=true;
gameBoard . removeBlock ( info . col , i ) ;
}
}
}
}
gameBoard . addClump ( c ) ;
gameBoard . getBlockClumps ( ) [ gameBoard . getBlockClumps ( ) . size ( ) - 1 ] . vspeed = gameBoard . launchSpd [ std : : min ( gameBoard . getBlockClumps ( ) [ gameBoard . getBlockClumps ( ) . size ( ) - 1 ] . combo , ( int ) gameBoard . launchSpd . size ( ) - 1 ) ] / ( 1 + ( gameBoard . getBlockClumps ( ) [ gameBoard . getBlockClumps ( ) . size ( ) - 1 ] . getBlocks ( ) . size ( ) * gameBoard . blockWeight ) ) ;
gameBoard . getBlockClumps ( ) [ gameBoard . getBlockClumps ( ) . size ( ) - 1 ] . launchTime = gameBoard . launchTime ;
gameBoard . getBlockClumps ( ) [ gameBoard . getBlockClumps ( ) . size ( ) - 1 ] . combo + + ;
vi2d randomOffset = { comboOverlayOffset ( gen ) , comboOverlayOffset ( gen ) } ;
comboDisplayList . push_back ( { baseBlockPos + randomOffset , gameBoard . getBlockClumps ( ) [ gameBoard . getBlockClumps ( ) . size ( ) - 1 ] . combo } ) ;
//std::cout<<"Combo value is "<<gameBoard.getBlockClumps()[gameBoard.getBlockClumps().size()-1].combo<<std::endl;
}
for ( int i = gameBoard . getBlockClumps ( ) . size ( ) - 1 ; i > = 0 ; i - - ) { //Resolve BlockClump movements.
BlockClump & c = gameBoard . getBlockClumps ( ) [ i ] ;
for ( int j = c . getBlocks ( ) . size ( ) - 1 ; j > = 0 ; j - - ) {
Block & b = c . getBlocks ( ) [ j ] ;
b . addedToLaunchList = false ;
if ( c . vspeed < 0 & & c . getBlockPosition ( b ) . y < 0 | | b . markedForRemoval ) {
std : : cout < < " Removed block @ " < < b . pos < < " from clump " < < i < < std : : endl ;
c . removeBlock ( j ) ;
break ;
}
}
c . y + = c . vspeed ;
if ( c . getBlocks ( ) . size ( ) < = 0 ) {
std : : cout < < " Block Clump " < < i < < " is empty. Removing. " < < std : : endl ;
gameBoard . removeClump ( i ) ;
continue ;
}
}
bool noWarning = true ;
for ( int i = 0 ; i < gameBoard . boardSize . x ; i + + ) {
if ( gameBoard . getBlocks ( i ) . size ( ) > = gameBoard . boardSize . y ) {
gameBoard . warningFlashingLevel [ i ] + = fElapsedTime ;
gameBoard . warningLevel + + ;
noWarning = false ;
} else {
gameBoard . warningFlashingLevel [ i ] = 0 ;
}
for ( int y = gameBoard . getBlocks ( i ) . size ( ) - 1 ; y > = 0 ; y - - ) {
Block & b = gameBoard . getBlocks ( i ) [ y ] ;
b . addedToLaunchList = false ;
if ( b . markedForRemoval ) {
gameBoard . removeBlock ( i , y ) ;
continue ;
}
}
}
if ( noWarning ) {
gameBoard . warningLevel = 0 ;
} else
if ( gameBoard . warningLevel > = gameBoard . maxWarningLevel ) {
//Planet crashes! For now we just clear all blocks and clumps on the board.
while ( gameBoard . getBlockClumps ( ) . size ( ) > 0 ) {
gameBoard . removeClump ( 0 ) ;
}
for ( int i = 0 ; i < gameBoard . boardSize . x ; i + + ) {
while ( gameBoard . getBlocks ( i ) . size ( ) > 0 ) {
gameBoard . removeBlock ( i , 0 ) ;
}
}
gameBoard . warningLevel = 0 ;
goto invalidatedExit ;
}
//Invalidate the selected block if something is strange about it.
if ( gameBoard . selectedBlock . col ! = - 1 ) {
if ( gameBoard . selectedBlock . c ! = - 1 ) {
if ( ! ( gameBoard . selectedBlock . c < gameBoard . getBlockClumps ( ) . size ( ) & & gameBoard . selectedBlock . ind < gameBoard . getBlockClumps ( ) [ gameBoard . selectedBlock . c ] . getBlocks ( ) . size ( ) & & gameBoard . getBlockClumps ( ) [ gameBoard . selectedBlock . c ] . getBlocks ( ) [ gameBoard . selectedBlock . ind ] . pos . x / 12 = = gameBoard . selectedBlock . col ) ) {
gameBoard . selectedBlock = { - 1 } ;
goto invalidatedExit ;
}
} else {
if ( ! ( gameBoard . selectedBlock . ind < gameBoard . getBlocks ( gameBoard . selectedBlock . col ) . size ( ) ) ) {
gameBoard . selectedBlock = { - 1 } ;
goto invalidatedExit ;
}
}
}
invalidatedExit :
for ( int i = comboDisplayList . size ( ) - 1 ; i > = 0 ; i - - ) {
ComboOverlay & c = comboDisplayList [ i ] ;
c . lifetime + + ;
c . pos . y - = 0.1 ;
if ( c . lifetime > 60 ) {
comboDisplayList . erase ( comboDisplayList . begin ( ) + i ) ;
}
}
}
void Meteos : : drawGame ( float fElapsedTime , bool debugView ) {
Clear ( Pixel ( 32 , 32 , 255 ) ) ;
for ( int x = - 1 ; x < = gameBoard . boardSize . x ; x + + ) {
for ( int y = 0 ; y < = gameBoard . boardSize . y ; y + + ) {
if ( x = = - 1 | | x = = 10 | | y = = 14 ) {
FillRectDecal ( { ( float ) ( gameBoard . drawOffset . x + x * 12 ) , ( float ) ( gameBoard . drawOffset . y + y * 12 ) } , { 12 , 12 } , Pixel ( 0 , 0 , 0 , 255 ) ) ;
} else {
DrawRectDecal ( { ( float ) ( gameBoard . drawOffset . x + x * 12 ) , ( float ) ( gameBoard . drawOffset . y + y * 12 ) } , { 12 , 12 } , Pixel ( 255 , 255 , 255 , 64 ) ) ;
}
}
}
int alpha = ( debugView ) ? 32 : 255 ;
for ( int i = 0 ; i < gameBoard . getBlockClumps ( ) . size ( ) ; i + + ) {
BlockClump & c = gameBoard . getBlockClumps ( ) [ i ] ;
for ( int j = 0 ; j < c . getBlocks ( ) . size ( ) ; j + + ) {
Block & b = c . getBlocks ( ) [ j ] ;
DrawPartialDecal ( c . getBlockPosition ( b ) + gameBoard . drawOffset , gameBoard . tileset , { ( float ) ( int ) b . col * 12 , 0 } , { 12 , 12 } , { 1 , 1 } , gameBoard . selectedBlock . col ! = - 1 & & gameBoard . selectedBlock . ind = = j & & gameBoard . selectedBlock . c = = i ? Pixel ( GREY . r , GREY . g , GREY . b , alpha ) : Pixel ( WHITE . r , WHITE . g , WHITE . b , alpha ) ) ;
}
//DrawStringDecal({32,c.y+i%4*4},std::to_string(c.landTime),WHITE,{0.4,0.4}); //Draws land times per clump.
}
for ( int i = 0 ; i < gameBoard . boardSize . x ; i + + ) {
for ( int y = 0 ; y < gameBoard . getBlocks ( i ) . size ( ) ; y + + ) {
Block & b = gameBoard . getBlocks ( i ) [ y ] ;
DrawPartialDecal ( b . pos + gameBoard . drawOffset , gameBoard . tileset , { ( float ) ( int ) b . col * 12 , 0 } , { 12 , 12 } , { 1 , 1 } , gameBoard . selectedBlock . col ! = - 1 & & gameBoard . selectedBlock . c = = - 1 & & gameBoard . selectedBlock . col = = i & & gameBoard . selectedBlock . ind = = y ? Pixel ( GREY . r , GREY . g , GREY . b , alpha ) : Pixel ( WHITE . r , WHITE . g , WHITE . b , alpha ) ) ;
}
if ( gameBoard . warningFlashingLevel [ i ] > 0 ) {
FillRectDecal ( { gameBoard . drawOffset . x + i * 12 , gameBoard . drawOffset . y } , { 12 , ( float ) gameBoard . boardSize . y * 12 } , Pixel ( 255 , 64 , 64 , std : : abs ( sin ( gameBoard . warningFlashingLevel [ i ] * M_PI ) ) * 128 ) ) ;
}
}
for ( int i = 0 ; i < comboDisplayList . size ( ) ; i + + ) {
ComboOverlay & c = comboDisplayList [ i ] ;
vi2d shadowOffset = { 1 , 1 } ;
DrawStringPropDecal ( c . pos + gameBoard . drawOffset + shadowOffset , " x " + std : : to_string ( c . combo ) , BLACK , { 0.8 , 0.6 } ) ;
DrawStringPropDecal ( c . pos + gameBoard . drawOffset , " x " + std : : to_string ( c . combo ) , ( c . lifetime % 6 > = 3 ) ? Pixel { 207 , 103 , 0 } : Pixel { 255 , 255 , 255 , 180 } , { 0.8 , 0.6 } ) ;
}
}
int main ( )
{
Meteos instance ;
if ( instance . Construct ( 256 , 240 , 4 , 4 ) )
instance . Start ( ) ;
return 0 ;
}