{"version":3,"file":"FlappyBlurrr.html","sources":["CircularQueue.c","TimeTicker.c","main_c.c","/opt/local/emscripten/include/chipmunk/cpVect.h","/opt/local/emscripten/include/chipmunk/cpBody.h","/opt/local/emscripten/include/chipmunk/cpSpace.h"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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","sourcesContent":["/*\n CircularQueue\n Copyright (C) 2002 Eric Wing\n\n\t(renamed CircularQueue to CircularQueue to avoid symbol clashes with ALmixer)\n\tzlib license\n*/\n\n#include \"CircularQueue.h\"\n#include /* for NULL */\n#include /* for malloc/free */\n#include /* for debugging */\n\nCircularQueueUnsignedInt* CircularQueueUnsignedInt_CreateQueue(unsigned int max_size)\n{\n\tCircularQueueUnsignedInt* ret_ptr;\n\tif(max_size < 1)\n\t{\n\t\treturn NULL;\n\t}\n\tret_ptr = (CircularQueueUnsignedInt*)malloc(sizeof(CircularQueueUnsignedInt));\n\tif(NULL == ret_ptr)\n\t{\n\t\t/* Out of memory */\n\t\treturn NULL;\n\t}\n\tret_ptr->internalQueue = (unsigned int*)malloc(sizeof(unsigned int) * max_size);\n\tif(NULL == ret_ptr->internalQueue)\n\t{\n\t\t/* Out of memory */\n\t\tfree(ret_ptr);\n\t\treturn NULL;\n\t}\n\tret_ptr->maxSize = max_size;\n\tret_ptr->currentSize = 0;\n\tret_ptr->headIndex = 0;\n\tret_ptr->tailIndex = 0;\n\n\treturn ret_ptr;\n}\n\nvoid CircularQueueUnsignedInt_FreeQueue(CircularQueueUnsignedInt* queue)\n{\n\tif(NULL == queue)\n\t{\n\t\treturn;\n\t}\n\n\tfree(queue->internalQueue);\n\tfree(queue);\n}\n\n/**\n * Returns 1 if successful, 0 if failure.\n */\nunsigned int CircularQueueUnsignedInt_PushBack(CircularQueueUnsignedInt* queue, unsigned int value)\n{\n//\tprintf(\"pushBack: %d\\n\", value);\n\t\n\tunsigned int temp_index;\n\tif(NULL == queue)\n\t{\n\t\treturn 0;\n\t}\n\tif(queue->currentSize >= queue->maxSize)\n\t{\n\t\tprintf(\"failed to pushBack: %d\\n\", value);\n\t\t\n\t\treturn 0;\n\t}\n\ttemp_index = queue->tailIndex + 1;\n\tif(temp_index >= queue->maxSize)\n\t{\n\t\t/* need to wrap tail index around */\n\t\ttemp_index = 0;\n\t}\n\t/* So with my implementation, the tail index actually points \n\t * to the slot right after the last value.\n\t * So we will enter the value in the current tail, and then increment\n\t * the tail.\n\t * Note that in a full queue, the head and tail will be the same (I think).\n\t */\n\tqueue->internalQueue[queue->tailIndex] = value;\n\tqueue->tailIndex = temp_index;\n\tqueue->currentSize++;\n\t\t\n\treturn 1;\n}\n\n/**\n * Returns 1 if successful, 0 if failure.\n */\nunsigned int CircularQueueUnsignedInt_PushFront(CircularQueueUnsignedInt* queue, unsigned int value)\n{\n\tunsigned int temp_index;\n\tif(NULL == queue)\n\t{\n\t\treturn 0;\n\t}\n\tif(queue->currentSize >= queue->maxSize)\n\t{\n\t\treturn 0;\n\t}\n\n\t/* This check is needed to prevent the unsigned int from overflowing. */\n\tif(0 == queue->headIndex)\n\t{\n\t\t/* Need to wrap head index around */\n\t\ttemp_index = queue->maxSize - 1;\n\t}\n\telse\n\t{\n\t\ttemp_index = queue->headIndex - 1;\n\t}\n\t/* So unlike the tail, the head index actually points to the element\n\t * at the head, and not an element before (or after) the head.\n\t */\n\tqueue->internalQueue[temp_index] = value;\n\tqueue->headIndex = temp_index;\n\tqueue->currentSize++;\n\treturn 1;\n}\n\nunsigned int CircularQueueUnsignedInt_PopFront(CircularQueueUnsignedInt* queue)\n{\n\tunsigned int temp_index;\n//\tprintf(\"PopFront: %d, %d\\n\", queue->headIndex,queue->internalQueue[queue->headIndex] );\n\t\n\tif(NULL == queue)\n\t{\n\t\treturn 0;\n\t}\n\tif(queue->currentSize == 0)\n\t{\n\t\treturn 0;\n\t}\n\ttemp_index = queue->headIndex + 1;\n\tif(temp_index >= queue->maxSize)\n\t{\n\t\t/* need to wrap tail index around */\n\t\ttemp_index = 0;\n\t}\n\tqueue->headIndex = temp_index;\n\tqueue->currentSize--;\n\treturn 1;\n}\n\n\nunsigned int CircularQueueUnsignedInt_PopBack(CircularQueueUnsignedInt* queue)\n{\n\tunsigned int temp_index;\n\tif(NULL == queue)\n\t{\n\t\treturn 0;\n\t}\n\tif(queue->currentSize == 0)\n\t{\n\t\treturn 0;\n\t}\n\n\t/* This check is needed to prevent the unsigned int from overflowing. */\n\tif(0 == queue->tailIndex)\n\t{\n\t\ttemp_index = queue->maxSize - 1;\n\t}\n\telse\n\t{\n\t\ttemp_index = queue->tailIndex - 1;\n\t}\n\n\tqueue->tailIndex = temp_index;\n\tqueue->currentSize--;\n\treturn 1;\n}\n\nunsigned int CircularQueueUnsignedInt_Front(CircularQueueUnsignedInt* queue)\n{\n\tif(NULL == queue)\n\t{\n\t\treturn 0;\n\t}\n\tif(0 == queue->currentSize)\n\t{\n\t\treturn 0;\n\t}\n\treturn queue->internalQueue[queue->headIndex];\n}\n\n\nunsigned int CircularQueueUnsignedInt_Back(CircularQueueUnsignedInt* queue)\n{\n\tunsigned int temp_index;\n\tif(NULL == queue)\n\t{\n\t\treturn 0;\n\t}\n\tif(0 == queue->currentSize)\n\t{\n\t\treturn 0;\n\t}\n\tif(0 == queue->tailIndex)\n\t{\n\t\t/* need to wrap tail index around */\n\t\ttemp_index = queue->maxSize-1;\n\t}\n\telse\n\t{\n\t\ttemp_index = queue->tailIndex-1;\n\t}\n\t\n\treturn queue->internalQueue[temp_index];\n}\n\nunsigned int CircularQueueUnsignedInt_Size(CircularQueueUnsignedInt* queue)\n{\n\tif(NULL == queue)\n\t{\n\t\treturn 0;\n\t}\n\treturn queue->currentSize;\n}\n\nunsigned int CircularQueueUnsignedInt_MaxSize(CircularQueueUnsignedInt* queue)\n{\n\tif(NULL == queue)\n\t{\n\t\treturn 0;\n\t}\n\treturn queue->maxSize;\n}\n\nvoid CircularQueueUnsignedInt_Clear(CircularQueueUnsignedInt* queue)\n{\n\tif(NULL == queue)\n\t{\n\t\treturn;\n\t}\n\n\tqueue->currentSize = 0;\n\tqueue->headIndex = 0;\n\tqueue->tailIndex = 0;\n}\n\nvoid CircularQueueUnsignedInt_Print(CircularQueueUnsignedInt* queue)\n{\n\tunsigned int i;\n\tunsigned int count;\n\tif(NULL == queue)\n\t{\n\t\treturn;\n\t}\n\tfprintf(stderr, \"Queue: \");\n\tfor(count=0, i=queue->headIndex; countcurrentSize; count++, i++)\n\t{\n\t\tif(i >= queue->maxSize)\n\t\t{\n\t\t\ti=0;\n\t\t}\n\t\tfprintf(stderr, \"%d \", queue->internalQueue[i]);\n\t}\n\tfprintf(stderr, \"\\n\");\n}\n\nunsigned int CircularQueueUnsignedInt_ValueAtIndex(CircularQueueUnsignedInt* queue, unsigned int the_index)\n{\n\tunsigned int i;\n\tif(NULL == queue)\n\t{\n\t\treturn 0;\n\t}\n\tif(the_index >= queue->currentSize)\n\t{\n\t\treturn 0;\n\t}\n\ti = (queue->headIndex + the_index) % queue->maxSize;\n//\tfprintf(stderr, \"%d\\n\", queue->internalQueue[i]);\n\treturn queue->internalQueue[i];\n}\n\n/*\n * Implementation for void* version starts here.\n */\n\nCircularQueueVoid* CircularQueueVoid_CreateQueue(unsigned int max_size)\n{\n\tCircularQueueVoid* ret_ptr;\n\tif(max_size < 1)\n\t{\n\t\treturn NULL;\n\t}\n\tret_ptr = (CircularQueueVoid*)malloc(sizeof(CircularQueueVoid));\n\tif(NULL == ret_ptr)\n\t{\n\t\t/* Out of memory */\n\t\treturn NULL;\n\t}\n\tret_ptr->internalQueue = (void**)malloc(sizeof(void*) * max_size);\n\tif(NULL == ret_ptr->internalQueue)\n\t{\n\t\t/* Out of memory */\n\t\tfree(ret_ptr);\n\t\treturn NULL;\n\t}\n\tret_ptr->maxSize = max_size;\n\tret_ptr->currentSize = 0;\n\tret_ptr->headIndex = 0;\n\tret_ptr->tailIndex = 0;\n\n\treturn ret_ptr;\n}\n\nvoid CircularQueueVoid_FreeQueue(CircularQueueVoid* queue)\n{\n\tif(NULL == queue)\n\t{\n\t\treturn;\n\t}\n\n\tfree(queue->internalQueue);\n\tfree(queue);\n}\n\n/**\n * Returns 1 if successful, 0 if failure.\n */\nunsigned int CircularQueueVoid_PushBack(CircularQueueVoid* queue, void* value)\n{\n\tunsigned int temp_index;\n\tif(NULL == queue)\n\t{\n\t\treturn 0;\n\t}\n\tif(queue->currentSize >= queue->maxSize)\n\t{\n\t\treturn 0;\n\t}\n\ttemp_index = queue->tailIndex + 1;\n\tif(temp_index >= queue->maxSize)\n\t{\n\t\t/* need to wrap tail index around */\n\t\ttemp_index = 0;\n\t}\n\tqueue->internalQueue[queue->tailIndex] = value;\n\tqueue->tailIndex = temp_index;\n\tqueue->currentSize++;\n\t\t\n\treturn 1;\n}\n\n/**\n * Returns 1 if successful, 0 if failure.\n */\nunsigned int CircularQueueVoid_PushFront(CircularQueueVoid* queue, void* value)\n{\n\tunsigned int temp_index;\n\tif(NULL == queue)\n\t{\n\t\treturn 0;\n\t}\n\tif(queue->currentSize >= queue->maxSize)\n\t{\n\t\treturn 0;\n\t}\n\n\t/* This check is needed to prevent the unsigned int from overflowing. */\n\tif(0 == queue->headIndex)\n\t{\n\t\t/* Need to wrap head index around */\n\t\ttemp_index = queue->maxSize - 1;\n\t}\n\telse\n\t{\n\t\ttemp_index = queue->headIndex - 1;\n\t}\n\tqueue->internalQueue[temp_index] = value;\n\tqueue->headIndex = temp_index;\n\tqueue->currentSize++;\n\treturn 1;\n}\n\nunsigned int CircularQueueVoid_PopFront(CircularQueueVoid* queue)\n{\n\tunsigned int temp_index;\n\tif(NULL == queue)\n\t{\n\t\treturn 0;\n\t}\n\tif(queue->currentSize == 0)\n\t{\n\t\treturn 0;\n\t}\n\ttemp_index = queue->headIndex + 1;\n\tif(temp_index >= queue->maxSize)\n\t{\n\t\t/* need to wrap tail index around */\n\t\ttemp_index = 0;\n\t}\n\tqueue->headIndex = temp_index;\n\tqueue->currentSize--;\n\treturn 1;\n}\n\n\nunsigned int CircularQueueVoid_PopBack(CircularQueueVoid* queue)\n{\n\tunsigned int temp_index;\n\tif(NULL == queue)\n\t{\n\t\treturn 0;\n\t}\n\tif(queue->currentSize == 0)\n\t{\n\t\treturn 0;\n\t}\n\n\t/* This check is needed to prevent the unsigned int from overflowing. */\n\tif(0 == queue->tailIndex)\n\t{\n\t\ttemp_index = queue->maxSize - 1;\n\t}\n\telse\n\t{\n\t\ttemp_index = queue->tailIndex - 1;\n\t}\n\n\tqueue->tailIndex = temp_index;\n\tqueue->currentSize--;\n\treturn 1;\n}\n\nvoid* CircularQueueVoid_Front(CircularQueueVoid* queue)\n{\n\tif(NULL == queue)\n\t{\n\t\treturn 0;\n\t}\n\tif(0 == queue->currentSize)\n\t{\n\t\treturn 0;\n\t}\n\treturn queue->internalQueue[queue->headIndex];\n}\n\n\nvoid* CircularQueueVoid_Back(CircularQueueVoid* queue)\n{\n\tunsigned int temp_index;\n\tif(NULL == queue)\n\t{\n\t\treturn 0;\n\t}\n\tif(0 == queue->currentSize)\n\t{\n\t\treturn 0;\n\t}\n\tif(0 == queue->tailIndex)\n\t{\n\t\t/* need to wrap tail index around */\n\t\ttemp_index = queue->maxSize-1;\n\t}\n\telse\n\t{\n\t\ttemp_index = queue->tailIndex-1;\n\t}\n\t\n\treturn queue->internalQueue[temp_index];\n}\n\nunsigned int CircularQueueVoid_Size(CircularQueueVoid* queue)\n{\n\tif(NULL == queue)\n\t{\n\t\treturn 0;\n\t}\n\treturn queue->currentSize;\n}\n\nunsigned int CircularQueueVoid_MaxSize(CircularQueueVoid* queue)\n{\n\tif(NULL == queue)\n\t{\n\t\treturn 0;\n\t}\n\treturn queue->maxSize;\n}\n\nvoid CircularQueueVoid_Clear(CircularQueueVoid* queue)\n{\n\tif(NULL == queue)\n\t{\n\t\treturn;\n\t}\n\n\tqueue->currentSize = 0;\n\tqueue->headIndex = 0;\n\tqueue->tailIndex = 0;\n}\n\nvoid CircularQueueVoid_Print(CircularQueueVoid* queue)\n{\n\tunsigned int i;\n\tunsigned int count;\n\tif(NULL == queue)\n\t{\n\t\treturn;\n\t}\n\tfprintf(stderr, \"Queue: \");\n\tfor(count=0, i=queue->headIndex; countcurrentSize; count++, i++)\n\t{\n\t\tif(i >= queue->maxSize)\n\t\t{\n\t\t\ti=0;\n\t\t}\n\t\tfprintf(stderr, \"%x \", (unsigned int)queue->internalQueue[i]);\n\t}\n\tfprintf(stderr, \"\\n\");\n}\n\nvoid* CircularQueueVoid_ValueAtIndex(CircularQueueVoid* queue, unsigned int the_index)\n{\n\tunsigned int i;\n\tif(NULL == queue)\n\t{\n\t\treturn NULL;\n\t}\n\tif(the_index >= queue->currentSize)\n\t{\n\t\treturn NULL;\n\t}\n\ti = (queue->headIndex + the_index) % queue->maxSize;\n\t//\tfprintf(stderr, \"%d\\n\", queue->internalQueue[i]);\n\treturn queue->internalQueue[i];\n}\n\n\n","/*\n\tThis is an abstraction around SDL_GetTicks() and works like a stop watch. \n\tUnlike SDL_GetTicks(), this can count independently of the system clock, \n\twhich is useful for things like pausing the game.\n\tThis also has a time scale factor which can allow for things like \"bullet time\".\n\n\tThis is a decendant of the SClone TimeClock circa 2002.\n*/\n\n#include \"TimeTicker.h\"\n\nstruct TimeTicker\n{\n\tdouble timeSpeed;\n\tUint32 previousTime;\n\tUint32 currentTime;\n\tSDL_bool isTickerEnabled;\n};\n\n//////////////////////////////////////////////////////////////////////\n// Construction/Destruction\n//////////////////////////////////////////////////////////////////////\n\nstruct TimeTicker* TimeTicker_Create()\n{\n\tstruct TimeTicker* time_ticker = SDL_calloc(1, sizeof(struct TimeTicker));\n\tTimeTicker_Reset(time_ticker);\n\treturn time_ticker;\n}\n\n\n\nvoid TimeTicker_Free(struct TimeTicker* time_ticker)\n{\n\tSDL_free(time_ticker);\n}\n\n\n//////////////////////////////////////////////////////////////////////\n// Clock manipulating functions.\n//////////////////////////////////////////////////////////////////////\n\n// Starts/resumes the clock.\nvoid TimeTicker_Start(struct TimeTicker* time_ticker)\n{\n\tif(NULL == time_ticker)\n\t{\n\t\treturn;\n\t}\n\n\tif( ! time_ticker->isTickerEnabled)\n\t{\n\t\t// We set previousTime here to SDL_GetTicks() because\n\t\t// we need a new base time to subtract from to get a \n\t\t// difference from the next call to SDL_GetTicks().\n\t\t// This will tell us how much time elapsed between start and \n\t\t// the next call. We can't use 0 as the base because\n\t\t// the timer may be paused at some point or the clock may not\n\t\t// start at 0.\n\t\ttime_ticker->previousTime = SDL_GetTicks();\n\t\ttime_ticker->isTickerEnabled = SDL_TRUE;\n\t}\n}\n\n// Stops the clock. Call the Start() function to resume the clock.\nvoid TimeTicker_Stop(struct TimeTicker* time_ticker)\n{\n\tif(time_ticker->isTickerEnabled)\n\t{\n\t\t// Once upon a time, I tried allowing for Stop() without\n\t\t// updating allowing for a missing delta beteen this call\n\t\t// and the last call to update(). The idea was to allow the \n\t\t// user to pause at the moment of the last update call so \n\t\t// the pause time could be predictably known. The missing\n\t\t// delta would then be added back to the point of resume\n\t\t// or a subsequent call to update.\n\t\t// However, this produced some bad bugs in the timer code\n\t\t// and it seems to be a messy fix at the moment.\n\t\t// So I'm giving up on the idea for now and will force \n\t\t// an update here to account for the potential timegap\n\t\t// between the call to Stop and UpdateTime().\n\t\tTimeTicker_UpdateTime(time_ticker);\n\t\ttime_ticker->isTickerEnabled = SDL_FALSE;\n\t}\n}\n\n// Stops the clock and sets the clock time to zero.\nvoid TimeTicker_Reset(struct TimeTicker* time_ticker)\n{\n\ttime_ticker->isTickerEnabled = SDL_FALSE;\n\ttime_ticker->previousTime = 0;\n\ttime_ticker->currentTime = 0;\n\ttime_ticker->timeSpeed = 1.0;\n}\n\n\n//////////////////////////////////////////////////////////////////////\n// Get functions.\n//////////////////////////////////////////////////////////////////////\n\n// Gets the clock's current time in milli-seconds.\nUint32 TimeTicker_GetTime(struct TimeTicker* time_ticker)\n{\n\t// Uint32 value = time_ticker->isTickerEnabled ? SDL_GetTicks() : time_stop;\n\t// return (Uint32)((value - time_offset) * timeSpeed);\n\treturn time_ticker->currentTime;\n}\n\n// Updates the clock.\n// Returns the new current time as a convenience.\n// Use GetTime() to get the time without updating it.\nUint32 TimeTicker_UpdateTime(struct TimeTicker* time_ticker)\n{\n\t// If the clock is on, we need to recompute the currentTime\n\t// Else, we just use the pre-existing currentTime\n\tif(SDL_TRUE == time_ticker->isTickerEnabled)\n\t{\n\t\tUint32 now_time = SDL_GetTicks();\n\t\t// The amount of time that has passed is (now-previous) * timeSpeed\n\t\t// Add that to the currentTime to get the new currentTime.\n\t\t// Note the the +0.5f is for rounding when the time gets converted back to Uint32\n\t\ttime_ticker->currentTime += (Uint32)(((now_time - time_ticker->previousTime) * time_ticker->timeSpeed) + 0.5);\n\t\t// Now reset the previousTime for the next time this function is called\n\t\ttime_ticker->previousTime = now_time;\n\t}\n\ttime_ticker->currentTime = SDL_abs(time_ticker->currentTime);\n\ttime_ticker->previousTime = SDL_abs(time_ticker->previousTime);\n\n\treturn time_ticker->currentTime;\n}\n\n\n\n//////////////////////////////////////////////////////////////////////\n// Set functions.\n//////////////////////////////////////////////////////////////////////\n\n// Sets the speed of the clock.\n// 1 is normal speed, 2 makes clock go twice as fast, 0.5 make clock go at half speed, etc.\nvoid TimeTicker_SetSpeed(struct TimeTicker* time_ticker, double new_speed)\n{\n\tif(new_speed >= 0)\n\t{\n\t\ttime_ticker->timeSpeed = new_speed;\n\t}\n}\n\n// Sets the speed of the clock.\n// 1 is normal speed, 2 makes clock go twice as fast, 0.5 make clock go at half speed, etc.\ndouble TimeTicker_GetSpeed(struct TimeTicker* time_ticker)\n{\n\treturn time_ticker->timeSpeed;\n}\n\n\n","\n/* This program is a derivative of a test program also shipped within SDL.\n It uses a happy face sprite and draws multiple instances of them, bouncing them around the screen.\n I (Eric Wing) have modified it to help test bringing up SDL on other platforms and to do both performance benchmarking.\n \n Please see the SDL documentation for details on using the SDL API:\n /Developer/Documentation/SDL/docs.html\n*/\n \n#include \n#include \n#include \n#include \n#include \n\n#include \"SDL.h\"\n#include \"SDL_image.h\"\n#include \"SDL_ttf.h\"\n#include \"ALmixer.h\"\n#include \"chipmunk.h\"\n\n//#include \"BlurrrCore.h\"\n\n#include \"CircularQueue.h\"\n#include \"TimeTicker.h\"\n\n#ifdef __EMSCRIPTEN__\n#include \n#endif\n\n\n\n#ifdef __ANDROID__\n#include \n#include \"SDL_system.h\"\n#include \"ALmixer_PlatformExtensions.h\"\n#endif\n\n#include \n\n#define NUMBER_OF_BIRD_FRAMES 3\n\n\n#ifdef __EMSCRIPTEN__\n/*\nchar* SDL_GetPrefPath(const char* one, const char* two)\n{\n\tchar* ret_val;\n\tret_val = SDL_calloc(2, sizeof(char));\n\tret_val[0] = '/';\n\treturn ret_val;\n}\n*/\n#endif\n\n\nstruct GameTextures\n{\n\tSDL_Texture* background;\n\tSDL_Texture* bush;\n\tSDL_Texture* clouds;\n//\tSDL_Texture* fly1;\n//\tSDL_Texture* fly2;\n\tSDL_Texture* ground;\n\tSDL_Texture* pipe_bottom;\n\tSDL_Texture* pipe_top;\n\tSDL_Texture* bird[NUMBER_OF_BIRD_FRAMES];\n\tSDL_Texture* medalBackground;\n\tSDL_Texture* placeholderMedal;\n\tSDL_Texture* bronzeMedal;\n\tSDL_Texture* silverMedal;\n\tSDL_Texture* goldMedal;\n\tSDL_Texture* platinumMedal;\n\n\tSDL_Texture* medalSceneRenderToTexture;\n\n\tSDL_Texture* playButton;\n\tSDL_Texture* quitButton;\n\n};\nstatic struct GameTextures g_gameTextures;\n\nstruct GameSounds\n{\n\tALmixer_Data* coin;\n\tALmixer_Data* flap;\n\tALmixer_Data* crash;\n\tALmixer_Data* fall;\n\tALmixer_Data* swoosh;\n\n};\nstatic struct GameSounds g_gameSounds;\n\ntypedef double MyFloat;\ntypedef struct Flappy_FloatPoint\n{\n\tMyFloat x;\n\tMyFloat y;\n} Flappy_FloatPoint;\n\nstruct SceneryModelData\n{\n\tSDL_Point position;\n\tSDL_Point size;\n\tFlappy_FloatPoint velocity;\n};\nstatic struct SceneryModelData g_cloudModelData;\nstatic struct SceneryModelData g_groundModelData;\nstatic struct SceneryModelData g_bushModelData;\n\nstatic struct SceneryModelData g_pipeTopModelData;\nstatic struct SceneryModelData g_pipeBottomModelData;\n\nstatic struct SceneryModelData g_playerModelData;\n\n\nenum GameState\n{\n\tGAMESTATE_TITLE_SCREEN = 0,\n\tGAMESTATE_FADE_OUT_TITLE_SCREEN,\n\tGAMESTATE_LOADING_NEW_GAME_AND_FADE_IN,\n\tGAMESTATE_BIRD_PRELAUNCH,\n\tGAMESTATE_BIRD_LAUNCHED_BUT_BEFORE_PIPES,\n\tGAMESTATE_MAIN_GAME_ACTIVE,\n//\tGAMESTATE_DIED_FROM_HITTING_GROUND,\n\tGAMESTATE_DIED_FROM_HITTING_PIPE_AND_FALLING,\n//\tGAMESTATE_DIED_FROM_HITTING_PIPE_AND_ON_GROUND,\n\tGAMESTATE_BIRD_DEAD_ON_GROUND,\n\tGAMESTATE_DEAD_TO_GAME_OVER_TRANSITION,\n\tGAMESTATE_SWOOPING_IN_GAME_OVER,\n\tGAMESTATE_SWOOPED_IN_GAME_OVER,\n\tGAMESTATE_SWOOPING_IN_MEDAL_DISPLAY,\n//\tGAMESTATE_SWOOPED_IN_MEDAL_DISPLAY,\n\tGAMESTATE_TALLYING_SCORE,\n//\tGAMESTATE_SWOOPING_IN_BUTTONS,\n\tGAMESTATE_GAME_OVER_WAITING_FOR_USER_ACTION,\n\tGAMESTATE_FADE_OUT_GAME_OVER\n};\n\nstatic int g_gameState = GAMESTATE_TITLE_SCREEN;\nstatic Uint32 g_gameStateCurrentPhaseStartTime = 0;\n\n\nstruct HighScoreData\n{\n\t/* Flappy Bird doesn't immediately write over the high score.\n\t\tInstead, it saves the previous high score until the tally at the end so you can see the record change.\n\t*/\n\tUint32 savedHighScore;\n\tUint32 previousHighScore;\n\tUint32 currentHighScore;\n};\nstatic struct HighScoreData g_highScoreData;\n\n\n\nstruct PipeModelData\n{\n\tSint32 intervalScalar;\n\tSint32 viewPositionX;\n\tSint32 realPositionX;\n\n\tSint32 upperViewPositionY;\n\tSint32 upperRealPositionY;\n\tSint32 lowerViewPositionY;\n\tSint32 lowerRealPositionY;\n\t\n\tSint32 pipeHeight;\n\n\tSDL_Point size;\n\tcpBody* upperPhysicsBody;\n\tcpShape* upperPhysicsShape;\n\n\tcpBody* lowerPhysicsBody;\n\tcpShape* lowerPhysicsShape;\n\t\n\tcpBody* scoreSensorPhysicsBody;\n\tcpShape* scoreSensorPhysicsShape;\n\t\n};\n\nstatic struct PipeModelData* g_arrayOfPipes = NULL;\nstatic CircularQueueVoid* g_circularQueueOfPipes = NULL;\nstatic CircularQueueVoid* g_queueOfAvailablePipes = NULL;\n\nstruct GameInstanceData\n{\n\tUint32 currentScore;\n\tUint32 distanceTraveled;\n\tUint32 diedAtTime;\n\tUint32 needsWhiteOut;\n\tSDL_bool isPaused;\n\t\n//\tUint32 tallyStartTime;\n\t\n};\n\nstatic struct GameInstanceData g_gameInstanceData;\n\n\nstatic cpSpace* g_mainSpace = NULL;\n\nstruct BirdModelData\n{\n\tcpBody* birdBody;\n\tcpShape* birdShape;\n//\tSDL_Point viewPosition;\n//\tSDL_Point realPosition;\n\tSDL_Point size;\n\t\n\tSDL_Point position;\n\tFlappy_FloatPoint velocity;\n\t/* For when the bird smacks the pipe and needs to fall */\n\tSDL_bool isFalling;\n\tSDL_bool isReadyToPlayFallingSound;\n\tSDL_bool isDead; /* smacks the pipe or ground */\n\tSDL_bool isGameOver; /* bird is completely dead on ground after falling from pipe or smacks ground */\n\n\t// TODO: Move to game state\n\tSDL_bool isPrelaunch;\n\tUint32 birdLaunchStartTime;\n\tSDL_bool isReadyForPipe;\n\n\t\n\tSDL_Texture* currentTexture;\n\tUint32 animationStartTime;\n\tUint32 animationDuration;\n\tSDL_bool isAnimatingSprite;\n\t\n};\n\n/*\nstruct SpriteAnimationData\n{\n\n};\n*/\nstatic struct BirdModelData g_birdModelData;\n\nstruct GroundPhysicsData\n{\n\tcpBody* body;\n\tcpShape* shape;\n\tSDL_Point position;\n\n};\nstatic struct GroundPhysicsData g_groundPhysicsData;\n\n\nstruct MedalBackgroundData\n{\n\tSDL_Rect dstRect;\n\tUint32 sweepInStartTime;\n\tUint32 tallyStartTime;\n\t\n};\nstatic struct MedalBackgroundData g_medalBackgroundData;\n\n\nstruct GameOverDisplayData\n{\n\tSDL_Rect dstRect;\n\tint textureWidth;\n\tint textureHeight;\n\tUint32 sweepInStartTime;\n};\nstatic struct GameOverDisplayData g_gameOverDisplayData;\n\n/* On consoles like SteamOS, we must have an explicit Quit option or the user will not be able\n to quit the game. (Tricks like Alt-F4 don't work unlessed explictly handled by the game.)\n But on iOS, we can't have a Quit button or we'll be rejeted.\n Android by convention doesn't display a Quit button either since the Exit button is available.\n Console-ized Androids have the Exit/Back button built into the controllers.\n So we will conditionalize the code depending on the platform.\n Desktops show both buttons.\n Mobiles will not.\n */\n#if defined(__IPHONEOS__) || defined(__ANDROID__) || defined(__EMSCRIPTEN__)\n\t#define FLAPPY_PROVIDE_QUIT_BUTTON 0\n#else\n\t#define FLAPPY_PROVIDE_QUIT_BUTTON 1\n#endif\n\nstruct GuiButton\n{\n SDL_Rect dstRect;\n SDL_Texture* currentTexture;\n SDL_bool isPressed;\n SDL_bool isSelected;\n};\nstatic struct GuiButton g_guiPlayButton;\n\n#if FLAPPY_PROVIDE_QUIT_BUTTON\nstatic struct GuiButton g_guiQuitButton;\n#endif /* FLAPPY_PROVIDE_QUIT_BUTTON */\n\n\nint Flappy_lroundf(float x)\n{\n\treturn (int)(x+0.5f);\n}\n\n/*\n Produces a random int x, min <= x <= max\n following a uniform distribution\n */\nint\nrandomInt(int min, int max)\n{\n return min + rand() % (max - min + 1);\n}\n\n/*\n Produces a random float x, min <= x <= max\n following a uniform distribution\n */\nfloat\nrandomFloat(float min, float max)\n{\n return rand() / (float) RAND_MAX *(max - min) + min;\n}\n\nvoid\nfatalError(const char *string)\n{\n SDL_Log(\"%s: %s\\n\", string, SDL_GetError());\n // exit(1);\n}\n\n\n\nstatic int NUM_HAPPY_FACES = 200; /* number of faces to draw */\n#define MILLESECONDS_PER_FRAME 16 * 1 /* about 60 frames per second */\n//#define MILLESECONDS_PER_FRAME 16 * 2 /* about 30 frames per second */\n#define HAPPY_FACE_SIZE 32 /* width and height of happyface (pixels) */\n\n//#define SCREEN_WIDTH 480*2\n//#define SCREEN_HEIGHT 320*2\n//#define SCREEN_WIDTH 768\n//#define SCREEN_HEIGHT 1024\n//#define SCREEN_WIDTH 1366\n//#define SCREEN_HEIGHT 768\n//#define SCREEN_WIDTH 1136\n//#define SCREEN_HEIGHT 640\n#define SCREEN_WIDTH 1280\n#define SCREEN_HEIGHT 720\n//#define SCREEN_WIDTH 1024\n//#define SCREEN_HEIGHT 768\n\n\n// How many frames time values to keep\n// The higher the value the smoother the result is...\n// Don't make it 0 or less :)\n#define FRAME_VALUES 10\n\n/* Measured from iPad mini with ruler */\n//#define GROUND_HEIGHT ((1024/16 * 1.9) * 768 / 1024) = 91.2\n#define GROUND_HEIGHT 30\n\n\n#define BIRD_WIDTH 62\n#define BIRD_HEIGHT 50\n\nconst int PIPE_WIDTH = (int)(1.9*(double)BIRD_WIDTH);\n\n/* Distance between pipes:\n\tiPad mini: 768 pixels (12cm) across screen,\n\tdistance between leading pipe edge to next pipe edge: 6.5cm => 416 pixels\n */\n//#define PIPE_DISTANCE 310\n//#define PIPE_DISTANCE 380\n//const int PIPE_DISTANCE = (int)(3.2*(double)BIRD_WIDTH) + PIPE_WIDTH;\n//#define PIPE_DISTANCE (3*BIRD_WIDTH + PIPE_WIDTH + 12);\n//#define PIPE_DISTANCE 400\n#define PIPE_DISTANCE 360\n//#define PIPE_DISTANCE 418\n//#define PIPE_DISTANCE 743\n\n/* About 3.5 Flappy Birds */\n//#define PIPE_HEIGHT_SEPARATION 256\n//#define PIPE_HEIGHT_SEPARATION 192\nconst int PIPE_HEIGHT_SEPARATION = (int)(3.5*(double)BIRD_HEIGHT);\n\n/* y from bottom increasing upwards\n roughly Flappy height?\n */\n//#define MIN_PIPE_HEIGHT 46\n#define MIN_PIPE_HEIGHT BIRD_HEIGHT\n#define NUM_PIPE_HEIGHT_QUANTA 20\n\n#define BIRD_COLLISION_TYPE 1\n#define GROUND_COLLISION_TYPE 2\n#define PIPE_COLLISION_TYPE 3\n#define SCORE_SENSOR_TYPE 4\n\n#define BIRD_FLAP_ANIMATION_DURATION 150\n#define BIRD_FLAP_ANIMATION_DURATION_FOR_PRELAUNCH 1000\n#define PIPE_START_TIME_DELAY 1200\n\n#define TALLY_DURATION 750\n\n#define FADE_OUT_TIME 500\n#define FADE_IN_TIME 500\n\n// An array to store frame times:\nstatic Uint32 frametimes[FRAME_VALUES];\n\n// Last calculated SDL_GetTicks\nstatic Uint32 frametimelast;\n\n// total frames rendered\nstatic Uint32 framecount;\n\nstatic struct TimeTicker* g_gameClock = NULL;\n\n\n// the value you want\nstatic float framespersecond;\n\n// This function gets called once on startup.\nvoid fpsinit() {\n\t\n\t// Set all frame times to 0ms.\n\tmemset(frametimes, 0, sizeof(frametimes));\n\tframecount = 0;\n\tframespersecond = 0;\n\tframetimelast = SDL_GetTicks();\n\t\n}\n\nvoid fpsthink() {\n\t\n\tUint32 frametimesindex;\n\tUint32 getticks;\n\tUint32 count;\n\tUint32 i;\n\t\n\t// frametimesindex is the position in the array. It ranges from 0 to FRAME_VALUES.\n\t// This value rotates back to 0 after it hits FRAME_VALUES.\n\tframetimesindex = framecount % FRAME_VALUES;\n\t\n\t// store the current time\n\tgetticks = SDL_GetTicks();\n\t\n\t// save the frame time value\n\tframetimes[frametimesindex] = getticks - frametimelast;\n\t\n\t// save the last frame time for the next fpsthink\n\tframetimelast = getticks;\n\t\n\t// increment the frame count\n\tframecount++;\n\t\n\t// Work out the current framerate\n\t\n\t// The code below could be moved into another function if you don't need the value every frame.\n\t\n\t// I've included a test to see if the whole array has been written to or not. This will stop\n\t// strange values on the first few (FRAME_VALUES) frames.\n\tif (framecount < FRAME_VALUES) {\n\t\t\n\t\tcount = framecount;\n\t\t\n\t} else {\n\t\t\n\t\tcount = FRAME_VALUES;\n\t\t\n\t}\n\t\n\t// add up all the values and divide to get the average frame time.\n\tframespersecond = 0;\n\tfor (i = 0; i < count; i++) {\n\t\t\n\t\tframespersecond += frametimes[i];\n\t\t\n\t}\n\t\n\tframespersecond /= count;\n\t\n\t// now to make it an actual frames per second value...\n\tframespersecond = 1000.f / framespersecond;\n\t\n}\n\n\n\nstatic SDL_Texture *texture = 0; /* reference to texture holding happyface */\n\nstruct HappyFaceData\n{\n float x, y; /* position of happyface */\n float xvel, yvel; /* velocity of happyface */\n};\n\nstatic struct HappyFaceData* faces = NULL;\n\nstatic SDL_Window* g_mainWindow = NULL;\nstatic SDL_Renderer* g_mainRenderer = NULL;\n\nstatic TTF_Font* s_veraMonoFont = NULL;\nstatic TTF_Font* s_retroFontForMainScore = NULL;\nstatic float s_lastRecordedFPS = 0.0f;\nstatic float s_lastDrawnFPS = 0.0f;\nstatic SDL_Surface* s_surfaceFPS = NULL;\nstatic SDL_Texture* s_textureFPS = NULL;\n\n\nstatic SDL_Texture* g_currentScoreTextTexture = NULL;\nstatic SDL_Texture* g_currentScoreTextShadowTexture = NULL;\n\nstruct TextTextureData\n{\n\tSDL_Texture* scoreLabelTextTexture;\n\tSDL_Texture* bestLabelTextTexture;\n\tSDL_Texture* newHighScoreLabelTextTexture;\n\n\tSDL_Texture* scoreNumberTextTexture;\n//\tSDL_Texture* scoreNumberTextShadowTexture;\n\t\n\tSDL_Texture* bestNumberTextTexture;\n//\tSDL_Texture* bestNumberTextShadowTexture;\n\n\tTTF_Font* fontForMedalLabels;\n\tTTF_Font* fontForScoreNumbers;\n\t\n\tSDL_Texture* getReadyTextTexture;\n\tSDL_Texture* gameOverTextTexture;\n\t\n\tSDL_Texture* flappyBlurrrTexture;\n\tSDL_Texture* taglineTexture;\n\n\n};\nstatic struct TextTextureData g_textTextureData;\n\n\n// Used to get the height of the game screen, minus the bird's Y\nSint32 Flappy_InvertY(Sint32 y)\n{\n\treturn (SCREEN_HEIGHT-y);\n};\n\n\nvoid Flappy_PauseGame()\n{\n\tif(g_gameInstanceData.isPaused)\n\t{\n\t}\n\telse\n\t{\n\t\tTimeTicker_Stop(g_gameClock);\n\t\tg_gameInstanceData.isPaused = SDL_TRUE;\n\t}\n\t\n}\nvoid Flappy_UnpauseGame()\n{\n\tif(g_gameInstanceData.isPaused)\n\t{\n\t\tTimeTicker_Start(g_gameClock);\n\t\tg_gameInstanceData.isPaused = SDL_FALSE;\n\t}\n\telse\n\t{\n\t}\n\t\n}\n\nvoid Flappy_TogglePause()\n{\n\tif(g_gameInstanceData.isPaused)\n\t{\n\t\tTimeTicker_Start(g_gameClock);\n\t\tg_gameInstanceData.isPaused = SDL_FALSE;\n\t}\n\telse\n\t{\n\t\tTimeTicker_Stop(g_gameClock);\n\t\tg_gameInstanceData.isPaused = SDL_TRUE;\n\t}\n\t\n}\n\nSDL_bool TemplateHelper_ToggleFullScreen(SDL_Window* the_window, SDL_Renderer* the_renderer)\n{\n\tint width = SCREEN_WIDTH;\n\tint height = SCREEN_HEIGHT;\n\t\n Uint32 flags = (SDL_GetWindowFlags(the_window) ^ SDL_WINDOW_FULLSCREEN_DESKTOP);\n if(SDL_SetWindowFullscreen(the_window, flags) < 0) // NOTE: this takes FLAGS as the second param, NOT true/false!\n {\n\t\tSDL_Log(\"SDL_SetWindowFullscreen() failed: %s\", SDL_GetError());\n return SDL_FALSE;\n }\n if((flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != 0)\n {\n SDL_RenderSetLogicalSize(the_renderer, SCREEN_WIDTH, SCREEN_HEIGHT); // TODO: pass renderer as param maybe?\n return SDL_TRUE;\n }\n SDL_SetWindowSize(the_window, width, height);\n return SDL_TRUE;\n}\n\n#if 1\nstruct FlappyGameControllerIdData\n{\n\tSDL_GameController* gameController;\n\tint instanceID;\n//\tint deviceID;\n};\n\n#define MAX_NUM_CONTROLLERS 16\nstatic struct FlappyGameControllerIdData s_gameControllerIdToControllerMapArray[MAX_NUM_CONTROLLERS];\n\nvoid Flappy_InitGameControllerDataMap()\n{\n\tint i;\n\tfor(i=0; i=48 && character <= 57)\n\t\t\t{\n\t\t\t\t/* convert ascii value to real number */\n\t\t\t\tint value = character - 48;\n//\t\t\t\tSDL_Log(\"value: %d\", value);\n\t\t\t\t/* update value */\n\t\t\t\tresult = 10 * result + value;\n\t\t\t}\n\t\t}\n\t\twhile(character >=48 && character <= 57);\n\n//\t\tSDL_Log(\"highscore.txt specified %d\", result);\n\t\tSDL_RWclose(rw_ops);\n\t\thigh_score = result;\n\t}\n#endif\n\t\n\treturn high_score;\n}\n\n\n\nSDL_bool Flappy_SaveHighScoreToStorage(Uint32 high_score)\n{\n#define MAX_NUMBER_OF_DIGITS 32\n\tchar number_string[MAX_NUMBER_OF_DIGITS];\n\tchar* pref_path;\n#define MAX_FILE_STRING_LENGTH 2048\n\tchar resource_file_path[MAX_FILE_STRING_LENGTH];\n\t\n#if 1\n\tFILE* resource_handle;\n\t\n\tpref_path = SDL_GetPrefPath(\"net.playcontrol\", \"FlappyBlurrr\");\n\tif(NULL == pref_path)\n\t{\n\t\treturn SDL_FALSE;\n\t}\n\n\tSDL_strlcpy(resource_file_path, pref_path, MAX_FILE_STRING_LENGTH);\n\tSDL_strlcat(resource_file_path, \"highscore.txt\", MAX_FILE_STRING_LENGTH);\n\n\tSDL_free(pref_path);\n\tpref_path = NULL;\n\n\tresource_handle = fopen(resource_file_path, \"w\");\n\t\n\t\n\tif(NULL != resource_handle)\n\t{\n\t\tfprintf(resource_handle, \"%d\", high_score);\n\t\tfclose(resource_handle);\n\t\treturn SDL_TRUE;\n\n\t}\n\telse\n\t{\n//\t\tSDL_Log(\"Failed to write high score to storage: %s\", strerror(errno));\n\t\treturn SDL_FALSE;\n\t}\n\n#else\n\tSDL_RWops* rw_ops;\n\t\n\tpref_path = SDL_GetPrefPath(\"net.playcontrol\", \"FlappyBlurrr\");\n\tif(NULL == pref_path)\n\t{\n\t\t/* This might be okay because it is a first time run and the file doesn't exist. */\n\t\treturn SDL_FALSE;\n\t}\n\t\n\tSDL_strlcpy(resource_file_path, pref_path, MAX_FILE_STRING_LENGTH);\n\tSDL_strlcat(resource_file_path, \"highscore.txt\", MAX_FILE_STRING_LENGTH);\n\t\n\tSDL_free(pref_path);\n\tpref_path = NULL;\n\t\n\t/* Please be nice. Assumes the file contains a single ASCII number representing the number of sprites. */\n\t/* RWops is more resiliant because platforms don't always give you access to fopen/fread, like Android's .apk system. */\n\t/* However in this case, all our target platforms allow fopen for preference files. */\n\t/* This is mainly done for demonstration. */\n\t/* No error checking is done for malicious input. */\n\trw_ops = SDL_RWFromFile(resource_file_path, \"w\");\n\tif(NULL != rw_ops)\n\t{\n\t\tint i = 0;\n\t\tSDL_uitoa(high_score, number_string, 10);\n\t\twhile('\\0' != number_string[i])\n\t\t{\n\t\t\tSDL_WriteU8(rw_ops, number_string[i]);\n\t\t\ti = i + 1;\n\t\t}\n\n\t\tSDL_RWclose(rw_ops);\n\t\treturn SDL_TRUE;\n\t}\n\telse\n\t{\n\t\tSDL_Log(\"Failed to write high score to storage: %s\", SDL_GetError());\n\t\treturn SDL_FALSE;\n\t}\n#endif\n\t\n\t\n}\n\nSDL_bool Flappy_SaveHighScoreToStorageIfNeeded()\n{\n\t/* We write to disk, but don't change the in memory value of previousHighScore\n\t \tbecause we need that value for the tally if the game is interrupted/resumed.\n\t */\n\tif(g_gameInstanceData.currentScore > g_highScoreData.savedHighScore)\n\t{\n\t\tg_highScoreData.savedHighScore = g_gameInstanceData.currentScore;\n\t\treturn Flappy_SaveHighScoreToStorage(g_gameInstanceData.currentScore);\n\t}\n\treturn SDL_TRUE;\n}\n\n\nchar* BlurrrCore_CreateResourceDirectoryString(void)\n{\n\tchar* result_string = NULL;\n\n\t/* SDL_GetBasePath() is a little unpredictable on Apple platforms because Info.plist settings can override its behavior.\n\t * So for Apple platforms, we'll just write it natively.\n\t */\n\t#ifdef __APPLE__\n\t\tresult_string = BlurrrCoreApple_CreateResourceDirectoryString();\n\t#else\n\t\tresult_string = SDL_GetBasePath();\n\t#endif\n\n\treturn result_string;\n\n\n}\n\nsize_t BlurrrCore_GetResourceDirectoryString(char* string_array, size_t array_length)\n{\n\tsize_t result_length = 0;\n\tchar* result_string = NULL;\n\n\tresult_string = BlurrrCore_CreateResourceDirectoryString();\n\tif(NULL != result_string)\n\t{\n\t\tif(NULL != string_array)\n\t\t{\n\t\t\tSDL_strlcpy(string_array, result_string, array_length);\n\t\t}\n\t\tresult_length = SDL_strlen(result_string) + 1;\n\t}\n\telse\n\t{\n\t\tif(NULL != string_array)\n\t\t{\n\t\t\tstring_array[0] = '\\0';\n\t\t}\n\t}\n\n\tSDL_free(result_string);\n\treturn result_length;\n}\n\n\n\n/*\n Sets initial positions and velocities of happyfaces\n units of velocity are pixels per millesecond\n */\nvoid\ninitializeHappyFaces()\n{\n\tint i = 0;\n#define MAX_FILE_STRING_LENGTH 2048\n\tchar resource_file_path[MAX_FILE_STRING_LENGTH];\n\tSDL_RWops* rw_ops;\n\n\tBlurrrCore_GetResourceDirectoryString(resource_file_path, MAX_FILE_STRING_LENGTH);\n\tSDL_strlcat(resource_file_path, \"config.txt\", MAX_FILE_STRING_LENGTH);\n\n\n#if 0\n\tFILE* resource_handle;\n\tresource_handle = fopen(resource_file_path, \"r\");\n\tif(NULL != resource_handle)\n\t{\n\t\t/* Please be nice. */\n\t\tfscanf(resource_handle, \"%d\", &i);\n\t\tNUM_HAPPY_FACES = i;\n\t}\n\tfclose(resource_handle);\n#else\n\n\t/* Please be nice. Assumes the file contains a single ASCII number representing the number of sprites. */\n\t/* Must use RWops because Android will bundle this inside the .apk which makes it inaccessible to functions like fopen(). */\n\t/* No error checking is done for malicious input. */\n\trw_ops = SDL_RWFromFile(resource_file_path, \"r\");\n\tif(NULL != rw_ops)\n\t{\n\t\tint result = 0;\n\t\tUint8 character;\n\t \tdo\n\t\t{\n\t\t\tcharacter = SDL_ReadU8(rw_ops);\n\t\t\tif(character >=48 && character <= 57)\n\t\t\t{\n\t\t\t\t/* convert ascii value to real number */\n\t\t\t\tint value = character - 48;\n//\t\t\t\tSDL_Log(\"value: %d\", value);\n\t\t\t\t/* update value */\n\t\t\t\tresult = 10 * result + value;\n\t\t\t}\n\t\t}\n\t\twhile(character >=48 && character <= 57);\n\n\t\tSDL_Log(\"config.txt specified %d sprites\", result);\n\t\tSDL_RWclose(rw_ops);\n\t\tNUM_HAPPY_FACES = result;\n\t}\n\n#endif\n\tfaces = (struct HappyFaceData*)SDL_malloc(NUM_HAPPY_FACES*sizeof(struct HappyFaceData));\n\n\tfor (i = 0; i < NUM_HAPPY_FACES; i++)\n\t{\n\t\tfaces[i].x = randomFloat(0.0f, SCREEN_WIDTH - HAPPY_FACE_SIZE);\n\t\tfaces[i].y = randomFloat(0.0f, SCREEN_HEIGHT - HAPPY_FACE_SIZE);\n\t\tfaces[i].xvel = randomFloat(-0.1f, 0.1f);\n\t\tfaces[i].yvel = randomFloat(-0.1f, 0.1f);\n\t}\n}\n\nMyFloat Flappy_ComputeLinearInterpolation(MyFloat current_value, MyFloat start_value, MyFloat end_value)\n{\n\t/* Use the linear interpolation formula:\n\t * X = (1-t)x0 + tx1\n\t * where x0 would be the start value\n\t * and x1 is the final value\n\t * and t is delta_time*inv_time (adjusts 0 <= time <= 1)\n\t * delta_time = current_time-start_time\n\t * inv_time = 1/ (end_time-start_time)\n\t * so t = current_time-start_time / (end_time-start_time)\n\t *\n\t */\n\tif(current_value > end_value)\n\t{\n\t\treturn 1.0;\n\t}\n\telse if(current_value < start_value)\n\t{\n\t\treturn 0.0;\n\t}\n\treturn (current_value-start_value) / (end_value-start_value);\n}\n\nvoid Flappy_StepPhysics(Uint32 delta_time)\n{\n\t// Recommended between 60 and 240; higher = more accuracy (but higher CPU load)\n\tconst MyFloat TICKS_PER_SECOND = 100.0;\n\tstatic MyFloat _accumulator = 0.0;\n\n\tMyFloat dt = (MyFloat)delta_time * 1.0/1000.0;\n\tMyFloat fixed_dt = 1.0/TICKS_PER_SECOND;\n\t\n\t// add the current dynamic timestep to the accumulator\n\t_accumulator += dt;\n//\t\tSDL_Log(\"delta_time=%d, _accumulator=%lf, dt=%lf, fixed_dt=%lf\", delta_time, _accumulator, dt, fixed_dt);\n\t\n\twhile(_accumulator > fixed_dt)\n\t{\n\t\t//SDL_Log(\"_accumulator=%lf > fixed_dt=%lf\", _accumulator, fixed_dt);\n\t\tcpSpaceStep(g_mainSpace, fixed_dt);\n\t\t_accumulator -= fixed_dt;\n\t}\n}\n\n\n\nvoid\nrender(SDL_Renderer *renderer)\n{\n\t\n int i;\n SDL_Rect srcRect;\n SDL_Rect dstRect;\n\t\n /* setup boundaries for happyface bouncing */\n Uint16 maxx = SCREEN_WIDTH - HAPPY_FACE_SIZE;\n Uint16 maxy = SCREEN_HEIGHT - HAPPY_FACE_SIZE;\n Uint16 minx = 0;\n Uint16 miny = 0;\n\t\n /* setup rects for drawing */\n srcRect.x = 0;\n srcRect.y = 0;\n srcRect.w = HAPPY_FACE_SIZE;\n srcRect.h = HAPPY_FACE_SIZE;\n dstRect.w = HAPPY_FACE_SIZE;\n dstRect.h = HAPPY_FACE_SIZE;\n\t\n /* fill background in with black */\n SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);\n SDL_RenderClear(renderer);\n\t\n /*\n\t loop through all the happy faces:\n\t - update position\n\t - update velocity (if boundary is hit)\n\t - draw\n */\n#if 0\n\n#else\n for (i = 0; i < 3; i++)\n {\n float XVEL = -1.0f;\n float YVEL = 0.0f;\n faces[i].xvel = XVEL;\n faces[i].yvel = YVEL;\n\n faces[i].x += faces[i].xvel * MILLESECONDS_PER_FRAME;\n faces[i].y += faces[i].yvel * MILLESECONDS_PER_FRAME;\n \n if (faces[i].x < minx)\n {\n faces[i].x = maxx;\n }\n dstRect.x = faces[i].x;\n dstRect.y = faces[i].y;\n\t\t\n\t\tUint32 the_format;\n\t\tint the_access;\n\t\tint the_width;\n\t\tint the_height;\n\t\tSDL_QueryTexture(g_gameTextures.clouds, &the_format, &the_access, &the_width, &the_height);\n\t\t\n\t\t\n\t\tsrcRect.x = 0;\n\t\tsrcRect.y = 0;\n\t\tsrcRect.w = the_width;\n\t\tsrcRect.h = the_height;\n\t\tdstRect.w = the_width;\n dstRect.h = the_height;\n\n// SDL_RenderCopy(renderer, g_gameTextures.clouds, &srcRect, &dstRect);\n // SDL_RenderCopy(renderer, g_gameTextures.clouds, NULL, NULL);\n }\n\t\n\t/* Render the background.\n\t\tWe stretch the sprite to fit the screen for convenience.\n\t */\n\t{\n\n\t\tSDL_Rect dst_rect = {0, 0, SCREEN_WIDTH, SCREEN_WIDTH};\n\t\tSDL_RenderCopy(renderer, g_gameTextures.background, NULL, &dst_rect);\n\n\t}\n\t\n\t/* Render the bush/hills */\n\t{\n\t\t\n\t\tSDL_Rect src_rect = {0, 0, g_bushModelData.size.x, g_bushModelData.size.y};\n\t\t/* The ground height in the image is actually really tall and we don't want all of it.\n\t\t So we can truncate the bottom part that we don't want.\n\t\t We'll take 1/5 of the image.\n\t\t */\n\t\tSDL_Rect dst_rect = {g_bushModelData.position.x, Flappy_InvertY(g_groundModelData.size.y + g_bushModelData.size.y), g_bushModelData.size.x, g_bushModelData.size.y};\n\t\t\n\t\t\n\t\t/* The texture does not fill the whole width of the screen.\n\t\t So draw it multiple times, shifted over\n\t\t until we fill the entire length of the screen.\n\t\t */\n\t\tSint32 number_of_times_to_repeat_draw;\n\t\tSint32 remainder;\n\t\tSint32 i;\n\t\t\n\t\tUint32 the_format;\n\t\tint the_access;\n\t\tint the_width;\n\t\tint the_height;\n\t\t\n\t\tSDL_QueryTexture(g_gameTextures.bush, &the_format, &the_access, &the_width, &the_height);\n\t\t\n\t\tnumber_of_times_to_repeat_draw = (SCREEN_WIDTH / the_width) + 1;\n\t\tremainder = SCREEN_WIDTH % the_width;\n\t\t\n\t\tif(remainder > 0)\n\t\t{\n\t\t\tnumber_of_times_to_repeat_draw = number_of_times_to_repeat_draw + 1;\n\t\t}\n\t\t\n\t\tfor(i=0; i 0)\n\t\t{\n\t\t\tnumber_of_times_to_repeat_draw = number_of_times_to_repeat_draw + 1;\n\t\t}\n\t\t\n\t\tfor(i=0; i 0)\n\t\t{\n\t\t\tnumber_of_times_to_repeat_draw = number_of_times_to_repeat_draw + 1;\n\t\t}\n\t\t\n\t\tfor(i=0; ipipeHeight};\n\t\t\tSDL_Rect dst_rect = {g_pipeTopModelData.position.x, current_pipe->lowerViewPositionY, g_pipeTopModelData.size.x, current_pipe->pipeHeight};\n\n\t\t\tdst_rect.x = current_pipe->viewPositionX - g_pipeTopModelData.size.x/2;\n//\t\t\tdst_rect.y = Flappy_InvertY(current_pipe->pipeHeight+GROUND_HEIGHT);\n\n\t\t\tSDL_RenderCopy(renderer, g_gameTextures.pipe_bottom, &src_rect, &dst_rect);\n//\t\t\tSDL_RenderCopy(renderer, g_gameTextures.pipe_bottom, NULL, &dst_rect);\n\t\t\t\n//\t\t\tsrc_rect.y = 512 - current_pipe->pipeHeight - PIPE_HEIGHT_SEPARATION;\n\t\t\tsrc_rect.y = 0;\n//\t\t\tsrc_rect.h = SCREEN_HEIGHT - current_pipe->pipeHeight - PIPE_HEIGHT_SEPARATION - GROUND_HEIGHT;\n\t\t\tsrc_rect.h = 512;\n//\t\t\tdst_rect.y = current_pipe->upperViewPositionY - PIPE_HEIGHT_SEPARATION - GROUND_HEIGHT - current_pipe->pipeHeight;\n//\t\t\tdst_rect.y = current_pipe->upperViewPositionY;\n\t\t\tdst_rect.y = SCREEN_HEIGHT - current_pipe->pipeHeight - PIPE_HEIGHT_SEPARATION - GROUND_HEIGHT - 512;\n\t\t\tdst_rect.h = 512;\n//\t\t\tdst_rect.h = SCREEN_HEIGHT - current_pipe->pipeHeight - PIPE_HEIGHT_SEPARATION - GROUND_HEIGHT;\n\n\t\t\tSDL_RenderCopy(renderer, g_gameTextures.pipe_top, &src_rect, &dst_rect);\n//\t\t\tSDL_RenderCopy(renderer, g_gameTextures.pipe_top, NULL, &dst_rect);\n\n\n\t\t}\n\t\t\n\t\t\n\t\t\n\n\t\t\n\t}\n\t\n\t\n\t/* render bird */\n\t{\n\t\t\n\t\tSDL_Rect src_rect = {0, 0, g_birdModelData.size.x, g_birdModelData.size.y};\n\t\t/* The ground height in the image is actually really tall and we don't want all of it.\n\t\t So we can truncate the bottom part that we don't want.\n\t\t We'll take 1/5 of the image.\n\t\t */\n\t\tSDL_Rect dst_rect = {g_birdModelData.position.x - g_birdModelData.size.x/2, g_birdModelData.position.y, g_birdModelData.size.x, g_birdModelData.size.y};\n\t\t\n\t\t\n\t\t\n//\t\tSDL_RenderCopy(renderer, g_gameTextures.fly1, NULL, &dst_rect);\n\t\tSDL_RenderCopyEx(renderer, g_birdModelData.currentTexture, NULL, &dst_rect, -cpBodyGetAngle(g_birdModelData.birdBody)/(2.0*M_PI/360.0), NULL, SDL_FLIP_NONE);\n\t\t\n\t\t\n\t}\n\t\n\t\n\t/* render ground */\n\t{\n\t\t\n\t\t\n\t\tSDL_Rect src_rect = {0, 0, g_groundModelData.size.x, g_groundModelData.size.y};\n\t\t/* The ground height in the image is actually really tall and we don't want all of it.\n\t\t So we can truncate the bottom part that we don't want.\n\t\t We'll take 1/5 of the image.\n\t\t */\n\t\tSDL_Rect dst_rect = {g_groundModelData.position.x, Flappy_InvertY(g_groundModelData.size.y), g_groundModelData.size.x, g_groundModelData.size.y};\n\t\t\n\t\t\n\t\t/* The texture does not fill the whole width of the screen.\n\t\t So draw it multiple times, shifted over\n\t\t until we fill the entire length of the screen.\n\t\t */\n\t\tSint32 number_of_times_to_repeat_draw;\n\t\tSint32 remainder;\n\t\tSint32 i;\n\t\t\n\t\tUint32 the_format;\n\t\tint the_access;\n\t\tint the_width;\n\t\tint the_height;\n\t\t\n\t\tSDL_QueryTexture(g_gameTextures.ground, &the_format, &the_access, &the_width, &the_height);\n\t\t\n\t\tnumber_of_times_to_repeat_draw = (SCREEN_WIDTH / the_width) + 1;\n\t\tremainder = SCREEN_WIDTH % the_width;\n\t\tif(remainder > 0)\n\t\t{\n\t\t\tnumber_of_times_to_repeat_draw = number_of_times_to_repeat_draw + 1;\n\t\t}\n\t\t\n\t\tfor(i=0; i= GAMESTATE_BIRD_PRELAUNCH) && (g_gameState < GAMESTATE_SWOOPING_IN_GAME_OVER))\n\t{\n\t\t/* render current score */\n\n\t\tUint32 the_format;\n\t\tint the_access;\n\t\tint the_width;\n\t\tint the_height;\n\t\tSDL_Rect dst_rect;\n\n\t\tSDL_QueryTexture(g_currentScoreTextTexture, &the_format, &the_access, &the_width, &the_height);\n\t\t\n\t\tdst_rect.x = SCREEN_WIDTH / 2 - the_width/2 + 4;\n\t\tdst_rect.y = SCREEN_HEIGHT/12 - the_height/2 + 4;\n\t\tdst_rect.w = the_width;\n\t\tdst_rect.h = the_height;\n\t\tSDL_RenderCopy(renderer, g_currentScoreTextShadowTexture, NULL, &dst_rect);\n//\t\tSDL_Log(\"text texture w,h: %d, %d\", the_width, the_height);\n\n\t\tdst_rect.x = SCREEN_WIDTH / 2 - the_width/2 - 2;\n\t\tdst_rect.y = SCREEN_HEIGHT/12 - the_height/2 - 2;\n\t\tSDL_RenderCopy(renderer, g_currentScoreTextShadowTexture, NULL, &dst_rect);\n\t\t\n\t\tdst_rect.x = SCREEN_WIDTH / 2 - the_width/2 + 2;\n\t\tdst_rect.y = SCREEN_HEIGHT/12 - the_height/2 + 2;\n\t\tSDL_RenderCopy(renderer, g_currentScoreTextShadowTexture, NULL, &dst_rect);\n\n\t\tdst_rect.x = SCREEN_WIDTH / 2 - the_width/2 + 2;\n\t\tdst_rect.y = SCREEN_HEIGHT/12 - the_height/2 - 2;\n\t\tSDL_RenderCopy(renderer, g_currentScoreTextShadowTexture, NULL, &dst_rect);\n\n\t\tdst_rect.x = SCREEN_WIDTH / 2 - the_width/2 - 2;\n\t\tdst_rect.y = SCREEN_HEIGHT/12 - the_height/2 + 2;\n\t\tSDL_RenderCopy(renderer, g_currentScoreTextShadowTexture, NULL, &dst_rect);\n\t\t\n\t\t\n\t\tdst_rect.x = SCREEN_WIDTH / 2 - the_width/2;\n\t\tdst_rect.y = SCREEN_HEIGHT/12 - the_height/2;\n\t\tdst_rect.w = the_width;\n\t\tdst_rect.h = the_height;\n\t\t\n\t\tSDL_RenderCopy(renderer, g_currentScoreTextTexture, NULL, &dst_rect);\n\t\t\n\t\t\n\n\t\t\n\t}\n#endif\n\t{\n\n#if 1\n\t\t\n\t\tif(g_gameState >= GAMESTATE_SWOOPING_IN_GAME_OVER)\n//\t\tif(SDL_TRUE == g_birdModelData.isGameOver)\n\t\t{\n\t\t\tSDL_Rect dst_rect = {0, 100, 512, 256 };\n\t\t\tUint32 the_format;\n\t\t\tint the_access;\n\t\t\tint the_width;\n\t\t\tint the_height;\n\t\t\tSDL_QueryTexture(g_textTextureData.gameOverTextTexture, &the_format, &the_access, &the_width, &the_height);\n\n\t\t\tdst_rect.w = the_width;\n\t\t\tdst_rect.h = the_height;\n\t\t\tdst_rect = g_gameOverDisplayData.dstRect;\n\t\t\t\n\t//\t\tSDL_RenderCopy(renderer, g_gameTextures.medalBackground, NULL, &g_medalBackgroundData.dstRect);\n\t\t\tSDL_RenderCopy(renderer, g_textTextureData.gameOverTextTexture, NULL, &dst_rect);\n//\t\t\tSDL_RenderCopy(renderer, g_textTextureData.getReadyTextTexture, NULL, &dst_rect);\n\n\t\t}\n#endif\n\t\t\n\t\tif(g_gameState >= GAMESTATE_SWOOPING_IN_MEDAL_DISPLAY)\n\t\t\t//\t\tif(SDL_TRUE == g_birdModelData.isGameOver)\n\t\t{\n\n\t\t\t\n\t\t\t//\t\tSDL_RenderCopy(renderer, g_gameTextures.medalBackground, NULL, &g_medalBackgroundData.dstRect);\n\t\t\tSDL_RenderCopy(renderer, g_gameTextures.medalSceneRenderToTexture, NULL, &g_medalBackgroundData.dstRect);\n\t\t\t//\t\t\tSDL_RenderCopy(renderer, g_textTextureData.getReadyTextTexture, NULL, &dst_rect);\n\t\t\t\n\t\t}\n\n\t}\n#if 1\n\t{\n// if(g_birdModelData.isPrelaunch)\n if((g_gameState >= GAMESTATE_LOADING_NEW_GAME_AND_FADE_IN) && (g_gameState <= GAMESTATE_BIRD_LAUNCHED_BUT_BEFORE_PIPES))\n {\n SDL_Rect dst_rect = {0, 0, 512, 256 };\n\t\t\tUint32 the_format;\n\t\t\tint the_access;\n\t\t\tint the_width;\n\t\t\tint the_height;\n\t\t\tSDL_QueryTexture(g_textTextureData.getReadyTextTexture, &the_format, &the_access, &the_width, &the_height);\n \n\t\t\tdst_rect.w = the_width;\n\t\t\tdst_rect.h = the_height;\n\n\t\t\tdst_rect.x = (SCREEN_WIDTH / 2) - (the_width / 2);\n\t\t\tdst_rect.y = SCREEN_HEIGHT / 5;\n \n \n if(g_gameState == GAMESTATE_BIRD_LAUNCHED_BUT_BEFORE_PIPES)\n {\n MyFloat linear_interp;\n Uint32 current_time = TimeTicker_GetTime(g_gameClock);\n#define GET_READY_TEXT_FADE_OUT_TIME 1000\n linear_interp = Flappy_ComputeLinearInterpolation(current_time, g_gameStateCurrentPhaseStartTime, g_gameStateCurrentPhaseStartTime + GET_READY_TEXT_FADE_OUT_TIME);\n\t\t\t\tUint8 alpha = 255 - linear_interp*255;\n\n SDL_SetTextureAlphaMod(g_textTextureData.getReadyTextTexture, alpha);\n SDL_RenderCopy(renderer, g_textTextureData.getReadyTextTexture, NULL, &dst_rect);\n }\n else\n {\n SDL_SetTextureAlphaMod(g_textTextureData.getReadyTextTexture, 255);\n SDL_RenderCopy(renderer, g_textTextureData.getReadyTextTexture, NULL, &dst_rect);\n }\n //\t\tSDL_RenderCopy(renderer, g_gameTextures.medalBackground, NULL, &g_medalBackgroundData.dstRect);\n \n }\n }\n #endif\n #if 1\n\t{\n\t\tif( (g_gameState >= GAMESTATE_TITLE_SCREEN) && (g_gameState <= GAMESTATE_FADE_OUT_TITLE_SCREEN) )\n\t\t{\n\t\t\tSDL_Rect dst_rect = {0, 0, 512, 256 };\n\t\t\tUint32 the_format;\n\t\t\tint the_access;\n\t\t\tint the_width;\n\t\t\tint the_height;\n\t\t\tint running_height;\n\t\t\tSDL_QueryTexture(g_textTextureData.getReadyTextTexture, &the_format, &the_access, &the_width, &the_height);\n \n\t\t\tdst_rect.w = the_width;\n\t\t\tdst_rect.h = the_height;\n\t\t\t\n\t\t\tdst_rect.x = (SCREEN_WIDTH / 2) - (the_width / 2);\n\t\t\tdst_rect.y = SCREEN_HEIGHT / 7;\n\t\t\t\n\t\t\tSDL_RenderCopy(renderer, g_textTextureData.flappyBlurrrTexture, NULL, &dst_rect);\n\t\t\t\n\t\t\trunning_height = dst_rect.y;\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\tSDL_QueryTexture(g_textTextureData.taglineTexture, &the_format, &the_access, &the_width, &the_height);\n \n\t\t\tdst_rect.w = the_width;\n\t\t\tdst_rect.h = the_height;\n\t\t\t\n\t\t\tdst_rect.x = (SCREEN_WIDTH / 2) - (the_width / 2);\n\t\t\tdst_rect.y = running_height + the_height;\n\t\t\t\n\t\t\tSDL_RenderCopy(renderer, g_textTextureData.taglineTexture, NULL, &dst_rect);\n\n\t\t\t\n\n\t\t}\n\t\t\t\n\t}\n#endif\n \n\t{\n if( ((g_gameState >= GAMESTATE_GAME_OVER_WAITING_FOR_USER_ACTION) && (g_gameState <= GAMESTATE_FADE_OUT_GAME_OVER) )\n\t\t\t|| ((g_gameState >= GAMESTATE_TITLE_SCREEN) && (g_gameState <= GAMESTATE_FADE_OUT_TITLE_SCREEN) )\n\t\t)\n {\n SDL_Rect dst_rect;\n dst_rect = g_guiPlayButton.dstRect;\n \n if(SDL_TRUE == g_guiPlayButton.isSelected)\n {\n SDL_SetTextureColorMod(g_guiPlayButton.currentTexture, 255, 255, 255);\n }\n else\n {\n SDL_SetTextureColorMod(g_guiPlayButton.currentTexture, 180, 180, 180);\n }\n if(SDL_TRUE == g_guiPlayButton.isPressed)\n {\n dst_rect.x = dst_rect.x + 6;\n dst_rect.y = dst_rect.y + 6;\n }\n else\n {\n }\n\t\t\tSDL_Log(\"draw playbutton\");\n SDL_RenderCopy(renderer, g_guiPlayButton.currentTexture, NULL, &dst_rect);\n \n#if FLAPPY_PROVIDE_QUIT_BUTTON\n if(SDL_TRUE == g_guiQuitButton.isSelected)\n {\n SDL_SetTextureColorMod(g_guiQuitButton.currentTexture, 255, 255, 255);\n }\n else\n {\n SDL_SetTextureColorMod(g_guiQuitButton.currentTexture, 180, 180, 180);\n }\n\n \n dst_rect = g_guiQuitButton.dstRect;\n if(SDL_TRUE == g_guiQuitButton.isPressed)\n {\n dst_rect.x = dst_rect.x + 6;\n dst_rect.y = dst_rect.y + 6;\n }\n else\n {\n }\n \n SDL_RenderCopy(renderer, g_guiQuitButton.currentTexture, NULL, &dst_rect);\n#endif /* FLAPPY_PROVIDE_QUIT_BUTTON */\n\n }\n\t\telse\n\t\t{\n//\t\t\tSDL_Log(\"gamestate is %d\", g_gameState);\n\n\t\t}\n }\n \n \n \n\t{\n\t\tif(g_gameInstanceData.needsWhiteOut == SDL_TRUE)\n\t\t{\n\t\t\tUint32 current_time = TimeTicker_GetTime(g_gameClock);\n\t\t\tfloat linear_interp;\n\t\t\tSDL_Rect dst_rect = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT};\n\n#define WHITE_OUT_TIME 200\n\t\t\tif(current_time > (g_gameInstanceData.diedAtTime + WHITE_OUT_TIME))\n\t\t\t{\n\t\t\t\t// FIXME: this needs to be moved/deleted. For testing only.\n\t\t\t\tg_gameInstanceData.needsWhiteOut = SDL_FALSE;\n\t\t\t\t\n\t\t\t\t\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t/* Use the linear interpolation formula:\n\t\t\t * X = (1-t)x0 + tx1\n\t\t\t * where x0 would be the start value\n\t\t\t * and x1 is the final value\n\t\t\t * and t is delta_time*inv_time (adjusts 0 <= time <= 1)\n\t\t\t * delta_time = current_time-start_time\n\t\t\t * inv_time = 1/ (end_time-start_time)\n\t\t\t * so t = current_time-start_time / (end_time-start_time)\n\t\t\t *\n\t\t\t */\n\t\t\t\tlinear_interp = Flappy_ComputeLinearInterpolation(current_time, g_gameInstanceData.diedAtTime, g_gameInstanceData.diedAtTime+WHITE_OUT_TIME);\n\t\t\t\tUint8 alpha = 255 - linear_interp*255;\n\t\t\t\tSDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);\n\t\t\t\tSDL_SetRenderDrawColor(renderer, 255, 255, 255, alpha);\n//\t\t\t\tSDL_RenderFillRect(renderer, &dst_rect);\n\t\t\t\tSDL_RenderFillRect(renderer, NULL);\n\t\t\t}\n\t\t\t\t\n\t\t}\n\t\t\n\t\t\n\t\t\n\t\t/* Render black fade-out */\n\t\t{\n\t\t\tif((GAMESTATE_FADE_OUT_GAME_OVER == g_gameState)\n\t\t\t\t|| (GAMESTATE_FADE_OUT_TITLE_SCREEN == g_gameState)\n\t\t\t)\n\t\t\t{\n\t\t\t\tUint32 current_time = TimeTicker_GetTime(g_gameClock);\n\t\t\t\tfloat linear_interp;\n\t\t\t\tSDL_Rect dst_rect = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT};\n\t\t\t\t\n\t\t\t\tif(current_time > (g_gameStateCurrentPhaseStartTime + FADE_OUT_TIME))\n\t\t\t\t{\n\n\t\t\t\t\tSDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);\n\t\t\t\t\tSDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);\n\t\t\t\t\t//\t\t\t\tSDL_RenderFillRect(renderer, &dst_rect);\n\t\t\t\t\tSDL_RenderFillRect(renderer, NULL);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t/* Use the linear interpolation formula:\n\t\t\t\t\t * X = (1-t)x0 + tx1\n\t\t\t\t\t * where x0 would be the start value\n\t\t\t\t\t * and x1 is the final value\n\t\t\t\t\t * and t is delta_time*inv_time (adjusts 0 <= time <= 1)\n\t\t\t\t\t * delta_time = current_time-start_time\n\t\t\t\t\t * inv_time = 1/ (end_time-start_time)\n\t\t\t\t\t * so t = current_time-start_time / (end_time-start_time)\n\t\t\t\t\t *\n\t\t\t\t\t */\n\t\t\t\t\tlinear_interp = Flappy_ComputeLinearInterpolation(current_time, g_gameStateCurrentPhaseStartTime, g_gameStateCurrentPhaseStartTime+FADE_OUT_TIME);\n\t\t\t\t\tUint8 alpha = linear_interp*255;\n\t\t\t\t\tSDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);\n\t\t\t\t\tSDL_SetRenderDrawColor(renderer, 0, 0, 0, alpha);\n\t\t\t\t\t//\t\t\t\tSDL_RenderFillRect(renderer, &dst_rect);\n\t\t\t\t\tSDL_RenderFillRect(renderer, NULL);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t}\n\t\t}\n\n\t\t/* Render black fade-in */\n\t\t{\n\t\t\tif(GAMESTATE_LOADING_NEW_GAME_AND_FADE_IN == g_gameState)\n\t\t\t{\n\t\t\t\tUint32 current_time = TimeTicker_GetTime(g_gameClock);\n\t\t\t\tfloat linear_interp;\n\t\t\t\tSDL_Rect dst_rect = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT};\n\t\t\t\t\n\t\t\t\tif(current_time > (g_gameStateCurrentPhaseStartTime + FADE_IN_TIME))\n\t\t\t\t{\n\t\t\t\t\t\n\t\t\t\t\tSDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);\n\t\t\t\t\tSDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);\n\t\t\t\t\t//\t\t\t\tSDL_RenderFillRect(renderer, &dst_rect);\n\t\t\t\t\tSDL_RenderFillRect(renderer, NULL);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t/* Use the linear interpolation formula:\n\t\t\t\t\t * X = (1-t)x0 + tx1\n\t\t\t\t\t * where x0 would be the start value\n\t\t\t\t\t * and x1 is the final value\n\t\t\t\t\t * and t is delta_time*inv_time (adjusts 0 <= time <= 1)\n\t\t\t\t\t * delta_time = current_time-start_time\n\t\t\t\t\t * inv_time = 1/ (end_time-start_time)\n\t\t\t\t\t * so t = current_time-start_time / (end_time-start_time)\n\t\t\t\t\t *\n\t\t\t\t\t */\n\t\t\t\t\tlinear_interp = Flappy_ComputeLinearInterpolation(current_time, g_gameStateCurrentPhaseStartTime, g_gameStateCurrentPhaseStartTime+FADE_IN_TIME);\n\t\t\t\t\tUint8 alpha = 255 - linear_interp*255;\n\t\t\t\t\tSDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);\n\t\t\t\t\tSDL_SetRenderDrawColor(renderer, 0, 0, 0, alpha);\n\t\t\t\t\t//\t\t\t\tSDL_RenderFillRect(renderer, &dst_rect);\n\t\t\t\t\tSDL_RenderFillRect(renderer, NULL);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t}\n\t\t}\n\n\t\t\n\t}\n\t\n\n#endif\n \n#if 0\n\t/* FPS counter */\n\tif(s_lastRecordedFPS != s_lastDrawnFPS)\n\t{\n\t\tchar fps_string[32];\n\t\tSDL_Color text_color = { 255, 255, 255, 0 };\n\t\ts_lastDrawnFPS = s_lastRecordedFPS;\n\t\tSDL_snprintf(fps_string, 32, \"%.2f fps\", s_lastRecordedFPS);\n\n\t\tSDL_FreeSurface(s_surfaceFPS);\n\t\ts_surfaceFPS = TTF_RenderText_Blended(s_veraMonoFont, fps_string, text_color);\n\t\n\t\tSDL_DestroyTexture(s_textureFPS);\n\t\ts_textureFPS = SDL_CreateTextureFromSurface(renderer, s_surfaceFPS);\n\t}\n\n\tif(NULL != s_textureFPS)\n\t{\n\t\tdstRect.x = 0;\n\t\tdstRect.y = 0;\n\t\tdstRect.w = s_surfaceFPS->w;\n\t\tdstRect.h = s_surfaceFPS->h;\n\n \tSDL_RenderCopy(renderer, s_textureFPS, NULL, &dstRect);\n\t}\n#endif\n\n /* update screen */\n SDL_RenderPresent(renderer);\n\t\n}\n/*\nvoid ShowFrame(void* renderer)\n{\n\tUint32 startFrame;\n Uint32 endFrame;\n\tstatic Uint32 my_fps_print_timer = 0;\n\t\n\tstartFrame = SDL_GetTicks();\n\t\n\trender(renderer);\n\tendFrame = SDL_GetTicks();\n\t\n\tfpsthink();\n\tif( (my_fps_print_timer + 3000) < (endFrame))\n\t{\n\t\tSDL_Log(\"%f\\n\", framespersecond);\n\t\tmy_fps_print_timer = endFrame;\n\t}\n}\n*/\n//#define GROUND_VELOCITY_X -SCREEN_WIDTH / 5000.0f\n// Original flappy seems to move across at about 3 seconds on 768 pixels (iPad)\n//#define GROUND_VELOCITY_X -768 / 3000.0f\n#define GROUND_VELOCITY_X -768.0 / 2800.0\n#define BIRD_VELOCITY_X -1*GROUND_VELOCITY_X\n\n//#define BUSH_VELOCITY_X -SCREEN_WIDTH / 200000.0f\n#define BUSH_VELOCITY_X -SCREEN_WIDTH / 80000.0f\n#define CLOUD_VELOCITY_X -SCREEN_WIDTH / 20000.0f\n\n#define MAX_NUM_PIPES_REMAINDER SCREEN_WIDTH % PIPE_DISTANCE\n#if MAX_NUM_PIPES_REMAINDER\n\t#define MAX_NUM_PIPES SCREEN_WIDTH / PIPE_DISTANCE + 2\n#else\n\t#define MAX_NUM_PIPES SCREEN_WIDTH / PIPE_DISTANCE + 1\n#endif\nstatic void Flappy_InitializeCloudModelData(SDL_Texture* the_texture)\n{\n\tUint32 the_format;\n\tint the_access;\n\tint the_width;\n\tint the_height;\n\t\n\tSDL_zero(g_cloudModelData);\n\tSDL_QueryTexture(the_texture, &the_format, &the_access, &the_width, &the_height);\n\t\n\t// 960 / 5000 msec = .192\n\tg_cloudModelData.velocity.x = CLOUD_VELOCITY_X;\n\tg_cloudModelData.size.x = the_width;\n\tg_cloudModelData.size.y = the_height;\n}\n\nstatic void Flappy_UpdateCloudPositions(Uint32 delta_time, Uint32 base_time, Uint32 current_time)\n{\n\tUint32 diff_time = current_time - base_time;\n\tSint32 current_position;\n\tSint32 shift_factor;\n\n//\tg_cloudModelData.position.x = Flappy_lroundf((MyFloat)g_cloudModelData.position.x + g_cloudModelData.velocity.x * (MyFloat)delta_time);\n\tcurrent_position = Flappy_lroundf(g_cloudModelData.velocity.x * (MyFloat)diff_time);\n\n\tshift_factor = SDL_abs(current_position) / g_cloudModelData.size.x;\n\tg_cloudModelData.position.x = (g_cloudModelData.size.x * shift_factor) + current_position;\n\t/*\n\tif(g_cloudModelData.position.x < (0 - g_cloudModelData.size.x))\n\t{\n\t\tg_cloudModelData.position.x = g_cloudModelData.position.x + g_cloudModelData.size.x;\n\t}\n\t */\n}\n\n\n\n\nstatic void Flappy_InitializeGroundModelData(SDL_Texture* the_texture)\n{\n\t/*\n\tUint32 the_format;\n\tint the_access;\n\tint the_width;\n\tint the_height;\n\t*/\n\t\n\tSDL_zero(g_playerModelData);\n\tSDL_zero(g_groundModelData);\n//\tSDL_QueryTexture(the_texture, &the_format, &the_access, &the_width, &the_height);\n\t\n\t// 960 / 5000 msec = .192\n\tg_groundModelData.velocity.x = GROUND_VELOCITY_X;\n//\tg_groundModelData.velocity.x = -0.1f;\n\tg_groundModelData.size.x = SCREEN_WIDTH;\n\t/* The ground height in the image is actually really tall and we don't want all of it.\n\t So we can truncate the bottom part that we don't want.\n\t We'll take 1/5 of the image.\n\t */\n\tg_groundModelData.size.y = GROUND_HEIGHT;\n\t\n\n}\n\nstatic void Flappy_UpdateGroundPosition(Uint32 delta_time, Uint32 base_time, Uint32 current_time)\n{\n\t/*\n\tg_groundModelData.position.x = Flappy_lroundf((MyFloat)g_groundModelData.position.x + g_groundModelData.velocity.x * (MyFloat)delta_time);\n\tif(g_groundModelData.position.x < (0 - g_groundModelData.size.x))\n\t{\n\t\tg_groundModelData.position.x = g_groundModelData.position.x + g_groundModelData.size.x;\n\t}\n\t*/\n\t\n\tUint32 diff_time = current_time - base_time;\n\tSint32 current_position;\n\tSint32 shift_factor;\n\t\n\tcurrent_position = Flappy_lroundf(g_groundModelData.velocity.x * (MyFloat)diff_time);\n\t\n\tshift_factor = SDL_abs(current_position) / g_groundModelData.size.x;\n\tg_groundModelData.position.x = (g_groundModelData.size.x * shift_factor) + current_position;\n\n\t\n\tg_playerModelData.position.x = current_position;\n\t\n\t\n\t\n\t\n\t// physics\n\n\t{\n\t\t\n\t\t//cpFloat ground_height = (1024/16 * 1.9) * 768 / 1024;\n\t\t\n\tcurrent_position = Flappy_lroundf(g_birdModelData.velocity.x * (MyFloat)diff_time);\n\n\t\n\n\n\t\tcpBodySetPos(g_groundPhysicsData.body, cpv(current_position + SCREEN_WIDTH/2, GROUND_HEIGHT/2.0));\n//\t\tcpBodySetPos(g_groundPhysicsData.body, cpv(current_position + SCREEN_WIDTH/2, GROUND_HEIGHT));\n//\tcpBodySetPos(g_groundPhysicsData.body, cpv(current_position + SCREEN_WIDTH/2, 0));\n\t\tcpSpaceReindexShape(g_mainSpace, g_groundPhysicsData.shape);\n//\t\tSDL_Log(\"current_bird pos:%f, %d\\n\", g_birdModelData.birdBody->p.x, current_position);\n\t}\n}\n\n\nstatic void Flappy_InitializeBushModelData(SDL_Texture* the_texture)\n{\n\tUint32 the_format;\n\tint the_access;\n\tint the_width;\n\tint the_height;\n\t\n\tSDL_zero(g_bushModelData);\n\tSDL_QueryTexture(the_texture, &the_format, &the_access, &the_width, &the_height);\n\t\n\t// 960 / 5000 msec = .192\n\tg_bushModelData.velocity.x = BUSH_VELOCITY_X;\n\tg_bushModelData.size.x = the_width;\n\tg_bushModelData.size.y = the_height;\n}\n\nstatic void Flappy_UpdateBushPositions(Uint32 delta_time, Uint32 base_time, Uint32 current_time)\n{\n\tUint32 diff_time = current_time - base_time;\n\tSint32 current_position;\n\tSint32 shift_factor;\n\t\n\t//\tg_cloudModelData.position.x = Flappy_lroundf((MyFloat)g_cloudModelData.position.x + g_cloudModelData.velocity.x * (MyFloat)delta_time);\n\tcurrent_position = Flappy_lroundf(g_bushModelData.velocity.x * (MyFloat)diff_time);\n\t\n\tshift_factor = SDL_abs(current_position) / g_bushModelData.size.x;\n\tg_bushModelData.position.x = (g_bushModelData.size.x * shift_factor) + current_position;\n\t/*\n\t if(g_cloudModelData.position.x < (0 - g_cloudModelData.size.x))\n\t {\n\t g_cloudModelData.position.x = g_cloudModelData.position.x + g_cloudModelData.size.x;\n\t }\n\t */\n}\n\n\n\nstatic void Flappy_InitializePipeModelData(SDL_Texture* the_texture)\n{\n\tUint32 the_format;\n\tint the_access;\n\tint the_width;\n\tint the_height;\n\t\n\tSint32 i;\n\n\tSDL_zero(g_pipeTopModelData);\n\tSDL_zero(g_pipeBottomModelData);\n\tSDL_QueryTexture(the_texture, &the_format, &the_access, &the_width, &the_height);\n\t\n\t// 960 / 5000 msec = .192\n\tg_pipeTopModelData.velocity.x = GROUND_VELOCITY_X;\n\tg_pipeBottomModelData.velocity.x = GROUND_VELOCITY_X;\n\t//\tg_groundModelData.velocity.x = -0.1f;\n\t\n\tg_pipeTopModelData.size.x = the_width;\n\tg_pipeBottomModelData.size.x = the_width;\n//#define PIPE_WIDTH 170\n//#define PIPE_WIDTH 106\n//#define PIPE_WIDTH 140\n//#define PIPE_WIDTH 249\n\tg_pipeTopModelData.size.x = PIPE_WIDTH;\n\tg_pipeBottomModelData.size.x = PIPE_WIDTH;\n\n\t/* The ground height in the image is actually really tall and we don't want all of it.\n\t So we can truncate the bottom part that we don't want.\n\t We'll take 1/5 of the image.\n\t */\n\tg_pipeTopModelData.size.y = the_height;\n\tg_pipeBottomModelData.size.y = the_height;\n\t\n\t\n\t\n\tg_arrayOfPipes = (struct PipeModelData*)SDL_calloc(MAX_NUM_PIPES, sizeof(struct PipeModelData));\n\tg_circularQueueOfPipes = CircularQueueVoid_CreateQueue(MAX_NUM_PIPES);\n\tg_queueOfAvailablePipes = CircularQueueVoid_CreateQueue(MAX_NUM_PIPES);\n\tfor(i=0; iupperPhysicsBody = cpBodyNewStatic();\n\t\tcurrent_pipe->upperPhysicsShape = cpBoxShapeNew(current_pipe->upperPhysicsBody, the_width, SCREEN_HEIGHT);\n\t\tcurrent_pipe->lowerPhysicsBody = cpBodyNewStatic();\n\t\tcurrent_pipe->lowerPhysicsShape = cpBoxShapeNew(current_pipe->lowerPhysicsBody, the_width, SCREEN_HEIGHT);\n\n\t\tcurrent_pipe->upperPhysicsShape->collision_type = PIPE_COLLISION_TYPE;\n\t\tcurrent_pipe->lowerPhysicsShape->collision_type = PIPE_COLLISION_TYPE;\n\n\t\t\n\t\tcurrent_pipe->scoreSensorPhysicsBody = cpBodyNewStatic();\n//\t\tcurrent_pipe->scoreSensorPhysicsShape = cpBoxShapeNew(current_pipe->scoreSensorPhysicsBody, the_width/2, PIPE_HEIGHT_SEPARATION);\n\t\tcurrent_pipe->scoreSensorPhysicsShape = cpBoxShapeNew(current_pipe->scoreSensorPhysicsBody, the_width/2, SCREEN_HEIGHT);\n\n\n\t\t\n\t\tcurrent_pipe->scoreSensorPhysicsShape->sensor = cpTrue;\n current_pipe->scoreSensorPhysicsShape->collision_type = SCORE_SENSOR_TYPE;\n\t\t\n\t\t\n\t\t// don't add to space to make it a \"rogue\" body (intended to be controlled manually)\n\t\t//\tcpSpaceAddShape(g_mainSpace, g_groundPhysicsData.shape);\n\t\t//cpSpaceAddShape(g_mainSpace, g_groundPhysicsData.shape);\n\t\t\n\n\t\t\n\t\t\t\t\n\t\t\n\t\tCircularQueueVoid_PushBack(g_queueOfAvailablePipes, &g_arrayOfPipes[i]);\n\t}\n}\n\nstatic void Flappy_UpdatePipePositions(Uint32 delta_time, Uint32 base_time, Uint32 current_time)\n{\n\t/*\n\t g_groundModelData.position.x = Flappy_lroundf((MyFloat)g_groundModelData.position.x + g_groundModelData.velocity.x * (MyFloat)delta_time);\n\t if(g_groundModelData.position.x < (0 - g_groundModelData.size.x))\n\t {\n\t g_groundModelData.position.x = g_groundModelData.position.x + g_groundModelData.size.x;\n\t }\n\t */\n\t\n\tUint32 diff_time = current_time - base_time;\n\tSint32 current_position;\n\tSint32 shift_factor;\n\tSint32 i;\n\t\n\tSint32 new_offscreen_pipe_position_x;\n\tSint32 left_most_pipe_position_x;\n\tSint32 right_most_pipe_position_x;\n\n\tstruct PipeModelData* the_pipe = NULL;\n\n\t\n\tif(g_birdModelData.isPrelaunch)\n\t{\n\t\treturn;\n\t}\n//\telse if(current_time < g_birdModelData.birdLaunchStartTime + PIPE_START_TIME_DELAY)\n else if(g_gameState < GAMESTATE_MAIN_GAME_ACTIVE)\n\t{\n\t\treturn;\n\t}\n\telse if(g_birdModelData.isDead)\n\t{\n\t\treturn;\n\t}\n\t\n\t// camera position\n//\tcurrent_position = Flappy_lroundf(g_pipeTopModelData.velocity.x * (MyFloat)diff_time);\n\tcurrent_position = -1 * Flappy_lroundf(g_pipeTopModelData.velocity.x * (MyFloat)diff_time);\n\t\n//\tshift_factor = SDL_abs(current_position) / g_pipeTopModelData.size.x;\n\tshift_factor = SDL_abs(current_position) / PIPE_DISTANCE;\n\tg_pipeTopModelData.position.x = (PIPE_DISTANCE * shift_factor) + current_position;\n\tg_pipeBottomModelData.position.x = (PIPE_DISTANCE * shift_factor) + current_position;\n\t\n\tleft_most_pipe_position_x = (PIPE_DISTANCE * shift_factor) + current_position;\n\t\n\tg_playerModelData.position.x = current_position;\n\t\n\t\n\n\n\n\t/* update all pipe positions in queue */\n\t/* To avoid drift/rounding-errors due to imperfect frame rate intervals,\n\t\tI am avoiding arithmetic based on this previous position.\n\t\tInstead, I am trying to use a formula, which will guarantee the perfect placement based on the current time.\n\t\tBut the trick we need to contend with is how to determine which pipe in the queue corresponds with the correct pipe multiple.\n\t\tOne way is to do the (bad) arthimetic with delta_time to figure out which 'slot' it is in.\n\t\tThen recompute the real position based on that slot.\n\t \n\t*/\n\tfor(i=0; iviewPositionX = current_pipe->realPositionX - current_position;\n\n\t\t/*\n\t\t\n\t\t//\t\t\tdst_rect.x = g_pipeTopModelData.position.x + PIPE_DISTANCE * i;\n\t\t\n\t\tSint32 approx_position_x = Flappy_lroundf((MyFloat)current_pipe->position.x + g_groundModelData.velocity.x * (MyFloat)delta_time);\n\n\t\tSint32 slot_multiple = ((approx_position_x - current_position) / PIPE_DISTANCE ) - shift_factor;\n\t\t\n//\t\tcurrent_pipe->position.x = (PIPE_DISTANCE * (shift_factor+i)) + current_position;\n\t\tcurrent_pipe->position.x = (PIPE_DISTANCE * (shift_factor+slot_multiple)) + current_position;\n\t\t\n\t\tSDL_Log(\"\\ni:%d, approx:%d, current:%d, slot:%d, x:%d\\n\", i, approx_position_x, current_position, slot_multiple, current_pipe->position.x);\n\t\t */\n//\t\tSDL_Log(\"\\ni:%d, real:%d, view:%d, slot:%d\\n\", i, current_pipe->realPosition.x, current_pipe->viewPosition, current_pipe->intervalScalar);\n\n\t}\n\t\n\t\n\t/* If an old pipe has fallen off the screen, we need to remove it. */\n\tthe_pipe = CircularQueueVoid_Front(g_circularQueueOfPipes);\n\t\n\tif((NULL != the_pipe) && ((the_pipe->realPositionX + the_pipe->size.x) < current_position))\n\t{\n//\t\tSDL_Log(\"removed pipe, x:%d\\n\", the_pipe->realPositionX);\n\n\t\tcpSpaceRemoveShape(g_mainSpace, the_pipe->scoreSensorPhysicsShape);\n\t\tcpSpaceRemoveShape(g_mainSpace, the_pipe->lowerPhysicsShape);\n\t\tcpSpaceRemoveShape(g_mainSpace, the_pipe->upperPhysicsShape);\n\n\t\tfor(i=0; irealPosition.x, current_pipe->viewPosition, current_pipe->intervalScalar);\n\t\t}\n\t\tCircularQueueVoid_PopFront(g_circularQueueOfPipes);\n\t\tfor(i=0; irealPosition.x, current_pipe->viewPosition, current_pipe->intervalScalar);\n\t\t}\n\t\t\n\t\tCircularQueueVoid_PushBack(g_queueOfAvailablePipes, the_pipe);\n\t\t\n\t}\n\t\n\t/* If a new pipe will be coming onto the screen, we need to create it. */\n\t/* Check the queue to see if the pipe has already been created.\n\t It should be at the end of the queue and will have the designated x position.\n\t */\n\t//shift_factor = SDL_abs(current_position) / g_bushModelData.size.x;\n\t//g_bushModelData.position.x = (g_bushModelData.size.x * shift_factor) + current_position;\n\t\n//\tright_most_pipe_position_x = left_most_pipe_position_x + PIPE_DISTANCE * MAX_NUM_PIPES;\n//\tright_most_pipe_position_x = (PIPE_DISTANCE * (MAX_NUM_PIPES)) + current_position;\n\tright_most_pipe_position_x = (PIPE_DISTANCE * (shift_factor+MAX_NUM_PIPES-1)) + current_position;\n\t//g_bushModelData.position.x = (g_bushModelData.size.x * shift_factor) + current_position;\n\t\n\tright_most_pipe_position_x = current_position + SCREEN_WIDTH + PIPE_WIDTH;\n\tSint32 new_pipe_interval_scalar = right_most_pipe_position_x / PIPE_DISTANCE;\n\t\n\t\n\tthe_pipe = (struct PipeModelData*)CircularQueueVoid_Back(g_circularQueueOfPipes);\n\tif((NULL == the_pipe) || (the_pipe->intervalScalar != new_pipe_interval_scalar))\n\t{\n\t\tSint32 real_x_pos = PIPE_DISTANCE * new_pipe_interval_scalar;\n\t\t\n\t\t\n\t\tif((real_x_pos) >= (current_position + SCREEN_WIDTH))\n\t\t{\n\t\t\t\n\t\t\tthe_pipe = CircularQueueVoid_Front(g_queueOfAvailablePipes);\n\t\t\tSDL_assert(NULL != the_pipe);\n\t\t\tif(NULL != the_pipe)\n\t\t\t{\n\t\t\t\t/* \n\t\t\t\t\thttp://c-faq.com/lib/randrange.html\n\t\t\t\t\tfor range [M, N]:\n\t\t\t\t\tM + rand() / (RAND_MAX / (N - M + 1) + 1)\n\t\t\t\t */\n\t\t\t\tint M = MIN_PIPE_HEIGHT;\n\t\t\t\tint N = SCREEN_HEIGHT - GROUND_HEIGHT - PIPE_HEIGHT_SEPARATION - MIN_PIPE_HEIGHT;\n\t\t\t\tint random_pipe_height = M + rand() / (RAND_MAX / (N - M + 1) + 1);\n\t//\t\t\tint random_pipe_height = MIN_PIPE_HEIGHT;\n\n\t\t\t\t\n\t\t\t\tCircularQueueVoid_PopFront(g_queueOfAvailablePipes);\n\t\t\t\t\n\t\t\t\tthe_pipe->realPositionX = PIPE_DISTANCE * new_pipe_interval_scalar;\n\t\t\t\tthe_pipe->intervalScalar = new_pipe_interval_scalar;\n\t\t\t\tthe_pipe->viewPositionX = the_pipe->realPositionX - current_position;\n\t\t\t\t\n\t\t\t\tthe_pipe->pipeHeight = random_pipe_height;\n\t\t\t\t/* Remember that SDL inverts the Y. */\n\n\t\t\t\tthe_pipe->lowerRealPositionY = GROUND_HEIGHT;\n\t\t\t\tthe_pipe->upperRealPositionY = GROUND_HEIGHT + random_pipe_height + PIPE_HEIGHT_SEPARATION;\n\n\n\t\t\t\tthe_pipe->lowerViewPositionY = Flappy_InvertY(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t the_pipe->lowerRealPositionY\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t )\n\t\t\t\t- the_pipe->pipeHeight\n\t\t\t\t\n\t\t\t\t;\n\t//\t\t\t\t\t\t\t\t\t\t\t\t\t\t the_pipe->size.y;\n\t\t\t\tthe_pipe->size.x = g_pipeBottomModelData.size.x;\n\n\n\t\t\t\tcpBodySetPos(the_pipe->lowerPhysicsBody, cpv(the_pipe->realPositionX, the_pipe->lowerRealPositionY + the_pipe->pipeHeight - SCREEN_HEIGHT/2));\n\t//\t\t\tcpBodySetPos(the_pipe->lowerPhysicsBody, cpv(the_pipe->realPositionX - the_pipe->size.x / 2, the_pipe->lowerRealPositionY + the_pipe->pipeHeight/2));\n\t\t//\t\tcpBodySetPos(the_pipe->upperPhysicsBody, cpv(the_pipe->realPositionX - the_pipe->size.x / 2, the_pipe->upperRealPositionY + (SCREEN_HEIGHT - the_pipe->pipeHeight - PIPE_HEIGHT_SEPARATION - GROUND_HEIGHT)/2));\n\t\t\t\tcpBodySetPos(the_pipe->upperPhysicsBody, cpv(the_pipe->realPositionX, the_pipe->upperRealPositionY + (SCREEN_HEIGHT/2)));\n\n\t//\t\t\tcpBodySetPos(the_pipe->scoreSensorPhysicsBody, cpv(the_pipe->realPositionX + the_pipe->size.x / 4, GROUND_HEIGHT+ random_pipe_height + PIPE_HEIGHT_SEPARATION - PIPE_HEIGHT_SEPARATION/2));\n//\t\t\t\tcpBodySetPos(the_pipe->scoreSensorPhysicsBody, cpv(the_pipe->realPositionX, GROUND_HEIGHT+ random_pipe_height + PIPE_HEIGHT_SEPARATION - PIPE_HEIGHT_SEPARATION/2));\n\t\t\t\tcpBodySetPos(the_pipe->scoreSensorPhysicsBody, cpv(the_pipe->realPositionX + PIPE_WIDTH/4, SCREEN_HEIGHT/2));\n\n\t\t\t//\tsrc_rect.h = SCREEN_HEIGHT - current_pipe->pipeHeight - PIPE_HEIGHT_SEPARATION - GROUND_HEIGHT;\n\n\n\t\t\t\tcpSpaceAddShape(g_mainSpace, the_pipe->upperPhysicsShape);\n\t\t\t\tcpSpaceAddShape(g_mainSpace, the_pipe->lowerPhysicsShape);\n\t\t\t\tcpSpaceAddShape(g_mainSpace, the_pipe->scoreSensorPhysicsShape);\n\n//\t\t\t\tSDL_Log(\"added pipe, x:%d\\n\", the_pipe->realPositionX);\n\n\t\t\t\tCircularQueueVoid_PushBack(g_circularQueueOfPipes, the_pipe);\n\t\t\t}\n\t\t}\n\t}\n\n\t\n\t\n\t\n\t\n#if 0\n\t\n\tSDL_Rect src_rect = {0, 0, 106, 672};\n\t\n\tSDL_Rect dst_rect = {g_pipeTopModelData.position.x, 0, 106, 672};\n\t\n\t\n\t/* The texture does not fill the whole width of the screen.\n\t So draw it multiple times, shifted over\n\t until we fill the entire length of the screen.\n\t */\n\tSint32 number_of_times_to_repeat_draw;\n\tSint32 remainder;\n\tSint32 i;\n\t\n\tnumber_of_times_to_repeat_draw = (SCREEN_WIDTH / PIPE_DISTANCE) + 1;\n\tremainder = SCREEN_WIDTH % PIPE_DISTANCE;\n\tif(remainder > 0)\n\t{\n\t\tnumber_of_times_to_repeat_draw = number_of_times_to_repeat_draw + 1;\n\t}\n\t\n\tfor(i=0; ip.y = pos_y;\n\t\n\tcpBodySetPos(g_birdModelData.birdBody, cpv( g_birdModelData.position.x, pos_y + (g_birdModelData.size.y / 2)));\n\n\t\n\t{\n\t\tg_birdModelData.animationDuration = BIRD_FLAP_ANIMATION_DURATION_FOR_PRELAUNCH;\n\t\tMyFloat linear_interp;\n\t\tUint32 mod_time = (current_time - g_birdModelData.animationStartTime) % g_birdModelData.animationDuration\n;\n\t\tUint32 texture_index;\n\t\t\n\t\tlinear_interp = Flappy_ComputeLinearInterpolation(mod_time, g_birdModelData.animationStartTime, g_birdModelData.animationStartTime+g_birdModelData.animationDuration);\n\t\ttexture_index = Flappy_lroundf(linear_interp * (MyFloat)NUMBER_OF_BIRD_FRAMES);\n\t\tif(texture_index >= NUMBER_OF_BIRD_FRAMES)\n\t\t{\n\t\t\ttexture_index = 0;\n\t\t}\n\t\tg_birdModelData.currentTexture = g_gameTextures.bird[texture_index];\n\t\t\n\t}\n\t\n}\n\nvoid Flappy_UpdateBirdPositionForGame(Uint32 delta_time, Uint32 base_time, Uint32 current_time)\n{\n\tUint32 diff_time = current_time - base_time;\n\tSint32 current_position;\n\tSint32 shift_factor;\n\tcpFloat bird_angle;\n\n\tg_birdModelData.velocity.x = BIRD_VELOCITY_X;\n\n\t\n\tif(g_birdModelData.isDead)\n\t{\n\t\tcurrent_position = g_gameInstanceData.distanceTraveled;\n\t}\n\telse\n\t{\n\t\t//\tg_cloudModelData.position.x = Flappy_lroundf((MyFloat)g_cloudModelData.position.x + g_cloudModelData.velocity.x * (MyFloat)delta_time);\n\t\tcurrent_position = Flappy_lroundf(g_birdModelData.velocity.x * (MyFloat)diff_time);\n\t\tg_gameInstanceData.distanceTraveled = current_position;\n\t\t\n\t}\n\t\n\t\n//\tshift_factor = SDL_abs(current_position) / g_cloudModelData.size.x;\n//\tg_birdModelData.position.x = SCREEN_WIDTH / 3;\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\tg_birdModelData.position.y = Flappy_InvertY(\n\t\tFlappy_lroundf(\n\t\t\tg_birdModelData.birdBody->p.y\n\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t+ \t\t(g_birdModelData.size.y / 2)\n\n\t);\n\n//\tSDL_Log(\"g_birdModelData.birdBody->p.y=%f, g_birdModelData.position.y=%d\", g_birdModelData.birdBody->p.y, g_birdModelData.position.y);\n\t// Trick to prevent bird from being drawn too far into the ground when physics collision penetrates too far.\n\t{\n\t\t\n\t\tint radius = ((cpCircleShape*)(g_birdModelData.birdShape))->r;\n\t\t// we need 2*radius because SDL draws from the edge of the sprite, not the center.\n\t\tint ground_threshold = SCREEN_HEIGHT - GROUND_HEIGHT - (2*radius); // g_birdModelData.size.y\n\t\t// should be 640\n\t\t\t\n\t\tif(g_birdModelData.position.y > ground_threshold)\n\t\t{\n\t\t\tg_birdModelData.position.y = ground_threshold;\n\t\t}\n\t}\n//\tcpBodySetPos(g_birdModelData.birdBody, cpv( current_position + (SCREEN_WIDTH / 3) - (g_birdModelData.size.x / 2), g_birdModelData.birdBody->p.y));\n\tcpBodySetPos(g_birdModelData.birdBody, cpv( current_position + (SCREEN_WIDTH / 3), g_birdModelData.birdBody->p.y));\n\tcpBodySetVel(g_birdModelData.birdBody, cpv(g_birdModelData.velocity.x, g_birdModelData.birdBody->v.y));\n\n\tbird_angle = cpBodyGetAngle(g_birdModelData.birdBody);\n\tif((bird_angle < -M_PI_2/4) && (bird_angle > -M_PI_2))\n\t{\n\t\tcpBodySetAngVel(g_birdModelData.birdBody, -5);\n\t\t/* Chipmunk API says to reindex after changing the angle */\n\t\tcpSpaceReindexShapesForBody(g_mainSpace, g_birdModelData.birdBody);\n\t\tg_birdModelData.isAnimatingSprite = SDL_FALSE;\n\t}\n\telse if(bird_angle <= -M_PI_2)\n\t{\n\t\tcpBodySetAngVel(g_birdModelData.birdBody, 0);\n\t\tcpBodySetAngle(g_birdModelData.birdBody, -M_PI_2);\n\n\t\t/* Chipmunk API says to reindex after changing the angle */\n\t\tcpSpaceReindexShapesForBody(g_mainSpace, g_birdModelData.birdBody);\n\n\t\t/* When in a nose dive, texture animation is off. */\n\t\tg_birdModelData.isAnimatingSprite = SDL_FALSE;\n\t}\n\telse\n\t{\n\t\tg_birdModelData.isAnimatingSprite = SDL_TRUE;\n\t}\n\t\n\t\n\tif(g_birdModelData.isAnimatingSprite)\n\t{\n\t\tg_birdModelData.animationDuration = BIRD_FLAP_ANIMATION_DURATION;\n\n\t\tMyFloat linear_interp;\n\t\tUint32 mod_time = (current_time - g_birdModelData.animationStartTime) % g_birdModelData.animationDuration;\n\t\tUint32 texture_index;\n\t\t\n\t\tlinear_interp = Flappy_ComputeLinearInterpolation(mod_time, g_birdModelData.animationStartTime, g_birdModelData.animationStartTime+g_birdModelData.animationDuration);\n\t\ttexture_index = Flappy_lroundf(linear_interp * (MyFloat)NUMBER_OF_BIRD_FRAMES);\n\t\tif(texture_index >= NUMBER_OF_BIRD_FRAMES)\n\t\t{\n\t\t\ttexture_index = 0;\n\t\t}\n\t\tg_birdModelData.currentTexture = g_gameTextures.bird[texture_index];\n\n\t}\n\telse\n\t{\n\t\t// The middle frame is the one with wings in the neutral position\n\t\tg_birdModelData.currentTexture = g_gameTextures.bird[1];\n\t}\n\t\n\t\n\tif(SDL_TRUE == g_birdModelData.isReadyToPlayFallingSound)\n\t{\n\t\tALmixer_PlayChannel(-1, g_gameSounds.fall, 0);\n\t\tg_birdModelData.isReadyToPlayFallingSound = SDL_FALSE;\n\t\tg_birdModelData.isFalling = SDL_FALSE;\n\t}\n\n\t\n\t\n//\tSDL_Log(\"current_bird pos:%f\\n\", g_birdModelData.birdBody->p.x);\n}\n\nvoid Flappy_UpdateBirdPosition(Uint32 delta_time, Uint32 base_time, Uint32 current_time)\n{\n//\tif(g_birdModelData.isPrelaunch)\n\tif((g_gameState >= GAMESTATE_TITLE_SCREEN) && (g_gameState <= GAMESTATE_FADE_OUT_TITLE_SCREEN))\n\t{\n\t\tFlappy_UpdateBirdPositionForPrelaunch(delta_time, base_time, current_time, SCREEN_WIDTH/2, (SCREEN_HEIGHT/3) + 32);\n\t}\n\telse if((g_gameState >= GAMESTATE_LOADING_NEW_GAME_AND_FADE_IN) && (g_gameState <= GAMESTATE_BIRD_PRELAUNCH))\n\t{\n\t\tFlappy_UpdateBirdPositionForPrelaunch(delta_time, base_time, current_time, SCREEN_WIDTH/3, SCREEN_HEIGHT/2);\n\t}\n\telse\n\t{\n\t\tFlappy_UpdateBirdPositionForGame(delta_time, base_time, current_time);\n\n\t}\n}\n\nSint32 Flappy_DetermineCurrentBirdTimePosition(delta_time, base_time, current_time)\n{\n\tif(g_birdModelData.isDead)\n\t{\n//\t\treturn g_gameInstanceData.distanceTraveled;\n\t\treturn g_gameInstanceData.diedAtTime;\n\t}\n\telse\n\t{\n\t\t/*\n\t\tUint32 diff_time = current_time - base_time;\n\t\tSint32 current_position;\n\t\t\n\t\t//\tg_cloudModelData.position.x = Flappy_lroundf((MyFloat)g_cloudModelData.position.x + g_cloudModelData.velocity.x * (MyFloat)delta_time);\n\t\tcurrent_position = Flappy_lroundf(BIRD_VELOCITY_X * (MyFloat)diff_time);\n\t\treturn current_position;\n\t\t */\n\t\treturn current_time;\n\t}\n}\n\n\n\nSDL_Texture* Flappy_CreateGameOverTexture(void);\n\nstatic void Flappy_InitializeGameOverDisplayData(SDL_Texture* the_texture)\n{\n\tUint32 the_format;\n\tint the_access;\n\tint the_width;\n\tint the_height;\n\t\n\tSDL_zero(g_gameOverDisplayData);\n\tthe_texture = Flappy_CreateGameOverTexture();\n\t\n\tSDL_QueryTexture(the_texture, &the_format, &the_access, &the_width, &the_height);\n\tg_gameOverDisplayData.textureWidth = the_width;\n\tg_gameOverDisplayData.textureHeight = the_height;\n\t\n\t// Midpoint of the screen, then subtract the midpoint of the texture\n\tg_gameOverDisplayData.dstRect.x = (SCREEN_WIDTH/2) - (the_width/2);\n\t// This isn't exactly dead center because Game Over and buttons need to be on screen\n//\tg_gameOverDisplayData.dstRect.y = (SCREEN_HEIGHT/3) - (the_height/2);\n//\tg_gameOverDisplayData.dstRect.y = (SCREEN_HEIGHT/3) - (the_height/2);\n\tg_gameOverDisplayData.dstRect.w = the_width;\n\tg_gameOverDisplayData.dstRect.h = the_height;\n\t\n\t\n}\n\nstatic void Flappy_UpdateGameOverDisplayData(Uint32 delta_time, Uint32 base_time, Uint32 current_time)\n{\n\t\n\tif( ! g_birdModelData.isGameOver)\n\t{\n\t\treturn;\n\t}\n\t\n\t\n\tif(GAMESTATE_SWOOPING_IN_GAME_OVER == g_gameState)\n\t{\n#define GAME_OVER_BOUNCE_HEIGHT 40\n\t\tMyFloat linear_interp;\n\t\tint displayed_score;\n\t\tint lower_target_y = (SCREEN_HEIGHT / 4) - (g_gameOverDisplayData.textureHeight/2) - 40;\n\t\tint upper_target_y = lower_target_y - GAME_OVER_BOUNCE_HEIGHT;\n\t\t\n#define SWEEP_IN_GAME_OVER_DURATION 200\n#define SWEEP_IN_GAME_OVER_DELAY_BEFORE_NEXT_STATE 1000\n\n\t\tif(current_time < (g_gameOverDisplayData.sweepInStartTime + (SWEEP_IN_GAME_OVER_DURATION/2)))\n\t\t{\n\t\t\tlinear_interp = Flappy_ComputeLinearInterpolation(current_time, g_gameOverDisplayData.sweepInStartTime, g_gameOverDisplayData.sweepInStartTime + (SWEEP_IN_GAME_OVER_DURATION/2));\n\t\t\t// X = (1-t)x0 + tx1\n\t\t\tg_gameOverDisplayData.dstRect.y = ((1.0-linear_interp) * lower_target_y) + (linear_interp * (MyFloat)(upper_target_y));\n\n\t\t}\n\t\telse if(current_time < (g_gameOverDisplayData.sweepInStartTime + (SWEEP_IN_GAME_OVER_DURATION)))\n\t\t{\n\t\t\tlinear_interp = Flappy_ComputeLinearInterpolation(current_time, g_gameOverDisplayData.sweepInStartTime + (SWEEP_IN_GAME_OVER_DURATION/2), g_gameOverDisplayData.sweepInStartTime + (SWEEP_IN_GAME_OVER_DURATION));\n\t\t\t// X = (1-t)x0 + tx1\n\t\t\tg_gameOverDisplayData.dstRect.y = ((1.0-linear_interp) * upper_target_y) + (linear_interp * (MyFloat)(lower_target_y));\n\t\t\t\t\t\n\t\t}\n\t\telse\n\t\t{\n\t\t\tg_gameOverDisplayData.dstRect.y = lower_target_y;\n\t\t\tif(current_time > (g_gameOverDisplayData.sweepInStartTime + SWEEP_IN_GAME_OVER_DURATION + SWEEP_IN_GAME_OVER_DELAY_BEFORE_NEXT_STATE))\n\t\t\t{\n\t\t\t\tg_gameState = GAMESTATE_SWOOPING_IN_MEDAL_DISPLAY;\n\t\t\t\tALmixer_PlayChannel(-1, g_gameSounds.swoosh, 0);\n\t\t\t\tg_medalBackgroundData.sweepInStartTime = TimeTicker_GetTime(g_gameClock);\n\t\t\t}\n\n\t\t}\n\t\t\n\t\t\n\t}\n\t\n}\n\n\nstatic void Flappy_InitializeMedalBackgroundData(SDL_Texture* the_texture)\n{\n\tUint32 the_format;\n\tint the_access;\n\tint the_width;\n\tint the_height;\n\t\n\tSDL_zero(g_medalBackgroundData);\n\tSDL_QueryTexture(the_texture, &the_format, &the_access, &the_width, &the_height);\n\t\n\t// Midpoint of the screen, then subtract the midpoint of the texture\n\tg_medalBackgroundData.dstRect.x = (SCREEN_WIDTH/2) - (the_width/2);\n\t// This isn't exactly dead center because Game Over and buttons need to be on screen\n\tg_medalBackgroundData.dstRect.y = (SCREEN_HEIGHT/2) - (the_height/2);\n\tg_medalBackgroundData.dstRect.w = the_width;\n\t\n\tg_medalBackgroundData.dstRect.h = the_height;\n\t\n\t\n\t/* Create texture for render-to-texture */\n g_gameTextures.medalSceneRenderToTexture = SDL_CreateTexture(g_mainRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, the_width, the_height);\n\tSDL_assert(NULL != g_gameTextures.medalSceneRenderToTexture);\n\tSDL_SetTextureBlendMode(g_gameTextures.medalSceneRenderToTexture, SDL_BLENDMODE_BLEND);\n\t\n\tg_textTextureData.scoreLabelTextTexture = NULL;\n\tg_textTextureData.bestLabelTextTexture = NULL;\n\tg_textTextureData.newHighScoreLabelTextTexture = NULL;\n\tg_textTextureData.bestNumberTextTexture = NULL;\n\tg_textTextureData.bestNumberTextTexture = NULL;\n\tg_textTextureData.bestNumberTextTexture = NULL;\n\tg_textTextureData.bestNumberTextTexture = NULL;\n\t\n#if 1\n\t{\n#define MAX_MEDAL_STRING_LENGTH 16\n\t\tchar the_string[MAX_MEDAL_STRING_LENGTH];\n\t\tSDL_Color white_text_color = { 255, 255, 255, 255 };\n\t\t//\tSDL_Color black_text_color = { 0, 0, 0, 255 };\n\t\tSDL_Color orange_text_color = { 220, 120, 0, 255 };\n\t\tSDL_Surface* text_surface = NULL;\n\t\t\n\t\t\n\t\tSDL_strlcpy(the_string, \"SCORE\", MAX_MEDAL_STRING_LENGTH);\n\t\ttext_surface = TTF_RenderText_Blended(g_textTextureData.fontForMedalLabels, the_string, orange_text_color);\n\t\tg_textTextureData.scoreLabelTextTexture = SDL_CreateTextureFromSurface(g_mainRenderer, text_surface);\n\t\t\n\t\tSDL_strlcpy(the_string, \"BEST\", MAX_MEDAL_STRING_LENGTH);\n\t\ttext_surface = TTF_RenderText_Blended(g_textTextureData.fontForMedalLabels, the_string, orange_text_color);\n\t\tg_textTextureData.bestLabelTextTexture = SDL_CreateTextureFromSurface(g_mainRenderer, text_surface);\n\t\t\n\t\t\n\t\t\n\t\tSDL_strlcpy(the_string, \"NEW\", MAX_MEDAL_STRING_LENGTH);\n\t\ttext_surface = TTF_RenderText_Blended(g_textTextureData.fontForMedalLabels, the_string, white_text_color);\n\t\tg_textTextureData.newHighScoreLabelTextTexture = SDL_CreateTextureFromSurface(g_mainRenderer, text_surface);\n\t}\n#endif\n}\n\n\n\nstatic void Flappy_UpdateMedalBackgroundData(Uint32 delta_time, Uint32 base_time, Uint32 current_time)\n{\n\t\n\tif( ! g_birdModelData.isGameOver)\n\t{\n\t\treturn;\n\t}\n\n\t\n\tif((g_gameState >= GAMESTATE_SWOOPING_IN_MEDAL_DISPLAY) && (g_gameState <= GAMESTATE_TALLYING_SCORE))\n\t{\n\t\tMyFloat linear_interp;\n\t\tint displayed_score;\n\t\t\n#define SWEEP_IN_MEDAL_PANEL_DURATION 300\n\t\tlinear_interp = Flappy_ComputeLinearInterpolation(current_time, g_medalBackgroundData.sweepInStartTime, g_medalBackgroundData.sweepInStartTime + SWEEP_IN_MEDAL_PANEL_DURATION);\n\n\t\t\n\t\tint the_height = 250;\n\t\t// X = (1-t)x0 + tx1\n\t\tg_medalBackgroundData.dstRect.y = ((1.0-linear_interp) * (MyFloat)SCREEN_HEIGHT) + (linear_interp * (MyFloat)((SCREEN_HEIGHT/2) - (the_height/2)));\n\t\t\n\t\t/*\n\t\tif(linear_interp >= 1.0)\n\t\t{\n\t\t\tg_gameState = GAMESTATE_SWOOPED_IN_MEDAL_DISPLAY;\n\t\t}\n\t\t */\n\t\tif((GAMESTATE_SWOOPING_IN_MEDAL_DISPLAY == g_gameState) && (current_time >= g_medalBackgroundData.sweepInStartTime + SWEEP_IN_MEDAL_PANEL_DURATION))\n\t\t{\n\t\t\tg_gameState = GAMESTATE_TALLYING_SCORE;\n\t\t\tg_gameStateCurrentPhaseStartTime = TimeTicker_GetTime(g_gameClock);\n\t\t}\n\t\t\n\t\tFlappy_SaveHighScoreToStorageIfNeeded();\n\n\t}\n\t\n\t\n\t{\n\t\t\n\t\tSDL_SetRenderTarget(g_mainRenderer, g_gameTextures.medalSceneRenderToTexture);\n\t\t\n\t\t// Clear screen\n\t\tSDL_SetRenderDrawColor(g_mainRenderer, 0, 0, 0, 0 );\n\t\tSDL_RenderClear(g_mainRenderer );\n\t\t\n\t\t{\n\t\t\tSDL_Rect dst_rect = {0, 0, g_medalBackgroundData.dstRect.w, g_medalBackgroundData.dstRect.h};\n\t\t\tSDL_RenderCopy(g_mainRenderer, g_gameTextures.medalBackground, NULL, NULL);\n\t\t}\n\t\t\n\t\t\n\t\t{\n#if 0\n\t\t/* Max score in Flappy Bird is 9999 */\n#define MAX_MEDAL_STRING_LENGTH 1024\n\t\tchar the_string[MAX_MEDAL_STRING_LENGTH];\n\t\tSDL_Color white_text_color = { 255, 255, 255, 255 };\n\t\tSDL_Color black_text_color = { 0, 0, 0, 255 };\n\t\tSDL_Color orange_text_color = { 220, 120, 0, 255 };\n\t\tSDL_Surface* text_surface = NULL;\n\t\t\n\t\tSDL_DestroyTexture(g_textTextureData.scoreLabelTextTexture);\n\t\t\n\t\tSDL_strlcpy(the_string, \"SCORE\", MAX_MEDAL_STRING_LENGTH);\n\t\ttext_surface = TTF_RenderText_Blended(g_textTextureData.fontForMedalLabels, the_string, orange_text_color);\n\t\tg_textTextureData.scoreLabelTextTexture = SDL_CreateTextureFromSurface(g_mainRenderer, text_surface);\n\t\t\n\t\t//\tSDL_Log(\"text surface w,h: %d, %d\", text_surface->w, text_surface->h);\n\t\t\n\t\t\n\t\tSDL_FreeSurface(text_surface);\n\t\t\n\t\ttext_surface = TTF_RenderText_Blended(s_retroFontForMainScore, the_string, black_text_color);\n\t\tg_currentScoreTextShadowTexture = SDL_CreateTextureFromSurface(g_mainRenderer, text_surface);\n\t\tSDL_FreeSurface(text_surface);\n#endif\n\t\t\tUint32 the_format;\n\t\t\tint the_access;\n\t\t\tint the_width;\n\t\t\tint the_height;\n\t\t\tSDL_QueryTexture(g_textTextureData.scoreLabelTextTexture, &the_format, &the_access, &the_width, &the_height);\n#define TOP_MARGIN 16\n#define RIGHT_MARGIN 60\n\t\t\t/* Draw \"SCORE\" label */\n\n\t\t\t{\n//\t\t\tSDL_Rect dst_rect = {g_medalBackgroundData.dstRect.w - the_width - RIGHT_MARGIN, 10, g_medalBackgroundData.dstRect.w, g_medalBackgroundData.dstRect.h};\n\t\t\tSDL_Rect dst_rect = {g_medalBackgroundData.dstRect.w - the_width - RIGHT_MARGIN, TOP_MARGIN, the_width, the_height};\n\t\t\tSDL_RenderCopy(g_mainRenderer, g_textTextureData.scoreLabelTextTexture, NULL, &dst_rect);\n\t\t\t}\n\n\t\t\t\n\t\t\t{\n\t\t\t\tint running_width;\n\t\t\t\t/* Draw \"BEST\" label */\n\t\t\t\t{\n\t\t\t\tSDL_QueryTexture(g_textTextureData.bestLabelTextTexture, &the_format, &the_access, &the_width, &the_height);\n\n\t\t\t\t//\t\t\tSDL_Rect dst_rect = {g_medalBackgroundData.dstRect.w - the_width - RIGHT_MARGIN, 10, g_medalBackgroundData.dstRect.w, g_medalBackgroundData.dstRect.h};\n\t\t\t\tSDL_Rect dst_rect = {g_medalBackgroundData.dstRect.w - the_width - RIGHT_MARGIN, TOP_MARGIN + 116, the_width, the_height};\n\t\t\t\tSDL_RenderCopy(g_mainRenderer, g_textTextureData.bestLabelTextTexture, NULL, &dst_rect);\n\t\t\t\t\trunning_width = dst_rect.w;\n\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* Draw \"NEW\" label */\n\t\t\t\tif( ((g_gameState >= GAMESTATE_GAME_OVER_WAITING_FOR_USER_ACTION) && (g_gameState <= GAMESTATE_FADE_OUT_GAME_OVER) )\n\t\t\t\t \t&& (g_gameInstanceData.currentScore > g_highScoreData.previousHighScore)\n\t\t\t\t)\n\t\t\t\t{\n\t\t\t\t\tSDL_QueryTexture(g_textTextureData.newHighScoreLabelTextTexture, &the_format, &the_access, &the_width, &the_height);\n\t\t\t\t\t{\n\t\t\t\t\t//\t\t\tSDL_Rect dst_rect = {g_medalBackgroundData.dstRect.w - the_width - RIGHT_MARGIN, 10, g_medalBackgroundData.dstRect.w, g_medalBackgroundData.dstRect.h};\n\t\t\t\t\tSDL_Rect dst_rect = {g_medalBackgroundData.dstRect.w - the_width - RIGHT_MARGIN - running_width - 20, TOP_MARGIN + 116, the_width, the_height};\n\t\t\t\t\tSDL_Rect dst_rect_red_box = dst_rect;\n\t\t\t\t\tdst_rect_red_box.w = dst_rect_red_box.w + 4;\n\t\t\t\t\tdst_rect_red_box.h = dst_rect_red_box.h - 17;\n\t\t\t\t\tdst_rect_red_box.x = dst_rect_red_box.x - 4;\n\t\t\t\t\tdst_rect_red_box.y = dst_rect_red_box.y + 14;\n\n//\t\t\t\t\tSDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);\n\t\t\t\t\tSDL_SetRenderDrawColor(g_mainRenderer, 255, 0, 0, 255);\n\t\t\t\t\t//\t\t\t\tSDL_RenderFillRect(renderer, &dst_rect);\n\t\t\t\t\tSDL_RenderFillRect(g_mainRenderer, &dst_rect_red_box);\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\tSDL_RenderCopy(g_mainRenderer, g_textTextureData.newHighScoreLabelTextTexture, NULL, &dst_rect);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t{\n#define PLATINUM_MEDAL_MINUIMUM 40\n#define GOLD_MEDAL_MINUIMUM 30\n#define SILVER_MEDAL_MINUIMUM 20\n#define BRONZE_MEDAL_MINUIMUM 10\n\t\t\t\t\n\t\t\t\tSDL_Texture* which_medal = NULL;\n\t\t\t\t\n\t\t\t\tif(g_gameInstanceData.currentScore >= PLATINUM_MEDAL_MINUIMUM)\n\t\t\t\t{\n\t\t\t\t\twhich_medal = g_gameTextures.platinumMedal;\n\t\t\t\t}\n\t\t\t\telse if(g_gameInstanceData.currentScore >= GOLD_MEDAL_MINUIMUM)\n\t\t\t\t{\n\t\t\t\t\twhich_medal = g_gameTextures.goldMedal;\n\t\t\t\t}\n\t\t\t\telse if(g_gameInstanceData.currentScore >= SILVER_MEDAL_MINUIMUM)\n\t\t\t\t{\n\t\t\t\t\twhich_medal = g_gameTextures.silverMedal;\n\t\t\t\t}\n\t\t\t\telse if(g_gameInstanceData.currentScore >= BRONZE_MEDAL_MINUIMUM)\n\t\t\t\t{\n\t\t\t\t\twhich_medal = g_gameTextures.bronzeMedal;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\twhich_medal = g_gameTextures.placeholderMedal;\n\t\t\t\t}\n\t\t\t\tSDL_QueryTexture(which_medal, &the_format, &the_access, &the_width, &the_height);\n\t\t\t\t\n\t\t\t\t//\t\t\tSDL_Rect dst_rect = {g_medalBackgroundData.dstRect.w - the_width - RIGHT_MARGIN, 10, g_medalBackgroundData.dstRect.w, g_medalBackgroundData.dstRect.h};\n\t\t\t\tSDL_Rect dst_rect = {0 + 36, TOP_MARGIN + 10, the_width, the_height};\n\t\t\t\tdst_rect.w = 150;\n\t\t\t\tdst_rect.h = 208;\n\t\t\t\t\n\t\t\t\tSDL_RenderCopy(g_mainRenderer, which_medal, NULL, &dst_rect);\n\t\t\t}\n\t\t\t\n#if 1\n\t\t\t{\n\t\t\t\t/* Max score in Flappy Bird is 9999 */\n#define MAX_SCORE_STRING_LENGTH 5\n\t\t\t\tchar score_string[MAX_SCORE_STRING_LENGTH];\n\t\t\t\tSDL_Color white_text_color = { 255, 255, 255, 0 };\n\t\t\t\tSDL_Color black_text_color = { 0, 0, 0, 0 };\n\t\t\t\tSDL_Surface* text_surface = NULL;\n\t\t\t\tMyFloat linear_interp;\n\t\t\t\tint displayed_score;\n\t\t\t\t\n\t\t\t\tif(g_gameState < GAMESTATE_TALLYING_SCORE)\n\t\t\t\t{\n\t\t\t\t\tdisplayed_score = 0;\n\t\t\t\t}\n\t\t\t\telse if(g_gameState == GAMESTATE_TALLYING_SCORE)\n\t\t\t\t{\n\t\t\t\t\tlinear_interp = Flappy_ComputeLinearInterpolation(current_time, g_gameStateCurrentPhaseStartTime, g_gameStateCurrentPhaseStartTime + TALLY_DURATION);\n\t\t\t\t\tdisplayed_score = Flappy_lroundf(linear_interp * (MyFloat)g_gameInstanceData.currentScore);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tdisplayed_score = g_gameInstanceData.currentScore;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t// Note: Could optimize to not recreate texture when there is no change.\n\t\t\t\t\n\t\t\t\t\n\t\t\t\tif(NULL != g_textTextureData.scoreNumberTextTexture)\n\t\t\t\t{\n//\t\t\t\t\tSDL_DestroyTexture(g_textTextureData.scoreNumberTextShadowTexture);\n\t\t\t\t\tSDL_DestroyTexture(g_textTextureData.scoreNumberTextTexture);\n\t\t\t\t}\n\t\t\t\t\n\n\n//\t\t\t\tSDL_Log(\"linear_interp %f, current_time=%d, diedAtTime=%d\", linear_interp, current_time, g_gameInstanceData.diedAtTime);\n\n\t\t\t\t\n\t\t\t\t\n\t\t\t\tSDL_snprintf(score_string, MAX_SCORE_STRING_LENGTH, \"%d\", displayed_score);\n\t\t\t\ttext_surface = TTF_RenderText_Blended(g_textTextureData.fontForScoreNumbers, score_string, white_text_color);\n\t\t\t\tg_textTextureData.scoreNumberTextTexture = SDL_CreateTextureFromSurface(g_mainRenderer, text_surface);\n\t\t\t\t//\tSDL_Log(\"text surface w,h: %d, %d\", text_surface->w, text_surface->h);\n\n//\t\t\t\tSDL_Log(\"score_string %s\\n\", score_string);\n\t\t\t\t\n\t\t\t\t\n\t\t\t\tSDL_FreeSurface(text_surface);\n\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\tSDL_QueryTexture(g_textTextureData.scoreNumberTextTexture, &the_format, &the_access, &the_width, &the_height);\n\t\t\t\t\n\t\t\t\t//\t\t\tSDL_Rect dst_rect = {g_medalBackgroundData.dstRect.w - the_width - RIGHT_MARGIN, 10, g_medalBackgroundData.dstRect.w, g_medalBackgroundData.dstRect.h};\n\t\t\t\tSDL_SetTextureColorMod(g_textTextureData.scoreNumberTextTexture, 0, 0, 0);\n\t\t\t\tSDL_Rect dst_rect = {g_medalBackgroundData.dstRect.w - the_width - RIGHT_MARGIN, TOP_MARGIN + 40, the_width, the_height};\n\t\t\t\tSDL_RenderCopy(g_mainRenderer, g_textTextureData.scoreNumberTextTexture, NULL, &dst_rect);\n\t\t\t\tdst_rect.x = dst_rect.x - 4;\n\t\t\t\tSDL_RenderCopy(g_mainRenderer, g_textTextureData.scoreNumberTextTexture, NULL, &dst_rect);\n\n\t\t\t\tdst_rect.y = dst_rect.y - 4;\n\t\t\t\tSDL_RenderCopy(g_mainRenderer, g_textTextureData.scoreNumberTextTexture, NULL, &dst_rect);\n\n\t\t\t\tdst_rect.x = dst_rect.x + 4;\n\t\t\t\tSDL_RenderCopy(g_mainRenderer, g_textTextureData.scoreNumberTextTexture, NULL, &dst_rect);\n\n\t\t\t\tdst_rect.x = dst_rect.x - 2;\n\t\t\t\tdst_rect.y = dst_rect.y + 2;\n\t\t\t\tSDL_SetTextureColorMod(g_textTextureData.scoreNumberTextTexture, 255, 255, 255);\n\t\t\t\tSDL_RenderCopy(g_mainRenderer, g_textTextureData.scoreNumberTextTexture, NULL, &dst_rect);\n\n\t\t\t}\n\n\t\t\n\t\t\t\n\t\t\t\n\t\t\t{\n\t\t\t\t/* Max score in Flappy Bird is 9999 */\n#define MAX_SCORE_STRING_LENGTH 5\n\t\t\t\tchar score_string[MAX_SCORE_STRING_LENGTH];\n\t\t\t\tSDL_Color white_text_color = { 255, 255, 255, 0 };\n\t\t\t\tSDL_Color black_text_color = { 0, 0, 0, 0 };\n\t\t\t\tSDL_Surface* text_surface = NULL;\n\t\t\t\tMyFloat linear_interp;\n\t\t\t\tint displayed_score;\n\t\t\t\t\n\t\t\t\tif(NULL != g_textTextureData.bestNumberTextTexture)\n\t\t\t\t{\n\t\t\t\t\t//\t\t\t\t\tSDL_DestroyTexture(g_textTextureData.scoreNumberTextShadowTexture);\n\t\t\t\t\tSDL_DestroyTexture(g_textTextureData.bestNumberTextTexture);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif( ((g_gameState >= GAMESTATE_GAME_OVER_WAITING_FOR_USER_ACTION) && (g_gameState <= GAMESTATE_FADE_OUT_GAME_OVER) )\n\t\t\t\t && (g_gameInstanceData.currentScore > g_highScoreData.previousHighScore)\n\t\t\t\t )\n\t\t\t\t{\n\t\t\t\t\tdisplayed_score = g_gameInstanceData.currentScore;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tdisplayed_score = g_highScoreData.previousHighScore;\n\t\t\t\t}\n\n\t\t\t\t\n\t\t\t\tSDL_snprintf(score_string, MAX_SCORE_STRING_LENGTH, \"%d\", displayed_score);\n\t\t\t\ttext_surface = TTF_RenderText_Blended(g_textTextureData.fontForScoreNumbers, score_string, white_text_color);\n\t\t\t\tg_textTextureData.bestNumberTextTexture = SDL_CreateTextureFromSurface(g_mainRenderer, text_surface);\n\t\t\t\t//\tSDL_Log(\"text surface w,h: %d, %d\", text_surface->w, text_surface->h);\n\t\t\t\t\n\t\t\t\t//\t\t\t\tSDL_Log(\"score_string %s\\n\", score_string);\n\t\t\t\t\n\t\t\t\t\n\t\t\t\tSDL_FreeSurface(text_surface);\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\tSDL_QueryTexture(g_textTextureData.bestNumberTextTexture, &the_format, &the_access, &the_width, &the_height);\n\t\t\t\t\n\t\t\t\t//\t\t\tSDL_Rect dst_rect = {g_medalBackgroundData.dstRect.w - the_width - RIGHT_MARGIN, 10, g_medalBackgroundData.dstRect.w, g_medalBackgroundData.dstRect.h};\n\t\t\t\tSDL_SetTextureColorMod(g_textTextureData.bestNumberTextTexture, 0, 0, 0);\n\t\t\t\tSDL_Rect dst_rect = {g_medalBackgroundData.dstRect.w - the_width - RIGHT_MARGIN, TOP_MARGIN + 40 + 116, the_width, the_height};\n\t\t\t\tSDL_RenderCopy(g_mainRenderer, g_textTextureData.bestNumberTextTexture, NULL, &dst_rect);\n\t\t\t\tdst_rect.x = dst_rect.x - 4;\n\t\t\t\tSDL_RenderCopy(g_mainRenderer, g_textTextureData.bestNumberTextTexture, NULL, &dst_rect);\n\t\t\t\t\n\t\t\t\tdst_rect.y = dst_rect.y - 4;\n\t\t\t\tSDL_RenderCopy(g_mainRenderer, g_textTextureData.bestNumberTextTexture, NULL, &dst_rect);\n\t\t\t\t\n\t\t\t\tdst_rect.x = dst_rect.x + 4;\n\t\t\t\tSDL_RenderCopy(g_mainRenderer, g_textTextureData.bestNumberTextTexture, NULL, &dst_rect);\n\t\t\t\t\n\t\t\t\tdst_rect.x = dst_rect.x - 2;\n\t\t\t\tdst_rect.y = dst_rect.y + 2;\n\t\t\t\tSDL_SetTextureColorMod(g_textTextureData.bestNumberTextTexture, 255, 255, 255);\n\t\t\t\tSDL_RenderCopy(g_mainRenderer, g_textTextureData.bestNumberTextTexture, NULL, &dst_rect);\n\t\t\t\t\n\t\t\t}\n\n#endif // ttf\n\t\t\n\t\t}\n\n\t\t/* We'll do the actual render in the render function */\n\t\t\n/*\n\t\t//Render red filled quad\n\t\tSDL_Rect fillRect = { SCREEN_WIDTH / 4, SCREEN_HEIGHT / 4, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 };\n\t\tSDL_SetRenderDrawColor(g_mainRenderer, 0xFF, 0x00, 0x00, 0xFF );\n\t\tSDL_RenderFillRect(g_mainRenderer, &fillRect );\n\t\t\n\t\t//Render green outlined quad\n\t\tSDL_Rect outlineRect = { SCREEN_WIDTH / 6, SCREEN_HEIGHT / 6, SCREEN_WIDTH / 3, SCREEN_HEIGHT / 3 };\n\t\tSDL_SetRenderDrawColor(g_mainRenderer, 0x00, 0xFF, 0x00, 0xFF );\n\t\tSDL_RenderDrawRect(g_mainRenderer, &outlineRect );\n\t\t\n\t\t//Draw blue horizontal line\n\t\tSDL_SetRenderDrawColor(g_mainRenderer, 0x00, 0x00, 0xFF, 0xFF );\n\t\tSDL_RenderDrawLine(g_mainRenderer, 0, SCREEN_HEIGHT / 8, SCREEN_WIDTH, SCREEN_HEIGHT / 8 );\n\t\t\n\t\t//Draw vertical line of yellow dots\n\t\tSDL_SetRenderDrawColor(g_mainRenderer, 0xFF, 0xFF, 0x00, 0xFF );\n\t\tfor( int i = 0; i < SCREEN_HEIGHT/8; i += 1 )\n\t\t{\n\t\t\tSDL_RenderDrawPoint(g_mainRenderer, SCREEN_WIDTH / 8, i );\n\t\t}\n */\n\t\t\n\t\t//Reset render target\n\t\tSDL_SetRenderTarget(g_mainRenderer, NULL );\n\n\t}\n}\n\nvoid Flappy_InitGuiButtons()\n{\n Uint32 the_format;\n int the_access;\n int the_width;\n int the_height;\n SDL_Rect dst_rect;\n\n SDL_QueryTexture(g_gameTextures.playButton, &the_format, &the_access, &the_width, &the_height);\n\n \n dst_rect.w = the_width;\n dst_rect.h = the_height;\n \n /* On consoles like SteamOS, we must have an explicit Quit option or the user will not be able\n \tto quit the game. (Tricks like Alt-F4 don't work unlessed explictly handled by the game.)\n \tBut on iOS, we can't have a Quit button or we'll be rejeted.\n \tAndroid by convention doesn't display a Quit button either since the Exit button is available.\n \tConsole-ized Androids have the Exit/Back button built into the controllers.\n \tSo we will conditionalize the code depending on the platform.\n \tDesktops show both buttons.\n \tMobiles will not.\n */\n#if FLAPPY_PROVIDE_QUIT_BUTTON\n dst_rect.x = 2*(SCREEN_WIDTH / 5) - (the_width / 2);\n#else\n dst_rect.x = (SCREEN_WIDTH / 2) - (the_width / 2);\n#endif\n dst_rect.y = SCREEN_HEIGHT - 2 * (SCREEN_HEIGHT / 7);\n \n SDL_assert(g_gameTextures.playButton != NULL);\n g_guiPlayButton.currentTexture = g_gameTextures.playButton;\n g_guiPlayButton.isPressed = SDL_FALSE;\n g_guiPlayButton.isSelected = SDL_TRUE;\n g_guiPlayButton.dstRect = dst_rect;\n \n \n \n#if FLAPPY_PROVIDE_QUIT_BUTTON\n \n SDL_QueryTexture(g_gameTextures.quitButton, &the_format, &the_access, &the_width, &the_height);\n \n dst_rect.w = the_width;\n dst_rect.h = the_height;\n \n dst_rect.x = 3*(SCREEN_WIDTH / 5) - (the_width / 2);\n dst_rect.y = SCREEN_HEIGHT - 2 * (SCREEN_HEIGHT / 7);\n \n \n SDL_assert(g_gameTextures.quitButton != NULL);\n g_guiQuitButton.currentTexture = g_gameTextures.quitButton;\n g_guiQuitButton.isPressed = SDL_FALSE;\n g_guiQuitButton.isSelected = SDL_FALSE;\n g_guiQuitButton.dstRect = dst_rect;\n#endif /* FLAPPY_PROVIDE_QUIT_BUTTON */\n \n}\n\nvoid Flappy_UpdateScoreTexture(Uint32 new_score)\n{\n#if 1\n\t/* Max score in Flappy Bird is 9999 */\n#define MAX_SCORE_STRING_LENGTH 5\n\tchar score_string[MAX_SCORE_STRING_LENGTH];\n\tSDL_Color white_text_color = { 255, 255, 255, 0 };\n\tSDL_Color black_text_color = { 0, 0, 0, 0 };\n\tSDL_Surface* text_surface = NULL;\n\t\n\tSDL_DestroyTexture(g_currentScoreTextTexture);\n\tSDL_DestroyTexture(g_currentScoreTextShadowTexture);\n\t\n\t\n\tSDL_snprintf(score_string, MAX_SCORE_STRING_LENGTH, \"%d\", new_score);\n\ttext_surface = TTF_RenderText_Blended(s_retroFontForMainScore, score_string, white_text_color);\n\tg_currentScoreTextTexture = SDL_CreateTextureFromSurface(g_mainRenderer, text_surface);\n\t\n\t//\tSDL_Log(\"text surface w,h: %d, %d\", text_surface->w, text_surface->h);\n\t\n\t\n\tSDL_FreeSurface(text_surface);\n\t\n\ttext_surface = TTF_RenderText_Blended(s_retroFontForMainScore, score_string, black_text_color);\n\tg_currentScoreTextShadowTexture = SDL_CreateTextureFromSurface(g_mainRenderer, text_surface);\n\tSDL_FreeSurface(text_surface);\n\t\n\t/* We'll do the actual render in the render function */\n#endif\n}\n\nvoid InitNewGame()\n{\n\tSint32 i;\n\t\n\tg_gameInstanceData.currentScore = 0;\n\tFlappy_UpdateScoreTexture(g_gameInstanceData.currentScore);\n\t\n\tg_highScoreData.previousHighScore = g_highScoreData.savedHighScore;\n\tg_highScoreData.currentHighScore = 0;\n\t\n\t\n\tg_gameInstanceData.distanceTraveled = 0;\n\t\n\t//\tg_gameState = GAMESTATE_BIRD_PRELAUNCH;\n\tg_gameState = GAMESTATE_LOADING_NEW_GAME_AND_FADE_IN;\n\t\n\tg_birdModelData.isPrelaunch = SDL_TRUE;\n\tg_birdModelData.isReadyForPipe = SDL_FALSE;\n\tg_birdModelData.birdLaunchStartTime = 0;\n\t\n\tg_birdModelData.isDead = SDL_FALSE;\n\tg_birdModelData.isGameOver = SDL_FALSE;\n\tg_birdModelData.isFalling = SDL_FALSE;\n\tg_birdModelData.isReadyToPlayFallingSound = SDL_FALSE;\n\t\n\t// because we change this for the title screen\n\tg_birdModelData.position.x = SCREEN_WIDTH / 3;\n\tg_birdModelData.position.y = SCREEN_HEIGHT / 2;\n\t\n\tif(cpSpaceContainsBody(g_mainSpace, g_birdModelData.birdBody))\n\t{\n\t\tcpSpaceRemoveBody(g_mainSpace, g_birdModelData.birdBody);\n\t\tcpSpaceRemoveShape(g_mainSpace, g_birdModelData.birdShape);\n\t\t\n\t}\n\t\n\tcpBodySetVel(g_birdModelData.birdBody, cpv(0, 0));\n\tcpBodySetPos(g_groundPhysicsData.body, cpv(0 + SCREEN_WIDTH/2, GROUND_HEIGHT/2.0));\n\tcpBodySetAngVel(g_birdModelData.birdBody, 0);\n\tcpBodySetAngle(g_birdModelData.birdBody, 0);\n\t\n\t\n\t\n\tfor(i=0; iscoreSensorPhysicsShape);\n\t\tcpSpaceRemoveShape(g_mainSpace, current_pipe->lowerPhysicsShape);\n\t\tcpSpaceRemoveShape(g_mainSpace, current_pipe->upperPhysicsShape);\n\t\t\n\t\tCircularQueueVoid_PushBack(g_queueOfAvailablePipes, current_pipe);\n\t}\n\t\n\twhile(CircularQueueVoid_Size(g_circularQueueOfPipes)>0)\n\t{\n\t\tCircularQueueVoid_PopFront(g_circularQueueOfPipes);\n\t}\n\t\n\t\n\t\n\t\n}\n\nvoid InitTitleScreen()\n{\n\tInitNewGame();\n\tg_gameState = GAMESTATE_TITLE_SCREEN;\n\tg_gameStateCurrentPhaseStartTime = TimeTicker_GetTime(g_gameClock);\n\tg_birdModelData.position.x = SCREEN_WIDTH / 2;\n\tg_birdModelData.position.y = SCREEN_HEIGHT / 2 + 20;\n\n\t\n}\n\nvoid Flappy_UpdateGameState(Uint32 delta_time, Uint32 base_time, Uint32 current_time)\n{\n\tswitch(g_gameState)\n\t{\n\t\tcase GAMESTATE_FADE_OUT_TITLE_SCREEN:\n\t\t{\n\t\t\tif(current_time > (g_gameStateCurrentPhaseStartTime + FADE_OUT_TIME))\n\t\t\t{\n\t\t\t\tInitNewGame();\n\t\t\t\tg_gameState = GAMESTATE_LOADING_NEW_GAME_AND_FADE_IN;\n\t\t\t\tg_gameStateCurrentPhaseStartTime = TimeTicker_GetTime(g_gameClock);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase GAMESTATE_LOADING_NEW_GAME_AND_FADE_IN:\n\t\t{\n\t\t\tif(current_time > (g_gameStateCurrentPhaseStartTime + FADE_IN_TIME))\n\t\t\t{\n\n\t\t\t\tg_gameState = GAMESTATE_BIRD_PRELAUNCH;\n\t\t\t\tg_gameStateCurrentPhaseStartTime = TimeTicker_GetTime(g_gameClock);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\t\n case GAMESTATE_BIRD_LAUNCHED_BUT_BEFORE_PIPES:\n {\n if(current_time >= g_gameStateCurrentPhaseStartTime + PIPE_START_TIME_DELAY)\n {\n g_gameState = GAMESTATE_MAIN_GAME_ACTIVE;\n g_gameStateCurrentPhaseStartTime = TimeTicker_GetTime(g_gameClock);\n }\n break;\n }\n\n\n \n\t\tcase GAMESTATE_DEAD_TO_GAME_OVER_TRANSITION:\n\t\t{\n#define DELAY_UNTIL_GAME_OVER_SWOOP_START 500\n\t\t\tif(current_time >= g_gameStateCurrentPhaseStartTime + DELAY_UNTIL_GAME_OVER_SWOOP_START)\n\t\t\t{\n\t\t\t\tg_gameState = GAMESTATE_SWOOPING_IN_GAME_OVER;\n\t\t\t\tg_gameOverDisplayData.sweepInStartTime = TimeTicker_GetTime(g_gameClock);\n\t\t\t\tg_gameStateCurrentPhaseStartTime = g_gameOverDisplayData.sweepInStartTime;\n\n\t\t\t\tALmixer_PlayChannel(-1, g_gameSounds.swoosh, 0);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\t\t\n\t\tcase GAMESTATE_TALLYING_SCORE:\n\t\t{\n\t\t\tif(current_time > (g_gameStateCurrentPhaseStartTime + TALLY_DURATION))\n\t\t\t{\n\t\t\t\tg_gameState = GAMESTATE_GAME_OVER_WAITING_FOR_USER_ACTION;\n\t\t\t\tg_gameStateCurrentPhaseStartTime = TimeTicker_GetTime(g_gameClock);\n\t\t\t\tFlappy_InitGuiButtons();\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\t\t\n\t\tcase GAMESTATE_FADE_OUT_GAME_OVER:\n\t\t{\n\t\t\tif(current_time > (g_gameStateCurrentPhaseStartTime + FADE_OUT_TIME))\n\t\t\t{\n\t\t\t\tInitNewGame();\n\n\t\t\t\tg_gameState = GAMESTATE_LOADING_NEW_GAME_AND_FADE_IN;\n\t\t\t\tg_gameStateCurrentPhaseStartTime = TimeTicker_GetTime(g_gameClock);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\t\t\n\t\tdefault:\n\t\t{\n\t\t\t\n\t\t}\n\t}\n}\n\n\nvoid Flappy_Update(Uint32 delta_time, Uint32 base_time, Uint32 current_time)\n{\n//\tSDL_Log(\"update physics\");\n\tFlappy_StepPhysics(delta_time);\n\t\n\t/* This is either based on time, or the place it crashed */\n\tSint32 current_bird_time_position = Flappy_DetermineCurrentBirdTimePosition(delta_time, base_time, current_time);\n//\tSDL_Log(\"current_bird_time_position:%d, current_time:%d\\n\", current_bird_time_position, current_time);\n\t\n//\tSDL_Log(\"update Flappy_UpdateGameState\");\n\tFlappy_UpdateGameState(delta_time, base_time, current_time);\n\n\t\n\tFlappy_UpdateCloudPositions(delta_time, base_time, current_bird_time_position);\n\tFlappy_UpdateGroundPosition(delta_time, base_time, current_bird_time_position);\n\tFlappy_UpdateBushPositions(delta_time, base_time, current_bird_time_position);\n\tFlappy_UpdateBirdPosition(delta_time, base_time, current_time);\n//\tSDL_Log(\"update Flappy_UpdatePipePositions\");\n\t\n\tFlappy_UpdatePipePositions(delta_time, base_time, current_bird_time_position);\n\t\n//\tSDL_Log(\"update Flappy_UpdateGameOverDisplayData\");\n\t\n\tFlappy_UpdateGameOverDisplayData(delta_time, base_time, current_time);\n//\tSDL_Log(\"update Flappy_UpdateMedalBackgroundData\");\n\n\tFlappy_UpdateMedalBackgroundData(delta_time, base_time, current_time);\n\t\n\n}\n\nvoid Flappy_LoadSounds()\n{\n\tALmixer_Data* audio_data;\n\t\n#define MAX_FILE_STRING_LENGTH 2048\n\tchar resource_file_path[MAX_FILE_STRING_LENGTH];\n\tchar base_path[MAX_FILE_STRING_LENGTH];\n\t\n\tBlurrrCore_GetResourceDirectoryString(base_path, MAX_FILE_STRING_LENGTH);\n\t\n\t/* load the sound */\n\t/*\n\t\tEric Wing\n\t\tCreative Commons Attribution 3.0\n\t */\n\tSDL_strlcpy(resource_file_path, base_path, MAX_FILE_STRING_LENGTH);\n\tSDL_strlcat(resource_file_path, \"coin_ding.wav\", MAX_FILE_STRING_LENGTH);\n//\tSDL_Log(\"loading %s\\n\", resource_file_path);\n\n\taudio_data = ALmixer_LoadAll(resource_file_path, AL_FALSE);\n\tif(NULL == audio_data)\n\t{\n\t\tSDL_Log(\"could not load %s: %s\\n\", resource_file_path, SDL_GetError());\n\n\t\tfatalError(\"could not load sound\");\n\t}\n\tg_gameSounds.coin = audio_data;\n\t\n\t/* load the sound */\n\t/*\n\t Paul Rodenburg\n\t I grant anyone the right to use this sound effect for any purpose commercial or non-commercial world wide for perpetuity, so long as it's not used in a stand alone manner.\n\t https://www.youtube.com/watch?v=IsJnuvbjL0s\n\t */\n\tSDL_strlcpy(resource_file_path, base_path, MAX_FILE_STRING_LENGTH);\n\tSDL_strlcat(resource_file_path, \"SlideWhistle.wav\", MAX_FILE_STRING_LENGTH);\n//\tSDL_Log(\"loading %s\\n\", resource_file_path);\n\taudio_data = ALmixer_LoadAll(resource_file_path, AL_FALSE);\n\tif(NULL == audio_data)\n\t{\n\t\tSDL_Log(\"could not load %s: %s\\n\", resource_file_path, SDL_GetError());\n\t\tfatalError(\"could not load sound\");\n\t}\n\tg_gameSounds.fall = audio_data;\n\n\t/* load the sound */\n\t/* \n\t\tDave Des\n\t\tCreative Commons 0 1.0 Universal (CC0 1.0)\n\t\thttp://www.freesound.org/people/dave.des/sounds/127197/\n\n\t */\n\tSDL_strlcpy(resource_file_path, base_path, MAX_FILE_STRING_LENGTH);\n\tSDL_strlcat(resource_file_path, \"davedes_fastsimplechop5b.wav\", MAX_FILE_STRING_LENGTH);\n//\tSDL_Log(\"loading %s\\n\", resource_file_path);\n\taudio_data = ALmixer_LoadAll(resource_file_path, AL_FALSE);\n\tif(NULL == audio_data)\n\t{\n\t\tSDL_Log(\"could not load %s: %s\\n\", resource_file_path, SDL_GetError());\n\t\tfatalError(\"could not load sound\");\n\t}\n\tg_gameSounds.flap = audio_data;\n\t\n\t\n\t/* load the sound */\n\t/*\n\t\tMike Koenig\n\t\tCreative Commons Attribution 3.0\n\t\thttp://soundbible.com/991-Left-Hook.html\n\t */\n\tSDL_strlcpy(resource_file_path, base_path, MAX_FILE_STRING_LENGTH);\n\tSDL_strlcat(resource_file_path, \"LeftHook_SoundBible_com-516660386.wav\", MAX_FILE_STRING_LENGTH);\n//\tSDL_Log(\"loading %s\\n\", resource_file_path);\n\taudio_data = ALmixer_LoadAll(resource_file_path, AL_FALSE);\n\tif(NULL == audio_data)\n\t{\n\t\tSDL_Log(\"could not load %s: %s\\n\", resource_file_path, SDL_GetError());\n\t\tfatalError(\"could not load sound\");\n\t}\n\tg_gameSounds.crash = audio_data;\n\n\t\n\n\t/* load the sound */\n\t/*\n\t\tman\n\t\tCreative Commons Attribution 3.0\n\t\thttp://www.freesound.org/people/man/sounds/14609/\n\t */\n\tSDL_strlcpy(resource_file_path, base_path, MAX_FILE_STRING_LENGTH);\n\tSDL_strlcat(resource_file_path, \"14609__man__swosh.wav\", MAX_FILE_STRING_LENGTH);\n\taudio_data = ALmixer_LoadAll(resource_file_path, AL_FALSE);\n\tif(NULL == audio_data)\n\t{\n\t\tSDL_Log(\"could not load %s: %s\\n\", resource_file_path, SDL_GetError());\n\t\tfatalError(\"could not load sound\");\n\t}\n\tg_gameSounds.swoosh = audio_data;\n\n\t\n}\n\nvoid Flappy_DoFlap()\n{\n\tif(g_gameInstanceData.isPaused)\n\t{\n\t\treturn;\n\t}\n\t\n\t\n\tif(g_birdModelData.isPrelaunch)\n\t{\n\t\tg_birdModelData.isPrelaunch = SDL_FALSE;\n\t\tcpSpaceAddBody(g_mainSpace, g_birdModelData.birdBody);\n\t\tcpSpaceAddShape(g_mainSpace, g_birdModelData.birdShape);\n\t\tg_birdModelData.birdLaunchStartTime = TimeTicker_GetTime(g_gameClock);\n g_gameStateCurrentPhaseStartTime = g_birdModelData.birdLaunchStartTime;\n g_gameState = GAMESTATE_BIRD_LAUNCHED_BUT_BEFORE_PIPES;\n \n \n\t}\n\tif(g_birdModelData.isDead)\n\t{\n\t\treturn;\n\t}\n\t\n\n\t\n\t/* In Flappy Bird, when the bird is above the screen,\n\t\tthere is some kind of limit imposed so you can't fly up really high.\n\t\tThis can be recreated easily by not allowing flaps when the bird is offscreen.\n\t\tWe add the size because SDL places y at the top of the sprite, not the bottom.\n\t\tWe add a fudge factor because Flappy Bird seems to give some extra space at the top.\n\t */\n\tif(g_birdModelData.position.y + g_birdModelData.size.y + g_birdModelData.size.y >= 0)\n\t{\n\t\t//\tcpBodyApplyImpulse(g_birdModelData.birdBody, cpv(0, 10), cpv(0,0));\n\t\t// We only want to use velocity for the y-axis because we are already manually computing x-axis movement.\n\t\tALmixer_PlayChannel(-1, g_gameSounds.flap, 0);\n//\t\tcpBodySetVel(g_birdModelData.birdBody, cpv(g_birdModelData.velocity.x, 460));\n//\t\tcpBodySetVel(g_birdModelData.birdBody, cpv(g_birdModelData.velocity.x, 460));\n\t\tcpBodySetVel(g_birdModelData.birdBody, cpv(g_birdModelData.velocity.x, 580));\n\t\tcpBodySetAngle(g_birdModelData.birdBody, M_PI_4);\n\t\tcpBodySetAngVel(g_birdModelData.birdBody, -2);\n\t\t/* Chipmunk API says to reindex after changing the angle */\n\t\tcpSpaceReindexShapesForBody(g_mainSpace, g_birdModelData.birdBody);\n\t}\n\n}\n\n\n/*\n loads the happyface graphic into a texture\n */\nvoid\ninitializeTexture(SDL_Renderer* the_renderer)\n{\n\tSDL_Surface* bmp_surface;\n\tSDL_Texture* the_texture;\n#define MAX_FILE_STRING_LENGTH 2048\n\tchar resource_file_path[MAX_FILE_STRING_LENGTH];\n\tchar base_path[MAX_FILE_STRING_LENGTH];\n\t\n\tBlurrrCore_GetResourceDirectoryString(base_path, MAX_FILE_STRING_LENGTH);\n\t\n\t/* load the image */\n\tSDL_strlcpy(resource_file_path, base_path, MAX_FILE_STRING_LENGTH);\n\tSDL_strlcat(resource_file_path, \"background.png\", MAX_FILE_STRING_LENGTH);\n\tthe_texture = IMG_LoadTexture(the_renderer, resource_file_path);\n\tif(NULL == the_texture)\n\t{\n\t\tfatalError(\"could not create texture\");\n\t}\n\t//\tSDL_SetTextureBlendMode(the_texture, SDL_BLENDMODE_BLEND);\n\tg_gameTextures.background = the_texture;\n\t\n\t\n\n\t\n\t/* load the image */\n\tSDL_strlcpy(resource_file_path, base_path, MAX_FILE_STRING_LENGTH);\n\tSDL_strlcat(resource_file_path, \"clouds.png\", MAX_FILE_STRING_LENGTH);\n\tthe_texture = IMG_LoadTexture(the_renderer, resource_file_path);\n\tif(NULL == the_texture)\n\t{\n\t\tfatalError(\"could not create texture\");\n\t}\n\tSDL_SetTextureBlendMode(the_texture, SDL_BLENDMODE_BLEND);\n//\tSDL_SetTextureAlphaMod(the_texture, .6 * 255);\n\tFlappy_InitializeCloudModelData(the_texture);\n\tg_gameTextures.clouds = the_texture;\n\t\n\t/* load the image */\n\tSDL_strlcpy(resource_file_path, base_path, MAX_FILE_STRING_LENGTH);\n\t/* fly0 is the wing in the neutral position */\n\tSDL_strlcat(resource_file_path, \"fly0.png\", MAX_FILE_STRING_LENGTH);\n\tthe_texture = IMG_LoadTexture(the_renderer, resource_file_path);\n\tif(NULL == the_texture)\n\t{\n\t\tfatalError(\"could not create texture\");\n\t}\n\tSDL_SetTextureBlendMode(the_texture, SDL_BLENDMODE_BLEND);\n\t//\tSDL_SetTextureAlphaMod(the_texture, .6 * 255);\n\tg_gameTextures.bird[2] = the_texture;\n\t\n\t/* load the image */\n\tSDL_strlcpy(resource_file_path, base_path, MAX_FILE_STRING_LENGTH);\n\t/* fly1 is the wing in the neutral position */\n\tSDL_strlcat(resource_file_path, \"fly1.png\", MAX_FILE_STRING_LENGTH);\n\tthe_texture = IMG_LoadTexture(the_renderer, resource_file_path);\n\tif(NULL == the_texture)\n\t{\n\t\tfatalError(\"could not create texture\");\n\t}\n\tSDL_SetTextureBlendMode(the_texture, SDL_BLENDMODE_BLEND);\n//\tSDL_SetTextureAlphaMod(the_texture, .6 * 255);\n\tg_gameTextures.bird[1] = the_texture;\n\t\n\t\n\t/* load the image */\n\tSDL_strlcpy(resource_file_path, base_path, MAX_FILE_STRING_LENGTH);\n\t/* fly2 is the wing in the up position */\n\tSDL_strlcat(resource_file_path, \"fly2.png\", MAX_FILE_STRING_LENGTH);\n\tthe_texture = IMG_LoadTexture(the_renderer, resource_file_path);\n\tif(NULL == the_texture)\n\t{\n\t\tfatalError(\"could not create texture\");\n\t}\n\tSDL_SetTextureBlendMode(the_texture, SDL_BLENDMODE_BLEND);\n//\tSDL_SetTextureAlphaMod(the_texture, .6 * 255);\n\tg_gameTextures.bird[0] = the_texture;\n\t\n\tFlappy_InitializeBirdModelData(g_gameTextures.bird[1]);\n\t\n\t\n\n\t/* load the image */\n\tSDL_strlcpy(resource_file_path, base_path, MAX_FILE_STRING_LENGTH);\n\tSDL_strlcat(resource_file_path, \"ground.png\", MAX_FILE_STRING_LENGTH);\n\tthe_texture = IMG_LoadTexture(the_renderer, resource_file_path);\n\tif(NULL == the_texture)\n\t{\n\t\tfatalError(\"could not create texture\");\n\t}\n//\tSDL_SetTextureBlendMode(the_texture, SDL_BLENDMODE_BLEND);\n//\tSDL_SetTextureAlphaMod(the_texture, .6 * 255);\n\tFlappy_InitializeGroundModelData(the_texture);\n\tg_gameTextures.ground = the_texture;\n\t\n\t\n\t/* load the image */\n\tSDL_strlcpy(resource_file_path, base_path, MAX_FILE_STRING_LENGTH);\n\tSDL_strlcat(resource_file_path, \"bush.png\", MAX_FILE_STRING_LENGTH);\n\tthe_texture = IMG_LoadTexture(the_renderer, resource_file_path);\n\tif(NULL == the_texture)\n\t{\n\t\tfatalError(\"could not create texture\");\n\t}\n\tSDL_SetTextureBlendMode(the_texture, SDL_BLENDMODE_BLEND);\n\t//\tSDL_SetTextureAlphaMod(the_texture, .6 * 255);\n\tFlappy_InitializeBushModelData(the_texture);\n\tg_gameTextures.bush = the_texture;\n\n\t\n\t/* load the image */\n\tSDL_strlcpy(resource_file_path, base_path, MAX_FILE_STRING_LENGTH);\n\tSDL_strlcat(resource_file_path, \"pipe_bottom.png\", MAX_FILE_STRING_LENGTH);\n\tthe_texture = IMG_LoadTexture(the_renderer, resource_file_path);\n\tif(NULL == the_texture)\n\t{\n\t\tfatalError(\"could not create texture\");\n\t}\n\tSDL_SetTextureBlendMode(the_texture, SDL_BLENDMODE_BLEND);\n//\tSDL_SetTextureAlphaMod(the_texture, .6 * 255);\n\tg_gameTextures.pipe_bottom = the_texture;\n\t\n\t\n\t/* load the image */\n\tSDL_strlcpy(resource_file_path, base_path, MAX_FILE_STRING_LENGTH);\n\tSDL_strlcat(resource_file_path, \"pipe_top.png\", MAX_FILE_STRING_LENGTH);\n\tthe_texture = IMG_LoadTexture(the_renderer, resource_file_path);\n\tif(NULL == the_texture)\n\t{\n\t\tfatalError(\"could not create texture\");\n\t}\n\tSDL_SetTextureBlendMode(the_texture, SDL_BLENDMODE_BLEND);\n//\tSDL_SetTextureAlphaMod(the_texture, .6 * 255);\n\tg_gameTextures.pipe_top = the_texture;\n\t\n\tFlappy_InitializePipeModelData(g_gameTextures.pipe_bottom);\n\t\n\t\n\t/* load the image */\n\tSDL_strlcpy(resource_file_path, base_path, MAX_FILE_STRING_LENGTH);\n\tSDL_strlcat(resource_file_path, \"MedalBackground.png\", MAX_FILE_STRING_LENGTH);\n\tthe_texture = IMG_LoadTexture(the_renderer, resource_file_path);\n\tif(NULL == the_texture)\n\t{\n\t\tfatalError(\"could not create texture\");\n\t}\n\tSDL_SetTextureBlendMode(the_texture, SDL_BLENDMODE_BLEND);\n\t//\tSDL_SetTextureAlphaMod(the_texture, .6 * 255);\n\tg_gameTextures.medalBackground = the_texture;\n\t\n\tFlappy_InitializeMedalBackgroundData(the_texture);\n\t\n\t\n\t/* load the image */\n\tSDL_strlcpy(resource_file_path, base_path, MAX_FILE_STRING_LENGTH);\n\tSDL_strlcat(resource_file_path, \"momoko_Bronze_Medallion.png\", MAX_FILE_STRING_LENGTH);\n\tthe_texture = IMG_LoadTexture(the_renderer, resource_file_path);\n\tif(NULL == the_texture)\n\t{\n\t\tfatalError(\"could not create texture\");\n\t}\n\tSDL_SetTextureBlendMode(the_texture, SDL_BLENDMODE_BLEND);\n\t//\tSDL_SetTextureAlphaMod(the_texture, .6 * 255);\n\tg_gameTextures.bronzeMedal = the_texture;\n\t\n\tSDL_strlcpy(resource_file_path, base_path, MAX_FILE_STRING_LENGTH);\n\tSDL_strlcat(resource_file_path, \"momoko_Silver_Medallion.png\", MAX_FILE_STRING_LENGTH);\n\tthe_texture = IMG_LoadTexture(the_renderer, resource_file_path);\n\tif(NULL == the_texture)\n\t{\n\t\tfatalError(\"could not create texture\");\n\t}\n\tSDL_SetTextureBlendMode(the_texture, SDL_BLENDMODE_BLEND);\n\t//\tSDL_SetTextureAlphaMod(the_texture, .6 * 255);\n\tg_gameTextures.silverMedal = the_texture;\n\t\n\tSDL_strlcpy(resource_file_path, base_path, MAX_FILE_STRING_LENGTH);\n\tSDL_strlcat(resource_file_path, \"momoko_Gold_Medallion.png\", MAX_FILE_STRING_LENGTH);\n\tthe_texture = IMG_LoadTexture(the_renderer, resource_file_path);\n\tif(NULL == the_texture)\n\t{\n\t\tfatalError(\"could not create texture\");\n\t}\n\tSDL_SetTextureBlendMode(the_texture, SDL_BLENDMODE_BLEND);\n\t//\tSDL_SetTextureAlphaMod(the_texture, .6 * 255);\n\tg_gameTextures.goldMedal = the_texture;\n\t\n\tSDL_strlcpy(resource_file_path, base_path, MAX_FILE_STRING_LENGTH);\n\tSDL_strlcat(resource_file_path, \"momoko_Platinum_Medallion.png\", MAX_FILE_STRING_LENGTH);\n\tthe_texture = IMG_LoadTexture(the_renderer, resource_file_path);\n\tif(NULL == the_texture)\n\t{\n\t\tfatalError(\"could not create texture\");\n\t}\n\tSDL_SetTextureBlendMode(the_texture, SDL_BLENDMODE_BLEND);\n\t//\tSDL_SetTextureAlphaMod(the_texture, .6 * 255);\n\tg_gameTextures.platinumMedal = the_texture;\n\t\n\t\n\tSDL_strlcpy(resource_file_path, base_path, MAX_FILE_STRING_LENGTH);\n\tSDL_strlcat(resource_file_path, \"Placeholder_Medallion.png\", MAX_FILE_STRING_LENGTH);\n\tthe_texture = IMG_LoadTexture(the_renderer, resource_file_path);\n\tif(NULL == the_texture)\n\t{\n\t\tfatalError(\"could not create texture\");\n\t}\n\tSDL_SetTextureBlendMode(the_texture, SDL_BLENDMODE_BLEND);\n\t//\tSDL_SetTextureAlphaMod(the_texture, .6 * 255);\n\tg_gameTextures.placeholderMedal = the_texture;\n\t\n//\tFlappy_InitializeMedalBackgroundData(the_texture);\n\t\n \n \n \n /* load the image */\n\tSDL_strlcpy(resource_file_path, base_path, MAX_FILE_STRING_LENGTH);\n\tSDL_strlcat(resource_file_path, \"playbutton.png\", MAX_FILE_STRING_LENGTH);\n\tthe_texture = IMG_LoadTexture(the_renderer, resource_file_path);\n\tif(NULL == the_texture)\n\t{\n\t\tfatalError(\"could not create texture\");\n\t}\n\tSDL_SetTextureBlendMode(the_texture, SDL_BLENDMODE_BLEND);\n\t//\tSDL_SetTextureAlphaMod(the_texture, .6 * 255);\n\tg_gameTextures.playButton = the_texture;\n\t\n /* load the image */\n\tSDL_strlcpy(resource_file_path, base_path, MAX_FILE_STRING_LENGTH);\n\tSDL_strlcat(resource_file_path, \"quitbutton.png\", MAX_FILE_STRING_LENGTH);\n\tthe_texture = IMG_LoadTexture(the_renderer, resource_file_path);\n\tif(NULL == the_texture)\n\t{\n\t\tfatalError(\"could not create texture\");\n\t}\n\tSDL_SetTextureBlendMode(the_texture, SDL_BLENDMODE_BLEND);\n\t//\tSDL_SetTextureAlphaMod(the_texture, .6 * 255);\n\tg_gameTextures.quitButton = the_texture;\n \n Flappy_InitGuiButtons();\n}\n\n\n\nSDL_Texture* Flappy_CreateGameOverTexture()\n{\n#if 1\n\tSDL_Color white_text_color = { 255, 255, 255, 0 };\n//\tSDL_Color green_text_color = { 0, 0, 0, 0 };\n\tSDL_Color black_text_color = { 0, 0, 0, 0 };\n\tSDL_Color orange_text_color = { 220, 120, 0, 255 };\n\n\tSDL_Surface* text_surface = NULL;\n\tTTF_Font* the_font = NULL;\n\tSDL_Texture* base_texture;\n\t\n\tUint32 the_format;\n\tint the_access;\n\tint the_width;\n\tint the_height;\n\t\n\n\t\n#define MAX_FILE_STRING_LENGTH 2048\n\tchar resource_file_path[MAX_FILE_STRING_LENGTH];\n\t\n\tBlurrrCore_GetResourceDirectoryString(resource_file_path, MAX_FILE_STRING_LENGTH);\n\tSDL_strlcat(resource_file_path, \"acknowtt.ttf\", MAX_FILE_STRING_LENGTH);\n//\tSDL_strlcat(resource_file_path, \"DisposableDroidBB.otf\", MAX_FILE_STRING_LENGTH);\n//\tSDL_strlcat(resource_file_path, \"04B_19__.TTF\", MAX_FILE_STRING_LENGTH);\n//\tSDL_strlcat(resource_file_path, \"VeraMono.ttf\", MAX_FILE_STRING_LENGTH);\n\t\nSDL_Log(\"opening font 04B_19__.ttf\");\n the_font = TTF_OpenFont(resource_file_path, 110);\n if(NULL == the_font)\n\t{\n SDL_Log(\"Couldn't load font %s: %s\\n\", resource_file_path, SDL_GetError());\n\t\treturn NULL;\n }\n\t\nSDL_Log(\"TTF_RenderText_Blended(Game Over) with font VeraMono.ttf\");\n\t\t\n\t\n\t\n\ttext_surface = TTF_RenderText_Blended(the_font, \"Game Over\", white_text_color);\nSDL_Log(\"SDL_CreateTextureFromSurface\");\n\tbase_texture = SDL_CreateTextureFromSurface(g_mainRenderer, text_surface);\n\n\tSDL_QueryTexture(base_texture, &the_format, &the_access, &the_width, &the_height);\n\n\t\n\tg_textTextureData.gameOverTextTexture = SDL_CreateTexture(g_mainRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, the_width+20, the_height+20);\n\tSDL_assert(NULL != g_textTextureData.gameOverTextTexture);\n\tSDL_SetTextureBlendMode(g_textTextureData.gameOverTextTexture, SDL_BLENDMODE_BLEND);\n\n\t\n\t\n\t\n\tSDL_SetRenderTarget(g_mainRenderer, g_textTextureData.gameOverTextTexture);\n\t\n\t// Clear screen\n\tSDL_SetRenderDrawColor(g_mainRenderer, 0, 0, 0, 0 );\n\tSDL_RenderClear(g_mainRenderer );\n\n\t\n\t{\n\t\tSDL_Rect dst_rect_center = {10, 10, the_width, the_height};\n\t\tSDL_Rect dst_rect;\n\t\n\n\t//\t\t\tSDL_Rect dst_rect = {g_medalBackgroundData.dstRect.w - the_width - RIGHT_MARGIN, 10, g_medalBackgroundData.dstRect.w, g_medalBackgroundData.dstRect.h};\n\tSDL_SetTextureColorMod(base_texture, 0, 0, 0);\n\tdst_rect = dst_rect_center;\n\n\t// left-top\n\tdst_rect.x = dst_rect.x - 10;\n\tdst_rect.y = dst_rect.y - 10;\n\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\n\t// right-top\n\tdst_rect.x = dst_rect.x + 20;\n\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\n\t// right-bottom\n\tdst_rect.y = dst_rect.y + 20;\n\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\n\t// left-bottom\n\tdst_rect.x = dst_rect.x - 20;\n\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\n\t// recenter\n\tdst_rect = dst_rect_center;\n\t// left\n\tdst_rect.x = dst_rect.x - 10;\n\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\n\t// right\n\tdst_rect.x = dst_rect.x + 20;\n\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\n\t// recenter\n\tdst_rect = dst_rect_center;\n\n\t// bottom\n\tdst_rect.y = dst_rect.y - 10;\n\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t// top\n\tdst_rect.y = dst_rect.y + 20;\n\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t\n\t// recenter\n\tdst_rect = dst_rect_center;\n\n\t\n\tSDL_SetTextureColorMod(base_texture, 255, 255, 255);\n\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\n\t\n\t\n\t\n\tdst_rect.x = dst_rect.x - 6;\n\tdst_rect.y = dst_rect.y - 6;\n\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\n\tdst_rect.x = dst_rect.x + 12;\n\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\n\tdst_rect.y = dst_rect.y + 12;\n\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\n\tdst_rect.x = dst_rect.x - 12;\n\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\n\t\n\t\t// recenter\n\t\tdst_rect = dst_rect_center;\n\t\t// left\n\t\tdst_rect.x = dst_rect.x - 6;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t// right\n\t\tdst_rect.x = dst_rect.x + 12;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t// recenter\n\t\tdst_rect = dst_rect_center;\n\t\t\n\t\t// bottom\n\t\tdst_rect.y = dst_rect.y - 6;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t// top\n\t\tdst_rect.y = dst_rect.y + 12;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t\n\t\n\tdst_rect = dst_rect_center;\n\n\tSDL_SetTextureColorMod(base_texture, 220, 120, 0);\n\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\n\t}\n\t\t\n\t\n\tSDL_SetRenderTarget(g_mainRenderer, NULL);\n\n\t\n\tSDL_DestroyTexture(base_texture);\n\tSDL_FreeSurface(text_surface);\n\n\tTTF_CloseFont(the_font);\n#endif\n\treturn g_textTextureData.gameOverTextTexture;\n\t\n}\n\n\nvoid Flappy_CreateGetReadyTexture()\n{\n#if 1\n\tSDL_Color white_text_color = { 255, 255, 255, 0 };\n\tSDL_Color black_text_color = { 0, 0, 0, 0 };\n\tSDL_Color green_text_color = { 64, 128, 0, 255 };\n\t\n\tSDL_Surface* text_surface = NULL;\n\tTTF_Font* the_font = NULL;\n\tSDL_Texture* base_texture;\n\t\n\tUint32 the_format;\n\tint the_access;\n\tint the_width;\n\tint the_height;\n\t\n\t\n\t\n#define MAX_FILE_STRING_LENGTH 2048\n\tchar resource_file_path[MAX_FILE_STRING_LENGTH];\n\t\n\tBlurrrCore_GetResourceDirectoryString(resource_file_path, MAX_FILE_STRING_LENGTH);\n\tSDL_strlcat(resource_file_path, \"acknowtt.ttf\", MAX_FILE_STRING_LENGTH);\n// SDL_strlcat(resource_file_path, \"04B_19__.TTF\", MAX_FILE_STRING_LENGTH);\n//\tSDL_strlcat(resource_file_path, \"VeraMono.ttf\", MAX_FILE_STRING_LENGTH);\n\n\t\n the_font = TTF_OpenFont(resource_file_path, 90);\n if(NULL == the_font)\n\t{\n SDL_Log(\"Couldn't load font %s: %s\\n\", resource_file_path, SDL_GetError());\n\t\treturn;\n }\n\t\n\t\n\t\n\t\n\ttext_surface = TTF_RenderText_Blended(the_font, \"Get Ready!\", white_text_color);\n\tbase_texture = SDL_CreateTextureFromSurface(g_mainRenderer, text_surface);\n\t\n\tSDL_QueryTexture(base_texture, &the_format, &the_access, &the_width, &the_height);\n\t\n\t\n\tg_textTextureData.getReadyTextTexture = SDL_CreateTexture(g_mainRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, the_width+20, the_height+20);\n\tSDL_assert(NULL != g_textTextureData.getReadyTextTexture);\n\tSDL_SetTextureBlendMode(g_textTextureData.getReadyTextTexture, SDL_BLENDMODE_BLEND);\n\t\n\t\n\t\n\t\n\tSDL_SetRenderTarget(g_mainRenderer, g_textTextureData.getReadyTextTexture);\n\t\n\t// Clear screen\n\tSDL_SetRenderDrawColor(g_mainRenderer, 0, 0, 0, 0 );\n\tSDL_RenderClear(g_mainRenderer );\n\t\n\t\n\t{\n\t\tSDL_Rect dst_rect_center = {10, 10, the_width, the_height};\n\t\tSDL_Rect dst_rect;\n\t\t\n\t\t\n\t\t//\t\t\tSDL_Rect dst_rect = {g_medalBackgroundData.dstRect.w - the_width - RIGHT_MARGIN, 10, g_medalBackgroundData.dstRect.w, g_medalBackgroundData.dstRect.h};\n\t\tSDL_SetTextureColorMod(base_texture, 0, 0, 0);\n\t\tdst_rect = dst_rect_center;\n\t\t\n\t\t// left-top\n\t\tdst_rect.x = dst_rect.x - 10;\n\t\tdst_rect.y = dst_rect.y - 10;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t// right-top\n\t\tdst_rect.x = dst_rect.x + 20;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t// right-bottom\n\t\tdst_rect.y = dst_rect.y + 20;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t// left-bottom\n\t\tdst_rect.x = dst_rect.x - 20;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t// recenter\n\t\tdst_rect = dst_rect_center;\n\t\t// left\n\t\tdst_rect.x = dst_rect.x - 10;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t// right\n\t\tdst_rect.x = dst_rect.x + 20;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t// recenter\n\t\tdst_rect = dst_rect_center;\n\t\t\n\t\t// bottom\n\t\tdst_rect.y = dst_rect.y - 10;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t// top\n\t\tdst_rect.y = dst_rect.y + 20;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t\n\t\t// recenter\n\t\tdst_rect = dst_rect_center;\n\t\t\n\t\t\n\t\tSDL_SetTextureColorMod(base_texture, 255, 255, 255);\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t\n\t\t\n\t\t\n\t\tdst_rect.x = dst_rect.x - 6;\n\t\tdst_rect.y = dst_rect.y - 6;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\tdst_rect.x = dst_rect.x + 12;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\tdst_rect.y = dst_rect.y + 12;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\tdst_rect.x = dst_rect.x - 12;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t\n\t\t// recenter\n\t\tdst_rect = dst_rect_center;\n\t\t// left\n\t\tdst_rect.x = dst_rect.x - 6;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t// right\n\t\tdst_rect.x = dst_rect.x + 12;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t// recenter\n\t\tdst_rect = dst_rect_center;\n\t\t\n\t\t// bottom\n\t\tdst_rect.y = dst_rect.y - 6;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t// top\n\t\tdst_rect.y = dst_rect.y + 12;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t\n\t\t\n\t\tdst_rect = dst_rect_center;\n\t\t\n\t\tSDL_SetTextureColorMod(base_texture, 64, 128, 0);\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t}\n\t\n\t\n\tSDL_SetRenderTarget(g_mainRenderer, NULL);\n\t\n\t\n\tSDL_DestroyTexture(base_texture);\n\tSDL_FreeSurface(text_surface);\n\t\n\tTTF_CloseFont(the_font);\n#endif\n\t\n}\n\n\n\nvoid Flappy_CreateFlappyBlurrrTexture()\n{\n#if 1\n\tSDL_Color white_text_color = { 255, 255, 255, 0 };\n\tSDL_Color black_text_color = { 0, 0, 0, 0 };\n\tSDL_Color green_text_color = { 64, 128, 0, 255 };\n\t\n\tSDL_Surface* text_surface = NULL;\n\tTTF_Font* the_font = NULL;\n\tSDL_Texture* base_texture;\n\t\n\tUint32 the_format;\n\tint the_access;\n\tint the_width;\n\tint the_height;\n\t\n\t\n\t\n#define MAX_FILE_STRING_LENGTH 2048\n\tchar resource_file_path[MAX_FILE_STRING_LENGTH];\n\t\n\tBlurrrCore_GetResourceDirectoryString(resource_file_path, MAX_FILE_STRING_LENGTH);\n\t//\tSDL_strlcat(resource_file_path, \"acknowtt.ttf\", MAX_FILE_STRING_LENGTH);\n// SDL_strlcat(resource_file_path, \"04B_19__.TTF\", MAX_FILE_STRING_LENGTH);\n\tSDL_strlcat(resource_file_path, \"VeraMono.ttf\", MAX_FILE_STRING_LENGTH);\n\t\n\t\n the_font = TTF_OpenFont(resource_file_path, 90);\n if(NULL == the_font)\n\t{\n SDL_Log(\"Couldn't load font %s: %s\\n\", resource_file_path, SDL_GetError());\n\t\treturn;\n }\n\t\n\t\n\t\n\t\n\ttext_surface = TTF_RenderText_Blended(the_font, \"FlappyBlurrr\", white_text_color);\n\tbase_texture = SDL_CreateTextureFromSurface(g_mainRenderer, text_surface);\n\t\n\tSDL_QueryTexture(base_texture, &the_format, &the_access, &the_width, &the_height);\n\t\n\t\n\tg_textTextureData.flappyBlurrrTexture = SDL_CreateTexture(g_mainRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, the_width+20, the_height+20);\n\tSDL_assert(NULL != g_textTextureData.flappyBlurrrTexture);\n\tSDL_SetTextureBlendMode(g_textTextureData.flappyBlurrrTexture, SDL_BLENDMODE_BLEND);\n\t\n\t\n\t\n\t\n\tSDL_SetRenderTarget(g_mainRenderer, g_textTextureData.flappyBlurrrTexture);\n\t\n\t// Clear screen\n\tSDL_SetRenderDrawColor(g_mainRenderer, 0, 0, 0, 0 );\n\tSDL_RenderClear(g_mainRenderer );\n\t\n\t\n\t{\n\t\tSDL_Rect dst_rect_center = {10, 10, the_width, the_height};\n\t\tSDL_Rect dst_rect;\n\t\t\n#if 0\n\t\t//\t\t\tSDL_Rect dst_rect = {g_medalBackgroundData.dstRect.w - the_width - RIGHT_MARGIN, 10, g_medalBackgroundData.dstRect.w, g_medalBackgroundData.dstRect.h};\n\t\tSDL_SetTextureColorMod(base_texture, 0, 0, 0);\n\t\tdst_rect = dst_rect_center;\n\t\t\n\t\t// left-top\n\t\tdst_rect.x = dst_rect.x - 10;\n\t\tdst_rect.y = dst_rect.y - 10;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t// right-top\n\t\tdst_rect.x = dst_rect.x + 20;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t// right-bottom\n\t\tdst_rect.y = dst_rect.y + 20;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t// left-bottom\n\t\tdst_rect.x = dst_rect.x - 20;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t// recenter\n\t\tdst_rect = dst_rect_center;\n\t\t// left\n\t\tdst_rect.x = dst_rect.x - 10;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t// right\n\t\tdst_rect.x = dst_rect.x + 20;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t// recenter\n\t\tdst_rect = dst_rect_center;\n\t\t\n\t\t// bottom\n\t\tdst_rect.y = dst_rect.y - 10;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t// top\n\t\tdst_rect.y = dst_rect.y + 20;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t\n\t\t// recenter\n\t\tdst_rect = dst_rect_center;\n\t\t\n\t\t\n\t\tSDL_SetTextureColorMod(base_texture, 255, 255, 255);\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n#endif\n\t\t\n\t\t\n\t\tdst_rect = dst_rect_center;\n\t\tSDL_SetTextureColorMod(base_texture, 0, 0, 0);\n\t\t\n//\t\tdst_rect.x = dst_rect.x + 4;\n\t\tdst_rect.y = dst_rect.y + 8;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t\n\t\tdst_rect.x = dst_rect.x + 4;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\tdst_rect.x = dst_rect.x - 8;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t\n\t\t\n\t\tdst_rect = dst_rect_center;\n\t\tSDL_SetTextureColorMod(base_texture, 0, 0, 0);\n\n\t\tdst_rect.x = dst_rect.x - 4;\n\t\tdst_rect.y = dst_rect.y - 4;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\tdst_rect.x = dst_rect.x + 8;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\tdst_rect.y = dst_rect.y + 8;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\tdst_rect.x = dst_rect.x - 8;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n/*\n\t\t// recenter\n\t\tdst_rect = dst_rect_center;\n\t\t// left\n\t\tdst_rect.x = dst_rect.x - 6;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t// right\n\t\tdst_rect.x = dst_rect.x + 12;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t// recenter\n\t\tdst_rect = dst_rect_center;\n\t\t\n\t\t// bottom\n\t\tdst_rect.y = dst_rect.y - 6;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t// top\n\t\tdst_rect.y = dst_rect.y + 12;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n*/\n\t\t\n\t\t\n\t\tdst_rect = dst_rect_center;\n\t\t\n\t\tSDL_SetTextureColorMod(base_texture, 255, 255, 255);\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t}\n\t\n\t\n\tSDL_SetRenderTarget(g_mainRenderer, NULL);\n\t\n\t\n\tSDL_DestroyTexture(base_texture);\n\tSDL_FreeSurface(text_surface);\n\t\n\tTTF_CloseFont(the_font);\n\t\n#endif\n}\n\n\n\nvoid Flappy_CreateTaglineTexture()\n{\n#if 1\n\tSDL_Color white_text_color = { 255, 255, 255, 0 };\n\tSDL_Color black_text_color = { 0, 0, 0, 0 };\n\tSDL_Color green_text_color = { 64, 128, 0, 255 };\n\t\n\tSDL_Surface* text_surface = NULL;\n\tTTF_Font* the_font = NULL;\n\tSDL_Texture* base_texture;\n\t\n\tUint32 the_format;\n\tint the_access;\n\tint the_width;\n\tint the_height;\n\t\n\t\n\t\n#define MAX_FILE_STRING_LENGTH 2048\n\tchar resource_file_path[MAX_FILE_STRING_LENGTH];\n\t\n\tBlurrrCore_GetResourceDirectoryString(resource_file_path, MAX_FILE_STRING_LENGTH);\n\tSDL_strlcat(resource_file_path, \"acknowtt.ttf\", MAX_FILE_STRING_LENGTH);\n//\tSDL_strlcat(resource_file_path, \"VeraMono.ttf\", MAX_FILE_STRING_LENGTH);\n// SDL_strlcat(resource_file_path, \"04B_19__.TTF\", MAX_FILE_STRING_LENGTH);\n\t\n\t\n the_font = TTF_OpenFont(resource_file_path, 30);\n if(NULL == the_font)\n\t{\n SDL_Log(\"Couldn't load font %s: %s\\n\", resource_file_path, SDL_GetError());\n\t\treturn;\n }\n\t\n\t\n\t\n\t\n\ttext_surface = TTF_RenderText_Blended_Wrapped(the_font, \"A tutorial for making a meticulous\\nFlappy Bird clone with Blurrr SDK\\n\\n http://playcontrol.net\", white_text_color, SCREEN_WIDTH/3 + 120);\n\tbase_texture = SDL_CreateTextureFromSurface(g_mainRenderer, text_surface);\n\t\n\tSDL_QueryTexture(base_texture, &the_format, &the_access, &the_width, &the_height);\n\t\n\t\n\tg_textTextureData.taglineTexture = SDL_CreateTexture(g_mainRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, the_width+10, the_height+10);\n\tSDL_assert(NULL != g_textTextureData.taglineTexture);\n\tSDL_SetTextureBlendMode(g_textTextureData.taglineTexture, SDL_BLENDMODE_BLEND);\n\t\n\t\n\t\n\t\n\tSDL_SetRenderTarget(g_mainRenderer, g_textTextureData.taglineTexture);\n\t\n\t// Clear screen\n\tSDL_SetRenderDrawColor(g_mainRenderer, 0, 0, 0, 0 );\n\tSDL_RenderClear(g_mainRenderer );\n\t\n\t\n\t{\n\t\tSDL_Rect dst_rect_center = {10, 10, the_width, the_height};\n\t\tSDL_Rect dst_rect;\n\t\t\n#if 0\n\t\t//\t\t\tSDL_Rect dst_rect = {g_medalBackgroundData.dstRect.w - the_width - RIGHT_MARGIN, 10, g_medalBackgroundData.dstRect.w, g_medalBackgroundData.dstRect.h};\n\t\tSDL_SetTextureColorMod(base_texture, 0, 0, 0);\n\t\tdst_rect = dst_rect_center;\n\t\t\n\t\t// left-top\n\t\tdst_rect.x = dst_rect.x - 10;\n\t\tdst_rect.y = dst_rect.y - 10;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t// right-top\n\t\tdst_rect.x = dst_rect.x + 20;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t// right-bottom\n\t\tdst_rect.y = dst_rect.y + 20;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t// left-bottom\n\t\tdst_rect.x = dst_rect.x - 20;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t// recenter\n\t\tdst_rect = dst_rect_center;\n\t\t// left\n\t\tdst_rect.x = dst_rect.x - 10;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t// right\n\t\tdst_rect.x = dst_rect.x + 20;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t// recenter\n\t\tdst_rect = dst_rect_center;\n\t\t\n\t\t// bottom\n\t\tdst_rect.y = dst_rect.y - 10;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t// top\n\t\tdst_rect.y = dst_rect.y + 20;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t\n\t\t// recenter\n\t\tdst_rect = dst_rect_center;\n\t\t\n\t\t\n\t\tSDL_SetTextureColorMod(base_texture, 255, 255, 255);\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n#endif\n\t\t\n\t\t/*\n\t\tdst_rect = dst_rect_center;\n\t\tSDL_SetTextureColorMod(base_texture, 0, 0, 0);\n\t\t\n\t\t//\t\tdst_rect.x = dst_rect.x + 4;\n\t\tdst_rect.y = dst_rect.y + 8;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t\n\t\tdst_rect.x = dst_rect.x + 4;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\tdst_rect.x = dst_rect.x - 8;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t*/\n\t\t\n\t\tdst_rect = dst_rect_center;\n\t\tSDL_SetTextureColorMod(base_texture, 0, 0, 0);\n\t\t\n\t\tdst_rect.x = dst_rect.x - 2;\n\t\tdst_rect.y = dst_rect.y - 2;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\tdst_rect.x = dst_rect.x + 4;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\tdst_rect.y = dst_rect.y + 4;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\tdst_rect.x = dst_rect.x - 4;\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t\t/*\n\t\t // recenter\n\t\t dst_rect = dst_rect_center;\n\t\t // left\n\t\t dst_rect.x = dst_rect.x - 6;\n\t\t SDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t \n\t\t // right\n\t\t dst_rect.x = dst_rect.x + 12;\n\t\t SDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t \n\t\t // recenter\n\t\t dst_rect = dst_rect_center;\n\t\t \n\t\t // bottom\n\t\t dst_rect.y = dst_rect.y - 6;\n\t\t SDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t \n\t\t // top\n\t\t dst_rect.y = dst_rect.y + 12;\n\t\t SDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t */\n\t\t\n\t\t\n\t\tdst_rect = dst_rect_center;\n\t\t\n\t\tSDL_SetTextureColorMod(base_texture, 255, 255, 255);\n\t\tSDL_RenderCopy(g_mainRenderer, base_texture, NULL, &dst_rect);\n\t\t\n\t}\n\t\n\t\n\tSDL_SetRenderTarget(g_mainRenderer, NULL);\n\t\n\t\n\tSDL_DestroyTexture(base_texture);\n\tSDL_FreeSurface(text_surface);\n\t\n\tTTF_CloseFont(the_font);\n\t\n#endif\n}\n\n\n\n\nvoid initializeFont()\n{\n#define MAX_FILE_STRING_LENGTH 2048\n\tchar resource_file_path[MAX_FILE_STRING_LENGTH];\n\n\tBlurrrCore_GetResourceDirectoryString(resource_file_path, MAX_FILE_STRING_LENGTH);\n\tSDL_strlcat(resource_file_path, \"VeraMono.ttf\", MAX_FILE_STRING_LENGTH);\n\n\nSDL_Log(\"opening veramono.ttf\");\n s_veraMonoFont = TTF_OpenFont(resource_file_path, 12);\n if(NULL == s_veraMonoFont)\n\t{\n SDL_Log(\"Couldn't load font %s: %s\\n\", resource_file_path, SDL_GetError());\n\t\treturn;\n }\n\t\n\t\nSDL_Log(\"opening acknowtt.ttf\");\n\tBlurrrCore_GetResourceDirectoryString(resource_file_path, MAX_FILE_STRING_LENGTH);\n\tSDL_strlcat(resource_file_path, \"acknowtt.ttf\", MAX_FILE_STRING_LENGTH);\n//\tSDL_strlcat(resource_file_path, \"VeraMono.ttf\", MAX_FILE_STRING_LENGTH);\n\t\n s_retroFontForMainScore = TTF_OpenFont(resource_file_path, 130);\n if(NULL == s_retroFontForMainScore)\n\t{\n SDL_Log(\"Couldn't load font %s: %s\\n\", resource_file_path, SDL_GetError());\n\t\treturn;\n }\n\t\n\t\n\t\n\tg_textTextureData.fontForMedalLabels = TTF_OpenFont(resource_file_path, 56);\n if(NULL == g_textTextureData.fontForMedalLabels)\n\t{\n SDL_Log(\"Couldn't load font %s: %s\\n\", resource_file_path, SDL_GetError());\n }\n\t\n\tg_textTextureData.fontForScoreNumbers = TTF_OpenFont(resource_file_path, 76);\n if(NULL == g_textTextureData.fontForMedalLabels)\n\t{\n SDL_Log(\"Couldn't load font %s: %s\\n\", resource_file_path, SDL_GetError());\n }\n\t\nSDL_Log(\"calling Flappy_UpdateScoreTexture\");\n\t\n\tFlappy_UpdateScoreTexture(0);\n//\tFlappy_CreateGameOverTexture();\nSDL_Log(\"calling Flappy_InitializeGameOverDisplayData\");\n\tFlappy_InitializeGameOverDisplayData(NULL);\nSDL_Log(\"calling Flappy_CreateGetReadyTexture\");\n\tFlappy_CreateGetReadyTexture();\nSDL_Log(\"calling Flappy_CreateFlappyBlurrrTexture\");\n\tFlappy_CreateFlappyBlurrrTexture();\nSDL_Log(\"calling Flappy_CreateTaglineTexture\");\n\tFlappy_CreateTaglineTexture();\n\n}\n\n\n\n#if 0\nstatic int report (lua_State *L, int status) {\n\tconst char *msg;\n\tif (status) {\n\t\tmsg = lua_tostring(L, -1);\n\t\tif (msg == NULL) msg = \"(error with no message)\";\n\t\tSDL_Log(\"status=%d, %s\\n\", status, msg);\n\t\tlua_pop(L, 1);\n\t}\n\treturn status;\n}\n#endif\n\nvoid Flappy_SoundFinishedCallback(ALint which_channel, ALuint al_source, ALmixer_Data* almixer_data, ALboolean finished_naturally, void* user_data)\n{\n\tif(almixer_data == g_gameSounds.crash)\n\t{\n\t\tif(g_birdModelData.isFalling)\n\t\t{\n\t\t\tg_birdModelData.isReadyToPlayFallingSound = SDL_TRUE;\n\t\t}\n\t}\n}\n\ncpBool Flappy_OnScorePointCallback(cpArbiter* the_arbiter, cpSpace* the_space, void* user_data)\n{\n\n\t\n\tALmixer_PlayChannel(-1, g_gameSounds.coin, 0);\n\n\t\n\t\n\tg_gameInstanceData.currentScore = g_gameInstanceData.currentScore + 1;\n\tFlappy_UpdateScoreTexture(g_gameInstanceData.currentScore);\n\t\n\n\t\n\treturn cpFalse;\n\n}\n\n\ncpBool Flappy_OnPipeCollisionCallback(cpArbiter* the_arbiter, cpSpace* the_space, void* user_data)\n{\n\tcpShape* a;\n\tcpShape* b;\n\tint i;\n\t\n/*\n\tcpContactPointSet set = cpArbiterGetContactPointSet(the_arbiter);\n\t//\tSDL_Log(\"set.count: %d\", set.count);\n\tfor(i=0; ip.x, ground_height + g_groundPhysicsData.body->p.y + g_birdModelData.size.y/2));\n\t\t//\t\tcpBodySetPos(g_birdModelData.birdBody, cpv(g_birdModelData.birdBody->p.x, ground_height + g_birdModelData.size.y/2));\n\t\t// TODO: Fix graphics to cap penetration in draw, Chipmunk will correct the penetration by itself eventually\n\t\t\n\t\treturn cpTrue;\n\t}\n\t*/\n//\telse\n\t\n\t// Don't let the bird smack the bottom pipe when falling from the top pipe\n\tif(!g_birdModelData.isDead)\n\t{\n\t\tg_gameInstanceData.diedAtTime = TimeTicker_GetTime(g_gameClock);\n//\t\tSDL_Log(\"hit pipe\");\n\t\tg_birdModelData.isFalling = SDL_TRUE;\n\t\tg_birdModelData.isDead = SDL_TRUE;\n\t\tg_gameInstanceData.needsWhiteOut = SDL_TRUE;\n\t\t\n\t\tALmixer_PlayChannel(-1, g_gameSounds.crash, 0);\n\t\treturn cpFalse;\n\t\t\n\t}\n\treturn cpFalse;\n}\n\ncpBool Flappy_OnGroundCollisionCallback(cpArbiter* the_arbiter, cpSpace* the_space, void* user_data)\n{\n\tcpShape* a;\n\tcpShape* b;\n\tint i;\n\t\n\t/*\n\tcpContactPointSet set = cpArbiterGetContactPointSet(the_arbiter);\n\t//\tSDL_Log(\"set.count: %d\", set.count);\n\tfor(i=0; ip.x, ground_height + g_groundPhysicsData.body->p.y + g_birdModelData.size.y/2));\n//\t\tcpBodySetPos(g_birdModelData.birdBody, cpv(g_birdModelData.birdBody->p.x, ground_height + g_birdModelData.size.y/2));\n\t\t// TODO: Fix graphics to cap penetration in draw, Chipmunk will correct the penetration by itself eventually\n\t\t\n\t\treturn cpTrue;\n\t}\n\t/*\n\telse\n\t{\n\t\tSDL_Log(\"hit pipe\");\n//\t\tg_birdModelData.isFalling = SDL_TRUE;\n\t\tALmixer_PlayChannel(-1, g_gameSounds.crash, 0);\n\t\treturn cpFalse;\n\n\t}\n\t */\n\treturn cpTrue;\n}\n\n\nvoid InitPhysics()\n{\n\tcpFloat mass = 10.0f;\n\tcpFloat moment;\n//\tcpFloat ground_height = (1024/16 * 1.9) * 768 / 1024;\n\n\t\n\tg_mainSpace = cpSpaceNew();\n\tcpSpaceSetIterations(g_mainSpace, 30);\n//\tcpSpaceSetGravity(g_mainSpace, cpv(0, -1300));\n\tcpSpaceSetGravity(g_mainSpace, cpv(0, -1900));\n//\tcpSpaceSetGravity(g_mainSpace, cpv(0, -1500));\n\t//\tcpSpaceSetGravity(s_mainSpace, cpv(0, -10));\n\t//\tcpSpaceSetGravity(s_mainSpace, cpv(0, 0));\n\tcpSpaceSetSleepTimeThreshold(g_mainSpace, 0.5);\n\tcpSpaceSetCollisionSlop(g_mainSpace, 0.5);\n\t\n\t\n\t\n\n\tmoment = cpMomentForBox(mass, g_birdModelData.size.x, g_birdModelData.size.y);\n\tg_birdModelData.birdBody = cpBodyNew(mass, moment);\n//\tcpSpaceAddBody(g_mainSpace, g_birdModelData.birdBody);\n\t\n//\tcpBodySetPos(g_birdModelData.birdBody, cpv( ((g_birdModelData.position.x + g_birdModelData.size.x) / 2.0f),\n\tcpBodySetPos(g_birdModelData.birdBody, cpv( g_birdModelData.position.x,\n\t\t\t\t\t\t\t\t\t\t\t Flappy_InvertY(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t Flappy_lroundf(g_birdModelData.position.y + (g_birdModelData.size.y / 2))\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t ))\n\t\t\t\t );\n\t\n\t// We only want to use velocity for the y-axis because we are already manually computing x-axis movement.\n\tcpBodySetVel(g_birdModelData.birdBody, cpv(0, 0));\n\n\t\n//\tg_birdModelData.birdShape = cpBoxShapeNew(g_birdModelData.birdBody, g_birdModelData.size.x, g_birdModelData.size.y);\n\tg_birdModelData.birdShape = cpCircleShapeNew(g_birdModelData.birdBody, g_birdModelData.size.y/2, cpvzero);\n\tg_birdModelData.birdShape->collision_type = BIRD_COLLISION_TYPE;\n//\tcpSpaceAddShape(g_mainSpace, g_birdModelData.birdShape);\n//\tcpShapeSetElasticity(g_birdModelData.birdShape, 0.0);\n//\tcpShapeSetFriction(g_birdModelData.birdShape, 1000.0);\n\t\n\t\n\t//g_groundPhysicsData.body = cpBodyNew(INFINITY, INFINITY);\n\tg_groundPhysicsData.body = cpBodyNewStatic();\n\tcpBodySetPos(g_groundPhysicsData.body, cpv(0 + SCREEN_WIDTH/2, GROUND_HEIGHT/2.0));\n//\tcpBodySetPos(g_groundPhysicsData.body, cpv(0 + SCREEN_WIDTH/2, GROUND_HEIGHT));\n\t\n//\tcpBodySetVel(g_groundPhysicsData.body, cpv(BIRD_VELOCITY_X, 0));\n\n\t\n\t// size is somewhat arbitrary\n\t// measured 1.9 cm for ground on iPad mini for 1024 pixels\n//\tg_groundPhysicsData.shape = cpBoxShapeNew(g_groundPhysicsData.body, SCREEN_WIDTH, GROUND_HEIGHT);\n\tg_groundPhysicsData.shape = cpBoxShapeNew(g_groundPhysicsData.body, SCREEN_WIDTH, GROUND_HEIGHT);\n//\tcpShapeSetElasticity(g_groundPhysicsData.shape, 0.0);\n//\tcpShapeSetFriction(g_groundPhysicsData.shape, 1000.0);\n\tg_groundPhysicsData.shape->collision_type = GROUND_COLLISION_TYPE;\n\n\t// don't add body to space to make it a \"rogue\" body (intended to be controlled manually). But still must add shape to space.\n\tcpSpaceAddShape(g_mainSpace, g_groundPhysicsData.shape);\n\n\t//cpShapeSetFriction(g_groundPhysicsData.shape, INFINITY);\n//\tcpShapeSetFriction(g_groundPhysicsData.shape, 100000);\n\n\t\n//\tcollisionBird = new cpSpaceAddCollisionHandlerContainer();\n//\tcpSpaceAddCollisionHandler(space, 0, 0, startCollision, null, null, endCollision, collisionBird);\n\t\n\tcpSpaceAddCollisionHandler(g_mainSpace, BIRD_COLLISION_TYPE, GROUND_COLLISION_TYPE, Flappy_OnGroundCollisionCallback, NULL, NULL, NULL, NULL);\n\tcpSpaceAddCollisionHandler(g_mainSpace, BIRD_COLLISION_TYPE, PIPE_COLLISION_TYPE, Flappy_OnPipeCollisionCallback, NULL, NULL, NULL, NULL);\n\tcpSpaceAddCollisionHandler(g_mainSpace, BIRD_COLLISION_TYPE, SCORE_SENSOR_TYPE, Flappy_OnScorePointCallback, NULL, NULL, NULL, NULL);\n\n}\n\nvoid Flappy_SetGameTimeScale(MyFloat new_value)\n{\n\tSint32 channel;\n\tSint32 total_channels = ALmixer_CountTotalChannels();\n\tTimeTicker_SetSpeed(g_gameClock, new_value);\n\tfor(channel=0; channel= GAMESTATE_BIRD_PRELAUNCH) && (g_gameState <= GAMESTATE_MAIN_GAME_ACTIVE))\n {\n\t\tSDL_Log(\"invoke DoFlap, g_gameState=%d\", g_gameState);\n Flappy_DoFlap();\n }\n else if(GAMESTATE_GAME_OVER_WAITING_FOR_USER_ACTION == g_gameState)\n {\n// InitNewGame();\n\t\tALmixer_PlayChannel(-1, g_gameSounds.swoosh, 0);\n\t\tg_gameState = GAMESTATE_FADE_OUT_GAME_OVER;\n\t\tg_gameStateCurrentPhaseStartTime = TimeTicker_GetTime(g_gameClock);\n\t\tSDL_Log(\"invoke GAMESTATE_FADE_OUT_GAME_OVER, g_gameState=%d\", g_gameState);\n }\n\telse if(GAMESTATE_TITLE_SCREEN == g_gameState)\n\t{\n\t\tALmixer_PlayChannel(-1, g_gameSounds.swoosh, 0);\n\t\tg_gameState = GAMESTATE_FADE_OUT_TITLE_SCREEN;\n\t\tg_gameStateCurrentPhaseStartTime = TimeTicker_GetTime(g_gameClock);\n\t\tSDL_Log(\"invoke GAMESTATE_FADE_OUT_TITLE_SCREEN, g_gameState=%d\", g_gameState);\n\t}\n /*\n \n\tif(g_birdModelData.isGameOver)\n\t{\n\t\tInitNewGame();\n\t}\n\telse\n\t{\n\t}\n */\n}\n\nvoid Flappy_DoMouseDown(SDL_MouseButtonEvent the_event)\n{\n if((GAMESTATE_GAME_OVER_WAITING_FOR_USER_ACTION == g_gameState)\n\t || (GAMESTATE_TITLE_SCREEN == g_gameState)\n\t)\n {\n SDL_Rect point_rect = { the_event.x, the_event.y, 1, 1 };\n if(SDL_HasIntersection(&point_rect, &g_guiPlayButton.dstRect))\n {\n g_guiPlayButton.isPressed = SDL_TRUE;\n }\n#if FLAPPY_PROVIDE_QUIT_BUTTON\n else if(SDL_HasIntersection(&point_rect, &g_guiQuitButton.dstRect))\n {\n g_guiQuitButton.isPressed = SDL_TRUE;\n }\n#endif /* FLAPPY_PROVIDE_QUIT_BUTTON */\n }\n else\n {\n Flappy_DoPrimaryAction();\n }\n}\n\nvoid Flappy_DoMouseMoved(SDL_MouseMotionEvent the_event)\n{\n if((GAMESTATE_GAME_OVER_WAITING_FOR_USER_ACTION == g_gameState)\n\t || (GAMESTATE_TITLE_SCREEN == g_gameState)\n\t)\n\t{\n SDL_Rect point_rect = { the_event.x, the_event.y, 1, 1 };\n if((SDL_TRUE == g_guiPlayButton.isPressed) && (SDL_FALSE == SDL_HasIntersection(&point_rect, &g_guiPlayButton.dstRect)))\n {\n g_guiPlayButton.isPressed = SDL_FALSE;\n }\n#if FLAPPY_PROVIDE_QUIT_BUTTON\n else if((SDL_TRUE == g_guiQuitButton.isPressed) && (SDL_FALSE == SDL_HasIntersection(&point_rect, &g_guiQuitButton.dstRect)))\n {\n g_guiQuitButton.isPressed = SDL_FALSE;\n }\n#endif /* FLAPPY_PROVIDE_QUIT_BUTTON */\n\n // Allows for if the person is dragging the mouse-down, leaves the button and goes over a button,\n // the button will now press.\n else if((SDL_TRUE == the_event.state) && (SDL_TRUE == SDL_HasIntersection(&point_rect, &g_guiPlayButton.dstRect)))\n {\n g_guiPlayButton.isPressed = SDL_TRUE;\n }\n#if FLAPPY_PROVIDE_QUIT_BUTTON\n else if((SDL_TRUE == the_event.state) && (SDL_TRUE == SDL_HasIntersection(&point_rect, &g_guiQuitButton.dstRect)))\n {\n g_guiQuitButton.isPressed = SDL_TRUE;\n }\n#endif /* FLAPPY_PROVIDE_QUIT_BUTTON */\n \n }\n else\n {\n }\n}\n\nvoid Flappy_DoMouseUp(SDL_MouseButtonEvent the_event)\n{\n if((GAMESTATE_GAME_OVER_WAITING_FOR_USER_ACTION == g_gameState)\n\t\t|| (GAMESTATE_TITLE_SCREEN == g_gameState)\n\t)\n {\n SDL_Rect point_rect = { the_event.x, the_event.y, 1, 1 };\n if(SDL_TRUE == g_guiPlayButton.isPressed)\n {\n g_guiPlayButton.isPressed = SDL_FALSE;\n Flappy_DoPrimaryAction();\n }\n#if FLAPPY_PROVIDE_QUIT_BUTTON\n else if(SDL_TRUE == g_guiQuitButton.isPressed)\n {\n SDL_QuitEvent quit_event = { SDL_QUIT, SDL_GetTicks() };\n SDL_Event quit_event_union;\n quit_event_union.quit = quit_event;\n\n g_guiQuitButton.isPressed = SDL_FALSE;\n \n SDL_PushEvent(&quit_event_union);\n }\n#endif /* FLAPPY_PROVIDE_QUIT_BUTTON */\n }\n else\n {\n // Don't do PrimaryAction because we only want to do it on mouse down\n }\n}\n\n\n\nvoid Flappy_DoLeftAction()\n{\n if((GAMESTATE_GAME_OVER_WAITING_FOR_USER_ACTION == g_gameState)\n\t || (GAMESTATE_TITLE_SCREEN == g_gameState)\n\t)\n {\n#if FLAPPY_PROVIDE_QUIT_BUTTON\n if(SDL_TRUE == g_guiQuitButton.isSelected)\n {\n g_guiQuitButton.isSelected = SDL_FALSE;\n g_guiPlayButton.isSelected = SDL_TRUE;\n }\n#endif /* FLAPPY_PROVIDE_QUIT_BUTTON */\n }\n}\n\nvoid Flappy_DoRightAction()\n{\n if((GAMESTATE_GAME_OVER_WAITING_FOR_USER_ACTION == g_gameState)\n\t || (GAMESTATE_TITLE_SCREEN == g_gameState)\n\t)\n {\n#if FLAPPY_PROVIDE_QUIT_BUTTON\n if(SDL_TRUE == g_guiPlayButton.isSelected)\n {\n g_guiQuitButton.isSelected = SDL_TRUE;\n g_guiPlayButton.isSelected = SDL_FALSE;\n }\n#endif /* FLAPPY_PROVIDE_QUIT_BUTTON */\n }\n}\n\n\nvoid Flappy_DoReturnKeyDownAction()\n{\n\tif((GAMESTATE_GAME_OVER_WAITING_FOR_USER_ACTION == g_gameState)\n\t || (GAMESTATE_TITLE_SCREEN == g_gameState)\n\t)\n\t{\n\t\tif(SDL_TRUE == g_guiPlayButton.isSelected)\n\t\t{\n\t\t\t/* Warning: The mouse, gamepad, and keyboard will fight over this state if users want to break it */\n\t\t\tg_guiPlayButton.isPressed = SDL_TRUE;\n\t\t\tFlappy_DoPrimaryAction();\n\t\t}\n#if FLAPPY_PROVIDE_QUIT_BUTTON\n\t\telse if(SDL_TRUE == g_guiQuitButton.isSelected)\n\t\t{\n\t\t\tSDL_QuitEvent quit_event = { SDL_QUIT, SDL_GetTicks() };\n\t\t\tSDL_Event quit_event_union;\n\t\t\tquit_event_union.quit = quit_event;\n\t\t\t\n\t\t\tg_guiQuitButton.isPressed = SDL_TRUE;\n\n\t\t\tSDL_PushEvent(&quit_event_union);\n\t\t}\n#endif /* FLAPPY_PROVIDE_QUIT_BUTTON */\n\t}\n else\n {\n Flappy_DoPrimaryAction();\n }\n}\n\n\nvoid Flappy_DoReturnKeyUpAction()\n{\n\tif( ((g_gameState >= GAMESTATE_GAME_OVER_WAITING_FOR_USER_ACTION) && (g_gameState <= GAMESTATE_FADE_OUT_GAME_OVER) )\n\t || ((g_gameState >= GAMESTATE_TITLE_SCREEN) && (g_gameState <= GAMESTATE_FADE_OUT_TITLE_SCREEN) )\n\t)\n\t{\n\t\tif(SDL_TRUE == g_guiPlayButton.isSelected)\n\t\t{\n\t\t\t/* Warning: The mouse, gamepad, and keyboard will fight over this state if users want to break it */\n\t\t\tg_guiPlayButton.isPressed = SDL_FALSE;\n\t\t}\n#if FLAPPY_PROVIDE_QUIT_BUTTON\n\t\telse if(SDL_TRUE == g_guiQuitButton.isSelected)\n\t\t{\n\t\t\tg_guiQuitButton.isPressed = SDL_FALSE;\n\t\t}\n#endif /* FLAPPY_PROVIDE_QUIT_BUTTON */\n\t}\n else\n {\n }\n}\n\n\nvoid Flappy_DoUpKeyAction()\n{\n if((GAMESTATE_GAME_OVER_WAITING_FOR_USER_ACTION == g_gameState)\n\t\t|| (GAMESTATE_TITLE_SCREEN == g_gameState)\n\t)\n {\n\n }\n else\n {\n Flappy_DoPrimaryAction();\n }\n}\n\n\n#if 1\nstatic int TemplateHelper_HandleAppEvents(void* user_data, SDL_Event* the_event)\n{\n switch(the_event->type)\n {\n\t\tcase SDL_APP_TERMINATING:\n\t\t\t/* Terminate the app.\n\t\t\t Shut everything down before returning from this function.\n\t\t\t */\n\t\t\tFlappy_SaveHighScoreToStorageIfNeeded();\n\t\t\t\n\t\t\treturn 0;\n\t\tcase SDL_APP_LOWMEMORY:\n\t\t\t/* You will get this when your app is paused and iOS wants more memory.\n\t\t\t Release as much memory as possible.\n\t\t\t */\n\t\t\treturn 0;\n\t\tcase SDL_APP_WILLENTERBACKGROUND:\n\t\t\t/* Prepare your app to go into the background. Stop loops, etc.\n\t\t\t This gets called when the user hits the home button, or gets a call.\n\t\t\t */\n\t\t\tFlappy_SaveHighScoreToStorageIfNeeded();\n\t\t\t\n\t\t\tFlappy_PauseGame();\n\t\t\treturn 0;\n\t\tcase SDL_APP_DIDENTERBACKGROUND:\n\t\t\t/* This will get called if the user accepted whatever sent your app to the background.\n\t\t\t If the user got a phone call and canceled it, you'll instead get an SDL_APP_DIDENTERFOREGROUND event and restart your loops.\n\t\t\t When you get this, you have 5 seconds to save all your state or the app will be terminated.\n\t\t\t Your app is NOT active at this point.\n\t\t\t */\n\t\t\treturn 0;\n\t\tcase SDL_APP_WILLENTERFOREGROUND:\n\t\t\t/* This call happens when your app is coming back to the foreground.\n\t\t\t Restore all your state here.\n\t\t\t */\n\t\t\treturn 0;\n\t\tcase SDL_APP_DIDENTERFOREGROUND:\n\t\t\t/* Restart your loops here.\n\t\t\t Your app is interactive and getting CPU again.\n\t\t\t */\n\t\t\tFlappy_UnpauseGame();\n\t\t\treturn 0;\n\t\tdefault:\n\t\t\t/* No special processing, add it to the event queue */\n\t\t\treturn 1;\n }\n}\n#endif\nstatic\tint g_appDone = 0;\nstatic\tint g_baseTime = 0;\n\nvoid main_loop()\n{\n\tSDL_Window *window = g_mainWindow;\n SDL_Renderer *renderer = g_mainRenderer;\n Uint32 startFrame = 0;\n Uint32 endFrame;\n Sint32 delay;\n int done;\n Uint32 last_frame_time;\n Uint32 current_frame_time;\n Uint32 delta_time;\n Uint32 base_time;\n\tstatic Uint32 my_fps_print_timer = 0;\n\n\tdone = 0;\n\tg_appDone = done;\t\n\t\tSDL_Event event;\n\t\tint the_result;\n\n\t/* We use TimeTicker for game time stuff, where time (the game) can be paused, or reset for a new game. */\n//\tbase_time = TimeTicker_UpdateTime(g_gameClock);\n\tbase_time = g_baseTime;\n\n\n\n\t\tlast_frame_time = TimeTicker_GetTime(g_gameClock);\n\t\tcurrent_frame_time = TimeTicker_UpdateTime(g_gameClock);\n\n startFrame = SDL_GetTicks();\n\t\t\n\t\t\n\t\tdelta_time = current_frame_time - last_frame_time;\n//\t\tSDL_Log(\"current_frame_time=%d, last_frame_time=%d\", current_frame_time, last_frame_time);\n\t\tdelta_time = SDL_abs(delta_time);\n\n#if 1\n\t\t\n//\t\t\tSDL_Log(\"start pollevent\");\n\t\t/* Check for events */\n\t\tdo\n\t\t{\n\t\t\tthe_result = SDL_PollEvent(&event);\n\t\t\tif(the_result > 0)\n\t\t\t{\n\t\t\t\tswitch (event.type)\n\t\t\t\t{\n\n\t\t\t\t\tcase SDL_MOUSEMOTION:\n\t\t\t\t\t//\tSDL_Log(\"SDL_MOUSEMOTION, %d\", the_result);\n Flappy_DoMouseMoved(event.motion);\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase SDL_MOUSEBUTTONDOWN:\n//\t\t\t\t\t\tSDL_Log(\"SDL_MOUSEBUTTONDOWN, %d\", the_result);\n \n//\t\t\t\t\t\tFlappy_DoPrimaryAction();\n Flappy_DoMouseDown(event.button);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase SDL_MOUSEBUTTONUP:\n //\tSDL_Log(\"SDL_MOUSEBUTTONDOWN, %d\", the_result);\n Flappy_DoMouseUp(event.button);\n//\t\t\t\t\t\tFlappy_DoPrimaryAction();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase SDL_KEYDOWN:\n//\t\t\t\t\t\tSDL_Log(\"SDL_KEYDOWN, %d\", the_result);\n\t\t\t\t\t\tif(SDLK_AC_BACK == event.key.keysym.sym)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tSDL_Log(\"Android back button pressed, going to quit, %d\", the_result);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tdone = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if(SDLK_SPACE == event.key.keysym.sym)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tFlappy_DoReturnKeyDownAction();\n\t\t\t//\t\t\tFlappy_DoPrimaryAction();\n\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if(SDLK_UP == event.key.keysym.sym)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tFlappy_DoUpKeyAction();\n\t\t\t\t\t\t}\n else if(SDLK_LEFT == event.key.keysym.sym)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tFlappy_DoLeftAction();\n\t\t\t\t\t\t}\n else if(SDLK_RIGHT == event.key.keysym.sym)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tFlappy_DoRightAction();\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\telse if(SDLK_RETURN == event.key.keysym.sym)\n\t\t\t\t\t\t{\n\n\t\t\t\t\t\t\t/* CMD-Enter (Mac) or Ctrl-Enter (everybody else) to toggle fullscreen */\n#if __MACOSX__\n\t\t\t\t\t\t\tif(event.key.keysym.mod & KMOD_GUI)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tTemplateHelper_ToggleFullScreen(g_mainWindow, g_mainRenderer);\n\t\t\t\t\t\t\t}\n#else\n\t\t\t\t\t\t\tif(event.key.keysym.mod & KMOD_ALT)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tTemplateHelper_ToggleFullScreen(g_mainWindow, g_mainRenderer);\n\t\t\t\t\t\t\t}\n#endif\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tFlappy_DoReturnKeyDownAction();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if(SDLK_RETURN2 == event.key.keysym.sym)\n\t\t\t\t\t\t{\n Flappy_DoReturnKeyDownAction();\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if(SDLK_p == event.key.keysym.sym)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tFlappy_TogglePause();\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t/* CMD-F (Mac) or Ctrl-F (everybody else) to toggle fullscreen */\n\t\t\t\t\t\telse if(SDLK_f == event.key.keysym.sym)\n\t\t\t\t\t\t{\n#if __MACOSX__\n\t\t\t\t\t\t\tif(event.key.keysym.mod & KMOD_GUI)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tTemplateHelper_ToggleFullScreen(g_mainWindow, g_mainRenderer);\n\t\t\t\t\t\t\t}\n#else\n\t\t\t\t\t\t\tif(event.key.keysym.mod & KMOD_CTRL)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tTemplateHelper_ToggleFullScreen(g_mainWindow, g_mainRenderer);\n\t\t\t\t\t\t\t}\n#endif\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tFlappy_DoPrimaryAction();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n#if ! __APPLE__\n\t\t\t\t\t\telse if(SDLK_F4 == event.key.keysym.sym)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif(event.key.keysym.mod & KMOD_ALT)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdone = 1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n#endif\n\t\t\t\t\t\telse if(SDLK_ESCAPE == event.key.keysym.sym)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdone = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\telse if(SDLK_0 == event.key.keysym.sym)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tFlappy_SetGameTimeScale(0.5);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if(SDLK_1 == event.key.keysym.sym)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tFlappy_SetGameTimeScale(1.0);\n\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if(SDLK_2 == event.key.keysym.sym)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tFlappy_SetGameTimeScale(2.0);\n\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if(SDLK_LSHIFT == event.key.keysym.sym)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tFlappy_SetGameTimeScale(0.5);\n\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if(SDLK_RSHIFT == event.key.keysym.sym)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tFlappy_SetGameTimeScale(2.0);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase SDL_KEYUP:\n\t\t\t\t\t\tif(SDLK_LSHIFT == event.key.keysym.sym)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tFlappy_SetGameTimeScale(1.0);\n\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if(SDLK_RSHIFT == event.key.keysym.sym)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tFlappy_SetGameTimeScale(1.0);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if(SDLK_RETURN == event.key.keysym.sym)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t/* CMD-Enter (Mac) or Ctrl-Enter (everybody else) to toggle fullscreen */\n#if __MACOSX__\n\t\t\t\t\t\t\tif(event.key.keysym.mod & KMOD_GUI)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t}\n#else\n\t\t\t\t\t\t\tif(event.key.keysym.mod & KMOD_ALT)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t}\n#endif\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tFlappy_DoReturnKeyUpAction();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if(SDLK_RETURN2 == event.key.keysym.sym)\n\t\t\t\t\t\t{\n Flappy_DoReturnKeyUpAction();\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if(SDLK_SPACE == event.key.keysym.sym)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tFlappy_DoReturnKeyUpAction();\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n#if 1\n\t\t\t\t\tcase SDL_CONTROLLERBUTTONDOWN:\n\t\t\t\t\t\tif(SDL_CONTROLLER_BUTTON_A == event.cbutton.button)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tFlappy_DoReturnKeyDownAction();\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if(SDL_CONTROLLER_BUTTON_LEFTSHOULDER == event.cbutton.button)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tFlappy_SetGameTimeScale(0.5);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER == event.cbutton.button)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tFlappy_SetGameTimeScale(2.0);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if(SDL_CONTROLLER_BUTTON_START == event.cbutton.button)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tFlappy_TogglePause();\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase SDL_CONTROLLERBUTTONUP:\n\t\t\t\t\t\tif(SDL_CONTROLLER_BUTTON_LEFTSHOULDER == event.cbutton.button)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tFlappy_SetGameTimeScale(1.0);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER == event.cbutton.button)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tFlappy_SetGameTimeScale(1.0);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif(SDL_CONTROLLER_BUTTON_A == event.cbutton.button)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tFlappy_DoReturnKeyUpAction();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\n\t\t\t\t\tcase SDL_CONTROLLERDEVICEADDED:\n\t\t\t\t\t\t/* Note: This is the device id, not the instance id */\n\t\t\t\t\t\tFlappy_AddController(event.cdevice.which);\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase SDL_CONTROLLERDEVICEREMOVED:\n\t\t\t\t\t\t/* Note: This is the instance id, not the device id */\n\t\t\t\t\t\tFlappy_RemoveController(event.cdevice.which);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase SDL_CONTROLLERAXISMOTION:\n {\n const Sint16 DEAD_ZONE = 15000; /* !!! FIXME: real deadzone */\n\n /* horizontal axis */\n if(SDL_CONTROLLER_AXIS_LEFTX == event.caxis.axis)\n {\n //SDL_Log(\"event.caxis.value %d\", event.caxis.value);\n if(event.caxis.value < -DEAD_ZONE)\n {\n Flappy_DoLeftAction();\n }\n else if(event.caxis.value > DEAD_ZONE)\n {\n Flappy_DoRightAction();\n }\n }\n\t\t\t\t\t\tbreak;\n }\n#endif\n\t\t\t\t\tcase SDL_WINDOWEVENT:\n\t\t\t\t\t\tswitch(event.window.event)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcase SDL_WINDOWEVENT_HIDDEN:\n\t\t\t\t\t\t\tcase SDL_WINDOWEVENT_MINIMIZED:\n//\t\t\t\t\t\t\t\tFlappy_PauseGame();\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\n\t\t\t\t\tcase SDL_QUIT:\n\t\t\t\t\tcase SDL_APP_TERMINATING:\n//\t\t\t\t\t\tSDL_Log(\"SDL_QUIT, %d\", the_result);\n\t\t\t\t\t\tdone = 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} while(the_result > 0);\n//\t\t\tSDL_Log(\"out of pollevent\");\n\t\t\n#endif\n\t\tALmixer_Update();\n//\t\t\tSDL_Log(\"passed ALmixer_Update \");\n\t\tFlappy_Update(delta_time, base_time, current_frame_time);\n//\t\t\tSDL_Log(\"passed Flappy_Update \");\n\t\trender(renderer);\n//\t\t\tSDL_Log(\"passed render \");\n\n\t\tendFrame = SDL_GetTicks();\n\t\tfpsthink();\n\t\tif( (my_fps_print_timer + 3000) < (endFrame))\n\t\t{\n\t\t\ts_lastRecordedFPS = framespersecond;\n\t\t//\tSDL_Log(\"%f\\n\", framespersecond);\n\n\t\t\tmy_fps_print_timer = endFrame;\n\t\t}\n//#define FPS_CAP\n#ifdef FPS_CAP\n#define SAFE_SLEEP_INTERVAL 10\n /* figure out how much time we have left, and then sleep */\n delay = MILLESECONDS_PER_FRAME - (Sint32)(endFrame - startFrame);\n if (delay <= 0) {\n delay = 0;\n }\n\t\t/*\n\t\telse if(delay < SAFE_SLEEP_INTERVAL)\n\t\t{\n\t\t\twhile((MILLESECONDS_PER_FRAME - (Sint32)(endFrame - startFrame)) >= 0)\n\t\t\t{\n//\t\t\t\tSDL_Delay(0);\n\t\t\t\tendFrame = SDL_GetTicks();\n\n\t\t\t}\n\t\t}\n\t\t */\n\t\t /*\n\t\telse if (delay > MILLESECONDS_PER_FRAME) {\n delay = MILLESECONDS_PER_FRAME;\n//\t\t\tSDL_Delay(delay);\n\t\t\twhile((MILLESECONDS_PER_FRAME - (Sint32)(endFrame - startFrame)) >= 0)\n\t\t\t{\n\t\t\t\t// SDL_Delay(0);\n\t\t\t\tendFrame = SDL_GetTicks();\n\n\t\t\t}\n\n }\n\t\t */\n\t\telse\n\t\t{\n\t\t//\tSDL_Log(\"%d\\n\", delay);\n\t\t\tUint32 remainder;\n\t\t\tUint32 safe_sleep;\n\t\t\tsafe_sleep = (delay / SAFE_SLEEP_INTERVAL) * SAFE_SLEEP_INTERVAL;\n//\t\t\tremainder = delay % SAFE_SLEEP_INTERVAL;\n\t\t\t\n#if 0\n\t\t\tSDL_Delay(safe_sleep);\n\t\t\tendFrame = SDL_GetTicks();\n\t\twhile((MILLESECONDS_PER_FRAME - (Sint32)(endFrame - startFrame)) >= 0)\n\t\t\t{\n//\t\t\t\tSDL_Delay(0);\n\t\t\t\tendFrame = SDL_GetTicks();\n\t\t\t\t\n\t\t\t}\n#else\n//\t\t\tSDL_Delay(delay);\n\n#endif\n\n\t\t}\n\t\tg_appDone = done;\n\t\n#endif\n\n\n}\nint main(int argc, char *argv[])\n{\n SDL_Window *window;\n SDL_Renderer *renderer;\n Uint32 startFrame = 0;\n Uint32 endFrame;\n Sint32 delay;\n int done;\n Uint32 last_frame_time;\n Uint32 current_frame_time;\n Uint32 delta_time;\n Uint32 base_time;\n\n\t//Uint32 my_fps_print_timer = 0;\n\n\tSDL_GameController* gamecontroller = NULL;\n\n\t\n /* initialize SDL */\n\tif (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) < 0)\n//\tif (SDL_Init(SDL_INIT_VIDEO) < 0)\n\t{\n\t\tSDL_Log(\"Could not initialize SDL\");\n\t}\n\n\tif(IMG_Init(IMG_INIT_JPG | IMG_INIT_PNG | IMG_INIT_TIF) < 0)\n\t{\n\t\tSDL_Log(\"Could not initialize SDL_image\");\n\t}\n\n\tif(TTF_Init() < 0)\n\t{\n\t\tSDL_Log(\"Could not initialize SDL_ttf\");\n\t}\n\n\t#ifdef __ANDROID__\n\t{\n\t\tjobject java_activity_context = (jobject)SDL_AndroidGetActivity();\n\t\tALmixer_Android_Init(java_activity_context);\n\t}\n\t#endif\n\tif(ALmixer_Init(0, 0, 0) == AL_FALSE)\n\t{\n\t\tSDL_Log(\"Could not initialize ALmixer\");\n\t}\n\n\n#if 1\n//\tSDL_SetEventFilter(TemplateHelper_HandleAppEvents, NULL);\n\n // SDL_Log(\"SDL_CreateWindow\");\n\t\n //window = SDL_CreateWindow(NULL, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, 0);\n window = SDL_CreateWindow(\"Flappy Blurrr C\", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT,\n\t\t\t\t\t\t\t SDL_WINDOW_RESIZABLE\n\t\t\t\t\t\t\t | SDL_WINDOW_FULLSCREEN_DESKTOP\n\n\t\t\t\t\t\t\t );\n\tif(NULL == window)\n\t{\n SDL_Log(\"SDL_CreateWindow failed\");\n SDL_Log(\"SDL_CreateWindow failed %s\", SDL_GetError());\n\t}\n\telse\n\t{\n// SDL_Log(\"SDL_CreateWindow passed\");\n\t}\n\t\n\tg_mainWindow = window;\n\t\n renderer = SDL_CreateRenderer(window, -1,\n\t\t\t\t\t\t\t\t 0\n\t |\tSDL_RENDERER_PRESENTVSYNC\n\t//\t| SDL_RENDERER_ACCELERATED\n\t);\n\tif(NULL == renderer)\n\t{\n SDL_Log(\"SDL_CreateRenderer failed\");\n SDL_Log(\"SDL_CreateRenderer failed %s\", SDL_GetError());\n\t\t\n\t}\n\telse\n\t{\n SDL_Log(\"SDL_CreateRenderer passed\");\n\t}\n\n\tg_mainRenderer = renderer;\n\n\tSDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, \"nearest\"); // going for an 8-bit retro blocky look, nearest is better than linear\n//\tSDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, \"linear\"); // make the scaled rendering look smoother.\n\tSDL_RenderSetLogicalSize(renderer, SCREEN_WIDTH, SCREEN_HEIGHT);\n\n\t/* We use rand() for pipe heights. Seed srand with results from time() so ever game should be unique. */\n\tsrand(time(NULL));\n\t\n\tg_gameClock = TimeTicker_Create();\ng_gameState = GAMESTATE_TITLE_SCREEN;\n\t\n\t\n\tinitializeFont();\n\n\tinitializeTexture(renderer);\n\n SDL_Log(\"initializeTexture passed\");\n\tFlappy_LoadSounds();\n\tALmixer_SetPlaybackFinishedCallback(Flappy_SoundFinishedCallback, NULL);\n\t\n\tInitPhysics();\n\t\n\tg_highScoreData.savedHighScore = Flappy_LoadSavedHighScoreFromStorage();\n\t\n//\tInitNewGame();\n\tInitTitleScreen();\n\t\n // initializeHappyFaces();\n // SDL_Log(\"initializeHappyFaces passed\");\n // SDL_Log(\"initializeFont passed\");\n#endif\n\t\n\t{\n#define MAX_FILE_STRING_LENGTH 2048\n\n\t\tchar base_path[MAX_FILE_STRING_LENGTH];\n\t\tchar resource_file_path[MAX_FILE_STRING_LENGTH];\n\t\tBlurrrCore_GetResourceDirectoryString(base_path, MAX_FILE_STRING_LENGTH);\n\n\t\tSDL_strlcpy(resource_file_path, base_path, MAX_FILE_STRING_LENGTH);\n\t\tSDL_strlcat(resource_file_path, \"gamecontrollerdb.txt\", MAX_FILE_STRING_LENGTH);\n\t\n\t\tSDL_GameControllerAddMappingsFromFile(resource_file_path);\n//\t\tgamecontroller = SDL_GameControllerOpen(0);\n\t\t\n\t\t{\n\t\t\tint i;\n\t\t\tint number_of_joysticks = SDL_NumJoysticks();\n\t\t\tfor(i=0; i < number_of_joysticks; i++)\n\t\t\t{\n\t\t\t\tFlappy_AddController(0);\n\t\t\t}\n\t\t}\n\n\t\t\n\t}\n\t\n\tdone = 0;\n//\tbase_time = SDL_GetTicks();\n\tTimeTicker_Start(g_gameClock);\n\n\t/* We use SDL_GetTicks() for real time stuff, like for regulating the fps */\n\tstartFrame = SDL_GetTicks();\n\t/* We use TimeTicker for game time stuff, where time (the game) can be paused, or reset for a new game. */\n\tbase_time = TimeTicker_UpdateTime(g_gameClock);\n\tg_baseTime = base_time;\n\t\n SDL_Log(\"entering main loop\");\n\n#ifdef __EMSCRIPTEN__\n emscripten_set_main_loop(main_loop, 0, 1);\n //emscripten_set_main_loop(main_loop, 30, 0);\n// emscripten_set_main_loop(main_loop, 0, 0);\n#else\n while (!g_appDone) {\n main_loop();\n }\n#endif\n\tFlappy_SaveHighScoreToStorageIfNeeded();\n\n\n\tSDL_DestroyTexture(s_textureFPS);\n\tSDL_FreeSurface(s_surfaceFPS);\n\n\tSDL_DestroyTexture(texture);\n\n\tTTF_CloseFont(s_retroFontForMainScore);\n\tTTF_CloseFont(s_veraMonoFont);\n\n\tSDL_free(faces);\n\n\t/* Clean up the SDL library */\n\tALmixer_Quit();\n\tTTF_Quit();\n\tIMG_Quit();\n\tSDL_Quit();\n\treturn(0);\n}\n","/* Copyright (c) 2007 Scott Lembcke\n * \n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n * \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/// @defgroup cpVect cpVect\n/// Chipmunk's 2D vector type along with a handy 2D vector math lib.\n/// @{\n\n/// Constant for the zero vector.\nstatic const cpVect cpvzero = {0.0f,0.0f};\n\n/// Convenience constructor for cpVect structs.\nstatic inline cpVect cpv(const cpFloat x, const cpFloat y)\n{\n\tcpVect v = {x, y};\n\treturn v;\n}\n\n/// Spherical linearly interpolate between v1 and v2.\ncpVect cpvslerp(const cpVect v1, const cpVect v2, const cpFloat t);\n\n/// Spherical linearly interpolate between v1 towards v2 by no more than angle a radians\ncpVect cpvslerpconst(const cpVect v1, const cpVect v2, const cpFloat a);\n\n///\tReturns a string representation of v. Intended mostly for debugging purposes and not production use.\n///\t@attention The string points to a static local and is reset every time the function is called.\n///\tIf you want to print more than one vector you will have to split up your printing onto separate lines.\nchar* cpvstr(const cpVect v);\n\n/// Check if two vectors are equal. (Be careful when comparing floating point numbers!)\nstatic inline cpBool cpveql(const cpVect v1, const cpVect v2)\n{\n\treturn (v1.x == v2.x && v1.y == v2.y);\n}\n\n/// Add two vectors\nstatic inline cpVect cpvadd(const cpVect v1, const cpVect v2)\n{\n\treturn cpv(v1.x + v2.x, v1.y + v2.y);\n}\n\n/// Subtract two vectors.\nstatic inline cpVect cpvsub(const cpVect v1, const cpVect v2)\n{\n\treturn cpv(v1.x - v2.x, v1.y - v2.y);\n}\n\n/// Negate a vector.\nstatic inline cpVect cpvneg(const cpVect v)\n{\n\treturn cpv(-v.x, -v.y);\n}\n\n/// Scalar multiplication.\nstatic inline cpVect cpvmult(const cpVect v, const cpFloat s)\n{\n\treturn cpv(v.x*s, v.y*s);\n}\n\n/// Vector dot product.\nstatic inline cpFloat cpvdot(const cpVect v1, const cpVect v2)\n{\n\treturn v1.x*v2.x + v1.y*v2.y;\n}\n\n/// 2D vector cross product analog.\n/// The cross product of 2D vectors results in a 3D vector with only a z component.\n/// This function returns the magnitude of the z value.\nstatic inline cpFloat cpvcross(const cpVect v1, const cpVect v2)\n{\n\treturn v1.x*v2.y - v1.y*v2.x;\n}\n\n/// Returns a perpendicular vector. (90 degree rotation)\nstatic inline cpVect cpvperp(const cpVect v)\n{\n\treturn cpv(-v.y, v.x);\n}\n\n/// Returns a perpendicular vector. (-90 degree rotation)\nstatic inline cpVect cpvrperp(const cpVect v)\n{\n\treturn cpv(v.y, -v.x);\n}\n\n/// Returns the vector projection of v1 onto v2.\nstatic inline cpVect cpvproject(const cpVect v1, const cpVect v2)\n{\n\treturn cpvmult(v2, cpvdot(v1, v2)/cpvdot(v2, v2));\n}\n\n/// Returns the unit length vector for the given angle (in radians).\nstatic inline cpVect cpvforangle(const cpFloat a)\n{\n\treturn cpv(cpfcos(a), cpfsin(a));\n}\n\n/// Returns the angular direction v is pointing in (in radians).\nstatic inline cpFloat cpvtoangle(const cpVect v)\n{\n\treturn cpfatan2(v.y, v.x);\n}\n\n/// Uses complex number multiplication to rotate v1 by v2. Scaling will occur if v1 is not a unit vector.\nstatic inline cpVect cpvrotate(const cpVect v1, const cpVect v2)\n{\n\treturn cpv(v1.x*v2.x - v1.y*v2.y, v1.x*v2.y + v1.y*v2.x);\n}\n\n/// Inverse of cpvrotate().\nstatic inline cpVect cpvunrotate(const cpVect v1, const cpVect v2)\n{\n\treturn cpv(v1.x*v2.x + v1.y*v2.y, v1.y*v2.x - v1.x*v2.y);\n}\n\n/// Returns the squared length of v. Faster than cpvlength() when you only need to compare lengths.\nstatic inline cpFloat cpvlengthsq(const cpVect v)\n{\n\treturn cpvdot(v, v);\n}\n\n/// Returns the length of v.\nstatic inline cpFloat cpvlength(const cpVect v)\n{\n\treturn cpfsqrt(cpvdot(v, v));\n}\n\n/// Linearly interpolate between v1 and v2.\nstatic inline cpVect cpvlerp(const cpVect v1, const cpVect v2, const cpFloat t)\n{\n\treturn cpvadd(cpvmult(v1, 1.0f - t), cpvmult(v2, t));\n}\n\n/// Returns a normalized copy of v.\nstatic inline cpVect cpvnormalize(const cpVect v)\n{\n\t// Neat trick I saw somewhere to avoid div/0.\n\treturn cpvmult(v, 1.0f/(cpvlength(v) + CPFLOAT_MIN));\n}\n\n/// @deprecated Just an alias for cpvnormalize() now.\nstatic inline cpVect cpvnormalize_safe(const cpVect v)\n{\n\treturn cpvnormalize(v);\n}\n\n/// Clamp v to length len.\nstatic inline cpVect cpvclamp(const cpVect v, const cpFloat len)\n{\n\treturn (cpvdot(v,v) > len*len) ? cpvmult(cpvnormalize(v), len) : v;\n}\n\n/// Linearly interpolate between v1 towards v2 by distance d.\nstatic inline cpVect cpvlerpconst(cpVect v1, cpVect v2, cpFloat d)\n{\n\treturn cpvadd(v1, cpvclamp(cpvsub(v2, v1), d));\n}\n\n/// Returns the distance between v1 and v2.\nstatic inline cpFloat cpvdist(const cpVect v1, const cpVect v2)\n{\n\treturn cpvlength(cpvsub(v1, v2));\n}\n\n/// Returns the squared distance between v1 and v2. Faster than cpvdist() when you only need to compare distances.\nstatic inline cpFloat cpvdistsq(const cpVect v1, const cpVect v2)\n{\n\treturn cpvlengthsq(cpvsub(v1, v2));\n}\n\n/// Returns true if the distance between v1 and v2 is less than dist.\nstatic inline cpBool cpvnear(const cpVect v1, const cpVect v2, const cpFloat dist)\n{\n\treturn cpvdistsq(v1, v2) < dist*dist;\n}\n\n/// @}\n\n/// @defgroup cpMat2x2 cpMat2x2\n/// 2x2 matrix type used for tensors and such.\n/// @{\n\nstatic inline cpMat2x2\ncpMat2x2New(cpFloat a, cpFloat b, cpFloat c, cpFloat d)\n{\n\tcpMat2x2 m = {a, b, c, d};\n\treturn m;\n}\n\nstatic inline cpVect\ncpMat2x2Transform(cpMat2x2 m, cpVect v)\n{\n\treturn cpv(v.x*m.a + v.y*m.b, v.x*m.c + v.y*m.d);\n}\n\n///@}\n","/* Copyright (c) 2007 Scott Lembcke\n * \n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n * \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/// @defgroup cpBody cpBody\n/// Chipmunk's rigid body type. Rigid bodies hold the physical properties of an object like\n/// it's mass, and position and velocity of it's center of gravity. They don't have an shape on their own.\n/// They are given a shape by creating collision shapes (cpShape) that point to the body.\n/// @{\n\n/// Rigid body velocity update function type.\ntypedef void (*cpBodyVelocityFunc)(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt);\n/// Rigid body position update function type.\ntypedef void (*cpBodyPositionFunc)(cpBody *body, cpFloat dt);\n\n/// Used internally to track information on the collision graph.\n/// @private\ntypedef struct cpComponentNode {\n\tcpBody *root;\n\tcpBody *next;\n\tcpFloat idleTime;\n} cpComponentNode;\n\n/// Chipmunk's rigid body struct.\nstruct cpBody {\n\t/// Function that is called to integrate the body's velocity. (Defaults to cpBodyUpdateVelocity)\n\tcpBodyVelocityFunc velocity_func;\n\t\n\t/// Function that is called to integrate the body's position. (Defaults to cpBodyUpdatePosition)\n\tcpBodyPositionFunc position_func;\n\t\n\t/// Mass of the body.\n\t/// Must agree with cpBody.m_inv! Use cpBodySetMass() when changing the mass for this reason.\n\tcpFloat m;\n\t/// Mass inverse.\n\tcpFloat m_inv;\n\t\n\t/// Moment of inertia of the body.\n\t/// Must agree with cpBody.i_inv! Use cpBodySetMoment() when changing the moment for this reason.\n\tcpFloat i;\n\t/// Moment of inertia inverse.\n\tcpFloat i_inv;\n\t\n\t/// Position of the rigid body's center of gravity.\n\tcpVect p;\n\t/// Velocity of the rigid body's center of gravity.\n\tcpVect v;\n\t/// Force acting on the rigid body's center of gravity.\n\tcpVect f;\n\t\n\t/// Rotation of the body around it's center of gravity in radians.\n\t/// Must agree with cpBody.rot! Use cpBodySetAngle() when changing the angle for this reason.\n\tcpFloat a;\n\t/// Angular velocity of the body around it's center of gravity in radians/second.\n\tcpFloat w;\n\t/// Torque applied to the body around it's center of gravity.\n\tcpFloat t;\n\t\n\t/// Cached unit length vector representing the angle of the body.\n\t/// Used for fast rotations using cpvrotate().\n\tcpVect rot;\n\t\n\t/// User definable data pointer.\n\t/// Generally this points to your the game object class so you can access it\n\t/// when given a cpBody reference in a callback.\n\tcpDataPointer data;\n\t\n\t/// Maximum velocity allowed when updating the velocity.\n\tcpFloat v_limit;\n\t/// Maximum rotational rate (in radians/second) allowed when updating the angular velocity.\n\tcpFloat w_limit;\n\t\n\tCP_PRIVATE(cpVect v_bias);\n\tCP_PRIVATE(cpFloat w_bias);\n\t\n\tCP_PRIVATE(cpSpace *space);\n\t\n\tCP_PRIVATE(cpShape *shapeList);\n\tCP_PRIVATE(cpArbiter *arbiterList);\n\tCP_PRIVATE(cpConstraint *constraintList);\n\t\n\tCP_PRIVATE(cpComponentNode node);\n};\n\n/// Allocate a cpBody.\ncpBody* cpBodyAlloc(void);\n/// Initialize a cpBody.\ncpBody* cpBodyInit(cpBody *body, cpFloat m, cpFloat i);\n/// Allocate and initialize a cpBody.\ncpBody* cpBodyNew(cpFloat m, cpFloat i);\n\n/// Initialize a static cpBody.\ncpBody* cpBodyInitStatic(cpBody *body);\n/// Allocate and initialize a static cpBody.\ncpBody* cpBodyNewStatic(void);\n\n/// Destroy a cpBody.\nvoid cpBodyDestroy(cpBody *body);\n/// Destroy and free a cpBody.\nvoid cpBodyFree(cpBody *body);\n\n/// Check that the properties of a body is sane. (Only in debug mode)\n#ifdef NDEBUG\n\t#define\tcpBodyAssertSane(body)\n#else\n\tvoid cpBodySanityCheck(cpBody *body);\n\t#define\tcpBodyAssertSane(body) cpBodySanityCheck(body)\n#endif\n\n// Defined in cpSpace.c\n/// Wake up a sleeping or idle body.\nvoid cpBodyActivate(cpBody *body);\n/// Wake up any sleeping or idle bodies touching a static body.\nvoid cpBodyActivateStatic(cpBody *body, cpShape *filter);\n\n/// Force a body to fall asleep immediately.\nvoid cpBodySleep(cpBody *body);\n/// Force a body to fall asleep immediately along with other bodies in a group.\nvoid cpBodySleepWithGroup(cpBody *body, cpBody *group);\n\n/// Returns true if the body is sleeping.\nstatic inline cpBool cpBodyIsSleeping(const cpBody *body)\n{\n\treturn (CP_PRIVATE(body->node).root != ((cpBody*)0));\n}\n\n/// Returns true if the body is static.\nstatic inline cpBool cpBodyIsStatic(const cpBody *body)\n{\n\treturn CP_PRIVATE(body->node).idleTime == INFINITY;\n}\n\n/// Returns true if the body has not been added to a space.\n/// Note: Static bodies are a subtype of rogue bodies.\nstatic inline cpBool cpBodyIsRogue(const cpBody *body)\n{\n\treturn (body->CP_PRIVATE(space) == ((cpSpace*)0));\n}\n\n\n#define CP_DefineBodyStructGetter(type, member, name) \\\nstatic inline type cpBodyGet##name(const cpBody *body){return body->member;}\n\n#define CP_DefineBodyStructSetter(type, member, name) \\\nstatic inline void cpBodySet##name(cpBody *body, const type value){ \\\n\tcpBodyActivate(body); \\\n\tbody->member = value; \\\n\tcpBodyAssertSane(body); \\\n}\n\n#define CP_DefineBodyStructProperty(type, member, name) \\\nCP_DefineBodyStructGetter(type, member, name) \\\nCP_DefineBodyStructSetter(type, member, name)\n\n// TODO add to docs\nCP_DefineBodyStructGetter(cpSpace*, CP_PRIVATE(space), Space)\n\nCP_DefineBodyStructGetter(cpFloat, m, Mass)\n/// Set the mass of a body.\nvoid cpBodySetMass(cpBody *body, cpFloat m);\n\nCP_DefineBodyStructGetter(cpFloat, i, Moment)\n/// Set the moment of a body.\nvoid cpBodySetMoment(cpBody *body, cpFloat i);\n\nCP_DefineBodyStructGetter(cpVect, p, Pos)\n/// Set the position of a body.\nvoid cpBodySetPos(cpBody *body, cpVect pos);\nCP_DefineBodyStructProperty(cpVect, v, Vel)\nCP_DefineBodyStructProperty(cpVect, f, Force)\nCP_DefineBodyStructGetter(cpFloat, a, Angle)\n/// Set the angle of a body.\nvoid cpBodySetAngle(cpBody *body, cpFloat a);\nCP_DefineBodyStructProperty(cpFloat, w, AngVel)\nCP_DefineBodyStructProperty(cpFloat, t, Torque)\nCP_DefineBodyStructGetter(cpVect, rot, Rot)\nCP_DefineBodyStructProperty(cpFloat, v_limit, VelLimit)\nCP_DefineBodyStructProperty(cpFloat, w_limit, AngVelLimit)\nCP_DefineBodyStructProperty(cpDataPointer, data, UserData)\n\n/// Default Integration functions.\nvoid cpBodyUpdateVelocity(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt);\nvoid cpBodyUpdatePosition(cpBody *body, cpFloat dt);\n\n/// Convert body relative/local coordinates to absolute/world coordinates.\nstatic inline cpVect cpBodyLocal2World(const cpBody *body, const cpVect v)\n{\n\treturn cpvadd(body->p, cpvrotate(v, body->rot));\n}\n\n/// Convert body absolute/world coordinates to relative/local coordinates.\nstatic inline cpVect cpBodyWorld2Local(const cpBody *body, const cpVect v)\n{\n\treturn cpvunrotate(cpvsub(v, body->p), body->rot);\n}\n\n/// Set the forces and torque or a body to zero.\nvoid cpBodyResetForces(cpBody *body);\n/// Apply an force (in world coordinates) to the body at a point relative to the center of gravity (also in world coordinates).\nvoid cpBodyApplyForce(cpBody *body, const cpVect f, const cpVect r);\n/// Apply an impulse (in world coordinates) to the body at a point relative to the center of gravity (also in world coordinates).\nvoid cpBodyApplyImpulse(cpBody *body, const cpVect j, const cpVect r);\n\n/// Get the velocity on a body (in world units) at a point on the body in world coordinates.\ncpVect cpBodyGetVelAtWorldPoint(cpBody *body, cpVect point);\n/// Get the velocity on a body (in world units) at a point on the body in local coordinates.\ncpVect cpBodyGetVelAtLocalPoint(cpBody *body, cpVect point);\n\n\n/// Get the kinetic energy of a body.\nstatic inline cpFloat cpBodyKineticEnergy(const cpBody *body)\n{\n\t// Need to do some fudging to avoid NaNs\n\tcpFloat vsq = cpvdot(body->v, body->v);\n\tcpFloat wsq = body->w*body->w;\n\treturn (vsq ? vsq*body->m : 0.0f) + (wsq ? wsq*body->i : 0.0f);\n}\n\n/// Body/shape iterator callback function type. \ntypedef void (*cpBodyShapeIteratorFunc)(cpBody *body, cpShape *shape, void *data);\n/// Call @c func once for each shape attached to @c body and added to the space.\nvoid cpBodyEachShape(cpBody *body, cpBodyShapeIteratorFunc func, void *data);\n\n/// Body/constraint iterator callback function type. \ntypedef void (*cpBodyConstraintIteratorFunc)(cpBody *body, cpConstraint *constraint, void *data);\n/// Call @c func once for each constraint attached to @c body and added to the space.\nvoid cpBodyEachConstraint(cpBody *body, cpBodyConstraintIteratorFunc func, void *data);\n\n/// Body/arbiter iterator callback function type. \ntypedef void (*cpBodyArbiterIteratorFunc)(cpBody *body, cpArbiter *arbiter, void *data);\n/// Call @c func once for each arbiter that is currently active on the body.\nvoid cpBodyEachArbiter(cpBody *body, cpBodyArbiterIteratorFunc func, void *data);\n\n///@}\n","/* Copyright (c) 2007 Scott Lembcke\n * \n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n * \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/// @defgroup cpSpace cpSpace\n/// @{\n\ntypedef struct cpContactBufferHeader cpContactBufferHeader;\ntypedef void (*cpSpaceArbiterApplyImpulseFunc)(cpArbiter *arb);\n\n/// Basic Unit of Simulation in Chipmunk\nstruct cpSpace {\n\t/// Number of iterations to use in the impulse solver to solve contacts.\n\tint iterations;\n\t\n\t/// Gravity to pass to rigid bodies when integrating velocity.\n\tcpVect gravity;\n\t\n\t/// Damping rate expressed as the fraction of velocity bodies retain each second.\n\t/// A value of 0.9 would mean that each body's velocity will drop 10% per second.\n\t/// The default value is 1.0, meaning no damping is applied.\n\t/// @note This damping value is different than those of cpDampedSpring and cpDampedRotarySpring.\n\tcpFloat damping;\n\t\n\t/// Speed threshold for a body to be considered idle.\n\t/// The default value of 0 means to let the space guess a good threshold based on gravity.\n\tcpFloat idleSpeedThreshold;\n\t\n\t/// Time a group of bodies must remain idle in order to fall asleep.\n\t/// Enabling sleeping also implicitly enables the the contact graph.\n\t/// The default value of INFINITY disables the sleeping algorithm.\n\tcpFloat sleepTimeThreshold;\n\t\n\t/// Amount of encouraged penetration between colliding shapes.\n\t/// Used to reduce oscillating contacts and keep the collision cache warm.\n\t/// Defaults to 0.1. If you have poor simulation quality,\n\t/// increase this number as much as possible without allowing visible amounts of overlap.\n\tcpFloat collisionSlop;\n\t\n\t/// Determines how fast overlapping shapes are pushed apart.\n\t/// Expressed as a fraction of the error remaining after each second.\n\t/// Defaults to pow(1.0 - 0.1, 60.0) meaning that Chipmunk fixes 10% of overlap each frame at 60Hz.\n\tcpFloat collisionBias;\n\t\n\t/// Number of frames that contact information should persist.\n\t/// Defaults to 3. There is probably never a reason to change this value.\n\tcpTimestamp collisionPersistence;\n\t\n\t/// Rebuild the contact graph during each step. Must be enabled to use the cpBodyEachArbiter() function.\n\t/// Disabled by default for a small performance boost. Enabled implicitly when the sleeping feature is enabled.\n\tcpBool enableContactGraph;\n\t\n\t/// User definable data pointer.\n\t/// Generally this points to your game's controller or game state\n\t/// class so you can access it when given a cpSpace reference in a callback.\n\tcpDataPointer data;\n\t\n\t/// The designated static body for this space.\n\t/// You can modify this body, or replace it with your own static body.\n\t/// By default it points to a statically allocated cpBody in the cpSpace struct.\n\tcpBody *staticBody;\n\t\n\tCP_PRIVATE(cpTimestamp stamp);\n\tCP_PRIVATE(cpFloat curr_dt);\n\n\tCP_PRIVATE(cpArray *bodies);\n\tCP_PRIVATE(cpArray *rousedBodies);\n\tCP_PRIVATE(cpArray *sleepingComponents);\n\t\n\tCP_PRIVATE(cpSpatialIndex *staticShapes);\n\tCP_PRIVATE(cpSpatialIndex *activeShapes);\n\t\n\tCP_PRIVATE(cpArray *arbiters);\n\tCP_PRIVATE(cpContactBufferHeader *contactBuffersHead);\n\tCP_PRIVATE(cpHashSet *cachedArbiters);\n\tCP_PRIVATE(cpArray *pooledArbiters);\n\tCP_PRIVATE(cpArray *constraints);\n\t\n\tCP_PRIVATE(cpArray *allocatedBuffers);\n\tCP_PRIVATE(int locked);\n\t\n\tCP_PRIVATE(cpHashSet *collisionHandlers);\n\tCP_PRIVATE(cpCollisionHandler defaultHandler);\n\t\n\tCP_PRIVATE(cpBool skipPostStep);\n\tCP_PRIVATE(cpArray *postStepCallbacks);\n\t\n\tCP_PRIVATE(cpBody _staticBody);\n};\n\n/// Allocate a cpSpace.\ncpSpace* cpSpaceAlloc(void);\n/// Initialize a cpSpace.\ncpSpace* cpSpaceInit(cpSpace *space);\n/// Allocate and initialize a cpSpace.\ncpSpace* cpSpaceNew(void);\n\n/// Destroy a cpSpace.\nvoid cpSpaceDestroy(cpSpace *space);\n/// Destroy and free a cpSpace.\nvoid cpSpaceFree(cpSpace *space);\n\n#define CP_DefineSpaceStructGetter(type, member, name) \\\nstatic inline type cpSpaceGet##name(const cpSpace *space){return space->member;}\n\n#define CP_DefineSpaceStructSetter(type, member, name) \\\nstatic inline void cpSpaceSet##name(cpSpace *space, type value){space->member = value;}\n\n#define CP_DefineSpaceStructProperty(type, member, name) \\\nCP_DefineSpaceStructGetter(type, member, name) \\\nCP_DefineSpaceStructSetter(type, member, name)\n\nCP_DefineSpaceStructProperty(int, iterations, Iterations)\nCP_DefineSpaceStructProperty(cpVect, gravity, Gravity)\nCP_DefineSpaceStructProperty(cpFloat, damping, Damping)\nCP_DefineSpaceStructProperty(cpFloat, idleSpeedThreshold, IdleSpeedThreshold)\nCP_DefineSpaceStructProperty(cpFloat, sleepTimeThreshold, SleepTimeThreshold)\nCP_DefineSpaceStructProperty(cpFloat, collisionSlop, CollisionSlop)\nCP_DefineSpaceStructProperty(cpFloat, collisionBias, CollisionBias)\nCP_DefineSpaceStructProperty(cpTimestamp, collisionPersistence, CollisionPersistence)\nCP_DefineSpaceStructProperty(cpBool, enableContactGraph, EnableContactGraph)\nCP_DefineSpaceStructProperty(cpDataPointer, data, UserData)\nCP_DefineSpaceStructGetter(cpBody*, staticBody, StaticBody)\nCP_DefineSpaceStructGetter(cpFloat, CP_PRIVATE(curr_dt), CurrentTimeStep)\n\n/// returns true from inside a callback and objects cannot be added/removed.\nstatic inline cpBool\ncpSpaceIsLocked(cpSpace *space)\n{\n\treturn space->CP_PRIVATE(locked);\n}\n\n/// Set a default collision handler for this space.\n/// The default collision handler is invoked for each colliding pair of shapes\n/// that isn't explicitly handled by a specific collision handler.\n/// You can pass NULL for any function you don't want to implement.\nvoid cpSpaceSetDefaultCollisionHandler(\n\tcpSpace *space,\n\tcpCollisionBeginFunc begin,\n\tcpCollisionPreSolveFunc preSolve,\n\tcpCollisionPostSolveFunc postSolve,\n\tcpCollisionSeparateFunc separate,\n\tvoid *data\n);\n\n/// Set a collision handler to be used whenever the two shapes with the given collision types collide.\n/// You can pass NULL for any function you don't want to implement.\nvoid cpSpaceAddCollisionHandler(\n\tcpSpace *space,\n\tcpCollisionType a, cpCollisionType b,\n\tcpCollisionBeginFunc begin,\n\tcpCollisionPreSolveFunc preSolve,\n\tcpCollisionPostSolveFunc postSolve,\n\tcpCollisionSeparateFunc separate,\n\tvoid *data\n);\n\n/// Unset a collision handler.\nvoid cpSpaceRemoveCollisionHandler(cpSpace *space, cpCollisionType a, cpCollisionType b);\n\n/// Add a collision shape to the simulation.\n/// If the shape is attached to a static body, it will be added as a static shape.\ncpShape* cpSpaceAddShape(cpSpace *space, cpShape *shape);\n/// Explicity add a shape as a static shape to the simulation.\ncpShape* cpSpaceAddStaticShape(cpSpace *space, cpShape *shape);\n/// Add a rigid body to the simulation.\ncpBody* cpSpaceAddBody(cpSpace *space, cpBody *body);\n/// Add a constraint to the simulation.\ncpConstraint* cpSpaceAddConstraint(cpSpace *space, cpConstraint *constraint);\n\n/// Remove a collision shape from the simulation.\nvoid cpSpaceRemoveShape(cpSpace *space, cpShape *shape);\n/// Remove a collision shape added using cpSpaceAddStaticShape() from the simulation.\nvoid cpSpaceRemoveStaticShape(cpSpace *space, cpShape *shape);\n/// Remove a rigid body from the simulation.\nvoid cpSpaceRemoveBody(cpSpace *space, cpBody *body);\n/// Remove a constraint from the simulation.\nvoid cpSpaceRemoveConstraint(cpSpace *space, cpConstraint *constraint);\n\n/// Test if a collision shape has been added to the space.\ncpBool cpSpaceContainsShape(cpSpace *space, cpShape *shape);\n/// Test if a rigid body has been added to the space.\ncpBool cpSpaceContainsBody(cpSpace *space, cpBody *body);\n/// Test if a constraint has been added to the space.\ncpBool cpSpaceContainsConstraint(cpSpace *space, cpConstraint *constraint);\n\n/// Convert a dynamic rogue body to a static one.\n/// If the body is active, you must remove it from the space first.\nvoid cpSpaceConvertBodyToStatic(cpSpace *space, cpBody *body);\n/// Convert a body to a dynamic rogue body.\n/// If you want the body to be active after the transition, you must add it to the space also.\nvoid cpSpaceConvertBodyToDynamic(cpSpace *space, cpBody *body, cpFloat mass, cpFloat moment);\n\n/// Post Step callback function type.\ntypedef void (*cpPostStepFunc)(cpSpace *space, void *key, void *data);\n/// Schedule a post-step callback to be called when cpSpaceStep() finishes.\n/// You can only register one callback per unique value for @c key.\n/// Returns true only if @c key has never been scheduled before.\n/// It's possible to pass @c NULL for @c func if you only want to mark @c key as being used.\ncpBool cpSpaceAddPostStepCallback(cpSpace *space, cpPostStepFunc func, void *key, void *data);\n\n/// Point query callback function type.\ntypedef void (*cpSpacePointQueryFunc)(cpShape *shape, void *data);\n/// Query the space at a point and call @c func for each shape found.\nvoid cpSpacePointQuery(cpSpace *space, cpVect point, cpLayers layers, cpGroup group, cpSpacePointQueryFunc func, void *data);\n/// Query the space at a point and return the first shape found. Returns NULL if no shapes were found.\ncpShape *cpSpacePointQueryFirst(cpSpace *space, cpVect point, cpLayers layers, cpGroup group);\n\n/// Nearest point query callback function type.\ntypedef void (*cpSpaceNearestPointQueryFunc)(cpShape *shape, cpFloat distance, cpVect point, void *data);\n/// Query the space at a point and call @c func for each shape found.\nvoid cpSpaceNearestPointQuery(cpSpace *space, cpVect point, cpFloat maxDistance, cpLayers layers, cpGroup group, cpSpaceNearestPointQueryFunc func, void *data);\n/// Query the space at a point and return the nearest shape found. Returns NULL if no shapes were found.\ncpShape *cpSpaceNearestPointQueryNearest(cpSpace *space, cpVect point, cpFloat maxDistance, cpLayers layers, cpGroup group, cpNearestPointQueryInfo *out);\n\n/// Segment query callback function type.\ntypedef void (*cpSpaceSegmentQueryFunc)(cpShape *shape, cpFloat t, cpVect n, void *data);\n/// Perform a directed line segment query (like a raycast) against the space calling @c func for each shape intersected.\nvoid cpSpaceSegmentQuery(cpSpace *space, cpVect start, cpVect end, cpLayers layers, cpGroup group, cpSpaceSegmentQueryFunc func, void *data);\n/// Perform a directed line segment query (like a raycast) against the space and return the first shape hit. Returns NULL if no shapes were hit.\ncpShape *cpSpaceSegmentQueryFirst(cpSpace *space, cpVect start, cpVect end, cpLayers layers, cpGroup group, cpSegmentQueryInfo *out);\n\n/// Rectangle Query callback function type.\ntypedef void (*cpSpaceBBQueryFunc)(cpShape *shape, void *data);\n/// Perform a fast rectangle query on the space calling @c func for each shape found.\n/// Only the shape's bounding boxes are checked for overlap, not their full shape.\nvoid cpSpaceBBQuery(cpSpace *space, cpBB bb, cpLayers layers, cpGroup group, cpSpaceBBQueryFunc func, void *data);\n\n/// Shape query callback function type.\ntypedef void (*cpSpaceShapeQueryFunc)(cpShape *shape, cpContactPointSet *points, void *data);\n/// Query a space for any shapes overlapping the given shape and call @c func for each shape found.\ncpBool cpSpaceShapeQuery(cpSpace *space, cpShape *shape, cpSpaceShapeQueryFunc func, void *data);\n\n/// Call cpBodyActivate() for any shape that is overlaps the given shape.\nvoid cpSpaceActivateShapesTouchingShape(cpSpace *space, cpShape *shape);\n\n\n/// Space/body iterator callback function type.\ntypedef void (*cpSpaceBodyIteratorFunc)(cpBody *body, void *data);\n/// Call @c func for each body in the space.\nvoid cpSpaceEachBody(cpSpace *space, cpSpaceBodyIteratorFunc func, void *data);\n\n/// Space/body iterator callback function type.\ntypedef void (*cpSpaceShapeIteratorFunc)(cpShape *shape, void *data);\n/// Call @c func for each shape in the space.\nvoid cpSpaceEachShape(cpSpace *space, cpSpaceShapeIteratorFunc func, void *data);\n\n/// Space/constraint iterator callback function type.\ntypedef void (*cpSpaceConstraintIteratorFunc)(cpConstraint *constraint, void *data);\n/// Call @c func for each shape in the space.\nvoid cpSpaceEachConstraint(cpSpace *space, cpSpaceConstraintIteratorFunc func, void *data);\n\n/// Update the collision detection info for the static shapes in the space.\nvoid cpSpaceReindexStatic(cpSpace *space);\n/// Update the collision detection data for a specific shape in the space.\nvoid cpSpaceReindexShape(cpSpace *space, cpShape *shape);\n/// Update the collision detection data for all shapes attached to a body.\nvoid cpSpaceReindexShapesForBody(cpSpace *space, cpBody *body);\n\n/// Switch the space to use a spatial has as it's spatial index.\nvoid cpSpaceUseSpatialHash(cpSpace *space, cpFloat dim, int count);\n\n/// Step the space forward in time by @c dt.\nvoid cpSpaceStep(cpSpace *space, cpFloat dt);\n\n/// @}\n"]}