/* gfx.cpp - Don Yang (uguu.org) 12/21/00 */ #include"global.h" #include"bg.h" #include"dd.h" #include"gfx.h" #include"resource.h" #include"sprite.h" #include"term.h" static int OldBlockX, OldBlockY = -1; static void DrawField(DWORD screen); static void DrawSystemStatus(DWORD screen); static void StatScreen(DWORD screen); static void TitleScreen(DWORD screen); /******************************************************************* Animate Draw one frame. */ BOOL Animate(void) { DDSURFACEDESC surface; DWORD screen; // Get buffer address if( !LockScreen(&surface) ) // (dd.cpp) return FALSE; screen = (DWORD)surface.lpSurface; // Draw according to DFA state switch( GameState ) { case GAME_STATE_WAIT_START: case GAME_STATE_SHOW_HISTORY: TitleScreen(screen); break; case GAME_STATE_GENERATE_BLOCK: case GAME_STATE_INPUT_LOOP: case GAME_STATE_CLEAR_SPECIAL: case GAME_STATE_REMOVE_CLUSTER: case GAME_STATE_MARK_CLUSTER: case GAME_STATE_GAME_OVER0: case GAME_STATE_GAME_OVER1: case GAME_STATE_GAME_OVER2: case GAME_STATE_GAME_OVER3: DrawField(screen); break; case GAME_STATE_ENTER_NAME: case GAME_STATE_SHOW_STATS: StatScreen(screen); break; default: if( GameState == TERMINAL_STATE ) RenderTerm(screen); // (term.cpp) else DrawSystemStatus(screen); break; } // Write to video memory if( !UnlockScreen() ) // (dd.cpp) return FALSE; return Blit(); // (dd.cpp) } // Animate() /***************************************************************** DrawField Draw game field. */ static void DrawField(DWORD screen) { int x, y; if( (FrameCount & BG_CHANGE_FREQ) == 0 ) AnimateBackground(); // (bgfx.cpp) if( RedrawAll || GameState != GAME_STATE_INPUT_LOOP ) { // Slow redraw (draw everything) OldBlockY = -1; // Draw background PaintBackground(screen); // (bg.cpp) // Draw decorations DrawLabel1(screen); // (sprite.cpp) DrawLabel2(screen); DrawLabel3(screen); DrawNumber(screen, LEVEL_LABEL_X + 91, LEVEL_LABEL_Y, GameLevel, 1); DrawNumber(screen, SCORE_LABEL_X + 91, SCORE_LABEL_Y, CurrentPlayer.data[HISTORY_SCORE], 6); // Draw cells for(x = 0; x < GRID_WIDTH; x++) { for(y = 0; y < GRID_HEIGHT; y++) { if( Grid[x][y] & CELL_FREE ) continue; if( Grid[x][y] & CELL_DEAD_CLUSTER ) DrawTile(screen, x, y, (int)Grid[x][y] & CELL_TYPE, 2); else if( Grid[x][y] & CELL_CLUSTER ) DrawTile(screen, x, y, (int)Grid[x][y] & CELL_TYPE, 1); else DrawTile(screen, x, y, (int)Grid[x][y] & CELL_TYPE, 0); } } if( GameState >= GAME_STATE_GAME_OVER0 && GameState <= GAME_STATE_GAME_OVER3 ) { // Draw dead tiles DrawTile(screen, BlockX, BlockY, BlockT0, 2); DrawTile(screen, BlockX, BlockY + 1, BlockT1, 2); // Draw text label RepaintBackgroundA(screen, (APP_WIDTH - 240) / 2, (APP_HEIGHT / 2) - 30 , 240, 90); DrawText(screen, (APP_WIDTH - 140) / 2, (APP_HEIGHT / 2) - 20, "Game over!"); DrawText(screen, (APP_WIDTH - 42) / 2, (APP_HEIGHT / 2) + 30, GameState > GAME_STATE_GAME_OVER1 ? GameState > GAME_STATE_GAME_OVER2 ? "X_X" : "-_-" : GameState > GAME_STATE_GAME_OVER0 ? "O_o" : "@_@"); } if( AppPaused ) { DrawText(screen, (APP_WIDTH - 140) / 2, (APP_HEIGHT - 20) / 2, " paused "); } RedrawAll = FALSE; } if( GameState == GAME_STATE_INPUT_LOOP && !AppPaused ) { if( OldBlockY >= 0 ) { RepaintBackground(screen, OldBlockX, OldBlockY); // (bg.cpp) RepaintBackground(screen, OldBlockX, OldBlockY + 1); } OldBlockX = BlockX; OldBlockY = BlockY; DrawTile(screen, BlockX, BlockY, BlockT0, BlockT0 == TILE_SPECIAL ? 2 : 0); DrawTile(screen, BlockX, BlockY + 1, BlockT1, BlockT1 == TILE_SPECIAL ? 2 : 0); } if( GameState < GAME_STATE_GAME_OVER0 || GameState > GAME_STATE_GAME_OVER3 ) { if( GameOptions & OPTION_SPR ) RepaintBackgroundA(screen, 91, 16, 100, 32); // (bg.cpp) DrawTime(screen); } RedrawAll = FALSE; } // DrawField() /********************************************************** DrawSystemStatus Show status in system state. */ static void DrawSystemStatus(DWORD screen) { char text[128]; int y; // Draw background if( RedrawAll ) { PaintBackground(screen); // (bg.cpp) RedrawAll = FALSE; } // Draw texts // This part could be optimized to draw only changes, // but drawing everything provides better calibration results y = APP_HEIGHT - GRID_MARGIN - 20; switch( GameState ) { case SYS_STATE_INIT4: // 4 seconds sprintf(text, "Expected FPS = %d", ExpectedFPS); DrawText(screen, 16, y, text); // (sprite.cpp) y -= 20; case SYS_STATE_INIT3: // 3 seconds switch( PixelFormat ) { case PIXEL_1555: DrawText(screen, 16, y, "Pixel format = 1:5:5:5 (16bit)"); break; case PIXEL_565: DrawText(screen, 16, y, "Pixel format = 5:6:5 (16bit)"); break; case PIXEL_888: DrawText(screen, 16, y, "Pixel format = 8:8:8 (24bit)"); break; case PIXEL_8888: DrawText(screen, 16, y, "Pixel format = 8:8:8:8 (32bit)"); break; default: break; } y -= 20; case SYS_STATE_INIT2: // 2 seconds sprintf(text, "Screen size = (%d, %d)", ScreenWidth, ScreenHeight); DrawText(screen, 16, y, text); y -= 20; case SYS_STATE_INIT1: // 1 second sprintf(text, "exec = %i", ExecCount); DrawText(screen, 16, y, text); y -= 40; case SYS_STATE_INIT0: // start DrawText(screen, 16, y, APP_AUTHOR); DrawText(screen, 16, y - 20, APP_VERSION); default: break; } } // DrawSystemStatus() /**************************************************************** StatScreen Show statistics and names. */ static void StatScreen(DWORD screen) { char text[256]; if( (FrameCount & BG_CHANGE_FREQ) == 0 ) AnimateBackground(); if( RedrawAll ) { PaintBackground(screen); if( GameState == GAME_STATE_SHOW_STATS ) { DrawText(screen, APP_WIDTH - 240, APP_HEIGHT - GRID_MARGIN - 20, "press any key..."); // (sprite.cpp) } else { DrawText(screen, GRID_MARGIN, APP_HEIGHT - GRID_MARGIN - 50, "Enter your name:"); DrawText(screen, GRID_MARGIN, APP_HEIGHT - 36, CurrentPlayer.n.name); } DrawText(screen, GRID_MARGIN, GRID_MARGIN, "score"); DrawText(screen, GRID_MARGIN, GRID_MARGIN + 40, "blocks"); DrawText(screen, GRID_MARGIN, GRID_MARGIN + 60, "cells cleared"); DrawText(screen, GRID_MARGIN, GRID_MARGIN + 80, "clusters cleared"); DrawText(screen, GRID_MARGIN, GRID_MARGIN + 120, "maximum chain"); DrawText(screen, GRID_MARGIN, GRID_MARGIN + 140, "maximum cluster"); sprintf(text, "%d", CurrentPlayer.data[HISTORY_SCORE]); DrawText(screen, 480, GRID_MARGIN, text); sprintf(text, "%d", CurrentPlayer.data[HISTORY_BLOCKS]); DrawText(screen, 480, GRID_MARGIN + 40, text); sprintf(text, "%d", CurrentPlayer.data[HISTORY_CELLS]); DrawText(screen, 480, GRID_MARGIN + 60, text); sprintf(text, "%d", CurrentPlayer.data[HISTORY_CLUSTER]); DrawText(screen, 480, GRID_MARGIN + 80, text); sprintf(text, "%d", CurrentPlayer.data[HISTORY_MAX_CHAIN]); DrawText(screen, 480, GRID_MARGIN + 120, text); sprintf(text, "%d", CurrentPlayer.data[HISTORY_MAX_CLUSTER]); DrawText(screen, 480, GRID_MARGIN + 140, text); RedrawAll = FALSE; } else { if( GameState == GAME_STATE_ENTER_NAME ) { RepaintBackgroundA(screen, GRID_MARGIN, APP_HEIGHT - GRID_MARGIN - 20, APP_WIDTH - GRID_MARGIN * 2, 20); // (bg.cpp) DrawText(screen, GRID_MARGIN, APP_HEIGHT - 36, CurrentPlayer.n.name); } } } // StatScreen() /*************************************************************** TitleScreen Show logo and high scores. */ static void TitleScreen(DWORD screen) { char text[256]; int i; if( (FrameCount & BG_CHANGE_FREQ) == 0 ) AnimateBackground(); if( RedrawAll ) { PaintBackground(screen); // (bg.cpp) DrawWaitLabel(screen); // (sprite.cpp) if( GameState == GAME_STATE_SHOW_HISTORY ) { // Draw high scores DrawText(screen, GRID_MARGIN, GRID_MARGIN, "High scores"); if( History[0].data[HISTORY_SCORE] == 0 ) { DrawText(screen, (APP_WIDTH - 84) / 2, APP_HEIGHT / 2, "nobody"); } else { sprintf(text, " 1.\t%s", History[0].n.name); DrawText(screen, GRID_MARGIN, GRID_MARGIN + 35, text); sprintf(text, "%d", History[0].data[HISTORY_SCORE]); DrawText(screen, APP_WIDTH - GRID_MARGIN - 14 * strlen(text), GRID_MARGIN + 35, text); sprintf(text, "blocks = %d", History[0].data[HISTORY_BLOCKS]); DrawText(screen, GRID_MARGIN + 60, GRID_MARGIN + 60, text); sprintf(text, "cells = %d", History[0].data[HISTORY_CELLS]); DrawText(screen, GRID_MARGIN + 60, GRID_MARGIN + 80, text); sprintf(text, "clusters = %d", History[0].data[HISTORY_CLUSTER]); DrawText(screen, GRID_MARGIN + 60, GRID_MARGIN + 100, text); sprintf(text, "max chain = %d", History[0].data[HISTORY_MAX_CHAIN]); DrawText(screen, APP_WIDTH / 2, GRID_MARGIN + 80, text); sprintf(text, "max cluster = %d", History[0].data[HISTORY_MAX_CLUSTER]); DrawText(screen, APP_WIDTH / 2, GRID_MARGIN + 100, text); for(i = 1; i < MAX_HISTORY_LENGTH; i++) { if( History[i].data[HISTORY_SCORE] == 0 ) break; sprintf(text, "%2d.\t%s", i + 1, History[i].n.name); DrawText(screen, GRID_MARGIN, GRID_MARGIN + 140 + i * 25, text); sprintf(text, "%d", History[i].data[HISTORY_SCORE]); DrawText(screen, APP_WIDTH - GRID_MARGIN - 14 * strlen(text), GRID_MARGIN + 140 + i * 25, text); } } } else { // Draw logo only DrawTitle(screen); // (sprite.cpp) } RedrawAll = FALSE; } } // TitleScreen() char *GfxObjTime = __TIME__ " " __DATE__; int GfxObjLines = __LINE__;