Example #1
0
/**
 * Update the state
 * 
 * @param  pGame The game's context
 * @return       GFMRV_OK, GFMRV_ARGUMENTS_BAD, ...
 */
gfmRV intro_update_flash(gameCtx *pGame) {
    gfmRV rv;
    int elapsed;
    introCtx *pIntro;
    
    // Sanitize arguments
    ASSERT(pGame, GFMRV_ARGUMENTS_BAD);
    ASSERT(pGame->pState, GFMRV_ARGUMENTS_BAD);
    // Get the current state
    pIntro = (introCtx*)(pGame->pState);
    
    rv = gfmTilemap_update(pIntro->pFlashFx, pGame->pCtx);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Update this animation's time so we can move to the next one
    rv = gfm_getElapsedTime(&elapsed, pGame->pCtx);
    ASSERT_NR(rv == GFMRV_OK);
    pIntro->flashAnimTime += elapsed;
    // Change the state after 2 seconds
    if (pIntro->flashAnimTime > 2000) {
        // TODO Change to the last part of the animation
        pIntro->state = intro_game;
    }
    
    rv = GFMRV_OK;
__ret:
    return rv;
}
Example #2
0
/**
 * Draw the state
 * 
 * @param  pGame The game's context
 * @return       GFMRV_OK, GFMRV_ARGUMENTS_BAD, ...
 */
gfmRV intro_draw_flash(gameCtx *pGame) {
    gfmRV rv;
    introCtx *pIntro;
    
    // Sanitize arguments
    ASSERT(pGame, GFMRV_ARGUMENTS_BAD);
    ASSERT(pGame->pState, GFMRV_ARGUMENTS_BAD);
    // Get the current state
    pIntro = (introCtx*)(pGame->pState);
    
    // TODO Draw everything
    rv = gfmTilemap_draw(pGame->common.pTMap, pGame->pCtx);
    ASSERT_NR(rv == GFMRV_OK);
    
    rv = player_draw(pIntro->pPl, pGame);
    ASSERT_NR(rv == GFMRV_OK);
    rv = doc_draw(pIntro->pDoc, pGame);
    ASSERT_NR(rv == GFMRV_OK);
    
    rv = gfmTilemap_draw(pIntro->pFlashFx, pGame->pCtx);
    ASSERT_NR(rv == GFMRV_OK);
    
    rv = GFMRV_OK;
__ret:
    return rv;
}
Example #3
0
/**
 * Draw the state
 * 
 * @param  pGame The game's context
 * @return       GFMRV_OK, GFMRV_ARGUMENTS_BAD, ...
 */
gfmRV intro_draw_game(gameCtx *pGame) {
    gfmRV rv;
    introCtx *pIntro;
    
    // Sanitize arguments
    ASSERT(pGame, GFMRV_ARGUMENTS_BAD);
    ASSERT(pGame->pState, GFMRV_ARGUMENTS_BAD);
    // Get the current state
    pIntro = (introCtx*)(pGame->pState);
    
    rv = gfmTilemap_draw(pGame->common.pTMap, pGame->pCtx);
    ASSERT_NR(rv == GFMRV_OK);
    
    rv = player_draw(pIntro->pPl, pGame);
    ASSERT_NR(rv == GFMRV_OK);
    rv = doc_draw(pIntro->pDoc, pGame);
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfmSprite_draw(pIntro->pBullet1, pGame->pCtx);
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfmSprite_draw(pIntro->pBullet2, pGame->pCtx);
    ASSERT_NR(rv == GFMRV_OK);
    
    // TODO Draw the bullets and the enemies...
    
    rv = GFMRV_OK;
__ret:
    return rv;
}
Example #4
0
/**
 * Subdivides a quadtree
 * 
 * @param  pCtx The node to be subdivided
 * @return      GFMRV_OK, GFMRV_ARGUMENTS_BAD, GFMRV_ALLOC_FAILED
 */
static gfmRV gfmQuadtree_subdivide(gfmQuadtreeRoot *pCtx, gfmQuadtree *pNode) {
    gfmQuadtree *pChild;
    gfmQuadtreePosition i;
    gfmRV rv;
    
    // Sanitize arguments
    ASSERT(pCtx, GFMRV_ARGUMENTS_BAD);
    ASSERT(pNode, GFMRV_ARGUMENTS_BAD);
    
    // Alloc and initialize all the children
    i = gfmQT_nw;
    while (i < gfmQT_max) {
        gfmGenArr_getNextRef(gfmQuadtree, pCtx->pQTPool, 5, pChild,
                gfmQuadtreeNode_getNew);
        gfmGenArr_push(pCtx->pQTPool);
        // Initialize the child
        rv = gfmQuadtree_init(pChild, pNode, i);
        ASSERT_NR(rv == GFMRV_OK);
        // Set the node's child
        pNode->ppChildren[i] = pChild;
        // Go to the next one
        i++;
    }
    
    // Insert every child to the tree it's contained
    while (pNode->pNodes) {
        gfmQuadtreeLL *pTmp;
        
        // Get the current node
        pTmp = pNode->pNodes;
        
        // Add it to every child (that it overlaps)
        i = gfmQT_nw;
        while (i < gfmQT_max) {
            // Get the current child
            pChild = pNode->ppChildren[i];
            // Check if the object collides this node
            rv = gfmQuadtree_overlap(pChild, pTmp->pSelf);
            if (rv == GFMRV_TRUE) {
                // Add it to the child
                rv = gfmQuadtree_insertObject(pCtx, pChild, pTmp->pSelf);
                ASSERT_NR(rv == GFMRV_OK);
            }
            
            i++;
        }
        
        // Go to the next node
        pNode->pNodes = pTmp->pNext;
        // Prepend the node to the free list
        pTmp->pNext = pCtx->pAvailable;
        pCtx->pAvailable = pTmp;
    }
    
    rv = GFMRV_OK;
__ret:
    return rv;
}
Example #5
0
/**
 * Adds a new gfmObject to the quadtree, subdividing it as necessary and
 * colliding with every possible node
 * 
 * @param  pCtx The quadtree's root
 * @param  pObj The gfmObject
 * @return      GFMRV_ARGUMENTS_BAD, GFMRV_QUADTREE_NOT_INITIALIZED, 
 *              GFMRV_QUADTREE_OVERLAPED, GFMRV_QUADTREE_DONE
 */
gfmRV gfmQuadtree_collideObject(gfmQuadtreeRoot *pCtx, gfmObject *pObj) {
    gfmRV rv;
    
    // Sanitize arguments
    ASSERT(pCtx, GFMRV_ARGUMENTS_BAD);
    ASSERT(pObj, GFMRV_ARGUMENTS_BAD);
    // Check if initialized
    ASSERT(pCtx->maxDepth > 0, GFMRV_QUADTREE_NOT_INITIALIZED);
    // Check if this node overlaps the root
    rv = gfmQuadtree_overlap(pCtx->pSelf, pObj);
    if (rv != GFMRV_TRUE) {
        rv = GFMRV_QUADTREE_DONE;
        goto __ret;
    }
    //ASSERT(rv == GFMRV_TRUE, GFMRV_QUADTREE_DONE);
    
    // Store the object to be added
    pCtx->pObject = pObj;
    // Clear the call stack
    pCtx->stack.pushPos = 0;
    // Clear any previous overlap
    pCtx->pOther = 0;
    
    // Push the root node to start colliding
    rv = gfmQuadtree_pushNode(pCtx, pCtx->pSelf);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Collide it
    rv = gfmQuadtree_continue(pCtx);
__ret:
    return rv;
}
Example #6
0
/**
 * Change the current input scheme, ignoring if it clashes with the other
 * player (but checking for controller presence)
 * 
 * @param ID ID of the player being set
 * @param mode The new controle mode
 * @param Whether the mode was switched successfully
 */
int ctr_setModeForce(int ID, ctr_mode mode) {
    int ret;
    
    ret = 0;
    // Check that the mode is valid
    ASSERT_NR(ID == ID_PL1 || ID == ID_PL2);
    ASSERT_NR(mode < CTR_PAD1_A || GFraMe_controller_max > 0);
    ASSERT_NR(mode < CTR_PAD2_A || GFraMe_controller_max > 1);
    
    if (ID == ID_PL1)
        _ctr_pl1 = mode;
    else
        _ctr_pl2 = mode;
    
    ret = 1;
__ret:
    return ret;
}
Example #7
0
/**
 * @return GFMRV_TRUE (if did shoot), GFMRV_FALSE (otherwise), ...
 */
gfmRV shoot_bullet(gameCtx *pGame, int x, int y) {
    gfmRV rv;
    gfmSprite *pSpr;
    int bX, bY, height, width;
    introCtx *pIntro;
    
    // Set default values
    pSpr = 0;
    
    // Sanitize arguments
    ASSERT(pGame, GFMRV_ARGUMENTS_BAD);
    ASSERT(pGame->pState, GFMRV_ARGUMENTS_BAD);
    // Check that the current state is the intro state
    ASSERT(pGame->state == state_intro, GFMRV_FUNCTION_FAILED);
    
    // Get the current state
    pIntro = (introCtx*)(pGame->pState);
    
    // Check that the bullet isn't on screen
    rv = gfmSprite_getPosition(&bX, &bY, pIntro->pBullet1);
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfm_getCameraDimensions(&width, &height, pGame->pCtx);
    ASSERT_NR(rv == GFMRV_OK);
    if (bX < 0 || bX > width) {
        pSpr = pIntro->pBullet1;
    }
    else {
        rv = gfmSprite_getPosition(&bX, &bY, pIntro->pBullet2);
        ASSERT_NR(rv == GFMRV_OK);
        rv = gfm_getCameraDimensions(&width, &height, pGame->pCtx);
        ASSERT_NR(rv == GFMRV_OK);
        if (bX < 0 || bX > width) {
            pSpr = pIntro->pBullet2;
        }
    }
    
    ASSERT(pSpr, GFMRV_FALSE);
    
    // Set the bullet's position
    rv = gfmSprite_setPosition(pSpr, x, y);
    ASSERT_NR(rv == GFMRV_OK);
    // Set it's velocity
    rv = gfmSprite_setHorizontalVelocity(pSpr, 200);
    ASSERT_NR(rv == GFMRV_OK);
    // Restart the animation
    rv = gfmSprite_playAnimation(pSpr, 1);
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfmSprite_playAnimation(pSpr, 0);
    ASSERT_NR(rv == GFMRV_OK);
    
    rv = GFMRV_TRUE;
__ret:
    return rv;
}
Example #8
0
/**
 * Populates a quadtree with tilemap's areas
 * 
 * @param  pCtx  The quadtree's root
 * @param  pTMap The tilemap
 * @return       GFMRV_OK, GFMRV_ARGUMENTS_BAD, GFMRV_QUADTREE_NOT_INITIALIZED
 */
