void BulletUpdate(ObjectStruct* bulletObject) { //KDebug_Alert("Bullet Update"); bulletObject->x += bulletObject->speedx; bulletObject->y += bulletObject->speedy; bulletObject->sprite.posx = VIRTUAL_TO_PIXEL(bulletObject->x) + scrollData.scrollx_vdp - 4; bulletObject->sprite.posy = VIRTUAL_TO_PIXEL(bulletObject->y) - scrollData.scrolly_vdp - 4; if (bulletObject->visible) { if (collidesWithTile(bulletObject->x, bulletObject->y)) { bulletObject->objectState = OBJECTSTATE_INACTIVE; #ifdef DEBUG_OBJECTS KDebug_Alert("Bullet Hit Background. Creating explosion"); #endif ExplosionCreate(bulletObject->x, bulletObject->y); #ifdef DEBUG_OBJECTS KDebug_Alert("Finished creating explosion"); #endif } } else { bulletObject->objectState = OBJECTSTATE_INACTIVE; } }
ObjectStruct* CreateObject(u16 objectType, ObjectFunctionType updateFunction, ObjectFunctionType destroyFunction, ObjectFunctionType drawFunction, ObjectCollisionFunctionType collisionFunction) { if (!CanCreateObject(objectType)) { return 0; } // Tries to find a free slot in the object array. // If there isn't, the object won't be created. ObjectCollection* objectCollection = objectCollections[objectType]; u16 loop = 0; ObjectStruct* tempObjectList = objectCollection->objectList; u16 numAliveObjects = 0; u16 numDeadObjects = 0; for (; loop < objectCollection->maxActiveObjects; loop++) { ObjectStruct* object = tempObjectList; if (object->objectState == OBJECTSTATE_FREE) { totalActiveObjects++; object->updateFunction = (ObjectFunctionTypePrototype)updateFunction; object->destroyFunction = (ObjectFunctionTypePrototype)destroyFunction; object->drawFunction = (ObjectFunctionTypePrototype)drawFunction; object->collisionFunction = (ObjectCollisionFunctionPrototype)collisionFunction; object->objectState = OBJECTSTATE_ACTIVE; object->objectType = objectType; objectCollection->numActiveObjects++; #ifdef DEBUG_OBJECT_MANAGEMENT KDebug_Alert("Created Object. Objects Total:"); PrintNumber(totalActiveObjects); #endif return object; } else if (object->objectState == OBJECTSTATE_ACTIVE) { numAliveObjects++; } else if (object->objectState == OBJECTSTATE_INACTIVE) { numDeadObjects++; } tempObjectList++; } #ifdef DEBUG_OBJECT_MANAGEMENT KDebug_Alert("Could not add object. Too many created"); PrintNumber(numAliveObjects); PrintNumber(numDeadObjects); #endif PrintText("none avialable"); return 0; }
void ProcessCollisions(ObjectCollection* firstObjectCollection, ObjectCollection* secondObjectCollection, CollisionFunction collisionFunction) { if (firstObjectCollection->numVisibleObjects == 0) return; if (secondObjectCollection->numVisibleObjects == 0) return; ObjectStruct** tempFirstList = firstObjectCollection->objectVisibilityList; u16 firstListCounter = firstObjectCollection->numVisibleObjects; while (firstListCounter--) { #ifdef DEBUG_COLLISIONS KDebug_Alert("firstObject"); PrintNumber((*tempFirstList)->objectType); #endif // no need to do anything if we're dead. if ((*tempFirstList)->healthPoints > 0 && (*tempFirstList)->objectState == OBJECTSTATE_ACTIVE) { u16 secondListCounter = secondObjectCollection->numVisibleObjects; ObjectStruct** tempSecondList = secondObjectCollection->objectVisibilityList; while (secondListCounter--) { #ifdef DEBUG_COLLISIONS KDebug_Alert("secondObject"); PrintNumber((*tempSecondList)->objectType); #endif // no need to do anything if we're dead. if ((*tempSecondList)->healthPoints > 0 && (*tempSecondList)->objectState == OBJECTSTATE_ACTIVE) { if (!((*tempFirstList)->x + (*tempFirstList)->rectLeft > (*tempSecondList)->x + (*tempSecondList)->rectRight || (*tempFirstList)->x + (*tempFirstList)->rectRight < (*tempSecondList)->x + (*tempSecondList)->rectLeft || (*tempFirstList)->y + (*tempFirstList)->rectTop > (*tempSecondList)->y + (*tempSecondList)->rectBottom || (*tempFirstList)->y + (*tempFirstList)->rectBottom < (*tempSecondList)->y + (*tempSecondList)->rectTop)) { (*tempFirstList)->collisionFunction(*tempFirstList, *tempSecondList); (*tempSecondList)->collisionFunction(*tempSecondList, *tempFirstList); } } tempSecondList++; } } tempFirstList++; } }
void* MEM_alloc(u16 size) { u16* p; u16 adjsize; u16 remaining; if (size == 0) return 0; // 2 bytes aligned adjsize = (size + sizeof(u16) + 1) & 0xFFFE; if (adjsize > *free) { p = pack(adjsize); // no enough memory if (p == NULL) { #if (LIB_DEBUG != 0) KDebug_Alert("MEM_alloc failed: no enough memory !"); #endif return NULL; } free = p; } else // at this point we can allocate memory p = free; // set free to next free block free += adjsize >> 1; // get remaining (old - allocated) remaining = *p - adjsize; // adjust remaining free space if (remaining > 0) *free = remaining; else { // no more space in bloc so we have to find the next free bloc u16 *newfree = free; u16 bloc; while((bloc = *newfree) & USED) newfree += bloc >> 1; free = newfree; } // set block size, mark as used and point to free region *p++ = adjsize | USED; // return block return p; }
u16 EnemyPlaneCreate(s16 x, s16 y) { ObjectStruct* enemyPlaneObject = CreateObject(TYPE_ENEMY, EnemyPlaneUpdate, EnemyPlaneDestroy, EnemyPlaneDraw, EnemyPlaneCollide); if (!enemyPlaneObject) { #ifdef DEBUG_OBJECTS KDebug_Alert("EnemyPlane could not be created!"); #endif return 0; } enemyPlaneObject->x = x; enemyPlaneObject->y = y; enemyPlaneObject->speedx = 0; enemyPlaneObject->speedy = 0; enemyPlaneObject->sprite.size = SPRITE_SIZE(3,3); enemyPlaneObject->spriteIndex = random() & 31; enemyPlaneObject->sprite.tile_attr = enemyPlaneAnimationFrames[enemyPlaneObject->spriteIndex] + enemyPlaneLoadedTileInfo.startIndex; enemyPlaneObject->aiState = ENEMYPLANE_AI_STATE_FLYING; enemyPlaneObject->rectLeft = PIXEL_TO_VIRTUAL(-12); enemyPlaneObject->rectRight = PIXEL_TO_VIRTUAL(12); enemyPlaneObject->rectTop = PIXEL_TO_VIRTUAL(-12); enemyPlaneObject->rectBottom = PIXEL_TO_VIRTUAL(12); enemyPlaneObject->healthPoints = 1; enemyPlaneObject->damage = 1; enemyPlaneObject->visible = 1; #ifdef DEBUG_OBJECTS KDebug_Alert("EnemyPlaneCreate"); #endif return 1; }
u16 EnemyBulletCreate(s16 x, s16 y, s16 speedx, s16 speedy) { ObjectStruct* enemyBulletObject = CreateObject(TYPE_ENEMY_PROJECTILE, EnemyBulletUpdate, EnemyBulletDestroy, EnemyBulletDraw, EnemyBulletCollide); if (!enemyBulletObject) { #ifdef DEBUG_OBJECTS KDebug_Alert("EnemyBullet could not be created!"); #endif return 0; } enemyBulletObject->x = x; enemyBulletObject->y = y; enemyBulletObject->speedx = speedx; enemyBulletObject->speedy = speedy; enemyBulletObject->sprite.size = SPRITE_SIZE(1,1); enemyBulletObject->spriteIndex = 0; enemyBulletObject->sprite.tile_attr = TILE_ATTR_FULL(PAL0,1,0,0,bulletLoadedTileInfo.startIndex); enemyBulletObject->rectLeft = PIXEL_TO_VIRTUAL(-4); enemyBulletObject->rectRight = PIXEL_TO_VIRTUAL(4); enemyBulletObject->rectTop = PIXEL_TO_VIRTUAL(-4); enemyBulletObject->rectBottom = PIXEL_TO_VIRTUAL(4); enemyBulletObject->damage = 1; enemyBulletObject->healthPoints = 1; enemyBulletObject->visible = 1; #ifdef DEBUG_OBJECTS KDebug_Alert("EnemyBulletCreate"); #endif return 1; }
static u16 findFreeRegion(TileCache *cache, u16 size) { u16 start, end, lim; // start from current position lim = cache->limit; start = cache->current; end = start + size; // search for a free region while(end < lim) { u16 pos = getConflictRegion(cache, start, end); // no conflict --> return region index if (!pos) return start; start = pos; end = start + size; } // restart from begining lim = cache->current; start = cache->startIndex; end = start + size; // search for a free region while(end < lim) { u16 pos = getConflictRegion(cache, start, end); // no conflict --> return region index if (!pos) return start; start = pos; end = start + size; } if (LIB_DEBUG) KDebug_Alert("TC_alloc failed: no enough available VRAM in cache !"); return (u16) -1; }
void Debug_print( char* output ) { KDebug_Alert( output ); }
void MEM_dump() { char str[40]; char strNum[16]; u16 *b; u16 psize; u16 memused; u16 memfree; KDebug_Alert("Memory dump:"); KDebug_Alert(" Used blocks:"); b = heap; memused = 0; while ((psize = *b)) { if (psize & USED) { strcpy(str, " "); intToHex((u32)b, strNum, 8); strcat(str, strNum); strcat(str, ": "); intToStr(psize & 0xFFFE, strNum, 0); strcat(str, strNum); KDebug_Alert(str); memused += psize & 0xFFFE; } b += psize >> 1; KDebug_Alert(""); } KDebug_Alert(" Free blocks:"); b = heap; memfree = 0; while ((psize = *b)) { if (!(psize & USED)) { strcpy(str, " "); intToHex((u32)b, strNum, 8); strcat(str, strNum); strcat(str, ": "); intToStr(psize & 0xFFFE, strNum, 0); strcat(str, strNum); KDebug_Alert(str); memfree += psize & 0xFFFE; } b += psize >> 1; KDebug_Alert(""); } KDebug_Alert("Total used:"); KDebug_AlertNumber(memused); KDebug_Alert("Total free:"); KDebug_AlertNumber(memfree); }
void EnemyBulletDestroy(ObjectStruct* enemyBulletObject) { #ifdef DEBUG_OBJECTS KDebug_Alert("EnemyBulletDestroy"); #endif }
s16 TC_alloc(TileCache *cache, TileSet *tileset, TCUpload upload) { TCBloc *bloc; // KDebug_Alert("Alloc TC"); // KDebug_AlertNumber(tileset); bloc = getBloc(cache, tileset); // bloc found if (bloc != NULL) { // get address of next fixed bloc u16 nextFixed = cache->nextFixed; TCBloc *nextFixedBloc = &cache->blocs[nextFixed]; // flushed bloc ? --> re allocate it if (bloc >= nextFixedBloc) { // need to swap blocs ? if (bloc != nextFixedBloc) { u16 tmpInd = bloc->index; bloc->index = nextFixedBloc->index; bloc->tileset = nextFixedBloc->tileset; nextFixedBloc->index = tmpInd; nextFixedBloc->tileset = tileset; bloc = nextFixedBloc; } // one more fixed bloc cache->nextFixed = nextFixed + 1; } return bloc->index; } // bloc not found --> alloc else { u16 index, size, lim; u16 nextFlush; // not more free bloc if (cache->nextFixed >= cache->numBloc) { if (LIB_DEBUG) KDebug_Alert("TC_alloc failed: no more free bloc !"); return -1; } size = tileset->numTile; // search for free region (this method can consume a lot of time :-/) index = findFreeRegion(cache, size); // not enough space in cache if ((s16) index == -1) return index; // process VDP upload if required if (upload != NO_UPLOAD) { // no compression if (tileset->compression == COMPRESSION_NONE) { // upload the tileset to VRAM now if (upload == UPLOAD_NOW) VDP_loadTileData(tileset->tiles, index, size, TRUE); // upload at VINT else addToUploadQueue(tileset, index); } else { // unpack tileset TileSet *unpacked = unpackTileSet(tileset, NULL); // error while unpacking tileset if (unpacked == NULL) return -1; // upload the tileset to VRAM now ? if (upload == UPLOAD_NOW) { // upload VDP_loadTileData(unpacked->tiles, index, size, TRUE); // and release memory MEM_free(unpacked); } // upload at VINT else { // we will use that to release automatically the TileSet after upload unpacked->compression = COMPRESSION_APLIB; // put in upload queue addToUploadQueue(unpacked, index); } } } lim = index + size; // update current position cache->current = lim; // release any previous flushable bloc in the allocated area releaseFlushable(cache, index, lim); // get new allocated bloc bloc = &cache->blocs[cache->nextFixed++]; // try to save flush bloc if we still have available bloc for that ? nextFlush = cache->nextFlush; if (nextFlush < cache->numBloc) { TCBloc *nextFlushBloc = &cache->blocs[nextFlush]; // test if we have something to save if (nextFlushBloc != bloc) { nextFlushBloc->index = bloc->index; nextFlushBloc->tileset = bloc->tileset; } // increase flush bloc address cache->nextFlush = nextFlush + 1; } // set bloc info bloc->tileset = tileset; bloc->index = index; } return bloc->index; }
void BulletDestroy(ObjectStruct* bulletObject) { #ifdef DEBUG_OBJECTS KDebug_Alert("BulletDestroy"); #endif }