예제 #1
0
파일: selection.c 프로젝트: callaa/luola
/* Draw the level bar in the middle of level selection screen */
static void draw_level_bar(SDL_Surface *surface, struct dllist *thumbnails,
        int offset) {
    struct dllist *ptr;
    SDL_Rect bar;
    int x,y;

    bar.x = 0; bar.w=screen->w;
    bar.y = screen->h/2 - BAR_HEIGHT/2; bar.h = BAR_HEIGHT;

    SDL_FillRect(surface,&bar,SDL_MapRGB(surface->format,220,220,220));

    /* Draw the selected level */
    x = bar.x + bar.w/2 - level_width(thumbnails->data) + offset;
    y = bar.y+bar.h/2 - THUMBNAIL_HEIGHT/2;
    x += draw_level(surface,thumbnails->data,x,y,bar.x+bar.w-x,1) + THUMBNAIL_SEP;

    /* Draw levels to the right of the selection */
    ptr = thumbnails->next;
    while(ptr && x<bar.x + bar.w) {
        int visible = bar.x + bar.w - x;
        x += draw_level(surface,ptr->data,x,y,visible,0) + THUMBNAIL_SEP;
        ptr=ptr->next;
    }

    /* Draw the levels to the left of the selection */
    ptr = thumbnails->prev;
    x = bar.x + bar.w/2 - level_width(thumbnails->data) + offset;
    while(ptr) {
        int curwidth = level_width(ptr->data);
        x -= curwidth + THUMBNAIL_SEP;
        if(x+curwidth < bar.x) break;
        draw_level(surface,ptr->data,x,y,x+curwidth-bar.x,0);
        ptr = ptr->prev;
    }
}
예제 #2
0
static void draw_level ( int num, double m00, double m01, double m10, double m11, double n0, double n1 )
{
  /* Draw a fractal transformed by "M", "N" as passed in */
  int i ;

  if ( num == 0 )
  {
    double x0 = m00 * affine[0].statx + m01 * affine[0].staty + n0 ;
    double y0 = m10 * affine[0].statx + m11 * affine[0].staty + n1 ;

    for ( i = 1; i < num_trans; i++ )
    {
      double x1 = m00 * affine[i].statx + m01 * affine[i].staty + n0 ;
      double y1 = m10 * affine[i].statx + m11 * affine[i].staty + n1 ;

      glVertex2d ( x0, y0 ) ;
      glVertex2d ( x1, y1 ) ;

      x0 = x1 ;
      y0 = y1 ;
    }
  }
  else
  {
    /* Map each affine transformation in the fractal through the one passed in and call "draw_level" */

    for ( i = 0; i < num_trans; i++ )
    {
      draw_level ( num-1, m00*affine[i].a00+m01*affine[i].a10,     m00*affine[i].a01+m01*affine[i].a11,
                          m10*affine[i].a00+m11*affine[i].a10,     m10*affine[i].a01+m11*affine[i].a11,
                          m00*affine[i].b0 +m01*affine[i].b1 + n0, m10*affine[i].b0 +m11*affine[i].b1  + n1 ) ;
    }
  }
}
예제 #3
0
파일: main.cpp 프로젝트: JoaoS/CG
void drawScene()
{
	
    
    reflection();


	//============================================Eixos
	if (noite)
		glColor4f(AMARELO);
	else
		glColor4f(BLACK);

    glColor4f(WHITE); //fazer reset as cores para o blend + texturas
    /*desenho da caixa*/

    duplicates();//mesmas funcoes que abaixo para meter os paineis a reflectir por  dentro
    //atras
     glPushMatrix();
        glColor4f(DEEPBLUE);
        glTranslatef(3, 0, 3);
        glRotatef(-90,1,0,0);  
        quad(2,0,0,0);
    glPopMatrix();

    //contrario a bola
     glPushMatrix();
        glColor4f(TORRADO);
        glTranslatef(3+multiplier*2, 0, 3+multiplier*2);
        glRotatef(180,0,1,0); //para a reflexao ficar na face exterior da caixa, senão ficava interior
        glRotatef(90,0,0,1); 
        quad(2,0,0,0);
    glPopMatrix();
    
    //em cima
   glPushMatrix();
        glColor4f(SBLUE);
        glTranslatef(3, multiplier*2, 3);   
        quad(2,0,0,0);
    glPopMatrix();

    //lado da bola
    glPushMatrix();
        glColor4f(TORRADO);
        glTranslatef(3, 0, 3);
        glRotatef(90,0,0,1); 
        quad(2,0,0,0);
    glPopMatrix();

    /* desenho do nivel */
    draw_level(level);
    /* desenho da bola */
    glPushMatrix();
        glColor4f(AMARELO);
        glTranslatef(posEsfera[0],posEsfera[1],posEsfera[2]);
        glutSolidSphere(raioEsfera, 256, 256);//radius , (slices(longitude), stacks(latitude))->malhas
    glPopMatrix();
   	glutPostRedisplay();
}
예제 #4
0
/*
 * Set up the required initial conditions for a match, and switch to playing state
 */
void start_game()
{
	/* Seed the RNG */
	srand(TCNT1);

	/* Load in the sprites */
	reticule_SPR = reticule(0);

	/* Generate and draw a level */
	clear_screen();
	free((void*) level_map);
	level_map = generate_flat(WIDTH, 129);	
	if(level_map != NULL)
		draw_level(level_map, SILVER, 0, WIDTH - 1);
	
	/* Set up the players in the field */
	playersX = malloc(players * sizeof(int16_t));
	playersY = malloc(players * sizeof(int16_t));
	players_HP = malloc(players * sizeof(uint8_t));
	if(playersX == NULL || playersY == NULL || players_HP == NULL)
	{
		display_string("Out of memory error!");
		return;
	}
	uint8_t i;
	for(i = 0; i < players; i++)
	{
		playersX[i] = (i + 1) * WIDTH / (players + 1);
		playersY[i] = 120;
		players_HP[i] = MAX_PLAYER_HP;

		free_sprite(player_SPR);
		player_SPR = botleft(i);
		fill_sprite(player_SPR, playersX[i], playersY[i], HEIGHT_NO_UI, WIDTH);
	}

	/* Pick a random player to ... go last
	 * First call to start_turn will cycle to next player. Poor sod. */
	current_player = rand() % players;

	reticuleX = (playersX[current_player] + (RETICULE_DISTANCE * ml_cos(position))/100);
	reticuleY = (playersY[current_player] + (RETICULE_DISTANCE * ml_sin(position))/100);

	/* Initialise movement variables */
	direction = 0;
	launch_speed = 0;

	/* Draw the UI */
	display_string_xy("POWER:", POWER_LABEL_X, POWER_LABEL_Y);
	fill_rectangle(power_outline, WHITE);
	fill_rectangle(power_empty, BLACK);
	display_string_xy("WIND:", WIND_LABEL_X, WIND_LABEL_Y);
	fill_rectangle(wind_outline, WHITE);
	fill_rectangle(wind_empty, BLACK);

	/* Start the first player's turn */
	start_turn();
}
예제 #5
0
파일: wizard.c 프로젝트: dmalves/cage
/* **update\_level()** is called by the Cage game loop for every frame
 * and has to update the game state ( animations, positions, etc..)
 * as well as redraw the frame using **draw\_level()**.
 */