gfmRV gfmQuadtree_populateTilemap(gfmQuadtreeRoot *pCtx, gfmTilemap *pTMap) {
    gfmObject *pList;
    gfmRV rv;
    int len;

    /* Sanitize arguments */
    ASSERT(pCtx, GFMRV_ARGUMENTS_BAD);
    ASSERT(pTMap, GFMRV_ARGUMENTS_BAD);

    /* Get how many areas there are */
    rv = gfmTilemap_getAreasLength(&len, pTMap);
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfmTilemap_getArea(&pList, pTMap, 0);
    ASSERT_NR(rv == GFMRV_OK);

    rv = gfmHitbox_populateQuadtree((gfmHitbox*)pList, pCtx, len);
__ret:
    return rv;
}
Example #9
0
/**
 * Checks if a quadtree node overlaps an object
 * 
 * @param  pCtx The quadtree node
 * @param  pObj The gfmObject
 * @return      GFMRV_TRUE, GFMRV_FALSE, GFMRV_ARGUMENTS_BAD
 */
static gfmRV gfmQuadtree_overlap(gfmQuadtree *pCtx, gfmObject *pObj) {
    gfmRV rv;
    int cX, cY, dist, hWidth, hHeight, maxDist;
    
    // Sanitize arguments
    ASSERT(pCtx, GFMRV_ARGUMENTS_BAD);
    ASSERT(pObj, GFMRV_ARGUMENTS_BAD);
    // Get the object's dimensions
    rv = gfmObject_getCenter(&cX, &cY, pObj);
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfmObject_getDimensions(&hWidth, &hHeight, pObj);
    ASSERT_NR(rv == GFMRV_OK);
    // Get half the dimensions (rounded up)
    hWidth = hWidth / 2 + (hWidth % 2);
    hHeight = hHeight / 2 + (hHeight % 2);
    
    // Check that they are overlaping (horizontally)
    dist = cX - pCtx->centerX;
    if (dist < 0) {
        dist = -dist;
    }
    maxDist = hWidth + pCtx->halfWidth;
    if (dist > maxDist) {
        return GFMRV_FALSE;
    }
    //ASSERT(dist <= maxDist, GFMRV_FALSE);
    
    // Check vertically...
    dist = cY - pCtx->centerY;
    if (dist < 0) {
        dist = -dist;
    }
    maxDist = hHeight + pCtx->halfHeight;
    if (dist > maxDist) {
        return GFMRV_FALSE;
    }
    //ASSERT(dist <= maxDist, GFMRV_FALSE);
    
    rv = GFMRV_TRUE;
__ret:
    return rv;
}
Example #10
0
/**
 * Draw the state
 * 
 * @param  pGame The game's context
 * @return       GFMRV_OK, GFMRV_ARGUMENTS_BAD, ...
 */
gfmRV intro_draw_begin(gameCtx *pGame) {
    gfmRV rv;
    introCtx *pIntro;
    
    // Sanitize arguments
    ASSERT(pGame, GFMRV_ARGUMENTS_BAD);
    ASSERT(pGame->pState, GFMRV_ARGUMENTS_BAD);
    // Get the current state
    pIntro = (introCtx*)(pGame->pState);
    
    // TODO Draw everything
    rv = gfmTilemap_draw(pGame->common.pTMap, pGame->pCtx);
    ASSERT_NR(rv == GFMRV_OK);
    
    rv = player_draw(pIntro->pPl, pGame);
    ASSERT_NR(rv == GFMRV_OK);
    rv = doc_draw(pIntro->pDoc, pGame);
    ASSERT_NR(rv == GFMRV_OK);
    
    rv = gfmTilemap_draw(pIntro->pMachineFx, pGame->pCtx);
    ASSERT_NR(rv == GFMRV_OK);
    
    rv = gfmText_draw(pGame->common.pText, pGame->pCtx);
    ASSERT_NR(rv == GFMRV_OK);
    
#if 0
    rv = gfmQuadtree_drawBounds(pGame->common.pQt, pGame->pCtx, 0/*colors*/);
    ASSERT_NR(rv == GFMRV_OK);
#endif
    
    rv = GFMRV_OK;
__ret:
    return rv;
}
Example #11
0
/**
 * Draw the FPS counter on the screen; It's position should be defined before
 * hand
 * 
 * @param  pCounter The FPS counter
 * @param  pCtx     The game's context
 * @return          GFMRV_OK, GFMRV_ARGUMENTS_BAD,
 *                  GFMRV_FPSCOUNTER_NOT_INITIALIZED
 */
gfmRV gfmFPSCounter_draw(gfmFPSCounter *pCounter, gfmCtx *pCtx) {
    gfmRV rv;
    int dps, ups;
    unsigned int curTime;

    /* Sanitize arguments */
    ASSERT(pCounter, GFMRV_ARGUMENTS_BAD);
    ASSERT(pCtx, GFMRV_ARGUMENTS_BAD);

    /* Calculate how long it took to draw */
    rv = gfmTimer_getCurTimeMs(&curTime);
    ASSERT_NR(rv == GFMRV_OK);

    /* Check if the fps should be updated */
    if (curTime - pCounter->lastTime >= 1000) {
        pCounter->updateCount = pCounter->updateAcc;
        pCounter->updateAcc = 0;
        pCounter->drawCount = pCounter->drawAcc;
        pCounter->drawAcc = 0;

        pCounter->lastTime = curTime;
    }

    /* Get the expected FPS */
    rv = gfm_getStateFrameRate(&ups, &dps, pCtx);
    ASSERT_NR(rv == GFMRV_OK);

    /* Draw the information */
    gfmDebug_printf(pCtx, pCounter->x, pCounter->y,
            " UPD %02i/%02i - %04iMS\n"
            "DRAW %02i/%02i - %04iMS\n",
            pCounter->updateCount, ups, pCounter->updateTime,
            pCounter->drawCount, dps, curTime - pCounter->drawInit);
    pCounter->updateTime = 0;

    rv = GFMRV_OK;
__ret:
    return rv;
}
Example #12
0
/**
 * The game's main menu
 * 
 * @param  pGame The game "global" context
 * @return       GFMRV_OK, GFMRV_ARGUMENTS_BAD, GFMRV_ALLOC_FAILED, ...
 */
gfmRV state_mainMenu(gameCtx *pGame) {
    gfmRV rv;
    
    // Sanitize arguments
    ASSERT(pGame, GFMRV_ARGUMENTS_BAD);
    
    // Initialize the main menu
    rv = state_mainMenu_init(pGame);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Run until the window is closed
    while (!pGame->switchState && pGame->isRunning
            && gfm_didGetQuitFlag(pGame->pCtx) == GFMRV_FALSE) {
        rv = gfm_handleEvents(pGame->pCtx);
        ASSERT_NR(rv == GFMRV_OK);
        
        // Update stuff
        while (gfm_isUpdating(pGame->pCtx) == GFMRV_TRUE) {
            rv = gfm_fpsCounterUpdateBegin(pGame->pCtx);
            ASSERT_NR(rv == GFMRV_OK);
            
            // Update everything
            rv = state_mainMenu_update(pGame);
            ASSERT_NR(rv == GFMRV_OK);
            
            rv = gfm_fpsCounterUpdateEnd(pGame->pCtx);
            ASSERT_NR(rv == GFMRV_OK);
        }
        // Draw stuff
        while (gfm_isDrawing(pGame->pCtx) == GFMRV_TRUE) {
            rv = gfm_drawBegin(pGame->pCtx);
            ASSERT_NR(rv == GFMRV_OK);
            
            // Draw everything
            rv = state_mainMenu_draw(pGame);
            ASSERT_NR(rv == GFMRV_OK);
            
            rv = gfm_drawEnd(pGame->pCtx);
            ASSERT_NR(rv == GFMRV_OK);
        }
    }
    
    rv = GFMRV_OK;
__ret:
     state_mainMenu_clean(pGame);
     
    return rv;
}
Example #13
0
/**
 * Update the state
 * 
 * @param  pGame The game's context
 * @return       GFMRV_OK, GFMRV_ARGUMENTS_BAD, ...
 */
gfmRV intro_update_gameover(gameCtx *pGame) {
    gfmRV rv;
    gfmInputState reset;
    int nreset;
    
    // Sanitize arguments
    ASSERT(pGame, GFMRV_ARGUMENTS_BAD);
    ASSERT(pGame->pState, GFMRV_ARGUMENTS_BAD);
    
    rv = gfmText_update(pGame->common.pText, pGame->pCtx);
    ASSERT_NR(rv == GFMRV_OK);
    
    rv = gfm_getKeyState(&reset, &nreset, pGame->pCtx, pGame->resetHnd);
    ASSERT_NR(rv == GFMRV_OK);
    if ((reset & gfmInput_justPressed) == gfmInput_justPressed) {
        pGame->state = state_reset;
        return GFMRV_OK;
    }
    
    rv = GFMRV_OK;
__ret:
    return rv;
}
Example #14
0
/**
 * Signal when an update started, to calculate how long it took
 * 
 * @param  pCtx      The FPS counter
 * @return           GFMRV_OK, GFMRV_ARGUMENTS_BAD
 */
