unsigned char processControls(void){ static int lastbuttons=0; unsigned int joy=ReadJoypad(0); if((joy&BTN_START) && !(lastbuttons&BTN_START)){ } if(joy&BTN_X){ TriggerNote(3,1,23,0xff); while(ReadJoypad(0)!=0); } if(joy&BTN_Y){ tracks[3].flags&= ~(TRACK_FLAGS_PLAYING); tracks[3].noteVol=0; } if(joy&BTN_SELECT){ while(ReadJoypad(0)!=0); } lastbuttons=joy; return 0; }
// intro screen void DoIntro() { // random number generator seed int rndSeed = 0; SetTileTable(tiles_mammoth); DrawMap2(0, 0, map_mammoth); // game loop char quit = 0; while(!quit) { // wait for v sync WaitVsync(1); // update the seed rndSeed += 7; if(ReadJoypad(0) & BTN_START) quit = 1; } // seed the prng srand(rndSeed); }
/** * \brief Logic for custom intro and processes controller input for skipping intro. */ void processIntro(void) { //cycles through our sine function to move the ghost smoothly wave_tick++; if(wave_tick > 127) wave_tick = 0; player_y = (u8)(100+pgm_read_byte(&(sine32[wave_tick]))); //set ghost height based on sine function player_x++; //move ghost left to right 1 pixel if(player_x == 104) //at correct moment, trigger sound effect TriggerFx(13,0x88,true); if(player_x > 224) //when ghost is off screen, end intro and move to main menu { ResumeSong(); SetTileTable(title_tiles); frame_tick = 8; current_frame = 0; game_state = MAIN_MENU; } //read in our player one joypad input joy=ReadJoypad(0); //if player 1 is currently pressing start if((joy&BTN_START) && (joy != lastbuttons)) { ResumeSong(); SetTileTable(title_tiles); frame_tick = 8; current_frame = 0; lastbuttons=joy; game_state = MAIN_MENU; } lastbuttons=joy; }
int main() { ClearVram(); SetTileTable(graphicsTiles); Screen.overlayTileTable = overlayTiles; for(int y=0;y<32;y++){ for(int x=0;x<32;x++){ SetTile(x,y,0); } } Screen.scrollHeight = SCREEN_SCROLL_HEIGHT; Screen.overlayHeight = SCREEN_OVERLAY_HEIGHT; Map_Init(); int cameraSpeed = 1; while(1) { uint16_t joypad = ReadJoypad(0); if((joypad & BTN_A)) { cameraSpeed = 4; } else { cameraSpeed = 1; } if((joypad & BTN_LEFT) && Camera_Position.x > cameraSpeed) { Camera_Position.x -= cameraSpeed; } if((joypad & BTN_RIGHT) && Camera_Position.x < (Map_Header.width - MAP_TILE_SCROLL_WRAP_X - 1) * MAP_TILE_PIXEL_SIZE - cameraSpeed) { Camera_Position.x += cameraSpeed; } if((joypad & BTN_UP) && Camera_Position.y > cameraSpeed) { Camera_Position.y -= cameraSpeed; } if((joypad & BTN_DOWN) && Camera_Position.y < (Map_Header.height - MAP_TILE_SCROLL_WRAP_Y - 1) * MAP_TILE_PIXEL_SIZE - cameraSpeed) { Camera_Position.y += cameraSpeed; } Map_Update(); // Screen.scrollX = Camera_Position.x; // Screen.scrollY = Camera_Position.y; WaitVsync(1); } return 0; }
void DisplayHowToPlay(){ SetTileTable(tiles); SetFontTilesIndex(TILES_SIZE); ClearTextVram(); DrawMap2(4,1,map_title2); Print(1,5,PSTR("The Game of Life is a cellular ")); Print(1,6,PSTR("automaton devised by the mathematician")); Print(1,7,PSTR("John Conway in 1970. One interacts ")); Print(1,8,PSTR("with the game by creating an initial ")); Print(1,9,PSTR("configuration and observing how it ")); Print(1,10,PSTR("evolves.")); Print(1,12,PSTR("The game is made of a grid of cells ")); Print(1,13,PSTR("each of which has two possible states")); Print(1,14,PSTR("alive or dead. Each turn, cells")); Print(1,15,PSTR("evolves according to four rules:")); Print(1,17,PSTR("1.Any live cell with fewer than two ")); Print(1,18,PSTR(" live neighbours dies")); Print(1,19,PSTR("2.Any live cell with two or three live")); Print(1,20,PSTR(" neighbours lives on to the next turn")); Print(1,21,PSTR("3.Any live cell with more than three")); Print(1,22,PSTR(" live neighbours dies")); Print(1,23,PSTR("4.Any dead cell with exactly three")); Print(1,24,PSTR(" live neighbours becomes a live cell")); Print(15,26,PSTR("PRESS START")); while(1){ if(ReadJoypad(0)==BTN_START){ while(ReadJoypad(0)!=0); return; } } }
/** * \brief Processes controller input during high score menu. */ void processHighScoreMenu(void) { //read in our player one joypad input joy=ReadJoypad(0); //if player 1 is currently pressing start if((joy&BTN_START) && (joy != lastbuttons)) { //switch our game state to game, which pops us out of the main menu and into the game (refer to main function) game_state = GAME; } lastbuttons=joy; }
/* Sample controllers. */ void sampleControllers(void) { uint16_t i; for (i=0; i<2; i++) { /* Read current value. */ controllers[i].previous = controllers[i].current; controllers[i].current = ReadJoypad(i); /* Set event bits. */ controllers[i].held |= controllers[i].current & controllers[i].previous; controllers[i].pressed |= controllers[i].current & (controllers[i].current ^ controllers[i].previous); controllers[i].released |= controllers[i].previous & (controllers[i].current ^ controllers[i].previous); } }
/** * \brief Handles input for gameplay. Reads player 1 joypad and processes input for the main game. */ void processControls(void){ //read current player 1 input, save in joy variable joy=ReadJoypad(0); if(joy) //if any button at is is being pressed { if(scrollingOn) //if we're scrolling the screen (player is alive) { if(lastbuttons!=joy) //if we're pressing a new button, not holding one { yspeed = -jumpspeed; //make player jump up TriggerFx(4,0x88,true);//play our bouncing sound effects TriggerFx(5,0x88,true); grav_tick=1; //reset gravity ticks. doing this ensures that no matter where the gravity timer was, we always get a consistent jump height } } else if(joy&BTN_START) //if player is dead and start was pressed { if(deathclock<105) game_state = HIGH_SCORES; //exit main game state, enter high score screen state (refer to main function) } if(joy&BTN_SELECT)//alive or note, if select was pressed... { if(lastbuttons!=joy) //if it was JUST pressed and not held { if(mute) //if volume is muted, unmute it { SetMasterVolume(0xff); mute=false; ResumeSong(); } else //if volume is normal, mute it { StopSong(); SetMasterVolume(0x00); mute=true; } } } } //save current input as lastbuttons so we can check if new buttons are pressed next time lastbuttons=joy; }
u8 Title(){ ClearTextVram(); SetTileTable(tiles); SetFontTilesIndex(TILES_SIZE); DrawMap2(8,3,map_title1); DrawMap2(4,6,map_title2); DrawMap2(24,13,map_title3); Print(8,15,PSTR("PLAY")); Print(8,16,PSTR("HOW TO PLAY")); // Print(8,17,PSTR("OPTIONS")); Print(13,26,PSTR("V1.1 \\ 2013 Uze")); u8 option=0; u8 animFrame=0,animDelay=0; u8 x=6,y=15; u16 joy,prevJoy=0; while(1){ WaitVsync(1); joy=ReadJoypad(0); AnimateCursor(x,y+option); /* if(animDelay==15){ //clear othercursor location SetTile(x,y+(option^1),0); SetTile(x+1,y+(option^1),0); animDelay=0; animFrame++; if(animFrame==4)animFrame=0; switch(animFrame){ case 0: SetTile(x,y+option,1); SetTile(x+1,y+option,2); break; case 1: SetTile(x,y+option,3); SetTile(x+1,y+option,4); break; case 2: SetTile(x,y+option,5); SetTile(x+1,y+option,6); break; default: SetTile(x,y+option,7); SetTile(x+1,y+option,8); break; } } animDelay++; */ if(prevJoy==0){ if (joy==BTN_SELECT || joy==BTN_UP || joy==BTN_DOWN){ option^=1; animDelay=15; }else if(joy==BTN_START){ while(ReadJoypad(0)!=0); return option; } } prevJoy=joy; } }
void VsyncCallBack(void){ static u16 lastButtons; static u16 autoRepeatDelay=0,interRepeatDelay=0; u16 joy; //process cursor asynchonously of cells processing if(inMainLoop && keyAction==ACTION_NONE){ joy=ReadJoypad(0); bool autoKey=(autoRepeatDelay>AUTO_REPEAT_DELAY && interRepeatDelay>INTER_REPEAT_DELAY); if((joy&BTN_START) && !(lastButtons&BTN_START)){ //paused=!paused; keyAction=ACTION_STARTSTOP; } if((joy&BTN_SELECT) && !(lastButtons&BTN_SELECT)){ keyAction=ACTION_OPENMENU; } if(joy&BTN_RIGHT){ if(!(lastButtons&BTN_RIGHT) || autoKey ){ cursor_x++; interRepeatDelay=0; } }else if(joy&BTN_LEFT){ if(!(lastButtons&BTN_LEFT) || autoKey){ cursor_x--; interRepeatDelay=0; } } if(joy&BTN_UP){ if(!(lastButtons&BTN_UP) || autoKey){ cursor_y--; interRepeatDelay=0; } }else if(joy&BTN_DOWN){ if(!(lastButtons&BTN_DOWN) || autoKey){ cursor_y++; interRepeatDelay=0; } } if(joy&(BTN_LEFT|BTN_RIGHT|BTN_UP|BTN_DOWN)){ autoRepeatDelay++; interRepeatDelay++; }else{ autoRepeatDelay=0; interRepeatDelay=0; } if((joy&BTN_A) && !(lastButtons&BTN_A)){ PutPixel(cursor_x,cursor_y,1,vmode_page); //set pixel } if((joy&BTN_B) && !(lastButtons&BTN_B)){ PutPixel(cursor_x,cursor_y,0,vmode_page); //clear pixel } lastButtons=joy; } }
char multiloop(GameStruct* game) { PlayerStruct players[2]; MainStruct mains; ItemStruct zombie[MAX_ZOMBIES]; ItemStruct shots[2][2]; init(&mains, players, 2, game, zombie, shots); for(;;game->frames++) { WaitVsync(1); multidrawoverlay(game, players); gameflags(game); for(int p = 0; p < 2; p++) { playerflags(&players[p]); players[p].joypad = ReadJoypad(p); } if(players[0].life <= 0 && players[1].life <= 0) { switch(gameovermenu(game, &players[0])) { case 1: return 2; case 2: return 0; default: break; } } else if((players[0].joypad&BTN_SELECT || players[1].joypad&BTN_SELECT) && game->flagcount >= DEBOUNCE_DELAY) { game->flagcount = 0; if(game->flags & GAMEPAUSED) game->flags &= ~GAMEPAUSED; else game->flags |= GAMEPAUSED; } if(game->flags & GAMEPAUSED) continue; rendermap(&mains, 2); screenSections[1].scrollX = mains.x.s; screenSections[1].scrollY = mains.y.s; if(players[0].life > 0 && players[1].life > 0) multimove(players, &mains, shots); else if(players[0].life <= 0) singlemove(&(players[1]), &mains, shots[1]); else if(players[1].life <= 0) singlemove(&(players[0]), &mains, shots[0]); necromancer(zombie, &mains, game, players, 2); for(int p = 0; p < 2; p++) { inputanim(&(players[p])); players[p].gundelay++; for(int i = 0; i < 2; i++) handleshot(&mains, game, &players[p], &shots[p][i], zombie); if(!(players[p].flags & PLAYERHURT) || game->frames&2) { sprites[1 + p * 4].x = sprites[2 + p * 4].x = players[p].x; sprites[1 + p * 4].y = players[p].y; sprites[2 + p * 4].y = players[p].y + TILE_HEIGHT; } else { sprites[1 + p * 4].x = sprites[2 + p * 4].x = DISABLED_SPRITE; sprites[2 + p * 4].y = sprites[1 + p * 4].y = DISABLED_SPRITE; } } } }
/** * Game loop */ void game() { while (level < LEVEL_COUNT) { level++; MENU: menu(); load_level(); refresh_game_screen(); while (!is_level_done()) { int buttons = ReadJoypad(0); char* cursor_field_ptr = &(level_field[cursor_x + cursor_y * LEVEL_FIELD_WIDTH]); if (holding_atom) { if ((buttons & (BTN_A | BTN_B | BTN_X | BTN_Y))) { while (ReadJoypad(0) & (BTN_A | BTN_B | BTN_X | BTN_Y)) {}; *cursor_field_ptr = holding_atom; holding_atom = false; draw_field(); play_sound(SOUND_LEVEL_RELEASE); } if (buttons & BTN_LEFT) { draw_field(); if (level_field[(cursor_x - 1) + cursor_y * LEVEL_FIELD_WIDTH] == TILE_FLOOR) { moves++; while (level_field[(cursor_x - 1) + cursor_y * LEVEL_FIELD_WIDTH] == TILE_FLOOR) { play_sound(SOUND_LEVEL_MOVE); for (uint8_t i = 0; i < TILE_WIDTH; i++) { sprites[SPRITE_CURSOR].x--; draw_statistics(); WaitVsync(1); } cursor_x--; distance++; } } else { play_sound(SOUND_LEVEL_CANT_MOVE); } } if (buttons & BTN_RIGHT) { draw_field(); if (level_field[(cursor_x + 1) + cursor_y * LEVEL_FIELD_WIDTH] == TILE_FLOOR) { moves++; while (level_field[(cursor_x + 1) + cursor_y * LEVEL_FIELD_WIDTH] == TILE_FLOOR) { play_sound(SOUND_LEVEL_MOVE); for (uint8_t i = 0; i < TILE_WIDTH; i++) { sprites[SPRITE_CURSOR].x++; draw_statistics(); WaitVsync(1); } cursor_x++; distance++; } } else { play_sound(SOUND_LEVEL_CANT_MOVE); } } if (buttons & BTN_UP) { draw_field(); if (level_field[cursor_x + (cursor_y - 1) * LEVEL_FIELD_WIDTH] == TILE_FLOOR) { moves++; while (level_field[cursor_x + (cursor_y - 1) * LEVEL_FIELD_WIDTH] == TILE_FLOOR) { play_sound(SOUND_LEVEL_MOVE); for (uint8_t i = 0; i < TILE_WIDTH; i++) { sprites[SPRITE_CURSOR].y--; draw_statistics(); WaitVsync(1); } cursor_y--; distance++; } } else { play_sound(SOUND_LEVEL_CANT_MOVE); } } if (buttons & BTN_DOWN) { draw_field(); if (level_field[cursor_x + (cursor_y + 1) * LEVEL_FIELD_WIDTH] == TILE_FLOOR) { moves++; while (level_field[cursor_x + (cursor_y + 1) * LEVEL_FIELD_WIDTH] == TILE_FLOOR) { play_sound(SOUND_LEVEL_MOVE); for (uint8_t i = 0; i < TILE_WIDTH; i++) { sprites[SPRITE_CURSOR].y++; draw_statistics(); WaitVsync(1); } cursor_y++; distance++; } } else { play_sound(SOUND_LEVEL_CANT_MOVE); } } } else { if ((buttons & (BTN_A | BTN_B | BTN_X | BTN_Y))) { if ((*cursor_field_ptr >= TILE_FIRST_ATOM) && (*cursor_field_ptr <= TILE_LAST_ATOM)) { while (ReadJoypad(0) & (BTN_A | BTN_B | BTN_X | BTN_Y)) {}; holding_atom = *cursor_field_ptr; *cursor_field_ptr = TILE_FLOOR; draw_field(); play_sound(SOUND_LEVEL_CATCH); } else { play_sound(SOUND_LEVEL_CANT_MOVE); } } if (buttons & BTN_LEFT) { if (cursor_x > 0) { for (uint8_t i = 0; i < TILE_WIDTH; i++) { sprites[SPRITE_CURSOR].x--; WaitVsync(1); } cursor_x--; } else { play_sound(SOUND_LEVEL_CANT_MOVE); } } if (buttons & BTN_RIGHT) { if (cursor_x < LEVEL_FIELD_WIDTH - 1) { for (uint8_t i = 0; i < TILE_WIDTH; i++) { sprites[SPRITE_CURSOR].x++; WaitVsync(1); } cursor_x++; } else { play_sound(SOUND_LEVEL_CANT_MOVE); } } if (buttons & BTN_UP) { if (cursor_y > 0) { for (uint8_t i = 0; i < TILE_WIDTH; i++) { sprites[SPRITE_CURSOR].y--; WaitVsync(1); } cursor_y--; } else { play_sound(SOUND_LEVEL_CANT_MOVE); } } if (buttons & BTN_DOWN) { if (cursor_y < LEVEL_FIELD_HEIGHT - 1) { for (uint8_t i = 0; i < TILE_WIDTH; i++) { sprites[SPRITE_CURSOR].y++; WaitVsync(1); } cursor_y++; } else { play_sound(1); } } } if (buttons & BTN_SELECT) { play_sound(SOUND_MENU_SELECT); goto MENU; } if (buttons & BTN_START) { play_sound(SOUND_MENU_SELECT); while (ReadJoypad(0) & BTN_START); load_level(); refresh_game_screen(); } draw_cursor(); draw_statistics(); WaitVsync(5); } hide_sprites(); play_sound(SOUND_LEVEL_CLEARED); WaitVsync(60); // mark level as cleared eeprom_data.data[level / 8] |= 1 << (level % 8); EepromWriteBlock(&eeprom_data); } }
/** * \brief Processes controller input for the main menu. */ void processMainMenu(void) { //read in our player one joypad input joy=ReadJoypad(0); //pressing something and it isn't the same buttons as last frame so it's a new button press, not a hold if(joy!=lastbuttons) { //if player 1 is currently pressing start if(joy&BTN_START) { //if player cursor is at top menu choice, which is 'start game' if(menu_y == 15) { seedprng(start_seed); //switch our game state to game, which pops us out of the main menu and into the game (refer to main function) game_state = GAME; } //if cursor is on second option, which is 'hi scores' else if(menu_y == 17) { seedprng(start_seed); //switch our game state to high scores, which pops us out of the main menu and into the high scores menu (refer to main function) game_state = HIGH_SCORES; } } if(joy&BTN_UP) //player pressed up { if(menu_y > 15) //if we're not at the top menu option { eraseMenuCursor(); //erase the old cursor position menu_y -= 2; //move cursor up one option } } else if (joy&BTN_DOWN) //player pressed down { if(menu_y < 19) //if we're above the bottom option { eraseMenuCursor(); //erase cursor at old position menu_y += 2; //move cursor down one option } } else if ((joy&BTN_LEFT) || (joy&BTN_RIGHT)) //player pressed left or right on d-pad { if(menu_y == 19) //if we're on the third menu option, which is sound on/off { if(mute) //if game is muted, unmute it { SetMasterVolume(0xff); mute=false; } else //if game is not muted, mute it { SetMasterVolume(0x00); mute=true; } refreshMainMenuSound(); //update menu screen to show music as on/off now that it changed } } } lastbuttons=joy; //track which buttons were pressed this frame for comparison next frame start_seed++; }
void Initialize(void){ int i; if(!isEepromFormatted()) FormatEeprom(); cli(); //Initialize the mixer buffer for(i=0;i<MIX_BANK_SIZE*2;i++){ mix_buf[i]=0x80; } mix_pos=mix_buf; mix_bank=0; for(i=0;i<CHANNELS;i++){ mixer.channels.all[i].volume=0; } #if MIXER_CHAN4_TYPE == 0 //initialize LFSR tr4_barrel_lo=1; tr4_barrel_hi=1; tr4_params=0b00000001; //15 bits no divider (1) #endif #if UART_RX_BUFFER == 1 uart_rx_buf_start=0; uart_rx_buf_end=0; #endif #if MIDI_IN == 1 UCSR0B=(1<<RXEN0); //set UART for MIDI in UCSR0C=(1<<UCSZ01)+(1<<UCSZ00); UBRR0L=56; //31250 bauds (.5% error) #endif //stop timers TCCR1B=0; TCCR0B=0; //set ports DDRC=0xff; //video dac DDRB=0xff; //h-sync for ad725 DDRD=(1<<PD7)+(1<<PD4); //audio-out + led PORTD|=(1<<PD4)+(1<<PD3)+(1<<PD2); //turn on led & activate pull-ups for soft-power switches //setup port A for joypads DDRA =0b00001100; //set only control lines as outputs PORTA=0b11111011; //activate pullups on the data lines //PORTD=0; //set sync parameters. starts at odd field, in pre-eq pulses, line 1 sync_phase=SYNC_PHASE_PRE_EQ; sync_pulse=SYNC_PRE_EQ_PULSES; //set rendering parameters render_lines_count_tmp=FRAME_LINES; first_render_line_tmp=FIRST_RENDER_LINE; //clear timers TCNT1H=0; TCNT1L=0; //set sync generator counter on TIMER1 OCR1AH=HDRIVE_CL_TWICE>>8; OCR1AL=HDRIVE_CL_TWICE&0xff; TCCR1B=(1<<WGM12)+(1<<CS10);//CTC mode, use OCR1A for match TIMSK1=(1<<OCIE1A); //generate interrupt on match //set clock divider counter for AD725 on TIMER0 //outputs 14.31818Mhz (4FSC) TCCR0A=(1<<COM0A0)+(1<<WGM01); //toggle on compare match + CTC OCR0A=0; //divide main clock by 2 TCCR0B=(1<<CS00); //enable timer, no pre-scaler //set sound PWM on TIMER2 TCCR2A=(1<<COM2A1)+(1<<WGM21)+(1<<WGM20); //Fast PWM OCR2A=0; //duty cycle (amplitude) TCCR2B=(1<<CS20); //enable timer, no pre-scaler SYNC_PORT=(1<<SYNC_PIN)|(1<<VIDEOCE_PIN); //set sync & chip enable line to hi burstOffset=0; curr_frame=0; vsync_phase=0; joypad1_status_hi=0; joypad2_status_hi=0; snesMouseEnabled=false; sound_enabled=1; //enable color correction ReadButtons(); if(ReadJoypad(0)&BTN_B){ SetColorBurstOffset(4); } InitializeVideoMode(); sei(); DisplayLogo(); }
int main() { // clear the video ClearVram(); // init the music InitMusicPlayer(patches); // show the intro screen DoIntro(); // joystick previous states int padPrev[2] = {0,0}; // now the game loop while(1) { // wait for v sync WaitVsync(1); // load the next state if we need to if(nextState > 0) { // set the new game state and reset the next state gameState = nextState; nextState = 0; // fade out FadeOut(1, true); // init the state if(gameState == STATE_MAINMENU) InitState_MainMenu(); else if(gameState == STATE_PLAYING) InitState_Playing(); else if(gameState == STATE_HOWTOPLAY) InitState_HowToPlay(); else if(gameState == STATE_CREDITS) InitState_Credits(); else if(gameState == STATE_PLAYERSTART) InitState_PlayerStart(); else if(gameState == STATE_GAMEOVER) InitState_GameOver(); } // handle the input padHeld[0] = ReadJoypad(0); padPressed[0] = padHeld[0] & (padHeld[0] ^ padPrev[0]); padReleased[0] = padPrev[0] & (padHeld[0] ^ padPrev[0]); padPrev[0] = padHeld[0]; padHeld[1] = ReadJoypad(0);//1); padPressed[1] = padHeld[1] & (padHeld[1] ^ padPrev[1]); padReleased[1] = padPrev[1] & (padHeld[1] ^ padPrev[1]); padPrev[1] = padHeld[1]; // handle the states if(gameState == STATE_MAINMENU) DoState_MainMenu(); else if(gameState == STATE_PLAYING) DoState_Playing(); else if(gameState == STATE_HOWTOPLAY) DoState_HowToPlay(); else if(gameState == STATE_CREDITS) DoState_Credits(); else if(gameState == STATE_PLAYERSTART) DoState_PlayerStart(); else if(gameState == STATE_GAMEOVER) DoState_GameOver(); } }
int main(){ SetTileTable(cTesterTiles); SetSpritesTileTable(cursor); ClearVram(); EnableSnesMouse(0,map_cursor); //Print the basic stuff on the screen DrawMap2(5,26,map_copyright); DrawMap2(0,13,map_divider); //Detect controller types cType[0] = 255; cType[1] = 255; //The controller vars int btnHeld[2] = {0,0}; int btnPressed[2] = {0,0}; int btnReleased[2] = {0,0}; int btnPrev[2] = {0,0}; //Main loop while(1){ //20fps WaitVsync(1); //Update the controller vars btnHeld[0] = ReadJoypad(0); btnHeld[1] = ReadJoypad(1); btnPressed[0] = btnHeld[0] & (btnHeld[0] ^ btnPrev[0]); btnPressed[1] = btnHeld[1] & (btnHeld[1] ^ btnPrev[1]); btnReleased[0] = btnPrev[0] & (btnHeld[0] ^ btnPrev[0]); btnReleased[1] = btnPrev[1] & (btnHeld[1] ^ btnPrev[1]); //Check if controllers changed if((DetectControllers() & 3) != cType[0]){ cType[0] = DetectControllers() & 3; Fill(0,0,30,13,0); if(cType[0] == GAMEPAD){ DrawMap2(9,2,map_gamepad); } else if(cType[0] == MOUSE){ DrawMap2(12,2,map_mouse); DrawMap2(1,4,map_warning); } else if(cType[0] == NOTHING){ DrawMap2(9,6,map_nocontroller); } } if((DetectControllers() & 12) / 4 != cType[1]){ cType[1] = (DetectControllers() & 12) / 4; Fill(0,14,30,12,0); if(cType[1] == GAMEPAD){ DrawMap2(9,15,map_gamepad); SetSpriteVisibility(false); } else if(cType[1] == MOUSE){ DrawMap2(12,15,map_mouse); SetSpriteVisibility(true); EnableSnesMouse(0,map_cursor); } else if(cType[1] == NOTHING){ DrawMap2(9,19,map_nocontroller); SetSpriteVisibility(false); } } //Update the buttons for(unsigned int i = 0; i < 2; i++){ if(cType[i] == MOUSE){ //Check pressed buttons if(btnPressed[i] & BTN_MOUSE_LEFT){ DrawMap2(14,4 + 13*i,map_pmouseb); } if(btnPressed[i] & BTN_MOUSE_RIGHT){ DrawMap2(16,4 + 13*i,map_pmouseb); } //Check released if(btnReleased[i] & BTN_MOUSE_LEFT){ DrawMap2(14,4 + 13*i,map_mouseb); } if(btnReleased[i] & BTN_MOUSE_RIGHT){ DrawMap2(16,4 + 13*i,map_mouseb); } } else if(cType[i] == GAMEPAD){ //Check pressed if(btnPressed[i] & BTN_UP){ DrawMap2(11,6 + 13*i,map_pdpad); } if(btnPressed[i] & BTN_DOWN){ DrawMap2(11,8 + 13*i,map_pdpad); } if(btnPressed[i] & BTN_LEFT){ DrawMap2(10,7 + 13*i,map_pdpad); } if(btnPressed[i] & BTN_RIGHT){ DrawMap2(12,7 + 13*i,map_pdpad); } if(btnPressed[i] & BTN_START){ DrawMap2(16,6 + 13*i,map_pstart); } if(btnPressed[i] & BTN_SELECT){ DrawMap2(14,6 + 13*i,map_pstart); } if(btnPressed[i] & BTN_A){ DrawMap2(20,7 + 13*i,map_pbutton); } if(btnPressed[i] & BTN_B){ DrawMap2(19,8 + 13*i,map_pbutton); } if(btnPressed[i] & BTN_X){ DrawMap2(19,6 + 13*i,map_pbutton); } if(btnPressed[i] & BTN_Y){ DrawMap2(18,7 + 13*i,map_pbutton); } if(btnPressed[i] & BTN_SL){ DrawMap2(10,4 + 13*i,map_pbumper); } if(btnPressed[i] & BTN_SR){ DrawMap2(18,4 + 13*i,map_pbumper); } if(btnReleased[i] & BTN_UP){ DrawMap2(11,6 + 13*i,map_dpad); } if(btnReleased[i] & BTN_DOWN){ DrawMap2(11,8 + 13*i,map_dpad); } if(btnReleased[i] & BTN_LEFT){ DrawMap2(10,7 + 13*i,map_dpad); } if(btnReleased[i] & BTN_RIGHT){ DrawMap2(12,7 + 13*i,map_dpad); } if(btnReleased[i] & BTN_START){ DrawMap2(16,6 + 13*i,map_start); } if(btnReleased[i] & BTN_SELECT){ DrawMap2(14,6 + 13*i,map_start); } if(btnReleased[i] & BTN_A){ DrawMap2(20,7 + 13*i,map_button); } if(btnReleased[i] & BTN_B){ DrawMap2(19,8 + 13*i,map_button); } if(btnReleased[i] & BTN_X){ DrawMap2(19,6 + 13*i,map_button); } if(btnReleased[i] & BTN_Y){ DrawMap2(18,7 + 13*i,map_button); } if(btnReleased[i] & BTN_SL){ DrawMap2(10,4 + 13*i,map_bumper); } if(btnReleased[i] & BTN_SR){ DrawMap2(18,4 + 13*i,map_bumper); } } } btnPrev[0] = btnHeld[0]; btnPrev[1] = btnHeld[1]; } }
/** * Main menu (level selection) */ void menu() { uint8_t scroll = 0; uint8_t delay = false; uint8_t e_traj_offset1 = 0; uint8_t e_traj_offset2 = ELECTRON_TRAJECTORY_LAST_STEP / 2; unsigned int joypad; ClearVram(); hide_sprites(); for (uint8_t sprite_id = 0; sprite_id < 6; sprite_id++) { sprites[sprite_id].tileIndex = TILE_FIRST_ELECTRON + sprite_id; } DrawMap2(2, 2, logo_logo_map); // credits Print(2, 23, PSTR("2011 UZEBOX ATOMIX")); Print(2, 24, PSTR("PROGRAM: MARTIN SUSTEK")); Print(2, 25, PSTR("LEVEL DESIGN: ANDREAS WUEST")); // initial scroll position scroll = (level - 1); if ((level - 1) < SCREEN_MENU_LEVEL_LINES) { scroll = 0; } if ((level - 1) > LEVEL_COUNT - SCREEN_MENU_LEVEL_LINES) { scroll = LEVEL_COUNT - SCREEN_MENU_LEVEL_LINES; } while (true) { WaitVsync(1); // electrons animation e_traj_offset1++; if (e_traj_offset1 > ELECTRON_TRAJECTORY_LAST_STEP) { e_traj_offset1 = 0; } e_traj_offset2++; if (e_traj_offset2 > ELECTRON_TRAJECTORY_LAST_STEP) { e_traj_offset2 = 0; } sprites[0].x = (SCREEN_ELECTRON_X + pgm_read_byte(e_traj_1x + e_traj_offset1)); sprites[0].y = (SCREEN_ELECTRON_Y + pgm_read_byte(e_traj_1y + e_traj_offset1)); sprites[1].x = (SCREEN_ELECTRON_X + pgm_read_byte(e_traj_2x + e_traj_offset2)); sprites[1].y = (SCREEN_ELECTRON_Y + pgm_read_byte(e_traj_2y + e_traj_offset2)); sprites[2].x = (SCREEN_ELECTRON_X + pgm_read_byte(e_traj_3x + e_traj_offset1)); sprites[2].y = (SCREEN_ELECTRON_Y + pgm_read_byte(e_traj_3y + e_traj_offset1)); sprites[3].x = (SCREEN_ELECTRON_X + pgm_read_byte(e_traj_1x + e_traj_offset2)); sprites[3].y = (SCREEN_ELECTRON_Y + pgm_read_byte(e_traj_1y + e_traj_offset2)); sprites[4].x = (SCREEN_ELECTRON_X + pgm_read_byte(e_traj_2x + e_traj_offset1)); sprites[4].y = (SCREEN_ELECTRON_Y + pgm_read_byte(e_traj_2y + e_traj_offset1)); sprites[5].x = (SCREEN_ELECTRON_X + pgm_read_byte(e_traj_3x + e_traj_offset2)); sprites[5].y = (SCREEN_ELECTRON_Y + pgm_read_byte(e_traj_3y + e_traj_offset2)); for (uint8_t i = 0; i < SCREEN_MENU_LEVEL_LINES; i++) { uint8_t current_level = (i + 1 + scroll); if ((current_level > 0) && (current_level <= 50)) { uint8_t y = 11 + i; // level number PrintByte(3, y, current_level, false); // level name (shorten and pad with spaces) for (uint8_t j = 0; j < 24; j++) { char ch = pgm_read_byte(levels + (current_level - 1) * LEVEL_BYTE_SIZE + j); if (ch == '\0') { ch = ' '; } PrintChar(6 + j, y, ch); } // level done yet symbol if (eeprom_data.data[current_level / 8] & 1 << (current_level % 8)) { PrintChar(4, y, FONT_TICK); } else { PrintChar(4, y, ' '); } // cursor symbol if (current_level == level) { PrintChar(5, y, FONT_CURSOR); } else { PrintChar(5, y, ' '); } } } // molecule thumbnail draw_molecule(21, 2); // controls if (delay) { WaitVsync(4); delay = false; } joypad = ReadJoypad(0); if (joypad & BTN_UP) { if (level > 1) { play_sound(SOUND_MENU_MOVE); level--; if (scroll + 1 > level) { scroll--; } delay = true; } else { play_sound(SOUND_MENU_CANT_MOVE); } } if (joypad & BTN_DOWN) { if (level < LEVEL_COUNT) { play_sound(SOUND_MENU_MOVE); level++; if (scroll + SCREEN_MENU_LEVEL_LINES < level) { scroll++; } delay = true; } else { play_sound(SOUND_MENU_CANT_MOVE); } } if (joypad & BTN_START) { hide_sprites(); play_sound(SOUND_MENU_SELECT); return; } } }
unsigned char processControls(void){ static unsigned char ov=4,scroll=0; static int lastbuttons=0; unsigned int joy=ReadJoypad(0); if(joy&BTN_A){ if(action!=ACTION_JUMP){ action=ACTION_JUMP; frame=0; jmpPos=0; } }else if(joy&BTN_X){ Scroll(0,1); // while(ReadJoypad(0)!=0); }else if(joy&BTN_Y){ Scroll(0,-1); // while(ReadJoypad(0)!=0); }else if(joy&BTN_SR){ // Scroll(1,0); // while(ReadJoypad(0)!=0); }else if(joy&BTN_SL){ // Scroll(-1,0); // while(ReadJoypad(0)!=0); }else if(joy&BTN_UP){ //if(sy==0)sy=(VRAM_TILES_V*8); //sy--; //while(ReadJoypad(0)!=0); }else if(joy&BTN_DOWN){ //sy++; //if(sy>=(VRAM_TILES_V*8))sy=0; // while(ReadJoypad(0)!=0); } if(joy&BTN_LEFT){ //while(ReadJoypad(0)!=0); if(action==ACTION_IDLE){ action=ACTION_WALK; dx=-1; frame=0; stopping=false; walkFrame=0; lastWalkDir=BTN_LEFT; sprDir=-1; } }else if(joy&BTN_RIGHT){ //while(ReadJoypad(0)!=0); if(action==ACTION_IDLE){ action=ACTION_WALK; dx=1; frame=0; stopping=false; walkFrame=0; lastWalkDir=BTN_RIGHT; sprDir=1; } if(sx>=110){ if(joy&BTN_B){ Scroll(2,0); scroll+=2; }else{ Scroll(1,0); scroll++; } if(scroll>=8){ loadNextStripe(); scroll=0; } } } if(joy&BTN_START){ ov++; if(ov>OVERLAY_LINES)ov=0; Screen.overlayHeight=ov; while(ReadJoypad(0)!=0); } if(joy&BTN_SELECT){ StopSong(); while((ReadJoypad(0)&BTN_SELECT)!=0); } if(stopping==true && stopFrame==1){ action=ACTION_IDLE; stopping=false; dx=0; }else if(lastWalkDir!= (joy & (BTN_LEFT+BTN_RIGHT)) && action==ACTION_WALK){ if((joy & (BTN_LEFT+BTN_RIGHT))!=0 ){ frame=17; }else{ stopping=true; stopFrame=0; } } lastbuttons=joy; lastWalkDir= joy & (BTN_LEFT+BTN_RIGHT); return 0; }
char singleloop(GameStruct* game) { PlayerStruct singlep; MainStruct mains; ItemStruct zombie[MAX_ZOMBIES]; ItemStruct shots[2]; init(&mains, &singlep, 1, game, zombie, shots); for(;; game->frames++) { WaitVsync(1); drawoverlay(game, &singlep); gameflags(game); playerflags(&singlep); singlep.joypad = ReadJoypad(0); if(singlep.life <= 0) { switch(gameovermenu(game, &singlep)) { case 1: return 1; case 2: return 0; default: break; } } else if(singlep.joypad&BTN_SELECT && game->flagcount >= DEBOUNCE_DELAY) { game->flagcount = 0; if(game->flags & GAMEPAUSED) game->flags &= ~GAMEPAUSED; else game->flags |= GAMEPAUSED; } if(game->flags & GAMEPAUSED) continue; rendermap(&mains, 1); screenSections[1].scrollX = mains.x.s; screenSections[1].scrollY = mains.y.s; singlemove(&singlep, &mains, shots); inputanim(&singlep); singlep.gundelay++; for(int i = 0; i < 2; i++) handleshot(&mains, game, &singlep, &shots[i], zombie); necromancer(zombie, &mains, game, &singlep, 1); if(!(singlep.flags & PLAYERHURT) || game->frames&2) { sprites[1].x = sprites[2].x = singlep.x; sprites[1].y = singlep.y; sprites[2].y = singlep.y + TILE_HEIGHT; } else { sprites[1].x = sprites[2].x = DISABLED_SPRITE; sprites[2].y = sprites[1].y = DISABLED_SPRITE; } } }
u8 OpenMenu(){ ClearTextVram(); SetTileTable(tiles); SetFontTilesIndex(TILES_SIZE); //Show object types Print(6,2,PSTR("Select life object to insert")); Print(5,3,PSTR("at the current cursor position")); Print(7,7,PSTR("Glider")); Print(7,8,PSTR("Lightweight spaceship (LWSS)")) ; Print(7,9,PSTR("R-Pentamino")); Print(7,10,PSTR("Gosper glider gun")); Print(7,11,PSTR("Clear field")); Print(7,12,PSTR("Exit game")); //slide in menu WaitVsync(1); Fill(0,0,40,1,0); for(u8 i=1;i<29;i++){ WaitVsync(1); vmode_text_lines=i; } s8 option=0,x=5,y=7; u16 joy,prevJoy=0; while(1){ WaitVsync(1); joy=ReadJoypad(0); if(prevJoy==0){ if (joy==BTN_UP){ if(option>0) option--; }else if (joy==BTN_DOWN){ if(option<5)option++; }else if(joy==BTN_SELECT){ break; }else if(joy==BTN_START){ switch(option){ case 0: glider(cursor_x,cursor_y); break; case 1: lwss(cursor_x,cursor_y); break; case 2: rPentamino(cursor_x,cursor_y); break; case 3: gliderGun(cursor_x,cursor_y); break; case 4: ClearVram(); break; default: while(ReadJoypad(0)!=0); return 1; //signal game end, back to main menu } break; } } prevJoy=joy; AnimateCursor(x,y+option); } while(ReadJoypad(0)!=0); //close menu for(u8 i=29;i>0;i--){ WaitVsync(1); vmode_text_lines=i; } ClearTextVram(); SetTileTable(font); SetFontTilesIndex(0); CreateStatusBar(); return 0; }
char introscreen(GameStruct* game) { unsigned char counter; unsigned int joypad; ClearVram(); memset(sprites, 0, sizeof(struct SpriteStruct)*32); SetFontTilesIndex(49); screenSections[1].flags = SCT_PRIORITY_BG; screenSections[0].tileTableAdress = zombienator_title; screenSections[1].scrollX = screenSections[1].scrollY = 0; setoverlay(0); game->menupos = counter = 0; DrawMap2(0,6, title_map); for(int i = 0; i < 22; i++) SetTile(i, 10, 27 + i); for(;;) { WaitVsync(1); Fill(0,13, SCREEN_TILES_H, SCREEN_TILES_V - 13, 0); Print(5, 14, singlestr); Print(5, 15, multistr); Print(5, 16, highstr); Print(3, 14 + game->menupos, selectstr); joypad = 0; counter++; game->frames++; if(counter >= 15) { counter = 0; while(!(joypad&(BTN_START|BTN_SELECT|BTN_UP|BTN_DOWN))) { joypad = ReadJoypad(0); switch(joypad&(BTN_START|BTN_SELECT|BTN_UP|BTN_DOWN)) { case BTN_START: case BTN_SELECT: if(game->menupos == 0) return 1; else if(game->menupos == 1) return 2; break; case BTN_UP: if(game->menupos > 0 ) game->menupos--; else game->menupos = 2; break; case BTN_DOWN: if(game->menupos < 2) game->menupos++; else game->menupos = 0; break; } } } } return 0; }
int main() { unsigned char x,corner; unsigned char frames; unsigned int joypad; unsigned char player_x, player_y; unsigned char exit_x=0, exit_y=0; unsigned int z=0; int ay,ax,j; SetFontTable(fonts); // this tells Print___() commands what font to use ClearVram(); // clears out display memory (like a 'clear screen') //DDRD &= 0xF7; // These are used by the "power" switch and LED on the "Gamer" baseboard that //PORTD|= 0x08; // is paired with the AVCore. The 'power' button is used to switch mazes for now. new_maze: for(ay=0; ay<Y_SIZE; ay++) { for(ax=0; ax<X_SIZE; ax++) if(ax>0 && ay>0 && ax<X_SIZE-1 && ay<Y_SIZE-1) // fills the maze with walls, that are then 'drilled' out maze[ay][ax]=WALL; else maze[ay][ax]=BLANK; } ay=2; // 2,2 is the top left corner of the maze ax=2; maze[ay][ax]=4; // starting state for the maze generator do { while(drill(&ay,&ax,(int)(rand()&0x03))) {} // start drilling things out (using random) j=maze[ay][ax]; // note that the first time the game runs, the maze will always be maze[ay][ax]=BLANK; // the same because of the random number generator always starting if(j<4) // in the same state. (Normally I will 'sum' the contents of RAM { // on power-up to make a random seed, but I don't know how to mess /* back-track */ // with WinAVR's C-startup yet.) ax=ax-2*dx[j]; ay=ay-2*dy[j]; } } while(j<4); do{ // This generates a random position inside the maze to start the do player_x=rand(); // player. Seems more interesting than a corner. while ((player_x>=X_SIZE-1)||(player_x<=1)); do player_y=rand(); while ((player_y>=Y_SIZE-1)||(player_y<=1)); } while (maze[player_y][player_x]==WALL); // (repeats until it picks a random spot that's not a wall) maze[player_y][player_x]=PLAYER; // place the player in the maze do // here we choose a random number from 0-3, representing one of the { // four corners of the maze. corner=rand()&0x03; switch (corner) { case 0: exit_x=2; exit_y=2; break; case 1: exit_x=X_SIZE-3; exit_y=2; break; case 2: exit_x=X_SIZE-3; exit_y=Y_SIZE-3;break; case 3: exit_x=2; exit_y=Y_SIZE-3; break; } } while (abs(player_x-exit_x)<16); // we compare the distance from the player to the exit (horizontally) // and only accept the corner if it's relatively far away from the player // (could use both x and y distance for better effect) maze[exit_y][exit_x]=EXIT; // place the exit in the maze redraw(); // draw the screen for the player // This is what happens when you turn a static demo into a 'game' // For a real game, you probably don't want to do this, but it works here and is simple... //while(PIND&0x04) // if the button on the Gamer Baseboard isn't pressed while(ReadPowerSwitch()==0) // if the button on the Gamer Baseboard isn't pressed {z++; // the z counter is used later on for a seed for the random number generator (user interaction = randomness) joypad=ReadJoypad(0); // get the joypad state WaitVsync(1); // this waits a frame and essentially slows the gameplay down frames++; // frame counter can be used for animations (later) if (joypad&0xff) // if the D-pad has a bit or more pressed { maze[player_y][player_x]=BLANK; // erase the old player position if (joypad&BTN_DOWN) // down? if (maze[player_y+1][player_x]!=WALL) // don't move if a wall is blocking your path player_y++; // you could 'switch/case' these with breaks to easily disable diagonal moves... if (joypad&BTN_UP) // up? if (maze[player_y-1][player_x]!=WALL) player_y--; if (joypad&BTN_LEFT) // left? if (maze[player_y][player_x-1]!=WALL) player_x--; if (joypad&BTN_RIGHT) // right if (maze[player_y][player_x+1]!=WALL) player_x++; if (maze[player_y][player_x]==EXIT) // if the new position is the EXIT, you just won { maze[exit_y][exit_x]=PLAYER; // place the player on top of the exit redraw(); // draw the screen for the user Print(14,25,strWin); // prints the "YOU ESCAPED!" message WaitVsync(30); // and waits for a while. for (x=14;x<26;x++) // this loops over the "YOU ESCAPED!" message SetTile(x,25,11); // and erases it. break; // this breaks out of the while(PIND...) loop, causing a new maze to be generated } maze[player_y][player_x]=PLAYER; // after the movement calculations, put the player in the new spot } else { // check for idle time // use the frame counter to make the player graphic change if you wait around. ;-) } srand(z); // our player-influenced 'z' value is now used to reseed the random number generator, resulting in a 'new' maze redraw(); // redraw the screen to update new player position } goto new_maze; // this is just a hack to go do everything over again. Before anyone lectures me about using GOTO, think about // why every CPU has a 'jump/goto' instruction in its assembly language and uses it-- frequently. :-) }