int main() { /* Turn on the 2D graphics core. */ powerOn(POWER_ALL_2D); /* * Configure the VRAM and background control registers. * * Place the main screen on the bottom physical screen. Then arrange the * VRAM banks. Next, confiure the background control registers. */ lcdMainOnBottom(); initVideo(); initBackgrounds(); /* Set up a few sprites. */ SpriteInfo spriteInfo[SPRITE_COUNT]; OAMTable *oam = new OAMTable(); initOAM(oam); initSprites(oam, spriteInfo); /* Display the backgrounds. */ displayStarField(); displayPlanet(); displaySplash(); /* Make the ship object. */ static const int SHUTTLE_OAM_ID = 0; SpriteEntry * shipEntry = &oam->oamBuffer[SHUTTLE_OAM_ID]; SpriteRotation * shipRotation = &oam->matrixBuffer[SHUTTLE_OAM_ID]; Ship * ship = new Ship(&spriteInfo[SHUTTLE_OAM_ID]); /* Accelerate the ship for a little while to make it move. */ for (int i = 0; i < 10; i++) { ship->accelerate(); } for (;;) { /* Update the game state. */ ship->moveShip(); /* Update sprite attributes. */ MathVector2D<float> position = ship->getPosition(); shipEntry->x = (int)position.x; shipEntry->y = (int)position.y; rotateSprite(shipRotation, -ship->getAngleDeg()); /* * Update the OAM. * * We have to copy our copy of OAM data into the actual OAM during * VBlank (writes to it are locked during other times). */ swiWaitForVBlank(); updateOAM(oam); } return 0; }
bool ArrangeSpriteOP<TBase>::onMouseDrag(int x, int y) { if (TBase::onMouseDrag(x, y)) return true; if (m_scaleOpen && m_scaling && m_scaleSelected.isValid()) { Vector pos = m_editPanel->transPosScreenToProject(x, y); scaleSprite(pos); return false; } if (m_selection->empty()) return false; Vector pos = m_editPanel->transPosScreenToProject(x, y); if (m_bRightPress) rotateSprite(pos); else translateSprite(pos - m_lastPos); m_lastPos = pos; return false; }
static void processKeyboard(Sprite* sprite) { tic_mem* tic = sprite->tic; if(tic->ram.input.keyboard.data == 0) return; switch(getClipboardEvent()) { case TIC_CLIPBOARD_CUT: cutToClipboard(sprite); break; case TIC_CLIPBOARD_COPY: copyToClipboard(sprite); break; case TIC_CLIPBOARD_PASTE: copyFromClipboard(sprite); break; default: break; } bool ctrl = tic->api.key(tic, tic_key_ctrl); if(ctrl) { if(keyWasPressed(tic_key_z)) undo(sprite); else if(keyWasPressed(tic_key_y)) redo(sprite); } else { if(hasCanvasSelection(sprite)) { if(keyWasPressed(tic_key_up)) upCanvas(sprite); else if(keyWasPressed(tic_key_down)) downCanvas(sprite); else if(keyWasPressed(tic_key_left)) leftCanvas(sprite); else if(keyWasPressed(tic_key_right)) rightCanvas(sprite); else if(keyWasPressed(tic_key_delete)) deleteCanvas(sprite); } else { if(keyWasPressed(tic_key_up)) upSprite(sprite); else if(keyWasPressed(tic_key_down)) downSprite(sprite); else if(keyWasPressed(tic_key_left)) leftSprite(sprite); else if(keyWasPressed(tic_key_right)) rightSprite(sprite); else if(keyWasPressed(tic_key_delete)) deleteSprite(sprite); else if(keyWasPressed(tic_key_tab)) switchBanks(sprite); if(!sprite->editPalette) { if(keyWasPressed(tic_key_1)) sprite->mode = SPRITE_DRAW_MODE; else if(keyWasPressed(tic_key_2)) sprite->mode = SPRITE_PICK_MODE; else if(keyWasPressed(tic_key_3)) sprite->mode = SPRITE_SELECT_MODE; else if(keyWasPressed(tic_key_4)) sprite->mode = SPRITE_FILL_MODE; else if(keyWasPressed(tic_key_5)) flipSpriteHorz(sprite); else if(keyWasPressed(tic_key_6)) flipSpriteVert(sprite); else if(keyWasPressed(tic_key_7)) rotateSprite(sprite); else if(keyWasPressed(tic_key_8)) deleteSprite(sprite); if(sprite->mode == SPRITE_DRAW_MODE) { if(keyWasPressed(tic_key_leftbracket)) {if(sprite->brushSize > 1) sprite->brushSize--;} else if(keyWasPressed(tic_key_rightbracket)) {if(sprite->brushSize < 4) sprite->brushSize++;} } } } } }
void initSprites(OAMTable * oam, SpriteInfo *spriteInfo) { /* Define some sprite configuration specific constants. * * We will use these to compute the proper index into memory for certain * tiles or palettes. * * OFFSET_MULTIPLIER is calculated based on the following formula from * GBATEK (http://nocash.emubase.de/gbatek.htm#dsvideoobjs): * TileVramAddress = TileNumber * BoundaryValue * Since SPRITE_GFX is a uint16*, the compiler will increment the address * it points to by 2 for each change in 1 of the array index into * SPRITE_GFX. (The compiler does pointer arithmetic.) */ static const int BYTES_PER_16_COLOR_TILE = 32; static const int COLORS_PER_PALETTE = 16; static const int BOUNDARY_VALUE = 32; /* This is the default boundary value * (can be set in REG_DISPCNT) */ static const int OFFSET_MULTIPLIER = BOUNDARY_VALUE / sizeof(SPRITE_GFX[0]); /* Keep track of the available tiles. */ int nextAvailableTileIdx = 0; /* Create the ship sprite. */ static const int SHUTTLE_OAM_ID = 0; assert(SHUTTLE_OAM_ID < SPRITE_COUNT); SpriteInfo * shuttleInfo = &spriteInfo[SHUTTLE_OAM_ID]; SpriteEntry * shuttle = &oam->oamBuffer[SHUTTLE_OAM_ID]; /* Initialize shuttleInfo */ shuttleInfo->oamId = SHUTTLE_OAM_ID; shuttleInfo->width = 64; shuttleInfo->height = 64; shuttleInfo->angle = 3186; shuttleInfo->entry = shuttle; /* * Configure attribute 0. * * OBJCOLOR_16 will make a 16-color sprite. We specify that we want an * affine sprite (via isRotateScale) here because we would like to rotate * the ship. */ shuttle->y = SCREEN_HEIGHT / 2 - shuttleInfo->height; shuttle->isRotateScale = true; /* This assert is a check to see a matrix is available to store the affine * transformation matrix for this sprite. Of course, you don't have to have * the matrix id match the affine id, but if you do make them match, this * assert can be helpful. */ assert(!shuttle->isRotateScale || (shuttleInfo->oamId < MATRIX_COUNT)); shuttle->isSizeDouble = false; shuttle->blendMode = OBJMODE_NORMAL; shuttle->isMosaic = false; shuttle->colorMode = OBJCOLOR_16; shuttle->shape = OBJSHAPE_SQUARE; /* * Configure attribute 1. * * rotationIndex refers to the loation of affine transformation matrix. We * set it to a location computed with a macro. OBJSIZE_64, in our case * since we are making a square sprite, creates a 64x64 sprite. */ shuttle->x = SCREEN_WIDTH / 2 - shuttleInfo->width * 2 + shuttleInfo->width / 2; shuttle->rotationIndex = shuttleInfo->oamId; shuttle->size = OBJSIZE_64; /* * Configure attribute 2. * * Configure which tiles the sprite will use, which priority layer it will * be placed onto, which palette the sprite should use, and whether or not * to show the sprite. */ shuttle->gfxIndex = nextAvailableTileIdx; nextAvailableTileIdx += orangeShuttleTilesLen / BYTES_PER_16_COLOR_TILE; shuttle->priority = OBJPRIORITY_0; shuttle->palette = shuttleInfo->oamId; /* Rotate the sprite */ rotateSprite(&oam->matrixBuffer[shuttleInfo->oamId], shuttleInfo->angle); /*************************************************************************/ /* Create the moon sprite. */ static const int MOON_OAM_ID = 1; assert(MOON_OAM_ID < SPRITE_COUNT); SpriteInfo * moonInfo = &spriteInfo[MOON_OAM_ID]; SpriteEntry * moon = &oam->oamBuffer[MOON_OAM_ID]; /* Initialize moonInfo */ moonInfo->oamId = MOON_OAM_ID; moonInfo->width = 32; moonInfo->height = 32; moonInfo->angle = 0; moonInfo->entry = moon; /* * Configure attribute 0. * * OBJCOLOR_16 will make a 16-color sprite. We won't specify that we want * an affine sprite here because we don't want one this time. */ moon->y = SCREEN_WIDTH / 2 + moonInfo->height / 2; moon->isRotateScale = false; /* This assert is a check to see a matrix is available to store the affine * transformation matrix for this sprite. Of course, you don't have to have * the matrix id match the affine id, but if you do make them match, this * assert can be helpful. */ assert(!moon->isRotateScale || (moonInfo->oamId < MATRIX_COUNT)); moon->isHidden = false; moon->blendMode = OBJMODE_NORMAL; moon->isMosaic = false; moon->colorMode = OBJCOLOR_16; moon->shape = OBJSHAPE_SQUARE; /* * Configure attribute 1. * * OBJSIZE_32 will create a sprite of size 32x32, since we are making a * square sprite. Since we are using a non-affine sprite, attribute 1 * doesn't have an rotationIndex anymore. Instead, it has the ability to * flip the sprite vertically or horizontally. */ moon->x = SCREEN_WIDTH / 2 + moonInfo->width + moonInfo->width / 2; moon->hFlip = false; moon->vFlip = false; moon->size = OBJSIZE_32; /* * Configure attribute 2. * * Configure which tiles the sprite will use, which priority layer it will * be placed onto, which palette the sprite should use, and whether or not * to show the sprite. */ moon->gfxIndex = nextAvailableTileIdx; nextAvailableTileIdx += moonTilesLen / BYTES_PER_16_COLOR_TILE; moon->priority = OBJPRIORITY_2; moon->palette = moonInfo->oamId; /*************************************************************************/ /* Copy over the sprite palettes */ dmaCopyHalfWords(SPRITE_DMA_CHANNEL, orangeShuttlePal, &SPRITE_PALETTE[shuttleInfo->oamId * COLORS_PER_PALETTE], orangeShuttlePalLen); dmaCopyHalfWords(SPRITE_DMA_CHANNEL, moonPal, &SPRITE_PALETTE[moonInfo->oamId * COLORS_PER_PALETTE], moonPalLen); /* Copy the sprite graphics to sprite graphics memory */ dmaCopyHalfWords(SPRITE_DMA_CHANNEL, orangeShuttleTiles, &SPRITE_GFX[shuttle->gfxIndex * OFFSET_MULTIPLIER], orangeShuttleTilesLen); dmaCopyHalfWords(SPRITE_DMA_CHANNEL, moonTiles, &SPRITE_GFX[moon->gfxIndex * OFFSET_MULTIPLIER], moonTilesLen); }
int main() { /* Turn on the 2D graphics core. */ powerOn(POWER_ALL_2D); /* * Configure the VRAM and background control registers. * * Place the main screen on the bottom physical screen. Then arrange the * VRAM banks. Next, confiure the background control registers. */ lcdMainOnBottom(); initVideo(); initBackgrounds(); /* Initialize maxmod using the memory based soundbank set up. */ mmInitDefaultMem((mm_addr)soundbank_bin); /* Set up a few sprites. */ SpriteInfo spriteInfo[SPRITE_COUNT]; OAMTable *oam = new OAMTable(); initOAM(oam); initSprites(oam, spriteInfo); /* Display the backgrounds. */ displayStarField(); displayPlanet(); displaySplash(); /*************************************************************************/ /* Keep track of the touch screen coordinates. */ touchPosition touch; /* Make the ship object. */ static const int SHUTTLE_OAM_ID = 0; SpriteEntry * shipEntry = &oam->oamBuffer[SHUTTLE_OAM_ID]; SpriteRotation * shipRotation = &oam->matrixBuffer[SHUTTLE_OAM_ID]; Ship * ship = new Ship(&spriteInfo[SHUTTLE_OAM_ID]); /* Make the moon. */ static const int MOON_OAM_ID = 1; SpriteEntry * moonEntry = &oam->oamBuffer[MOON_OAM_ID]; SpriteInfo * moonInfo = &spriteInfo[MOON_OAM_ID]; MathVector2D<int> * moonPos = new MathVector2D<int>(); moonPos->x = moonEntry->x; moonPos->y = moonEntry->y; /* Set up sound data. */ mmLoadEffect(SFX_THRUST); for (;;) { /* Update the game state. */ updateInput(&touch); handleInput(ship, moonPos, moonInfo, &touch); ship->moveShip(); /* Update ship sprite attributes. */ MathVector2D<float> position = ship->getPosition(); shipEntry->x = (int)position.x; shipEntry->y = (int)position.y; rotateSprite(shipRotation, -ship->getAngleDeg()); /* Update moon sprite attributes. */ moonEntry->x = (int)moonPos->x; moonEntry->y = (int)moonPos->y; /* * Update the OAM. * * We have to copy our copy of OAM data into the actual OAM during * VBlank (writes to it are locked during other times). */ swiWaitForVBlank(); updateOAM(oam); } return 0; }