gfmRV gfmFPSCounter_updateBegin(gfmFPSCounter *pCtx) {
    gfmRV rv;
    
    // Sanitize arguments
    ASSERT(pCtx, GFMRV_ARGUMENTS_BAD);
    
    // Store the moment an update was initialized
    rv = gfmTimer_getCurTimeMs(&(pCtx->updateInit));
    ASSERT_NR(rv == GFMRV_OK);
    
    rv = GFMRV_OK;
__ret:
    return rv;
}
Example #15
0
/**
 * Add a sprite to the quadtree without collinding it against the tree's objs
 * 
 * @param  pCtx The quadtree's root
 * @param  pSpr The gfmSprite
 * @return      GFMRV_OK, GFMRV_ARGUMENTS_BAD, GFMRV_QUADTREE_NOT_INITIALIZED
 */
gfmRV gfmQuadtree_populateSprite(gfmQuadtreeRoot *pCtx, gfmSprite *pSpr) {
    gfmObject *pObj;
    gfmRV rv;
    
    // Sanitize sprite (other checks are done in sub-functions)
    ASSERT(pSpr, GFMRV_ARGUMENTS_BAD);
    // Retrieve the sprite's object
    rv = gfmSprite_getObject(&pObj, pSpr);
    ASSERT_NR(rv == GFMRV_OK);
    // Add it to the quadtree
    rv = gfmQuadtree_populateObject(pCtx, pObj);
__ret:
    return rv;
}
Example #16
0
/**
 * Called on gfm_drawBegin to calculate how long it takes to render a frame
 * 
 * @param  pCtx      The FPS counter
 * @return           GFMRV_OK, GFMRV_ARGUMENTS_BAD, ...
 */
gfmRV gfmFPSCounter_initDraw(gfmFPSCounter *pCtx) {
    gfmRV rv;
    
    // Sanitize arguments
    ASSERT(pCtx, GFMRV_ARGUMENTS_BAD);
    
    // Store the moment a draw was initialized
    rv = gfmTimer_getCurTimeMs(&(pCtx->drawInit));
    ASSERT_NR(rv == GFMRV_OK);
    
    // Increase the draw count
    pCtx->drawAcc++;
    
    rv = GFMRV_OK;
__ret:
    return rv;
}
Example #17
0
/**
 * Draw everything in this state
 * 
 * @param  pGame The game "global" context
 */
static gfmRV state_mainMenu_draw(gameCtx *pGame) {
    gfmRV rv;
    mainMenuCtx *pMainMenu;
    
    // Sanitize arguments
    ASSERT(pGame, GFMRV_ARGUMENTS_BAD);
    ASSERT(pGame->pMainMenu, GFMRV_ARGUMENTS_BAD);
    // Retrieve the main menu context
    pMainMenu = pGame->pMainMenu;
    
    // Draw the background
    rv = gfmTilemap_draw(pMainMenu->pBackground, pGame->pCtx);
    ASSERT_NR(rv == GFMRV_OK);
    // Draw the floor
    rv = gfmTilemap_draw(pMainMenu->pFloor, pGame->pCtx);
    ASSERT_NR(rv == GFMRV_OK);
    // Draw the title
    rv = gfmTilemap_draw(pMainMenu->pTitle, pGame->pCtx);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Draw the text
    if (pMainMenu->textTimer >= 0) {
        rv = gfmText_draw(pMainMenu->pText, pGame->pCtx);
        ASSERT_NR(rv == GFMRV_OK);
    }
    
    // If the animation finished playing
    if (pMainMenu->titleAnimation >= sizeof(titleData) / sizeof(int)) {
        // Draw my icon
        rv = gfm_drawTile(pGame->pCtx, pGame->pSset32x32, 272/*x*/, /*y*/200,
                15/*tile*/, 0/*isFlipped*/);
        ASSERT_NR(rv == GFMRV_OK);
        
        // Draw the options button
        rv = gfm_drawTile(pGame->pCtx, pGame->pSset32x32, 8/*x*/, /*y*/200,
                14/*tile*/, 0/*isFlipped*/);
        ASSERT_NR(rv == GFMRV_OK);
        // Draw the options icon
        rv = gfm_drawTile(pGame->pCtx, pGame->pSset16x16, 16/*x*/, /*y*/205,
                41/*tile*/, 0/*isFlipped*/);
        ASSERT_NR(rv == GFMRV_OK);
    }
    
    rv = GFMRV_OK;
__ret:
    return rv;
}
Example #18
0
int main(int arg, char *argv[]) {
    double volume;
    gfmCtx *pCtx;
    gfmRV rv;
    int handle;
    
    // Initialize every variable
    pCtx = 0;
    
    // Try to get a new context
    rv = gfm_getNew(&pCtx);
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfm_initStatic(pCtx, "com.gfmgamecorner", "gfmAudioTest");
    ASSERT_NR(rv == GFMRV_OK);
    
    // Initialize the audio sub-system
    //rv = gfm_initAudio(pCtx, gfmAudio_lowQuality);
    //rv = gfm_initAudio(pCtx, gfmAudio_medQuality);
    rv = gfm_initAudio(pCtx, gfmAudio_defQuality);
    //rv = gfm_initAudio(pCtx, gfmAudio_highQuality);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Load an audio
    rv = gfm_loadAudio(&handle, pCtx, "bossBattle.wav",
            sizeof("bossBattle.wav") - 1);
    ASSERT_NR(rv == GFMRV_OK);
    // Make the audio loop
    rv = gfm_setRepeat(pCtx, handle, 0 /* pos */);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Play the audio
    volume = 0.8;
    rv = gfm_playAudio(0/* ignore the instance */, pCtx, handle, volume);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Wait for some time while the song should be playing...
#if defined(WIN32)
    Sleep(10);
#else
    sleep(10);
#endif
    
    rv = GFMRV_OK;
__ret:
    gfm_free(&pCtx);
    
    return rv;
}
Example #19
0
/**
 * Signal that the update ended, and actually calculate how long it took
 * 
 * @param  pCtx      The FPS counter
 * @return           GFMRV_OK, GFMRV_ARGUMENTS_BAD
 */
gfmRV gfmFPSCounter_updateEnd(gfmFPSCounter *pCtx) {
    gfmRV rv;
    unsigned int curTime;
    
    // Sanitize arguments
    ASSERT(pCtx, GFMRV_ARGUMENTS_BAD);
    
    // Store the moment an update was initialized
    rv = gfmTimer_getCurTimeMs(&curTime);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Update the update operation time
    pCtx->updateTime += curTime - pCtx->updateInit;
    
    // Update the number of updates
    pCtx->updateAcc++;
    
    rv = GFMRV_OK;
__ret:
    return rv;
}
Example #20
0
/**
 * Add an object to the quadtree without collinding it against the tree's objs
 * 
 * @param  pCtx The quadtree's root
 * @param  pObj The gfmObject
 * @return      GFMRV_OK, GFMRV_ARGUMENTS_BAD, GFMRV_QUADTREE_NOT_INITIALIZED
 */
gfmRV gfmQuadtree_populateObject(gfmQuadtreeRoot *pCtx, gfmObject *pObj) {
    gfmRV rv;
    
    // Sanitize arguments
    ASSERT(pCtx, GFMRV_ARGUMENTS_BAD);
    ASSERT(pObj, GFMRV_ARGUMENTS_BAD);
    // Check if initialized
    ASSERT(pCtx->maxDepth > 0, GFMRV_QUADTREE_NOT_INITIALIZED);
    
    // Check that the object overlaps the root node
    rv = gfmQuadtree_overlap(pCtx->pSelf, pObj);
    ASSERT(rv == GFMRV_TRUE, GFMRV_OK);
    
    // Clear the call stack
    pCtx->stack.pushPos = 0;
    // Clear any previous overlap
    pCtx->pOther = 0;
    
    // Push the root node to start overlaping
    rv = gfmQuadtree_pushNode(pCtx, pCtx->pSelf);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Continue adding the object
    while (pCtx->stack.pushPos > 0) {
        gfmQuadtree *pNode;
        
        // Pop the current node
        rv = gfmQuadtree_popNode(&pNode, pCtx);
        ASSERT_NR(rv == GFMRV_OK);

        // If it has children, push its children
        if (pNode->ppChildren[gfmQT_nw]) {
            gfmQuadtreePosition i;
            gfmQuadtree *pChild;

            i = gfmQT_nw;
            while (i < gfmQT_max) {
                // Get the current child
                pChild = pNode->ppChildren[i];
                // Check if the object overlaps this node
                rv = gfmQuadtree_overlap(pChild, pObj);
                if (rv == GFMRV_TRUE) {
                    // Push it (so it will collide later)
                    rv = gfmQuadtree_pushNode(pCtx, pChild);
                    ASSERT_NR(rv == GFMRV_OK);
                }
                i++;
            }
        }
        else {
            // Check if adding the node will subdivide the tree and if it
            // can still be subdivided
            if (pNode->numObjects + 1 > pCtx->maxNodes &&
                    pNode->depth + 1 < pCtx->maxDepth) {
                // Subdivide the tree
                rv = gfmQuadtree_subdivide(pCtx, pNode);
                ASSERT_NR(rv == GFMRV_OK);
                // Push the node again so its children are overlapped/pushed
                rv = gfmQuadtree_pushNode(pCtx, pNode);
                ASSERT_NR(rv == GFMRV_OK);
            }
            else {
                // Add the object to this node 
                rv = gfmQuadtree_insertObject(pCtx, pNode, pObj);
                ASSERT_NR(rv == GFMRV_OK);
            }
        }
    }
    
    rv = GFMRV_OK;
__ret:
    return rv;
}
Example #21
0
/**
 * The game's first state
 * 
 * @param  gameCtx The game's context
 * @return         GFMRV_OK, GFMRV_ARGUMENTS_BAD, ...
 */