static void update_level(void* data, float elapsed_ms)
{
    struct level_data* ldata = data;
    animate_wizard(ldata->wizard, elapsed_ms);
    animate_sprite(ldata->tree.sprite, elapsed_ms);
    draw_level(data, elapsed_ms);
    update_timeline(ldata->timeline, data, elapsed_ms);
    if (key_pressed(KB_ESC)) exit(0);
}
예제 #6
0
파일: main.c 프로젝트: bmoscon/Rogue
static void draw(state_st *state)
{
    log_func_enter;

    draw_stats(state);
    draw_message(state);
    draw_level(state);

    log_func_exit;
}
예제 #7
0
int
FFSControlFrameTexture::draw(CVIEWptr& v)
{

    if (_ctrl)
        return _ctrl->draw(v);

    // Create a strip for the given mesh type (BMESH or LMESH):
    assert(_patch && _patch->mesh());
    if (_strip)
        _strip->reset();
    else
        _strip = _patch->mesh()->new_edge_strip();


    // Init line smoothing and push attributes:
    GL_VIEW::init_line_smooth(1.0f, GL_CURRENT_BIT);

    glDisable(GL_LIGHTING);      // GL_ENABLE_BIT

    if (!BasicTexture::draw(v)) {

        int dl = 0;
        if ((dl = _dl.get_dl(v, 1, _patch->stamp())))
            glNewList(dl, GL_COMPILE);

        // Draw control curves down to the current "edit level"
        int el = _patch->rel_edit_level();

        // Draw each level:
        for (int k = 0; k <= el; k++)
            draw_level(v, k);

        // end the display list here
        if (_dl.dl(v)) {
            _dl.close_dl(v);

            // the display list is built; now execute it
            BasicTexture::draw(v);
        }
    }

    // Restore gl state:
    GL_VIEW::end_line_smooth();

    draw_selected_faces();
    draw_selected_edges();
    draw_selected_verts();

    return _patch->num_faces();
}
예제 #8
0
//---------------------------------------------------------------------------
// Name: draw_csl_dbuff()
// Desc: Show the console buffer.
//---------------------------------------------------------------------------
void draw_csl_dbuff(BITMAP *csl_dbuff, int csl_y)
{
    acquire_screen();
    if((csl_get_y() != csl_y) && (in_the_game))
    {
        draw_level();
        blit(csl_dbuff, virt, 0, csl_dbuff->h-csl_y, 0, 0, csl_dbuff->w, csl_y);
        blit(virt, screen, 0,0,80,0,480,480);
    }
    else
    {
        blit(csl_dbuff, screen, 0, csl_dbuff->h-csl_y, 80, 0, csl_dbuff->w, csl_y);
    }
    release_screen();
}
예제 #9
0
static void 
Display(void)
{
  glClear( GL_COLOR_BUFFER_BIT );

  /* the curve */
  glPushMatrix();
  glScalef(2.5, 2.5, 2.5);

  glColor4f(0.0, 0.0, 0.0, 1.0);
  glBegin ( GL_LINES ) ;
  draw_level ( num_levels, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 );
  glEnd () ;

  glPopMatrix();
  glutSwapBuffers();
}
예제 #10
0
파일: terminal.c 프로젝트: nicocoffo/zabar
void reset_terminal(void){
	clear_terminal();
	
	set_display_attribute(BAR_COLOUR);
	draw_horizontal_line(1,1,WIDTH);
	set_display_attribute(BAR_COLOUR);
	draw_vertical_line(40,1,HEIGHT);
	
	move_cursor(TITLE_X,TITLE_Y);
	printf_P(PSTR("FROGGER"));
	
	draw_lives();
	draw_score();
	draw_level();
	draw_time(16);
	display_scores();
	draw_status(0);
	draw_frog();
	
	set_display_attribute(8);
}
예제 #11
0
enum piglit_result
piglit_display(void)
{
	GLboolean pass = GL_TRUE;
	GLuint tex1d;
	int level;

	glClearColor(0.1, 0.1, 0.1, 0.1);
	glClear(GL_COLOR_BUFFER_BIT);

	tex1d = create_texture_1d();

	for (level = 0; level < TEX_LEVELS; level++) {
		draw_level(5, 5 + level * 10, level);
		pass = pass && test_level(level);
	}

	glDeleteTextures(1, &tex1d);
	piglit_present_results();
	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
}
예제 #12
0
static void 
Display(void)
{
  if (needClear) {
    glClear(GL_COLOR_BUFFER_BIT);
    needClear = GL_FALSE;
  }

  /* the curve */
  glPushMatrix();
  glScaled(2.5, 2.5, 2.5);

  glColor4f(0.0, 0.0, 0.0, 1.0);
  glBegin ( GL_POINTS ) ;
  draw_level ( num_levels, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 );
  glEnd () ;

  glPopMatrix();

  glFlush();
  glutPostRedisplay();  /* Needed so that this function will be called again */
}
예제 #13
0
파일: jeu.c 프로젝트: BullPaf/Pacman
/*Fonction du jeu*/
void jouer(Pacman *pac, Fantome *ftm, Input in, config *cfg, int level, score_message **msg_list)
{
	int i;
	SDL_Delay(DELAY);
	set_pac_target(pac); //Cherche l'endroit ou aller pour pacman
	//Fonction de déplacement de pacman
	pac->controllerFonction(in, *cfg, pac->controlled_by, &(pac->position), &(pac->cur_direction), &(pac->nb_keys), &(pac->speed), &(pac->num_image), pac->target);
	for(i=0; i<NB_GHOST; i++)
	{
		set_ftm_target(ftm+i, pac->position);
		ftm[i].controllerFonction(in, *cfg, ftm[i].controlled_by, &(ftm[i].position), &(ftm[i].cur_direction), &(ftm[i].nb_keys), &(ftm[i].speed), &(ftm[i].num_image), ftm[i].target);
	}
	updatePacman(pac);
	updateGhosts(ftm);
	SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0));
	draw_level();
	draw_pac_infos(pac);
	draw_score(pac->score, level);
	affiche_pacman(pac);
	affiche_fantomes(ftm);
	action(pac, ftm, msg_list);
	display_messages(msg_list);
	SDL_Flip(screen);
}
int sokoban_game::start_game()
{
    int iScore = 0;
    int iMoves = 0;
    iTotalMoves = 0;

    int iDirY, iDirX;

    const int iOffsetX = (TERMX > FULL_SCREEN_WIDTH) ? (TERMX - FULL_SCREEN_WIDTH) / 2 : 0;
    const int iOffsetY = (TERMY > FULL_SCREEN_HEIGHT) ? (TERMY - FULL_SCREEN_HEIGHT) / 2 : 0;

    parse_level();

    WINDOW *w_sokoban = newwin(FULL_SCREEN_HEIGHT, FULL_SCREEN_WIDTH, iOffsetY, iOffsetX);
    draw_border(w_sokoban);
    center_print(w_sokoban, 0, hilite(c_white), _("Sokoban"));

    input_context ctxt("SOKOBAN");
    ctxt.register_cardinal();
    ctxt.register_action("NEXT");
    ctxt.register_action("PREV");
    ctxt.register_action("RESET");
    ctxt.register_action("QUIT");
    ctxt.register_action("UNDO");
    ctxt.register_action("HELP_KEYBINDINGS");

    std::vector<std::string> shortcuts;
    shortcuts.push_back(_("<+> next"));    // '+': next
    shortcuts.push_back(_("<-> prev"));    // '-': prev
    shortcuts.push_back(_("<r>eset"));     // 'r': reset
    shortcuts.push_back(_("<q>uit"));      // 'q': quit
    shortcuts.push_back(_("<u>ndo move")); // 'u': undo move

    int indent = 10;
    for (size_t i = 0; i < shortcuts.size(); i++) {
        indent = std::max(indent, utf8_width(shortcuts[i].c_str()) + 1);
    }
    indent = std::min(indent, 30);

    for (size_t i = 0; i < shortcuts.size(); i++) {
        shortcut_print(w_sokoban, i + 1, FULL_SCREEN_WIDTH - indent,
                       c_white, c_ltgreen, shortcuts[i]);
    }

    int iPlayerY = 0;
    int iPlayerX = 0;

    bool bNewLevel = true;
    bool bMoved = false;
    do {
        if (bNewLevel) {
            bNewLevel = false;

            iMoves = 0;
            vUndo.clear();

            iPlayerY = mLevelInfo[iCurrentLevel]["PlayerY"];
            iPlayerX = mLevelInfo[iCurrentLevel]["PlayerX"];
            mLevel = vLevel[iCurrentLevel];
        }

        print_score(w_sokoban, iScore, iMoves);

        std::string action;
        if (check_win()) {
            //we won yay
            if (!mAlreadyWon[iCurrentLevel]) {
                iScore += 500;
                mAlreadyWon[iCurrentLevel] = true;
            }
            action = "NEXT";

        } else {
            draw_level(w_sokoban);
            wrefresh(w_sokoban);

            //Check input
            action = ctxt.handle_input();
        }

        bMoved = false;
        if (ctxt.get_direction(iDirX, iDirY, action)) {
            bMoved = true;
        } else if (action == "QUIT") {
            return iScore;
        } else if (action == "UNDO") {
            int iPlayerYNew = 0;
            int iPlayerXNew = 0;
            bool bUndoSkip = false;
            //undo move
            if (!vUndo.empty()) {
                //reset last player pos
                mLevel[iPlayerY][iPlayerX] = (mLevel[iPlayerY][iPlayerX] == "+") ? "." : " ";
                iPlayerYNew = vUndo[vUndo.size() - 1].iOldY;
                iPlayerXNew = vUndo[vUndo.size() - 1].iOldX;
                mLevel[iPlayerYNew][iPlayerXNew] = vUndo[vUndo.size() - 1].sTileOld;

                vUndo.pop_back();

                bUndoSkip = true;
            }

            if (bUndoSkip && !vUndo.empty()) {
                iDirY = vUndo[vUndo.size() - 1].iOldY;
                iDirX = vUndo[vUndo.size() - 1].iOldX;

                if (vUndo[vUndo.size() - 1].sTileOld == "$" ||
                    vUndo[vUndo.size() - 1].sTileOld == "*") {
                    mLevel[iPlayerY][iPlayerX] = (mLevel[iPlayerY][iPlayerX] == ".") ? "*" : "$";
                    mLevel[iPlayerY + iDirY][iPlayerX + iDirX] = (mLevel[iPlayerY + iDirY][iPlayerX + iDirX] == "*") ?
                            "." : " ";

                    vUndo.pop_back();
                }
            }

            if (bUndoSkip) {
                iPlayerY = iPlayerYNew;
                iPlayerX = iPlayerXNew;
            }
        } else if (action == "RESET") {
            //reset level
            bNewLevel = true;
        } else if (action == "NEXT") {
            //next level
            clear_level(w_sokoban);
            iCurrentLevel++;
            if (iCurrentLevel >= iNumLevel) {
                iCurrentLevel = 0;
            }
            bNewLevel = true;
        } else if (action == "PREV") {
            //prev level
            clear_level(w_sokoban);
            iCurrentLevel--;
            if (iCurrentLevel < 0) {
                iCurrentLevel =  iNumLevel - 1;
            }
            bNewLevel = true;
        }

        if (bMoved) {
            //check if we can move the player
            std::string sMoveTo = mLevel[iPlayerY + iDirY][iPlayerX + iDirX];
            bool bMovePlayer = false;

            if (sMoveTo != "#") {
                if (sMoveTo == "$" || sMoveTo == "*") {
                    //Check if we can move the package
                    std::string sMovePackTo = mLevel[iPlayerY + (iDirY * 2)][iPlayerX + (iDirX * 2)];
                    if (sMovePackTo == "." || sMovePackTo == " ") {
                        //move both
                        bMovePlayer = true;
                        mLevel[iPlayerY + (iDirY * 2)][iPlayerX + (iDirX * 2)] = (sMovePackTo == ".") ? "*" : "$";

                        vUndo.push_back(cUndo(iDirY, iDirX, sMoveTo));

                        iMoves--;
                    }
                } else {
                    bMovePlayer = true;
                }

                if (bMovePlayer) {
                    //move player
                    vUndo.push_back(cUndo(iPlayerY, iPlayerX, mLevel[iPlayerY][iPlayerX]));

                    mLevel[iPlayerY][iPlayerX] = (mLevel[iPlayerY][iPlayerX] == "+") ? "." : " ";
                    mLevel[iPlayerY + iDirY][iPlayerX + iDirX] = (sMoveTo == "." || sMoveTo == "*") ? "+" : "@";

                    iPlayerY += iDirY;
                    iPlayerX += iDirX;

                    iMoves++;
                    iTotalMoves++;
                }
            }
        }

    } while (true);

    return iScore;
}
예제 #15
0
int sokoban_game::start_game()
{
    int iScore = 0;
    int iMoves = 0;
    iTotalMoves = 0;

    int iDirY, iDirX;

    const int iOffsetX = (TERMX > FULL_SCREEN_WIDTH) ? (TERMX-FULL_SCREEN_WIDTH)/2 : 0;
    const int iOffsetY = (TERMY > FULL_SCREEN_HEIGHT) ? (TERMY-FULL_SCREEN_HEIGHT)/2 : 0;

    WINDOW* w_sokoban = newwin(FULL_SCREEN_HEIGHT, FULL_SCREEN_WIDTH, iOffsetY, iOffsetX);
    wborder(w_sokoban, LINE_XOXO, LINE_XOXO, LINE_OXOX, LINE_OXOX, LINE_OXXO, LINE_OOXX, LINE_XXOO, LINE_XOOX);

    parse_level();

    mvwprintz(w_sokoban, 0, (FULL_SCREEN_WIDTH/2)-5, hilite(c_white), "Sokoban");

    mvwprintz(w_sokoban, 1, FULL_SCREEN_WIDTH-10, c_ltgreen, "+");
    wprintz(w_sokoban, c_white, " next");

    mvwprintz(w_sokoban, 2, FULL_SCREEN_WIDTH-10, c_ltgreen, "-");
    wprintz(w_sokoban, c_white, " prev");

    mvwprintz(w_sokoban, 3, FULL_SCREEN_WIDTH-10, c_ltgreen,  "r");
    wprintz(w_sokoban, c_white, "eset");

    mvwprintz(w_sokoban, 4, FULL_SCREEN_WIDTH-10, c_ltgreen,  "q");
    wprintz(w_sokoban, c_white, "uit");

    mvwprintz(w_sokoban, 5, FULL_SCREEN_WIDTH-10, c_ltgreen,  "u");
    wprintz(w_sokoban, c_white, "ndo move");

    int input = '.';

    int iPlayerY = 0;
    int iPlayerX = 0;

    bool bNewLevel = true;
    bool bMoved = false;
    do {
        if (bNewLevel) {
            bNewLevel = false;

            iMoves = 0;
            vUndo.clear();

            iPlayerY = mLevelInfo[iCurrentLevel]["PlayerY"];
            iPlayerX = mLevelInfo[iCurrentLevel]["PlayerX"];
            mLevel = vLevel[iCurrentLevel];
        }

        print_score(w_sokoban, iScore, iMoves);

        if (check_win()) {
            //we won yay
            if (!mAlreadyWon[iCurrentLevel]) {
                iScore += 500;
                mAlreadyWon[iCurrentLevel] = true;
            }
            input = '+';

        } else {
            draw_level(w_sokoban);
            wrefresh(w_sokoban);

            //Check input
            input = getch();
        }

        bMoved = false;
        switch (input) {
            case KEY_UP: /* up */
                iDirY = -1;
                iDirX = 0;
                bMoved = true;
                break;
            case KEY_DOWN: /* down */
                iDirY = 1;
                iDirX = 0;
                bMoved = true;
                break;
            case KEY_LEFT: /* left */
                iDirY = 0;
                iDirX = -1;
                bMoved = true;
                break;
            case KEY_RIGHT: /* right */
                iDirY = 0;
                iDirX = 1;
                bMoved = true;
                break;
            case 'q':
                return iScore;
                break;
            case 'u':
                {
                    int iPlayerYNew = 0;
                    int iPlayerXNew = 0;
                    bool bUndoSkip = false;
                    //undo move
                    if (vUndo.size() > 0) {
                        //reset last player pos
                        mLevel[iPlayerY][iPlayerX] = (mLevel[iPlayerY][iPlayerX] == "+") ? "." : " ";
                        iPlayerYNew = vUndo[vUndo.size()-1].iOldY;
                        iPlayerXNew = vUndo[vUndo.size()-1].iOldX;
                        mLevel[iPlayerYNew][iPlayerXNew] = vUndo[vUndo.size()-1].sTileOld;

                        vUndo.pop_back();

                        bUndoSkip = true;
                    }

                    if (bUndoSkip && vUndo.size() > 0) {
                        iDirY = vUndo[vUndo.size()-1].iOldY;
                        iDirX = vUndo[vUndo.size()-1].iOldX;

                        if (vUndo[vUndo.size()-1].sTileOld == "$" || vUndo[vUndo.size()-1].sTileOld == "*") {
                            mLevel[iPlayerY][iPlayerX] = (mLevel[iPlayerY][iPlayerX] == ".") ? "*" : "$";
                            mLevel[iPlayerY + iDirY][iPlayerX + iDirX] = (mLevel[iPlayerY + iDirY][iPlayerX + iDirX] == "*") ? "." : " ";

                            vUndo.pop_back();
                        }
                    }

                    if (bUndoSkip) {
                        iPlayerY = iPlayerYNew;
                        iPlayerX = iPlayerXNew;
                    }
                }
                break;
            case 'r':
                //reset level
                bNewLevel = true;
                break;
            case '+':
                //next level
                clear_level(w_sokoban);
                iCurrentLevel++;
                if (iCurrentLevel >= iNumLevel) {
                    iCurrentLevel = 0;
                }
                bNewLevel = true;
                break;
            case '-':
                //prev level
                clear_level(w_sokoban);
                iCurrentLevel--;
                if (iCurrentLevel < 0) {
                    iCurrentLevel =  iNumLevel - 1;
                }
                bNewLevel = true;
                break;
            default:
                break;
        }

        if (bMoved) {
            //check if we can move the player
            std::string sMoveTo = mLevel[iPlayerY + iDirY][iPlayerX + iDirX];
            bool bMovePlayer = false;

            if (sMoveTo != "#") {
                if (sMoveTo == "$" || sMoveTo == "*") {
                    //Check if we can move the package
                    std::string sMovePackTo = mLevel[iPlayerY + (iDirY * 2)][iPlayerX + (iDirX * 2)];
                    if (sMovePackTo == "." || sMovePackTo == " ") {
                        //move both
                        bMovePlayer = true;
                        mLevel[iPlayerY + (iDirY * 2)][iPlayerX + (iDirX * 2)] = (sMovePackTo == ".") ? "*" : "$";

                        vUndo.push_back(cUndo(iDirY, iDirX, sMoveTo));

                        iMoves--;
                    }
                } else {
                    bMovePlayer = true;
                }

                if (bMovePlayer) {
                    //move player
                    vUndo.push_back(cUndo(iPlayerY, iPlayerX, mLevel[iPlayerY][iPlayerX]));

                    mLevel[iPlayerY][iPlayerX] = (mLevel[iPlayerY][iPlayerX] == "+") ? "." : " ";
                    mLevel[iPlayerY + iDirY][iPlayerX + iDirX] = (sMoveTo == "." || sMoveTo == "*") ? "+" : "@";

                    iPlayerY += iDirY;
                    iPlayerX += iDirX;

                    iMoves++;
                    iTotalMoves++;
                }
            }
        }

    } while (true);

    return iScore;
}
예제 #16
0
static bool sokoban_loop(void)
{
    char new_spot;
    bool moved = true;
    int i = 0, button = 0, lastbutton = 0;
    short r = 0, c = 0;

    current_info.level.level = 1;

    load_level();
    update_screen();

    while (1) {
        moved = true;

        r = current_info.player.row;
        c = current_info.player.col;

        button = rb->button_get(true);

        add_undo(button);

        switch(button)
        {
        case BUTTON_OFF:
            /* get out of here */
            return PLUGIN_OK;

        case SOKOBAN_UNDO:
#ifdef SOKOBAN_UNDO_PRE
            if (lastbutton != SOKOBAN_UNDO_PRE)
                break;
#else       /* repeat can't work here for Ondio */
        case SOKOBAN_UNDO | BUTTON_REPEAT:
#endif
            /* this is UNDO */
            undo();
            rb->lcd_clear_display();
            update_screen();
            moved = false;
            break;

        case SOKOBAN_LEVEL_UP:
        case SOKOBAN_LEVEL_UP | BUTTON_REPEAT:
            /* increase level */
            init_undo();
            current_info.level.boxes_to_go=0;
            moved = true;
            break;

        case SOKOBAN_LEVEL_DOWN:
        case SOKOBAN_LEVEL_DOWN | BUTTON_REPEAT:
            /* previous level */
            init_undo();
            if (current_info.level.level > 1)
                current_info.level.level--;

            draw_level();
            moved = false;
            break;

        case SOKOBAN_LEVEL_REPEAT:
        case SOKOBAN_LEVEL_REPEAT | BUTTON_REPEAT:
            /* same level */
            init_undo();
            draw_level();
            moved = false;
            break;

        case BUTTON_LEFT:
            switch(current_info.board[r][c-1])
            {
            case ' ': /* if it is a blank spot */
            case '.': /* if it is a home spot */
                new_spot = current_info.board[r][c-1];
                current_info.board[r][c-1] = '@';
                current_info.board[r][c] = current_info.player.spot;
                current_info.player.spot = new_spot;
                break;

            case '$':
                switch(current_info.board[r][c-2])
                {
                case ' ': /* going from blank to blank */
                    current_info.board[r][c-2] = current_info.board[r][c-1];
                    current_info.board[r][c-1] = current_info.board[r][c];
                    current_info.board[r][c] = current_info.player.spot;
                    current_info.player.spot = ' ';
                    break;

                case '.': /* going from a blank to home */
                    current_info.board[r][c-2] = '%';
                    current_info.board[r][c-1] = current_info.board[r][c];
                    current_info.board[r][c] = current_info.player.spot;
                    current_info.player.spot = ' ';
                    current_info.level.boxes_to_go--;
                    break;

                default:
                    moved = false;
                    break;
                }
                break;

            case '%':
                switch(current_info.board[r][c-2]) {
                case ' ': /* we are going from a home to a blank */
                    current_info.board[r][c-2] = '$';
                    current_info.board[r][c-1] = current_info.board[r][c];
                    current_info.board[r][c] = current_info.player.spot;
                    current_info.player.spot = '.';
                    current_info.level.boxes_to_go++;
                    break;

                case '.': /* if we are going from a home to home */
                    current_info.board[r][c-2] = '%';
                    current_info.board[r][c-1] = current_info.board[r][c];
                    current_info.board[r][c] = current_info.player.spot;
                    current_info.player.spot = '.';
                    break;

                default:
                    moved = false;
                    break;
                }
                break;

            default:
                moved = false;
                break;
            }

            if (moved)
                current_info.player.col--;
            break;

        case BUTTON_RIGHT: /* if it is a blank spot */
            switch(current_info.board[r][c+1]) {
            case ' ':
            case '.': /* if it is a home spot */
                new_spot = current_info.board[r][c+1];
                current_info.board[r][c+1] = '@';
                current_info.board[r][c] = current_info.player.spot;
                current_info.player.spot = new_spot;
                break;

            case '$':
                switch(current_info.board[r][c+2]) {
                case ' ': /* going from blank to blank */
                    current_info.board[r][c+2] = current_info.board[r][c+1];
                    current_info.board[r][c+1] = current_info.board[r][c];
                    current_info.board[r][c] = current_info.player.spot;
                    current_info.player.spot = ' ';
                    break;

                case '.': /* going from a blank to home */
                    current_info.board[r][c+2] = '%';
                    current_info.board[r][c+1] = current_info.board[r][c];
                    current_info.board[r][c] = current_info.player.spot;
                    current_info.player.spot = ' ';
                    current_info.level.boxes_to_go--;
                    break;

                default:
                    moved = false;
                    break;
                }
                break;

            case '%':
                switch(current_info.board[r][c+2]) {
                case ' ': /* going from a home to a blank */
                    current_info.board[r][c+2] = '$';
                    current_info.board[r][c+1] = current_info.board[r][c];
                    current_info.board[r][c] = current_info.player.spot;
                    current_info.player.spot = '.';
                    current_info.level.boxes_to_go++;
                    break;

                case '.':
                    current_info.board[r][c+2] = '%';
                    current_info.board[r][c+1] = current_info.board[r][c];
                    current_info.board[r][c] = current_info.player.spot;
                    current_info.player.spot = '.';
                    break;

                default:
                    moved = false;
                    break;
                }
                break;

            default:
                moved = false;
                break;
            }

            if (moved)
                current_info.player.col++;
            break;

        case BUTTON_UP:
            switch(current_info.board[r-1][c]) {
            case ' ': /* if it is a blank spot */
            case '.': /* if it is a home spot */
                new_spot = current_info.board[r-1][c];
                current_info.board[r-1][c] = '@';
                current_info.board[r][c] = current_info.player.spot;
                current_info.player.spot = new_spot;
                break;

            case '$':
                switch(current_info.board[r-2][c]) {
                case ' ': /* going from blank to blank */
                    current_info.board[r-2][c] = current_info.board[r-1][c];
                    current_info.board[r-1][c] = current_info.board[r][c];
                    current_info.board[r][c] = current_info.player.spot;
                    current_info.player.spot = ' ';
                    break;

                case '.': /* going from a blank to home */
                    current_info.board[r-2][c] = '%';
                    current_info.board[r-1][c] = current_info.board[r][c];
                    current_info.board[r][c] = current_info.player.spot;
                    current_info.player.spot = ' ';
                    current_info.level.boxes_to_go--;
                    break;

                default:
                    moved = false;
                    break;
                }
                break;

            case '%':
                switch(current_info.board[r-2][c]) {
                case ' ': /* we are going from a home to a blank */
                    current_info.board[r-2][c] = '$';
                    current_info.board[r-1][c] = current_info.board[r][c];
                    current_info.board[r][c] = current_info.player.spot;
                    current_info.player.spot = '.';
                    current_info.level.boxes_to_go++;
                    break;

                case '.': /* if we are going from a home to home */
                    current_info.board[r-2][c] = '%';
                    current_info.board[r-1][c] = current_info.board[r][c];
                    current_info.board[r][c] = current_info.player.spot;
                    current_info.player.spot = '.';
                    break;

                default:
                    moved = false;
                    break;
                }
                break;

            default:
                moved = false;
                break;
            }

            if (moved)
                current_info.player.row--;
            break;

        case BUTTON_DOWN:
            switch(current_info.board[r+1][c]) {
            case ' ': /* if it is a blank spot */
            case '.': /* if it is a home spot */
                new_spot = current_info.board[r+1][c];
                current_info.board[r+1][c] = '@';
                current_info.board[r][c] = current_info.player.spot;
                current_info.player.spot = new_spot;
                break;

            case '$':
                switch(current_info.board[r+2][c]) {
                case ' ': /* going from blank to blank */
                    current_info.board[r+2][c] = current_info.board[r+1][c];
                    current_info.board[r+1][c] = current_info.board[r][c];
                    current_info.board[r][c] = current_info.player.spot;
                    current_info.player.spot = ' ';
                    break;

                case '.': /* going from a blank to home */
                    current_info.board[r+2][c] = '%';
                    current_info.board[r+1][c] = current_info.board[r][c];
                    current_info.board[r][c] = current_info.player.spot;
                    current_info.player.spot = ' ';
                    current_info.level.boxes_to_go--;
                    break;

                default:
                    moved = false;
                    break;
                }
                break;

            case '%':
                switch(current_info.board[r+2][c]) {
                case ' ': /* going from a home to a blank */
                    current_info.board[r+2][c] = '$';
                    current_info.board[r+1][c] = current_info.board[r][c];
                    current_info.board[r][c] = current_info.player.spot;
                    current_info.player.spot = '.';
                    current_info.level.boxes_to_go++;
                    break;

                case '.': /* going from a home to home */
                    current_info.board[r+2][c] = '%';
                    current_info.board[r+1][c] = current_info.board[r][c];
                    current_info.board[r][c] = current_info.player.spot;
                    current_info.player.spot = '.';
                    break;

                default:
                    moved = false;
                    break;
                }
                break;

            default:
                moved = false;
                break;
            }

            if (moved)
                current_info.player.row++;
            break;

        default:
            if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
                return PLUGIN_USB_CONNECTED;

            moved = false;
            break;
        }

        if (button != BUTTON_NONE)
            lastbutton = button;

        if (moved) {
            current_info.level.moves++;
            rb->lcd_clear_display();
            update_screen();
        }

        /* We have completed this level */
        if (current_info.level.boxes_to_go == 0) {
            current_info.level.level++;

            /* clear undo stats */
            init_undo();

            rb->lcd_clear_display();

            if (current_info.level.level > current_info.max_level) {
                rb->lcd_putsxy(10, 20, "You WIN!!");

                rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
                for (i = 0; i < 30000 ; i++) {
                    rb->lcd_fillrect(0, 0, 111, 63);
                    rb->lcd_update();

                    button = rb->button_get(false);
                    if (button && ((button & BUTTON_REL) != BUTTON_REL))
                        break;
                }
                rb->lcd_set_drawmode(DRMODE_SOLID);

                return PLUGIN_OK;
            }

            load_level();
            update_screen();
        }

    } /* end while */

    return PLUGIN_OK;
}
int sokoban_game::start_game()
{
    int iScore = 0;
    int iMoves = 0;
    iTotalMoves = 0;

    int iDirY, iDirX;

    const int iOffsetX = (TERMX > FULL_SCREEN_WIDTH) ? (TERMX - FULL_SCREEN_WIDTH) / 2 : 0;
    const int iOffsetY = (TERMY > FULL_SCREEN_HEIGHT) ? (TERMY - FULL_SCREEN_HEIGHT) / 2 : 0;

    parse_level();

    WINDOW *w_sokoban = newwin(FULL_SCREEN_HEIGHT, FULL_SCREEN_WIDTH, iOffsetY, iOffsetX);
    draw_border(w_sokoban);
    center_print(w_sokoban, 0, hilite(c_white), _("Sokoban"));

    std::vector<std::string> shortcuts;
    shortcuts.push_back(_("<+> next"));    // '+': next
    shortcuts.push_back(_("<-> prev"));    // '-': prev
    shortcuts.push_back(_("<r>eset"));     // 'r': reset
    shortcuts.push_back(_("<q>uit"));      // 'q': quit
    shortcuts.push_back(_("<u>ndo move")); // 'u': undo move

    int indent = 10;
    for (size_t i = 0; i < shortcuts.size(); i++) {
        indent = std::max(indent, utf8_width(shortcuts[i].c_str()) + 1);
    }
    indent = std::min(indent, 30);

    for (size_t i = 0; i < shortcuts.size(); i++) {
        shortcut_print(w_sokoban, i + 1, FULL_SCREEN_WIDTH - indent,
                       c_white, c_ltgreen, shortcuts[i].c_str());
    }

    int input = '.';

    int iPlayerY = 0;
    int iPlayerX = 0;

    bool bNewLevel = true;
    bool bMoved = false;
    do {
        if (bNewLevel) {
            bNewLevel = false;

            iMoves = 0;
            vUndo.clear();

            iPlayerY = mLevelInfo[iCurrentLevel]["PlayerY"];
            iPlayerX = mLevelInfo[iCurrentLevel]["PlayerX"];
            mLevel = vLevel[iCurrentLevel];
        }

        print_score(w_sokoban, iScore, iMoves);

        if (check_win()) {
            //we won yay
            if (!mAlreadyWon[iCurrentLevel]) {
                iScore += 500;
                mAlreadyWon[iCurrentLevel] = true;
            }
            input = '+';

        } else {
            draw_level(w_sokoban);
            wrefresh(w_sokoban);

            //Check input
            input = getch();
        }

        bMoved = false;
        switch (input) {
        case KEY_UP: /* up */
            iDirY = -1;
            iDirX = 0;
            bMoved = true;
            break;
        case KEY_DOWN: /* down */
            iDirY = 1;
            iDirX = 0;
            bMoved = true;
            break;
        case KEY_LEFT: /* left */
            iDirY = 0;
            iDirX = -1;
            bMoved = true;
            break;
        case KEY_RIGHT: /* right */
            iDirY = 0;
            iDirX = 1;
            bMoved = true;
            break;
        case 'q':
            return iScore;
            break;
        case 'u': {
            int iPlayerYNew = 0;
            int iPlayerXNew = 0;
            bool bUndoSkip = false;
            //undo move
            if (vUndo.size() > 0) {
                //reset last player pos
                mLevel[iPlayerY][iPlayerX] = (mLevel[iPlayerY][iPlayerX] == "+") ? "." : " ";
                iPlayerYNew = vUndo[vUndo.size() - 1].iOldY;
                iPlayerXNew = vUndo[vUndo.size() - 1].iOldX;
                mLevel[iPlayerYNew][iPlayerXNew] = vUndo[vUndo.size() - 1].sTileOld;

                vUndo.pop_back();

                bUndoSkip = true;
            }

            if (bUndoSkip && vUndo.size() > 0) {
                iDirY = vUndo[vUndo.size() - 1].iOldY;
                iDirX = vUndo[vUndo.size() - 1].iOldX;

                if (vUndo[vUndo.size() - 1].sTileOld == "$" ||
                    vUndo[vUndo.size() - 1].sTileOld == "*") {
                    mLevel[iPlayerY][iPlayerX] = (mLevel[iPlayerY][iPlayerX] == ".") ? "*" : "$";
                    mLevel[iPlayerY + iDirY][iPlayerX + iDirX] = (mLevel[iPlayerY + iDirY][iPlayerX + iDirX] == "*") ? "." : " ";

                    vUndo.pop_back();
                }
            }

            if (bUndoSkip) {
                iPlayerY = iPlayerYNew;
                iPlayerX = iPlayerXNew;
            }
        }
        break;
        case 'r':
            //reset level
            bNewLevel = true;
            break;
        case '+':
            //next level
            clear_level(w_sokoban);
            iCurrentLevel++;
            if (iCurrentLevel >= iNumLevel) {
                iCurrentLevel = 0;
            }
            bNewLevel = true;
            break;
        case '-':
            //prev level
            clear_level(w_sokoban);
            iCurrentLevel--;
            if (iCurrentLevel < 0) {
                iCurrentLevel =  iNumLevel - 1;
            }
            bNewLevel = true;
            break;
        default:
            break;
        }

        if (bMoved) {
            //check if we can move the player
            std::string sMoveTo = mLevel[iPlayerY + iDirY][iPlayerX + iDirX];
            bool bMovePlayer = false;

            if (sMoveTo != "#") {
                if (sMoveTo == "$" || sMoveTo == "*") {
                    //Check if we can move the package
                    std::string sMovePackTo = mLevel[iPlayerY + (iDirY * 2)][iPlayerX + (iDirX * 2)];
                    if (sMovePackTo == "." || sMovePackTo == " ") {
                        //move both
                        bMovePlayer = true;
                        mLevel[iPlayerY + (iDirY * 2)][iPlayerX + (iDirX * 2)] = (sMovePackTo == ".") ? "*" : "$";

                        vUndo.push_back(cUndo(iDirY, iDirX, sMoveTo));

                        iMoves--;
                    }
                } else {
                    bMovePlayer = true;
                }

                if (bMovePlayer) {
                    //move player
                    vUndo.push_back(cUndo(iPlayerY, iPlayerX, mLevel[iPlayerY][iPlayerX]));

                    mLevel[iPlayerY][iPlayerX] = (mLevel[iPlayerY][iPlayerX] == "+") ? "." : " ";
                    mLevel[iPlayerY + iDirY][iPlayerX + iDirX] = (sMoveTo == "." || sMoveTo == "*") ? "+" : "@";

                    iPlayerY += iDirY;
                    iPlayerX += iDirX;

                    iMoves++;
                    iTotalMoves++;
                }
            }
        }

    } while (true);

    return iScore;
}
예제 #18
0
void gameloop_draw_playing(game_t *game)
{
	int x, y, i;
	obj_t *ob;
	cell_t *ce;

	// Draw level
	draw_level(screen, game->lv, game->camx, game->camy, 0);

	// Draw overlays
	for(i = 0; i < game->lv->ocount; i++)
	{
		ob = game->lv->objects[i];

		if(ob == NULL) continue;

		// Cell occupancy
		/*
		draw_border_d(screen,
			ob->f.cx*32 - game->camx,
			ob->f.cy*24 - game->camy,
			32,
			24,
			1);*/

		// Bounding box
		if(ob == game->selob)
		draw_border_d(screen,
			ob->bx + ob->f.ox + ob->f.cx*32 - game->camx,
			ob->by + ob->f.oy + ob->f.cy*24 - game->camy,
			ob->bw,
			ob->bh,
			2);
	}

	// TEST: Mark walkable paths
	/*
	for(y = 0; y < game->lv->layers[0]->w; y++)
	for(x = 0; x < game->lv->layers[0]->h; x++)
	{
		cell_t *ce = layer_cell_ptr(game->lv->layers[0], x, y);

		if(ce != NULL && ce->f.ctyp == CELL_FLOOR)
		{
			draw_border_d(screen,
				32*x + 8 - game->camx,
				24*y + 6 - game->camy,
				16,
				12,
				ce->ob == NULL ? 1 : 2);
		}

	}
	*/

	// Draw A* route for selected object
	if(game->selob != NULL && game->claim_team[game->curplayer] != 0xFC)
	{
		// Get coordinates
		int asendx = (game->mx + game->camx)/32;
		int asendy = (game->my + game->camy)/24;

		// Line trace
		int canattack = line_layer(game->lv->layers[0], &x, &y,
			game->selob->f.cx, game->selob->f.cy, asendx, asendy);
		draw_border_d(screen,
			x*32 - game->camx + 1,
			y*24 - game->camy + 1,
			30,
			22,
			2);

		int pointself = (asendx == game->selob->f.cx && asendy == game->selob->f.cy);
		int shifts = (key_state[SDLK_LSHIFT] || key_state[SDLK_RSHIFT]);
		canattack |= shifts;
		canattack = canattack && !pointself;

		// Draw attack icon if that would make sense
		if(canattack)
		{
			ce = layer_cell_ptr(game->lv->layers[0], x, y);
			if(shifts || (ce != NULL && ce->ob != NULL && ce->ob->f.otyp == OBJ_PLAYER
				&& ((struct fd_player *)(ce->ob->f.fd))->team != game->curplayer))
			{
				if(game->selob->steps_left >= STEPS_ATTACK)
				{
					draw_img_trans_d_sd(screen, i_icons1,
						x*32 - game->camx,
						y*24 - game->camy,
						32*1, 24*1, 32, 24, 0);
				} else {
					draw_img_trans_d_sd(screen, i_icons1,
						x*32 - game->camx,
						y*24 - game->camy,
						32*4, 24*0, 32, 24, 0);

				}
			}

		} else if(pointself && (game->selob->f.ox == 0 && game->selob->f.oy == 0)) {
			// Crouch/stand icon
			if(game->selob->steps_left < 1)
			{
				draw_img_trans_d_sd(screen, i_icons1,
					x*32 - game->camx,
					y*24 - game->camy,
					32*4, 24*0, 32, 24, 0);

			} else if(game->selob->f.flags & OF_CROUCH) {
				draw_img_trans_d_sd(screen, i_icons1,
					x*32 - game->camx,
					y*24 - game->camy,
					32*3, 24*1, 32, 24, 0);

			} else {
				draw_img_trans_d_sd(screen, i_icons1,
					x*32 - game->camx,
					y*24 - game->camy,
					32*2, 24*1, 32, 24, 0);
			}

		}

		// Do A* trace
		int dirlist[1024];
		int dirlen = astar_layer(game->lv->layers[0], dirlist, 1024,
			game->selob->f.cx, game->selob->f.cy, asendx, asendy);

		// Trace
		if((!shifts) && dirlen >= 1)
		{
			int moves_left = game->selob->steps_left;
			if(game->selob->f.flags & OF_CROUCH) moves_left >>= 1;

			// Get start pos
			x = game->selob->f.cx;
			y = game->selob->f.cy;

			for(i = 0; i < dirlen; i++)
			{
				// Get delta
				int dx = face_dir[dirlist[i]][0];
				int dy = face_dir[dirlist[i]][1];

				// Draw line
				if(i == moves_left)
					draw_img_trans_d_sd(screen, i_icons1,
						x*32 - game->camx,
						y*24 - game->camy,
						32*0, 24*1, 32, 24, 0);
				else if(i < moves_left)
					draw_img_trans_d_sd(screen, i_icons1,
						x*32 - game->camx,
						y*24 - game->camy,
						32*dirlist[i], 24*0, 32, 24, 0);
				else
					draw_img_trans_d_sd(screen, i_icons1,
						x*32 - game->camx,
						y*24 - game->camy,
						32*4, 24*0, 32, 24, 0);

				// Move
				x += dx;
				y += dy;

			}

			// Show position
			if(dirlen <= moves_left)
				draw_img_trans_d_sd(screen, i_icons1,
					x*32 - game->camx,
					y*24 - game->camy,
					32*0, 24*1, 32, 24, 0);
			else
				draw_img_trans_d_sd(screen, i_icons1,
					x*32 - game->camx,
					y*24 - game->camy,
					32*4, 24*0, 32, 24, 0);

		}
예제 #19
0
/*
 * Main function to run one tick of the game
 */
int run_game()
{
	cli();

	/* Movement phase */
	if(game_state == 1)
	{
		/* Move the reticule based on readings from the rotary encoder */
		int16_t newRX = (playersX[current_player] + (RETICULE_DISTANCE * ml_cos(position))/100);
		int16_t newRY = (playersY[current_player] + (RETICULE_DISTANCE * ml_sin(position))/100);
		
		rectangle reticuleOld = {reticuleX - reticule_SPR->width / 2, reticuleX + reticule_SPR->width / 2 - 1, reticuleY - reticule_SPR->height / 2, reticuleY + reticule_SPR->height / 2 - 1};
		draw_background(level_map, SILVER, reticuleOld, HEIGHT_NO_UI, WIDTH);

		//fill_rectangle(reticuleOld, BLACK);
		if(newRX >= 0 && newRX < WIDTH && newRY >= 0 && newRY < HEIGHT)
			fill_sprite(reticule_SPR, newRX, newRY, HEIGHT_NO_UI, WIDTH);
	
		reticuleX = newRX;
		reticuleY = newRY;

		/* Read firing input */
		if (get_switch_long(_BV(SWC)))
		{
			game_state = 3;
			return 0;
		}		

		/* Read directional input.*/
		if (get_switch_rpt(_BV(SWE))) 
		{
			direction = 4;
			free_sprite(player_SPR);
			player_SPR = botright(current_player);
		}
		else if (get_switch_rpt(_BV(SWW)))
		{
			direction = -4;
			free_sprite(player_SPR);
			player_SPR = botleft(current_player);
		}
		else
		{
			direction = 0;
			return 0;
		}

		/* Move the player */
		int16_t newX = playersX[current_player] + direction;
		int16_t newY = ml_min(level_map[newX - PLAYER_WIDTH], level_map[newX + PLAYER_WIDTH - 1]) - PLAYER_HEIGHT;

		int8_t i;
		int8_t player_collision = 0;
		for(i = 0; i < players; i++)
		{
			if(players_HP[i] != 0 && i != current_player && newX >= playersX[i] - PLAYER_WIDTH && newX <= playersX[i] + PLAYER_WIDTH - 1)
			{
				player_collision = 1;
				break;
			}				
		}

		/* Cancel movement if trying to climb to high or off the sides of the screen */
		if(player_collision || playersY[current_player] - newY > MAX_CLIMB_HEIGHT || newX <= PLAYER_WIDTH || newX + PLAYER_WIDTH > WIDTH)
		{
			/* DEBUGGING prints: */
			//display_string_xy("Error\n", 10, 10);
			//ml_printf("Cannot move there... (%u,%u) to (%u,%u)", playersX[0], playersY[0], newX, newY);
			return 0;
		}
		
		rectangle playerOld = {playersX[current_player] - PLAYER_WIDTH, playersX[current_player] + PLAYER_WIDTH - 1, playersY[current_player] - PLAYER_HEIGHT, playersY[current_player] + PLAYER_HEIGHT - 1};

		fill_rectangle(playerOld, BLACK);
		fill_sprite(player_SPR, newX, newY, HEIGHT_NO_UI, WIDTH);
		
		playersX[current_player] = newX;
		playersY[current_player] = newY;
	}
	/* Projectile phase (missile in the air) */
	else if(game_state == 2)
	{
		/* Find the new position of the projectile */
		int16_t newX = projectileX + proVelX/1000;
		int16_t newY = projectileY + proVelY/1000;
		
		rectangle projectileOld = {projectileX, projectileX, projectileY, projectileY};
		fill_rectangle(projectileOld, BLACK);

		/* End turn if projectile goes off the sides of the level */
		if(newX < 0 || newX > WIDTH)
		{
			start_turn();
			return 0;
		}
		
		/* If the new position is in the ground, EXPLODE!
		 * (Also, if off the bottom of the level) */
		if(newY >= level_map[newX] || newY > HEIGHT_NO_UI)
		{
			int i;
			for(i = -EXPLOSION_RADIUS; i <= EXPLOSION_RADIUS; i++)
			{
				/* Make sure that terrain is on screen */
				if(newX + i >= 0 && newX + i < WIDTH)
				{
					uint16_t new_ground_level = newY + ml_sqrt(EXPLOSION_RADIUS * EXPLOSION_RADIUS - i * i);
					if(new_ground_level >= HEIGHT_NO_UI)
						level_map[newX + i] = HEIGHT_NO_UI - 1; //Clamp to bottom of level
					else if(new_ground_level > level_map[newX + i]) //Don't raise the ground level!
						level_map[newX + i] = new_ground_level; 
				}
			}

			draw_level(level_map, SILVER, newX - EXPLOSION_RADIUS, newX + EXPLOSION_RADIUS);

			/* Check players for damage + redraw them */
			for(i = 0; i < players; i++)
			{
				int16_t deltaX = playersX[i] - newX;
				int16_t deltaY = playersY[i] - newY;
				int16_t distance = ml_sqrt(deltaX * deltaX + deltaY * deltaY);
				if(distance < BLAST_RADIUS)
				{
					int16_t damage = ml_clamp(0, players_HP[i], MAX_EXPLOSION_DAMAGE - (distance * MAX_EXPLOSION_DAMAGE / BLAST_RADIUS));
					players_HP[i] -= damage;
				}

				rectangle playerOld = {playersX[i] - PLAYER_WIDTH, playersX[i] + PLAYER_WIDTH - 1, playersY[i] - PLAYER_HEIGHT, playersY[i] + PLAYER_HEIGHT - 1};
				fill_rectangle(playerOld, BLACK);

				/* If the player is still alive, redraw them */
				if(players_HP[i] != 0)
				{
					free_sprite(player_SPR);
					player_SPR = botleft(i);
					playersY[i] = ml_min(level_map[playersX[i] - PLAYER_WIDTH], level_map[playersX[i] + PLAYER_WIDTH - 1]) - PLAYER_HEIGHT;
					fill_sprite(player_SPR, playersX[i], playersY[i], HEIGHT_NO_UI, WIDTH);
				}
			}

			start_turn();
			return 0;
		}	

		rectangle projectileNew = {newX, newX, newY, newY};
		
		/* Continue turn if off top of level, but only draw if projectile onscreen */
		if(newY >= 0)
		{
			fill_rectangle(projectileNew, RED);
		}

		projectileX = newX;
		projectileY = newY;		

		/* Apply gravity and wind */
		proVelY += 500;
		proVelX += (wind_velocity - 10) * 50;
	}
	/* Charging phase */
	else if(game_state == 3)
	{
		/* Increase the launch speed while the fire button is held */
		if (get_switch_state(_BV(SWC)))
		{
			launch_speed++;
			rectangle bar = {POWER_BAR_START, POWER_BAR_START + launch_speed, 231, 236};
			fill_rectangle(bar, WHITE);

			/* Fire once max power is reached */
			if(launch_speed == 100)
				fire_projectile();
		}
		else
		{
			fire_projectile();
		}
	}	
	/* Menu phase */
	else if(game_state == 4)
	{
		if (get_switch_press(_BV(SWE)))
		{
			if(players == 4)
				players = 2;
			else
				players++;
		}
		else if (get_switch_press(_BV(SWW)))
		{
			if(players == 2)
				players = 4;
			else
				players--;
		}

		ml_printf_at("< %u Players >", 5, 115, players);
		
		if (get_switch_long(_BV(SWC)))
		{
			start_game();
		}
	}
	/* End game phase */
	else if(game_state == 5)
	{
		if (get_switch_long(_BV(SWC)))
		{
			start_menu();
		}
	}

	sei();
	
	return 0;
}