gfmRV intro(gameCtx *pGame, int jumpIntro) {
    gfmRV rv;
    introCtx _intro;
    
    // Sanitize arguments
    ASSERT(pGame, GFMRV_ARGUMENTS_BAD);
    
    // Clean the state's context (the stack may have "trash")
    memset(&_intro, 0x0, sizeof(introCtx));
    // Set the current state date
    pGame->pState = &_intro;
    
    // Initialize this state
    rv = intro_init(pGame);
    ASSERT_NR(rv == GFMRV_OK);
    
    if (jumpIntro) {
        _intro.state = intro_game;
    }
    
    // Run until the window is closed (or the state changes)
    while (pGame->state == state_intro && pGame->isRunning
            && gfm_didGetQuitFlag(pGame->pCtx) == GFMRV_FALSE) {
        rv = gfm_handleEvents(pGame->pCtx);
        ASSERT_NR(rv == GFMRV_OK);
        
        // Update stuff
        while (gfm_isUpdating(pGame->pCtx) == GFMRV_TRUE) {
            rv = gfm_fpsCounterUpdateBegin(pGame->pCtx);
            ASSERT_NR(rv == GFMRV_OK);
            
            // Update everything
            switch (_intro.state) {
                case intro_begin: {
                    rv = intro_update_begin(pGame);
                    ASSERT_NR(rv == GFMRV_OK);
                } break;
                case intro_flash: {
                    rv = intro_update_flash(pGame);
                    ASSERT_NR(rv == GFMRV_OK);
                } break;
                case intro_game: {
                    rv = intro_update_game(pGame);
                    ASSERT_NR(rv == GFMRV_OK);
                } break;
                case intro_gameover: {
                    rv = intro_update_gameover(pGame);
                    ASSERT_NR(rv == GFMRV_OK);
                } break;
                default: break;
            }
            
            rv = gfm_fpsCounterUpdateEnd(pGame->pCtx);
            ASSERT_NR(rv == GFMRV_OK);
        }
        // Draw stuff
        while (gfm_isDrawing(pGame->pCtx) == GFMRV_TRUE) {
            rv = gfm_drawBegin(pGame->pCtx);
            ASSERT_NR(rv == GFMRV_OK);
            
            // Draw everything
            switch (_intro.state) {
                case intro_begin: {
                    rv = intro_draw_begin(pGame);
                    ASSERT_NR(rv == GFMRV_OK);
                } break;
                case intro_flash: {
                    rv = intro_draw_flash(pGame);
                    ASSERT_NR(rv == GFMRV_OK);
                } break;
                case intro_game: {
                    rv = intro_draw_game(pGame);
                    ASSERT_NR(rv == GFMRV_OK);
                } break;
                case intro_gameover: {
                    rv = intro_draw_gameover(pGame);
                    ASSERT_NR(rv == GFMRV_OK);
                } break;
                default: break;
            }
            
            rv = gfm_drawEnd(pGame->pCtx);
            ASSERT_NR(rv == GFMRV_OK);
        }
    }
    
    rv = GFMRV_OK;
__ret:
    intro_clean(pGame);
    
    return rv;
}
Example #22
0
/**
 * Initializes (and loads) everything used by this state
 * 
 * @param  pGame The game's context
 * @return       GFMRV_OK, GFMRV_ARGUMENTS_BAD, ...
 */
gfmRV intro_init(gameCtx *pGame) {
    gfmRV rv;
    int height, width;
    introCtx *pIntro;
    
    // Sanitize arguments
    ASSERT(pGame, GFMRV_ARGUMENTS_BAD);
    ASSERT(pGame->pState, GFMRV_ARGUMENTS_BAD);
    // Get the current state
    pIntro = (introCtx*)(pGame->pState);
    
    // Initialize the background
    rv = gfmTilemap_init(pGame->common.pTMap, pGame->pSset8x8, 1/*width*/,
        1/*height*/, -1/*defTile*/);
    ASSERT_NR(rv == GFMRV_OK);
    // Load the background from a file
    rv = gfmTilemap_loadf(pGame->common.pTMap, pGame->pCtx, "lab.gfm",
            7/*filenameLen*/, pDictNames, pDictTypes, dictLen);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Alloc the fx tilemap
    rv = gfmTilemap_getNew(&(pIntro->pMachineFx));
    ASSERT_NR(rv == GFMRV_OK);
    // Initialize and load the fx
    rv = gfmTilemap_init(pIntro->pMachineFx, pGame->pSset8x8, 5/*width*/,
        9/*height*/, -1/*defTile*/);
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfmTilemap_loadf(pIntro->pMachineFx, pGame->pCtx, "machine-fx.gfm",
            14/*filenameLen*/, pDictNames, pDictTypes, dictLen);
    ASSERT_NR(rv == GFMRV_OK);
    // Set its position
    rv = gfmTilemap_setPosition(pIntro->pMachineFx, 24/*x*/, 120/*y*/);
    ASSERT_NR(rv == GFMRV_OK);
    // Add the tilemap animations
    rv = gfmTilemap_addAnimations(pIntro->pMachineFx, pMachineFxAnim,
            sizeof(pMachineFxAnim) / sizeof(int) - 1);
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfmTilemap_recacheAnimations(pIntro->pMachineFx);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Alloc the fx tilemap
    rv = gfmTilemap_getNew(&(pIntro->pFlashFx));
    ASSERT_NR(rv == GFMRV_OK);
    // Initialize and load the flash fx
    rv = gfmTilemap_init(pIntro->pFlashFx, pGame->pSset8x8, 40/*width*/,
        30/*height*/, -1/*defTile*/);
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfmTilemap_loadf(pIntro->pFlashFx, pGame->pCtx, "flash-fx.gfm",
            14/*filenameLen*/, pDictNames, pDictTypes, dictLen);
    ASSERT_NR(rv == GFMRV_OK);
    // Add the tilemap animations
    rv = gfmTilemap_addAnimations(pIntro->pFlashFx, pFlashFxAnim,
            sizeof(pFlashFxAnim) / sizeof(int) - 1);
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfmTilemap_recacheAnimations(pIntro->pFlashFx);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Get the camera's dimensions (to limit the text's dimensions)
    rv = gfm_getCameraDimensions(&width, &height, pGame->pCtx);
    ASSERT_NR(rv == GFMRV_OK);
    // Prepare the text
    rv = gfmText_init(pGame->common.pText, 0/*x*/, 16/*y*/, width / 8,
            3/*maxLines*/, 50/*delay*/, 0/*dontBindToWorld*/, pGame->pSset8x8,
            0/*firstTile*/);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Initialize the player
    rv = player_init(&(pIntro->pPl), pGame, 36/*x*/, 150/*y*/);
    ASSERT_NR(rv == GFMRV_OK);
    // Initialize the doc
    rv = doc_init(&(pIntro->pDoc), pGame, 145/*x*/, 186/*y*/);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Alloc and initialize the bullet
    rv = gfmSprite_getNew(&(pIntro->pBullet1));
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfmSprite_init(pIntro->pBullet1, 1000, -100, 14/*width*/, 8/*height*/,
            pGame->pSset16x16, -1/*offX*/, -4/*offY*/, 0/*child*/, BULLET);
    ASSERT_NR(rv == GFMRV_OK);
    // Stupid trick, add the animation twice so we can reset it
    rv = gfmSprite_addAnimations(pIntro->pBullet1, pBulletAnimData, bulletAnimDataLen);
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfmSprite_getNew(&(pIntro->pBullet2));
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfmSprite_init(pIntro->pBullet2, 1000, -100, 14/*width*/, 8/*height*/,
            pGame->pSset16x16, -1/*offX*/, -4/*offY*/, 0/*child*/, BULLET);
    ASSERT_NR(rv == GFMRV_OK);
    // Stupid trick, add the animation twice so we can reset it
    rv = gfmSprite_addAnimations(pIntro->pBullet2, pBulletAnimData, bulletAnimDataLen);
    ASSERT_NR(rv == GFMRV_OK);
    
    pIntro->state = intro_begin;
    
    rv = GFMRV_OK;
__ret:
    return rv;
}
Example #23
0
int main(int arg, char *argv[]) {
    gfmCtx *pCtx;
    gfmObject *pObj;
    gfmQuadtreeRoot *pQTRoot;
    gfmRV rv;
    gfmSprite *pSpr;
    gfmSpriteset *pSset8, *pSset16;
    int iTex;
    
    // Initialize every variable
    pCtx = 0;
    pObj = 0;
    pQTRoot = 0;
    pSpr = 0;
    
    // Try to get a new context
    rv = gfm_getNew(&pCtx);
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfm_initStatic(pCtx, "com.gfmgamecorner", "gframe_quadtree_basic");
    ASSERT_NR(rv == GFMRV_OK);
    
    // Initialize the window
    rv = gfm_initGameWindow(pCtx, WNDW, WNDH, 640, 480, 0, 0);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Load the texture
    rv = gfm_loadTextureStatic(&iTex, pCtx, "big_atlas.bmp", 0xff00ff);
    ASSERT_NR(rv == GFMRV_OK);
    // Set it as the default
    rv = gfm_setDefaultTexture(pCtx, iTex);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Create the spritesets
    rv = gfm_createSpritesetCached(&pSset8, pCtx, iTex, 8/*tw*/, 8/*th*/);
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfm_createSpritesetCached(&pSset16, pCtx, iTex, 16/*tw*/, 16/*th*/);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Initalize the FPS counter
    rv = gfm_initFPSCounter(pCtx, pSset8, 64/*firstTile*/);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Create an object
    rv = gfmObject_getNew(&pObj);
    ASSERT_NR(rv == GFMRV_OK);
    // Initialize it
    rv = gfmObject_init(pObj, 0/*x*/, WNDH - 16/*y*/, WNDW, 16, 0/*pChild*/, 0);
    ASSERT_NR(rv == GFMRV_OK);
    // Make it immovable
    rv = gfmObject_setFixed(pObj);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Create a sprite
    rv = gfmSprite_getNew(&pSpr);
    ASSERT_NR(rv == GFMRV_OK);
    // Initialize it
    rv = gfmSprite_init(pSpr, 16/*x*/, 16/*y*/, 6/*width*/, 12/*height*/,
            pSset16, -4/*offX*/, -4/*offY*/, 0/*pChild*/, 0/*type*/);
    ASSERT_NR(rv == GFMRV_OK);
    // Add the animations
    rv = gfmSprite_addAnimationsStatic(pSpr, pSprAnims);
    ASSERT_NR(rv == GFMRV_OK);
    // Set the sprite's gravity
    rv = gfmSprite_setVerticalAcceleration(pSpr, 500.0);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Play an animation
    rv = gfmSprite_playAnimation(pSpr, ANIM_FALL);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Alloc the quadtree
    rv = gfmQuadtree_getNew(&pQTRoot);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Set the main loop framerate
    rv = gfm_setStateFrameRate(pCtx, FPS, FPS);
    ASSERT_NR(rv == GFMRV_OK);
    // Initialize the timer
    rv = gfm_setFPS(pCtx, FPS);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Run until the window is closed
    while (gfm_didGetQuitFlag(pCtx) == GFMRV_FALSE) {
        rv = gfm_handleEvents(pCtx);
        ASSERT_NR(rv == GFMRV_OK);
        
        // Update stuff
        while (gfm_isUpdating(pCtx) == GFMRV_TRUE) {
            rv = gfm_fpsCounterUpdateBegin(pCtx);
            ASSERT_NR(rv == GFMRV_OK);
            
            // Update the sprite's physics
            rv = gfmSprite_update(pSpr, pCtx);
            ASSERT_NR(rv == GFMRV_OK);
            // Update the object's physics
            rv = gfmObject_update(pObj, pCtx);
            ASSERT_NR(rv == GFMRV_OK);
            
            // Initialize the root of the quadtree
            //rv = gfmQuadtree_initRoot(pQTRoot, -16, -16, WNDW+32, WNDH+32, 2, 4);
            //ASSERT_NR(rv == GFMRV_OK);
            
            // These parameters forces the qt to be subdivided even with 2 objs
            // Also, it's a little smaller than the screen to be visible
            rv = gfmQuadtree_initRoot(pQTRoot, 2, 2, WNDW-4, WNDH-4, 2, 1);
            ASSERT_NR(rv == GFMRV_OK);
            // Populate the quadtree with the object
            rv = gfmQuadtree_populateObject(pQTRoot, pObj);
            ASSERT_NR(rv == GFMRV_OK);
            
            // Add the sprite, colliding with everything
            rv = gfmQuadtree_collideSprite(pQTRoot, pSpr);
            ASSERT_NR(rv == GFMRV_QUADTREE_DONE ||
                    rv == GFMRV_QUADTREE_OVERLAPED);
            while (rv != GFMRV_QUADTREE_DONE) {
                gfmObject *pObj1, *pObj2;
                gfmSprite *pSpr1, *pSpr2;
                int pType1, pType2;
                
                // Get the objects that collided
                rv = gfmQuadtree_getOverlaping(&pObj1, &pObj2, pQTRoot);
                ASSERT_NR(rv == GFMRV_OK);
                
                // Separate both objects
                rv = gfmObject_separateHorizontal(pObj1, pObj2);
                rv = gfmObject_separateVertical(pObj1, pObj2);
                
                // Try to get both sprites children
                rv = gfmObject_getChild((void**)&pSpr1, &pType1, pObj1);
                ASSERT_NR(rv == GFMRV_OK);
                rv = gfmObject_getChild((void**)&pSpr2, &pType2, pObj2);
                ASSERT_NR(rv == GFMRV_OK);
                
                // Change the sprite animation and cap its velocity
                if (pType1 == gfmType_sprite) {
                    rv = gfmSprite_playAnimation(pSpr1, ANIM_STAND);
                    ASSERT_NR(rv == GFMRV_OK);
                    rv = gfmSprite_setVerticalVelocity(pSpr1, 0.0);
                    ASSERT_NR(rv == GFMRV_OK);
                    rv = gfmSprite_setVerticalAcceleration(pSpr1, 0.0);
                    ASSERT_NR(rv == GFMRV_OK);
                }
                if (pType2 == gfmType_sprite) {
                    rv = gfmSprite_playAnimation(pSpr2, ANIM_STAND);
                    ASSERT_NR(rv == GFMRV_OK);
                    rv = gfmSprite_setVerticalVelocity(pSpr2, 0.0);
                    ASSERT_NR(rv == GFMRV_OK);
                    rv = gfmSprite_setVerticalAcceleration(pSpr2, 0.0);
                    ASSERT_NR(rv == GFMRV_OK);
                }
                
                // Continue colliding
                rv = gfmQuadtree_continue(pQTRoot);
                ASSERT_NR(rv == GFMRV_QUADTREE_DONE ||
                        rv == GFMRV_QUADTREE_OVERLAPED);
            }
            
            rv = gfm_fpsCounterUpdateEnd(pCtx);
            ASSERT_NR(rv == GFMRV_OK);
        }
        
        // Draw stuff
        while (gfm_isDrawing(pCtx) == GFMRV_TRUE) {
            rv = gfm_drawBegin(pCtx);
            ASSERT_NR(rv == GFMRV_OK);
            
            // Draw the sprite
            rv = gfmSprite_draw(pSpr, pCtx);
            ASSERT_NR(rv == GFMRV_OK);
            
            // Draw the quadtree's bounds
            rv = gfmQuadtree_drawBounds(pQTRoot, pCtx, 0);
            ASSERT_NR(rv == GFMRV_OK);
            
            rv = gfm_drawEnd(pCtx);
            ASSERT_NR(rv == GFMRV_OK);
        }
    }
    
    rv = GFMRV_OK;
__ret:
    gfmQuadtree_free(&pQTRoot);
    gfmSprite_free(&pSpr);
    gfmObject_free(&pObj);
    gfm_free(&pCtx);
    
    return rv;
}
Example #24
0
/**
 * Draw the quadtree to the screen.
 *
 * The object's type acts as index for the color. The first five colors are
 * reserved to represent the framework's types. It loops at gfmType_max
 * (currently 32).
 *
 * It's possible (and quite easy) to force different types to use the same
 * color. The following bitmask combination can be used:
 *
 *   27 bits for dif. entities | 5 bits for the different types
 * |---------------------------|-----|
 *
 * This way, the user may specify 27 different types, each of which may be used
 * in any of 2^27 different entities.
 * NOTE: This functions will be most likely slow!! Be careful when calling it!
 * 
 * @param  pQt     The quadtree's root
 * @param  pCtx    The game's context
 * @param  pColors The colors to be used; Must have 32 colors, each with RGB
 *                 components; The first set is for quadtree nodes, while the
 *                 others respect the types on gfmTypes.h
 * @return         GFMRV_OK, GFMRV_ARGUMENTS_BAD
 */
gfmRV gfmQuadtree_drawBounds(gfmQuadtreeRoot *pQt, gfmCtx *pCtx,
        unsigned char *pColors) {
    gfmRV rv;
    
    // Sanitize arguments
    ASSERT(pQt, GFMRV_ARGUMENTS_BAD);
    ASSERT(pCtx, GFMRV_ARGUMENTS_BAD);
    
    // If no color was set, use the default ones
    if (pColors == 0) {
        pColors = gfmQt_defColors;
    }
    
    // Clear the call stack
    pQt->stack.pushPos = 0;
    
    // Push the root node to start colliding
    rv = gfmQuadtree_pushNode(pQt, pQt->pSelf);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Iterate through all nodes
    while (pQt->stack.pushPos > 0 || pQt->pColliding) {
        gfmQuadtree *pNode;
        unsigned char *pNodeColor;
        
        // Pop the current node
        rv = gfmQuadtree_popNode(&pNode, pQt);
        ASSERT_NR(rv == GFMRV_OK);
        
        // Get the colors for the qt node
        pNodeColor = pColors;
        // Draw the current node
        rv = gfm_drawRect(pCtx, pNode->centerX - pNode->halfWidth,
                pNode->centerY - pNode->halfHeight, pNode->halfWidth * 2,
                pNode->halfHeight * 2, pNodeColor[0], pNodeColor[1],
                pNodeColor[2]);
        ASSERT_NR(rv == GFMRV_OK);
        
        // If it has children, push its children
        if (pNode->ppChildren[gfmQT_nw]) {
            gfmQuadtreePosition i;
            gfmQuadtree *pChild;

            i = gfmQT_nw;
            while (i < gfmQT_max) {
                // Get the current child
                pChild = pNode->ppChildren[i];
                // Push it (so it will be drawn later)
                rv = gfmQuadtree_pushNode(pQt, pChild);
                ASSERT_NR(rv == GFMRV_OK);
                i++;
            }
        }
        else {
            gfmQuadtreeLL *pTmp;
            
            // Otherwise, draw its nodes
            pTmp = pNode->pNodes;
            
            while (pTmp) {
                unsigned int type;
                int height, width, x, y;
                void *pChild;
                
                // Get the object's child
                rv = gfmObject_getChild(&pChild, (int*)&type, pTmp->pSelf);
                ASSERT_NR(rv == GFMRV_OK);
                if (type == gfmType_sprite) {
                    rv = gfmSprite_getChild(&pChild, (int*)&type,
                            (gfmSprite*)pChild);
                    ASSERT_NR(rv == GFMRV_OK);
                    
                    if (type == gfmType_none) {
                        // If no custom type was specified, set it to sprite
                        type = gfmType_sprite;
                    }
                }
                else if (type == gfmType_none) {
                    // If no custom type was specified, set it to object
                    type = gfmType_object;
                }
                
                // Get the object's color
                if (type >= gfmType_max)
                    type = (type % gfmType_max);
                pNodeColor = pColors + type * 3;
                
                // Get the object's position
                rv = gfmObject_getPosition(&x, &y, pTmp->pSelf);
                ASSERT_NR(rv == GFMRV_OK);
                // Get the object's dimensions
                rv = gfmObject_getDimensions(&width, &height, pTmp->pSelf);
                ASSERT_NR(rv == GFMRV_OK);
                
                // Draw the current node
                rv = gfm_drawRect(pCtx, x, y, width, height, pNodeColor[0],
                        pNodeColor[1], pNodeColor[2]);
                ASSERT_NR(rv == GFMRV_OK);
                
                pTmp = pTmp->pNext;
            }
        }
    }
    
    rv = GFMRV_OK;
__ret:
    return rv;
}
Example #25
0
/**
 * Continue colliding and adding the node to the quadtree
 * 
 * @param  pCtx The quadtree's root
 * @return      GFMRV_ARGUMENTS_BAD, GFMRV_QUADTREE_OPERATION_NOT_ACTIVE,
 *              GFMRV_QUADTREE_OVERLAPED, GFMRV_QUADTREE_DONE
 */
gfmRV gfmQuadtree_continue(gfmQuadtreeRoot *pCtx) {
    gfmRV rv;
    
    // Sanitize arguments
    ASSERT(pCtx, GFMRV_ARGUMENTS_BAD);
    // Check that the operation is active
    ASSERT(pCtx->pGroupList || pCtx->pObject,
            GFMRV_QUADTREE_OPERATION_NOT_ACTIVE);
    
    // Continue adding the object
    while (pCtx->stack.pushPos > 0 || pCtx->pColliding) {
        gfmQuadtree *pNode;
        
        // If we were colliding againts objects
        if (pCtx->pColliding) {
            gfmQuadtreeLL *pTmp;
            
            // Retrieve the current object and update the list
            pTmp = pCtx->pColliding;
            pCtx->pColliding = pCtx->pColliding->pNext;
            
            // Check if both objects overlaps
            pCtx->pOther = pTmp->pSelf;
            rv = gfmObject_isOverlaping(pCtx->pObject, pCtx->pOther);
            
            // -- Exit point --
            // If they did overlap, return with that status
            if (rv == GFMRV_TRUE) {
                return GFMRV_QUADTREE_OVERLAPED;
            }
            //ASSERT(rv != GFMRV_TRUE, GFMRV_QUADTREE_OVERLAPED);
        }
        else {
            // Pop the current node
            rv = gfmQuadtree_popNode(&pNode, pCtx);
            ASSERT_NR(rv == GFMRV_OK);
            
            // If it has children, push its children
            if (pNode->ppChildren[gfmQT_nw]) {
                gfmQuadtreePosition i;
                gfmQuadtree *pChild;

                i = gfmQT_nw;
                while (i < gfmQT_max) {
                    // Get the current child
                    pChild = pNode->ppChildren[i];
                    // Check if the object overlaps this node
                    rv = gfmQuadtree_overlap(pChild, pCtx->pObject);
                    if (rv == GFMRV_TRUE) {
                        // Push it (so it will collide later)
                        rv = gfmQuadtree_pushNode(pCtx, pChild);
                        ASSERT_NR(rv == GFMRV_OK);
                    }
                    i++;
                }
            }
            else {
                // If it's static, collide against the node's children
                if (pCtx->isStatic) {
                    pCtx->pColliding = pNode->pNodes;
                }
                // Otherwise, check if inserting the node would subdivide
                // the node (and if there's still room for that
                else if (pNode->numObjects + 1 > pCtx->maxNodes &&
                        pNode->depth + 1 < pCtx->maxDepth) {
                    // Subdivide the tree
                    rv = gfmQuadtree_subdivide(pCtx, pNode);
                    ASSERT_NR(rv == GFMRV_OK);
                    // Push the node again so its children are overlapped/pushed
                    rv = gfmQuadtree_pushNode(pCtx, pNode);
                    ASSERT_NR(rv == GFMRV_OK);
                }
                else {
                    // Otherwise, collide with its nodes
                    pCtx->pColliding = pNode->pNodes;
                    // Add the object to this node 
                    // NOTE: It's added to the begin, so it won't overlap itself
                    rv = gfmQuadtree_insertObject(pCtx, pNode, pCtx->pObject);
                    ASSERT_NR(rv == GFMRV_OK);
                }
            }
        }
    }
    
    // Check if there's another object from a group
    if (pCtx->pGroupList) {
        gfmSprite *pSpr;
        
        while (pCtx->pGroupList) {
            // Retrieve the next sprite...
            rv = gfmGroup_getNextSprite(&pSpr, &(pCtx->pGroupList));
            ASSERT(rv == GFMRV_OK, rv);
            
            // Collide it!
            rv = gfmQuadtree_collideSprite(pCtx, pSpr);
            if (rv != GFMRV_QUADTREE_DONE) {
                // If this sprite didn't finish, return its status
                return rv;
            }
            // If this sprite didn't collide, go to the next
        }
    }
    
    // If the loop stoped, the operation finished
    pCtx->pObject = 0;
    rv = GFMRV_QUADTREE_DONE;
__ret:
    return rv;
}
Example #26
0
/**
 * Updates everything in this state
 * 
 * @param  pGame The game "global" context
 */
static gfmRV state_mainMenu_update(gameCtx *pGame) {
    gfmInputState actionState, gifState;
    gfmRV rv;
    int actionCount, camWidth, camHeight, elapsed, gifCount, y;
    mainMenuCtx *pMainMenu;
    
    // Sanitize arguments
    ASSERT(pGame, GFMRV_ARGUMENTS_BAD);
    ASSERT(pGame->pMainMenu, GFMRV_ARGUMENTS_BAD);
    // Retrieve the main menu context
    pMainMenu = pGame->pMainMenu;
    
    // Get how long elapsed since the last frame
    rv = gfm_getElapsedTime(&elapsed, pGame->pCtx);
    ASSERT_NR(rv == GFMRV_OK);
    
    pMainMenu->animationTime += elapsed;
    while (pMainMenu->animationTime > 16) {
        // Get the tile data and animate it
        if (pMainMenu->titleAnimation < sizeof(titleData) / sizeof(int)) {
            int *pData;
            
            // Go to the next valid (i.e., non-invisible) tile
            while (pMainMenu->titleAnimation + 1 < sizeof(titleData) &&
                    titleData[pMainMenu->titleAnimation] == -1) {
                pMainMenu->titleAnimation++;
            }
            
            // Get its data
            rv = gfmTilemap_getData(&pData, pMainMenu->pTitle);
            ASSERT_NR(rv == GFMRV_OK);
            // Update the tile
            pData[pMainMenu->titleAnimation] =
                    titleData[pMainMenu->titleAnimation];
            
            pMainMenu->titleAnimation++;
            pMainMenu->frameCount++;
        }
        pMainMenu->animationTime -= 16;
    }
    
    // Get the game's dimensions
    rv = gfm_getCameraDimensions(&camWidth, &camHeight, pGame->pCtx);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Animate the BG and floor position
    // BG position is calculate as "-height + (height + pos) * alpha" to start
    // it outside the screen and move until 'pos'
    y = -128 + (128 + 56) * pMainMenu->frameCount / pMainMenu->numAnimFrames;
    rv = gfmTilemap_setPosition(pMainMenu->pBackground, 0, y);
    ASSERT_NR(rv == GFMRV_OK);
    // For the same reason, the floor position is calculated as
    // "WND_HEIGHT - (WND_HEIGHT - pos) * alpha"
    y = camHeight - (camHeight - 176) * pMainMenu->frameCount /
            pMainMenu->numAnimFrames;
    rv = gfmTilemap_setPosition(pMainMenu->pFloor, 0, y);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Update the text timer (it will only render on positive times, and should
    // flick every half second)
    pMainMenu->textTimer += elapsed;
    if (pMainMenu->textTimer >= 750) {
        pMainMenu->textTimer -= 1000;
    }
    
    // Get the action button state to, possibly, go to the play state
    rv = gfm_getKeyState(&actionState, &actionCount, pGame->pCtx,
            pGame->actionHnd);
    ASSERT_NR(rv == GFMRV_OK);
    
    // TODO Check for button presses
    if (actionState & gfmInput_pressed) {
        // TODO Actually switch to the game_stageSelect
        pGame->state = game_playState;
        pGame->switchState = 1;
    }
    
    // Get the gif button state
    rv = gfm_getKeyState(&gifState, &gifCount, pGame->pCtx, pGame->gifHnd);
    ASSERT_NR(rv == GFMRV_OK);
    //if ((gifState & gfmInput_justPressed) == gfmInput_justPressed) {
    //    rv = gfm_recordGif(pGame->pCtx, 10000, "./promo/mainMenu.gif", 20/*len*/,
    //        0/*saveToCurrentPath*/);
    //    ASSERT_NR(rv == GFMRV_OK);
    //}
    
    rv = GFMRV_OK;
__ret:
    return rv;
}
Example #27
0
/**
 * Initialize the menustate
 * 
 * @return GFraMe error code
 */
static GFraMe_ret ms_init(struct stMenustate *ms) {
    GFraMe_ret rv;
    GFraMe_save sv;
    int tmp, ctrPl1, ctrPl2;
    
    ms->pO = 0;
    ms->pM = 0;
    // Check if there's already a saved game
    rv = GFraMe_save_bind(&sv, SAVEFILE);
    ASSERT_NR(rv == GFraMe_ret_ok);
    // Check if something other than the version is written
    if (sv.size > 50)
        ms->hasSave = 1;
    else
        ms->hasSave = 0;
    GFraMe_save_close(&sv);
    
    // Check the configurations
    rv = GFraMe_save_bind(&sv, CONFFILE);
    GFraMe_assertRet(rv == GFraMe_ret_ok, "Error reading config file", __ret);
    // Try to read both players control mode
    ctrPl1 = -1;
    ctrPl2 = -1;
    rv = GFraMe_save_read_int(&sv, "ctr_pl1", &tmp);
    if (rv == GFraMe_ret_ok)
        ctrPl1 = tmp;
    rv = GFraMe_save_read_int(&sv, "ctr_pl2", &tmp);
    if (rv == GFraMe_ret_ok)
        ctrPl2 = tmp;
    // set the control scheme
    if (ctrPl1 != -1 && ctrPl2 != -1) {
        tmp = ctr_setModeForce(ID_PL1, ctrPl1);
        if (tmp)
            tmp = ctr_setModeForce(ID_PL2, ctrPl2);
        // In case any error happened, set the default
        if (!tmp)
            ctr_setDef();
    }
    else
        ctr_setDef();
    // Set the song volume
    rv = GFraMe_save_read_int(&sv, "music", &tmp);
    if (rv == GFraMe_ret_ok)
        audio_setVolume(tmp);
    else
        audio_setVolume(60);
    // Set the sfx volume
    rv = GFraMe_save_read_int(&sv, "sfx", &tmp);
    if (rv == GFraMe_ret_ok)
        sfx_setVolume(tmp);
    else
        sfx_setVolume(50);
    GFraMe_save_close(&sv);
    
    // Zero some variables
    ms->lastPressedTime = 0;
    ms->firstPress = 0;
    // Set the selected option
    if (ms->hasSave)
        ms->curOpt = 0;
    else
        ms->curOpt = 1;
    // Set text position
    ms->textX = 112;
    ms->textY = 176;
    // Set the dev icon position
    ms->iconX = 35 * 8;
    ms->iconY = 25 * 8;
    // Start the menu
    ms->runMenu = 1;
    // Set the title position
    ms->isTitleSet = 0;
    ms->j1X = 82;
    ms->j1Yf = -32.0f;
    ms->j1Y = -32;
    ms->j2X = 122;
    ms->j2Yf = -40.0f;
    ms->j2Y = -40;
    ms->aX = 154;
    ms->aYf = -48.0f;
    ms->aY = -48;
    ms->tX = 194;
    ms->tYf = -54.0f;
    ms->tY = -54;
    ms->idleTime = 0;
    
    rv = map_init(&ms->pM);
    GFraMe_assertRet(rv == GFraMe_ret_ok, "Failed to load background", __ret);
    rv = map_loadf(ms->pM, "maps/mainmenu.gfm");
    GFraMe_assertRet(rv == GFraMe_ret_ok, "Failed to load background", __ret);
    
    rv = obj_getNew(&ms->pO);
    GFraMe_assertRet(rv == GFraMe_ret_ok, "Failed to load background", __ret);
    obj_setZero(ms->pO);
    obj_setBounds(ms->pO, 8*8, 17*8, 2*8, 2*8);
    obj_setID(ms->pO, ID_HEARTUP);
    obj_setCommonEvent(ms->pO, CE_NONE);
    
    cam_x = 0;
    cam_y = 0;
    cam_setMapDimension(40, 30);
    
    audio_playMenu();
    
    rv = GFraMe_ret_ok;
__ret:
    
    return rv;
}
Example #28
0
int main(int arg, char *argv[]) {
    gfmCtx *pCtx;
    gfmGroup *pGrp;
    gfmRV rv;
    gfmQuadtreeRoot *pQt;
    gfmSpriteset *pSset4, *pSset8;
    int click, gif, frame, iTex;
    
    // Initialize every variable
    pCtx = 0;
    pGrp = 0;
    pQt = 0;
    
    // Try to get a new context
    rv = gfm_getNew(&pCtx);
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfm_initStatic(pCtx, "com.gfmgamecorner", "gframe_particle_collision");
    ASSERT_NR(rv == GFMRV_OK);
    
    // Initialize the window
    rv = gfm_initGameWindow(pCtx, WNDW, WNDH, 640, 480, 0, 0);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Create the inputs
    rv = gfm_addVirtualKey(&click, pCtx);
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfm_bindInput(pCtx, click, gfmPointer_button);
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfm_addVirtualKey(&gif, pCtx);
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfm_bindInput(pCtx, gif, gfmKey_space);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Load the texture
    rv = gfm_loadTextureStatic(&iTex, pCtx, "rainbow_atlas.bmp", 0xff00ff);
    ASSERT_NR(rv == GFMRV_OK);
    // Set it as the default
    rv = gfm_setDefaultTexture(pCtx, iTex);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Create the spritesets
    rv = gfm_createSpritesetCached(&pSset8, pCtx, iTex, 8/*tw*/, 8/*th*/);
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfm_createSpritesetCached(&pSset4, pCtx, iTex, 4/*tw*/, 4/*th*/);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Initalize the FPS counter
    rv = gfm_initFPSCounter(pCtx, pSset8, 0/*firstTile*/);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Create the group
    rv = gfmGroup_getNew(&pGrp);
    ASSERT_NR(rv == GFMRV_OK);
    // Set the group attributes
    rv = gfmGroup_setDefSpriteset(pGrp, pSset4);
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfmGroup_setDefDimensions(pGrp, 4/*width*/, 4/*height*/, -2/*offX*/,
        -2/*offY*/);
    ASSERT_NR(rv == GFMRV_OK);
    // Create the group's sprite
    rv = gfmGroup_preCache(pGrp, 0/*initLen*/, 8192/*maxLen*/);
    ASSERT_NR(rv == GFMRV_OK);
    // Those can be set after caching everything, since they are global
    rv = gfmGroup_setDeathOnLeave(pGrp, 1);
    ASSERT_NR(rv == GFMRV_OK);
    // Set the draw order (FUN!!!)
    rv = gfmGroup_setDrawOrder(pGrp, gfmDrawOrder_oldestFirst);
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfmGroup_setDefType(pGrp, PARTICLE);
    ASSERT_NR(rv == GFMRV_OK);
    // Set collision (EVEN MORE FUN!!!)
    rv = gfmGroup_setCollisionQuality(pGrp,
            gfmCollisionQuality_collideEverything);
    ASSERT_NR(rv == GFMRV_OK);
    
    rv = gfmQuadtree_getNew(&pQt);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Set the main loop framerate
    rv = gfm_setStateFrameRate(pCtx, FPS, FPS);
    ASSERT_NR(rv == GFMRV_OK);
    // Initialize the timer
    rv = gfm_setFPS(pCtx, FPS);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Run until the window is closed
    frame = 0;
    while (gfm_didGetQuitFlag(pCtx) == GFMRV_FALSE) {
        rv = gfm_handleEvents(pCtx);
        ASSERT_NR(rv == GFMRV_OK);
        
        // Update stuff
        while (gfm_isUpdating(pCtx) == GFMRV_TRUE) {
            gfmInput *pInput;
            gfmInputState kclick, kgif;
            int nclick, ngif;
            
            rv = gfm_fpsCounterUpdateBegin(pCtx);
            ASSERT_NR(rv == GFMRV_OK);
            
            rv = gfm_getInput(&pInput, pCtx);
            ASSERT_NR(rv == GFMRV_OK);
            
            rv = gfm_getKeyState(&kclick, &nclick, pCtx, click);
            ASSERT_NR(rv == GFMRV_OK);
            rv = gfm_getKeyState(&kgif, &ngif, pCtx, gif);
            ASSERT_NR(rv == GFMRV_OK);
            
            if ((kgif & gfmInput_justPressed) == gfmInput_justPressed) {
                gfm_didExportGif(pCtx);
                rv = gfm_recordGif(pCtx, 10000/*ms*/, "anim.gif", 8, 0);
                ASSERT_NR(rv == GFMRV_OK);
            }
            
            // Spawn particles!
            if ((kclick & gfmInput_pressed) == gfmInput_pressed && nclick == 2) {
                int i, x, y;
                
                rv = gfmInput_getPointerPosition(&x, &y, pInput);
                ASSERT_NR(rv == GFMRV_OK);
                
                i = 0;
                while (i < 8) {
                    gfmSprite *pSpr;
                    
                    rv = gfmGroup_recycle(&pSpr, pGrp);
                    ASSERT_NR(rv == GFMRV_OK || rv == GFMRV_GROUP_MAX_SPRITES);
                    
                    if (rv == GFMRV_OK) {
                        int sprX, sprY;
                        float fvx, fvy;
                        
                        if (i < 4) {
                            int vx, vy;
                            
                            // Set X = 1 on even and Y = 1 on odd
                            vx = (i % 2);
                            vy = 1 - vx;
                            // Set to positive on 0,1 and negative on 2,3
                            fvx = vx * (1 - i / 2) - vx * (i / 2);
                            fvy = vy * (1 - i / 2) - vy * (i / 2);
                        }
                        else if (i >= 4) {
                            int j;
                            
                            // Set to positive on 0,1 and negative on 2,3
                            j = i % 4;
                            fvx = (1 - j / 2) - (j / 2);
                            // Set to positive on 1,2 and negative on 0,3
                            j = (i - 1) % 4;
                            fvy = (1 - j / 2) - (j / 2);
                            
                            fvx *= 0.7071;
                            fvy *= 0.7071;
                        }
                        
                        sprX = x + 16 * fvx;
                        sprY = y + 16 * fvy;
                        fvx *= 100;
                        fvy *= 100;
                        
                        rv = gfmGroup_setPosition(pGrp, sprX, sprY);
                        ASSERT_NR(rv == GFMRV_OK);
                        rv = gfmGroup_setFrame(pGrp, frame);
                        ASSERT_NR(rv == GFMRV_OK);
                        rv = gfmGroup_setVelocity(pGrp, fvx, fvy);
                        ASSERT_NR(rv == GFMRV_OK);
                        
                        frame = (frame + 1) % 7;
                    }
                    i++;
                }
            }
            
            // Update group
            rv = gfmGroup_update(pGrp, pCtx);
            ASSERT_NR(rv == GFMRV_OK);
            
            rv = gfmQuadtree_initRoot(pQt, 0, 0, WNDW, WNDH, 6, 10);
            ASSERT_NR(rv == GFMRV_OK);
            
            // Collide everything
            rv = gfmQuadtree_collideGroup(pQt, pGrp);
            ASSERT(rv == GFMRV_QUADTREE_OVERLAPED || rv == GFMRV_QUADTREE_DONE,
                    rv);
            while (rv != GFMRV_QUADTREE_DONE) {
                gfmObject *pObj1, *pObj2;
                gfmSprite *pSpr1, *pSpr2;
                gfmGroupNode *pNode1, *pNode2;
                int type1, type2;
                
                // Retrieve the colliding objects
                rv = gfmQuadtree_getOverlaping(&pObj1, &pObj2, pQt);
                ASSERT(rv == GFMRV_OK, rv);
                
                // Retrieve its child and the child's type
                rv = gfmObject_getChild((void**)&pSpr1, &type1, pObj1);
                ASSERT(rv == GFMRV_OK, rv);
                rv = gfmObject_getChild((void**)&pSpr2, &type2, pObj2);
                ASSERT(rv == GFMRV_OK, rv);
                
                // Retrieve the child's child and type
                if (type1 == gfmType_sprite) {
                    rv = gfmSprite_getChild((void**)&pNode1, &type1, pSpr1);
                    ASSERT(rv == GFMRV_OK, rv);
                }
                if (type2 == gfmType_sprite) {
                    rv = gfmSprite_getChild((void**)&pNode2, &type2, pSpr2);
                    ASSERT(rv == GFMRV_OK, rv);
                }
                
                // If two particles are colliding, do fun stuff
                if (type1 == PARTICLE && type2 == PARTICLE) {
                    rv = gfmObject_collide(pObj1, pObj2);
                    ASSERT(rv == GFMRV_TRUE || rv == GFMRV_FALSE, rv);
                    
                    if (rv == GFMRV_TRUE) {
                        double vx, vy;
                        
                        rv = gfmObject_getVelocity(&vx, &vy, pObj1);
                        ASSERT(rv == GFMRV_OK, rv);
                        rv = gfmObject_setVelocity(pObj1, vy * 1.01, vx * 1.01);
                        ASSERT(rv == GFMRV_OK, rv);
                        rv = gfmObject_getVelocity(&vx, &vy, pObj2);
                        ASSERT(rv == GFMRV_OK, rv);
                        rv = gfmObject_setVelocity(pObj2, vy * 1.01, vx * 1.01);
                        ASSERT(rv == GFMRV_OK, rv);
                    }
                }
                
                rv = gfmQuadtree_continue(pQt);
                ASSERT(rv == GFMRV_QUADTREE_OVERLAPED ||
                        rv == GFMRV_QUADTREE_DONE, rv);
            }
            
            rv = gfm_fpsCounterUpdateEnd(pCtx);
            ASSERT_NR(rv == GFMRV_OK);
        }
        
        // Draw stuff
        while (gfm_isDrawing(pCtx) == GFMRV_TRUE) {
            rv = gfm_drawBegin(pCtx);
            ASSERT_NR(rv == GFMRV_OK);
            
            // Draw group
            rv = gfmGroup_draw(pGrp, pCtx);
            ASSERT_NR(rv == GFMRV_OK);
            
            rv = gfm_drawEnd(pCtx);
            ASSERT_NR(rv == GFMRV_OK);
        }
    }
    
    rv = GFMRV_OK;
__ret:
    gfmGroup_free(&pGrp);
    gfmQuadtree_free(&pQt);
    gfm_free(&pCtx);
    
    return rv;
}
Example #29
0
/**
 * Initialize everything needed by the main menu
 * 
 * @param  pGame The game "global" context
 * @return       GFMRV_OK, GFMRV_ARGUMENTS_BAD, GFMRV_ALLOC_FAILED, ...
 */
static gfmRV state_mainMenu_init(gameCtx *pGame) {
    gfmRV rv;
    int i;
    mainMenuCtx *pMainMenu;
    
    // Sanitize arguments
    ASSERT(pGame, GFMRV_ARGUMENTS_BAD);
    
    // Alloc the main menu
    pGame->pMainMenu = (mainMenuCtx*)malloc(sizeof(mainMenuCtx));
    ASSERT(pGame->pMainMenu, GFMRV_ALLOC_FAILED);
    pMainMenu = pGame->pMainMenu;
    // Clean it
    memset(pMainMenu, 0x0, sizeof(mainMenuCtx));
    
    // Alloc and initialize the title
    rv = gfmTilemap_getNew(&(pMainMenu->pTitle));
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfmTilemap_init(pMainMenu->pTitle, pGame->pSset8x8, 32, 16, -1);
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfmTilemap_setPosition(pMainMenu->pTitle, 32, 0);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Alloc and load the background
    rv = gfmTilemap_getNew(&(pMainMenu->pBackground));
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfmTilemap_init(pMainMenu->pBackground, pGame->pSset8x16, 40, 8, -1);
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfmTilemap_loadStatic(pMainMenu->pBackground, backgroundData, 40, 8);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Alloc and load the floor
    rv = gfmTilemap_getNew(&(pMainMenu->pFloor));
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfmTilemap_init(pMainMenu->pFloor, pGame->pSset16x16, 20, 8, -1);
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfmTilemap_loadStatic(pMainMenu->pFloor, floorData, 20, 4);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Alloc and initialize the "touch to play" text
    rv = gfmText_getNew(&(pMainMenu->pText));
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfmText_init(pMainMenu->pText, 96/*x*/, 168/*y*/, 17/*maxWidth*/,
            1/*maxLines*/, 0/*delay*/, 0/*doBindToScreen*/, pGame->pSset8x8,
            0/*firstTile*/);
    ASSERT_NR(rv == GFMRV_OK);
    // TODO Initialize accordingly with desktop or mobile
    rv = gfmText_setTextStatic(pMainMenu->pText, "--TOUCH TO PLAY--", 1);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Count how many frames there will be in the animation
    pMainMenu->numAnimFrames = 0;
    i = 0;
    while (i < sizeof(titleData) / sizeof(int)) {
        if (titleData[i] != -1) {
            pMainMenu->numAnimFrames++;
        }
        i++;
    }
    
    // TODO initialize everything else
    
    rv = GFMRV_OK;
__ret:
    return rv;
}
Example #30
0
int main(int arg, char *argv[]) {
    gfmCtx *pCtx;
    gfmRV rv;
    gfmQuadtreeRoot *pQTRoot;
    gfmSpriteset *pSset;
    gfmTilemap *pTMap;
    int iTex;
    
    // Initialize every variable
    pCtx = 0;
    pTMap = 0;
    pSset = 0;
    pQTRoot = 0;
    
    // Try to get a new context
    rv = gfm_getNew(&pCtx);
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfm_initStatic(pCtx, "com.gfmgamecorner", "gframe_test_tilemap");
    ASSERT_NR(rv == GFMRV_OK);
    
    // Initialize the window
    rv = gfm_initGameWindow(pCtx, 160, 120, 640, 480, 0, 0);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Load the texture
    rv = gfm_loadTextureStatic(&iTex, pCtx, "ld32-atlas.bmp", 0xff00ff);
    ASSERT_NR(rv == GFMRV_OK);
    // Set it as the default
    rv = gfm_setDefaultTexture(pCtx, iTex);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Create a spriteset
    rv = gfmSpriteset_getNew(&pSset);
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfmSpriteset_initCached(pSset, pCtx, iTex, 8/*tw*/, 8/*th*/);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Create and load the tilemap
    rv = gfmTilemap_getNew(&pTMap);
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfmTilemap_init(pTMap, pSset, 1/*mapWidth*/, 1/*mapHeight*/,
            0/*defTile*/);
    ASSERT_NR(rv == GFMRV_OK);
    rv = gfmTilemap_loadf(pTMap, pCtx, "map.gfm", 7/*strLen*/, pDictStr,
            pDictTypes, 2);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Alloc the quadtree
    rv = gfmQuadtree_getNew(&pQTRoot);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Set the main loop framerate
    rv = gfm_setStateFrameRate(pCtx, FPS, FPS);
    ASSERT_NR(rv == GFMRV_OK);
    // Initialize the timer
    rv = gfm_setFPS(pCtx, FPS);
    ASSERT_NR(rv == GFMRV_OK);
    
    // Run until the window is closed
    while (gfm_didGetQuitFlag(pCtx) == GFMRV_FALSE) {
        rv = gfm_handleEvents(pCtx);
        ASSERT_NR(rv == GFMRV_OK);
        
        // Update stuff
        while (gfm_isUpdating(pCtx) == GFMRV_TRUE) {
            rv = gfm_fpsCounterUpdateBegin(pCtx);
            ASSERT_NR(rv == GFMRV_OK);
            
            // These parameters forces the qt to be subdivided even with 2 objs
            // Also, it's a little smaller than the screen to be visible
            rv = gfmQuadtree_initRoot(pQTRoot, 2, 2, WNDW-4, WNDH-4, 2, 1);
            ASSERT_NR(rv == GFMRV_OK);
            // Populate the quadtree with the object
            rv = gfmQuadtree_populateTilemap(pQTRoot, pTMap);
            ASSERT_NR(rv == GFMRV_OK);
            
            rv = gfm_fpsCounterUpdateEnd(pCtx);
            ASSERT_NR(rv == GFMRV_OK);
        }
        
        // Draw stuff
        while (gfm_isDrawing(pCtx) == GFMRV_TRUE) {
            rv = gfm_drawBegin(pCtx);
            ASSERT_NR(rv == GFMRV_OK);
            
            rv = gfmTilemap_draw(pTMap, pCtx);
            ASSERT_NR(rv == GFMRV_OK);
            // Draw the quadtree's bounds
            rv = gfmQuadtree_drawBounds(pQTRoot, pCtx, 0);
            ASSERT_NR(rv == GFMRV_OK);
            
            rv = gfm_drawEnd(pCtx);
            ASSERT_NR(rv == GFMRV_OK);
        }
    }
            
    rv = GFMRV_OK;
__ret:
    gfmQuadtree_free(&pQTRoot);
    gfmTilemap_free(&pTMap);
    gfmSpriteset_free(&pSset);
    gfm_free(&pCtx);
    
    return rv;
}