⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 app_shell.cpp

📁 国外游戏开发者杂志2003年第七期配套代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:

void App_Shell::bitmap_mode_end() {
    glEnable(GL_CULL_FACE);

    glMatrixMode(GL_TEXTURE);
    glLoadIdentity();
    draw_mode = MODE_NONE;
}

void App_Shell::text_mode_begin(Font *font) {
    if (font == NULL) return;

    glMatrixMode(GL_TEXTURE);
    glLoadIdentity();

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, screen_width, 0, screen_height, 0, -100);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glDepthFunc(GL_ALWAYS);
    glDisable(GL_LIGHTING);
    glDisable(GL_CULL_FACE);

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glBindTexture(GL_TEXTURE_2D, font->texture_handle);

    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
/*
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_NEAREST);
*/

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    glEnable(GL_TEXTURE_2D);
    GLfloat ambient[] = { 1.0f, 1.0f, 1.0f, 1.0f };
    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient);
    
    draw_mode = MODE_TEXT;
}

void App_Shell::text_mode_end() {
    glEnable(GL_CULL_FACE);

    glMatrixMode(GL_TEXTURE);
    glLoadIdentity();
    draw_mode = MODE_NONE;
}

bool App_Shell::init(int width, int height) {
    loaded_textures = new List();

    mouse_button_1_is_down = false;
    mouse_button_2_is_down = false;

    last_frame_time = 0;

	screen_width = width;
	screen_height = height;

    show_mouse_pointer = true;
    center_mouse_pointer = false;

	mouse_pointer_x = 0;
	mouse_pointer_y = 0;

	mouse_pointer_delta_x = 0;
	mouse_pointer_delta_y = 0;

    draw_mode = MODE_NONE;

	// Init time.
	global_base_time = get_time_reading();

	// Init other stuff.
	bool success;

	success = init_gl();
	if (!success) return false;
	
	init_textures();
	init_modelview_transform();

	return true;
}

void App_Shell::init_modelview_transform() {
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

	float pos_x = 0;
	float pos_y = 0;
	float pos_z = 5;
    gluLookAt(pos_x, pos_y, pos_z, 0, 0, 0, 0, 0, 1);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(90, (float)screen_width / (float)screen_height,
				   0.4f, 1000.0f);
}





///// OpenGL stuff here

const char *window_class_name = "AppShellWindowClass";
HWND get_hwnd(App_Shell *shell) {
	return *(HWND *)&shell->hwnd;
}

bool App_Shell::init_gl() {
	WNDCLASS wc;

	wc.style                = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
	wc.lpfnWndProc          = (WNDPROC)WindowProc;
	wc.cbClsExtra           = 0;
	wc.cbWndExtra           = 0;
	wc.hInstance            = global_hinstance;
	wc.hIcon                = LoadIcon(NULL, "APPICON");
	wc.hCursor              = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	
	wc.lpszMenuName         = NULL; 
	wc.lpszClassName        = window_class_name;

	// Register the window class
	if (RegisterClass(&wc) == 0) return false;

	extern char *app_name;
	
	HWND app_hwnd;
    app_hwnd = CreateWindow(window_class_name,
							app_name,
							WS_OVERLAPPEDWINDOW,
							0, 0,
							screen_width, screen_height,
							NULL,
							NULL,
							global_hinstance,
							NULL);

    assert(global_dc != 0);

	hwnd = (void *)app_hwnd;

    // Display the window
    ShowWindow(app_hwnd, SW_SHOW);
    UpdateWindow(app_hwnd);

	
    wglMakeCurrent(global_dc, global_gl_rc);
    glViewport(0, 0, screen_width, screen_height);

	return true;
}


double App_Shell::get_time() {
    LARGE_INTEGER time = get_time_reading();
	time.QuadPart = time.QuadPart - global_base_time.QuadPart;

	return (double)time.QuadPart * 0.001;
}

void App_Shell::sleep(float seconds) {
    Sleep(seconds * 1000);
}

void set_pixel_format(HDC dc) {
	static PIXELFORMATDESCRIPTOR pfd = {
		sizeof(PIXELFORMATDESCRIPTOR),  // Size
		1,                              // Version
		PFD_DRAW_TO_WINDOW |
		PFD_SUPPORT_OPENGL |
		PFD_DOUBLEBUFFER,
		PFD_TYPE_RGBA,
		24,                              // 24-bit color 
		0, 0, 0, 0, 0, 0,                // A bunch of unused stuff.
		0, 0,
		0, 0, 0, 0, 0,
		32,                              // Z-buffer depth
		0,
		0,
		PFD_MAIN_PLANE,
		0,
		0, 0, 0 };
	
	int format = ChoosePixelFormat(dc, &pfd);
	SetPixelFormat(dc, format, &pfd);
}

static int translate_ascii_code(WPARAM wParam) {
    switch (wParam) {
    // Hacky keybindings so that we don't have to define a bunch of
    // OS-independent constants for these, like we would if we
    // were writing a real game input system.
    case VK_LEFT:
    case VK_PRIOR:
        return App_Shell::ARROW_LEFT;
    case VK_RIGHT:
    case VK_NEXT:
        return App_Shell::ARROW_RIGHT;
    case VK_UP:
        return App_Shell::ARROW_UP;
    case VK_DOWN:
        return App_Shell::ARROW_DOWN;
    case VK_DELETE:
        return ')';
    default:
        return wParam;
    }
}

LRESULT CALLBACK WindowProc(HWND    hWnd,
							UINT    message,
							WPARAM  wParam,
							LPARAM  lParam) {
  	switch (message) {
      case WM_CREATE:
          global_dc = GetDC(hWnd);

          set_pixel_format(global_dc);

          // Make a rendering context.
          global_gl_rc = wglCreateContext(global_dc);
          assert(global_gl_rc != NULL);

          BOOL succ;
          succ = wglMakeCurrent(global_dc, global_gl_rc);
          assert(succ);

          break;

    case WM_DESTROY:
        wglMakeCurrent(global_dc, NULL);
        wglDeleteContext(global_gl_rc);

        if (global_palette != NULL) DeleteObject(global_palette);
        ReleaseDC(hWnd, global_dc);

		PostQuitMessage(0);
		break;

	case WM_ACTIVATEAPP:
        if (wParam) app_is_active = true;
        else app_is_active = false;
		break;
		
	case WM_SIZE: {
		int width, height;

		width = LOWORD(lParam);
		height = HIWORD(lParam);

		wglMakeCurrent(global_dc, global_gl_rc);
		glViewport(0, 0, width, height);
		app_shell->screen_width = width;
		app_shell->screen_height = height;

		break;
	}

	case WM_KEYDOWN: {
		extern void handle_keydown(int);
		int ascii_code;
		ascii_code = translate_ascii_code(wParam);
		handle_keydown(ascii_code);
		break;
	}
	case WM_KEYUP: {
		extern void handle_keyup(int);
		int ascii_code;
		ascii_code = translate_ascii_code(wParam);
		handle_keyup(ascii_code);
		break;
	}

	case WM_PAINT: 
		ValidateRect(hWnd,NULL);
		break;

	case WM_QUERYNEWPALETTE:
        if (global_palette) {
            int nRet;

            SelectPalette(global_dc, global_palette, FALSE);
            nRet = RealizePalette(global_dc);
            InvalidateRect(hWnd, NULL, FALSE);
			
            return nRet;
        }

        break;

	
	case WM_PALETTECHANGED:
		if ((global_palette != NULL) && ((HWND)wParam != hWnd)) {
			SelectPalette(global_dc, global_palette, FALSE);
			RealizePalette(global_dc);
			UpdateColors(global_dc);
			return 0;
		}

		break;

    case WM_LBUTTONDOWN:
        app_shell->mouse_button_1_is_down = true;
        break;
    case WM_LBUTTONUP:
        app_shell->mouse_button_1_is_down = false;
        break;
    case WM_RBUTTONDOWN:
        app_shell->mouse_button_2_is_down = true;
        break;
    case WM_RBUTTONUP:
        app_shell->mouse_button_2_is_down = false;
        break;
	default:
	    return DefWindowProc(hWnd, message, wParam, lParam);
	}

    return 0;
}

double App_Shell::get_dt() {
    return dt;
}


void do_beginning_of_frame_stuff() {
    // Compute dt...
    double now = app_shell->get_time();
    if (app_shell->last_frame_time == 0) {
        app_shell->dt = 0.05f;   // Arbitrary bootstrap value!
    } else {
        app_shell->dt = now - app_shell->last_frame_time;
    }

    app_shell->last_frame_time = now;
}

void do_end_of_frame_stuff() {
    // Do mouse stuff...

    // Constrain the mouse pointer to the screen and make it invisible

    // Don't actually screw with the mouse if we don't have focus.
    if (!app_is_active) return;

    if (!app_shell->show_mouse_pointer) {
        int count = ShowCursor(FALSE);
        while (count < -1) {
            ShowCursor(TRUE);
            count++;
        }
    } else {
        int count = ShowCursor(TRUE);
        while (count > 1) {
            ShowCursor(FALSE);
            count--;
        }
    }


    HWND hwnd = (HWND)app_shell->hwnd;
    RECT rect;
    GetClientRect(hwnd, &rect);

    POINT point;
    point.x = 0;
    point.y = 0;
    ClientToScreen(hwnd, &point);

    rect.left += point.x;
    rect.right += point.x;
    rect.top += point.y;
    rect.bottom += point.y;

    ClipCursor(&rect);

    if (app_shell->center_mouse_pointer) {
        // Put the pointer in the middle of the screen
        int cx = (rect.left + rect.right) / 2;
        int cy = (rect.bottom + rect.top) / 2;

        POINT old_point;
        GetCursorPos(&old_point);
        SetCursorPos(cx, cy);

        app_shell->mouse_pointer_delta_x = old_point.x - cx;
        app_shell->mouse_pointer_delta_y = cy - old_point.y;
    }
}


void draw_one_frame() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    extern void draw_scene();
    draw_scene();
    SwapBuffers(global_dc);
}


int PASCAL WinMain(HINSTANCE hinst, HINSTANCE,
                   LPSTR command_line, int ShowMode) {
    global_hinstance = hinst;

    // get the user's specified display parameters, or defaults
    // the shortened names work because of the default value
    
	app_shell = new App_Shell();
	bool success = app_shell->init(DEFAULT_WIDTH, DEFAULT_HEIGHT);
	assert(success);

	extern void app_init(int argc, char **argv);
    if (command_line[0] != '\0') {
        app_init(1, &command_line);
    } else {
        app_init(0, &command_line);
    }
	
    SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);

    double last_time = 0;

    MSG msg;
    while (1) {
		HWND hwnd = get_hwnd(app_shell);
        assert(hwnd);

        // Do time stuff.

		// Do mouse pointer stuff.
		POINT point;
		BOOL success = GetCursorPos(&point);
        assert(success);

		if (success) {
			RECT client_rect;
			GetClientRect(hwnd, &client_rect);

            POINT upper_left;
            upper_left.x = 0;
            upper_left.y = 0;

            POINT lower_right;
            lower_right.x = client_rect.right;
            lower_right.y = client_rect.bottom;

            ClientToScreen(hwnd, &upper_left);
            ClientToScreen(hwnd, &lower_right);

            int cursor_x = point.x - upper_left.x;
            int cursor_y = lower_right.y - point.y;

			app_shell->mouse_pointer_x = cursor_x;
			app_shell->mouse_pointer_y = cursor_y;
		}


        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
            if (msg.message == WM_QUIT) break;

            TranslateMessage(&msg);
            DispatchMessage(&msg);
        } else {
            do_beginning_of_frame_stuff();

            if (app_is_active) {
                draw_one_frame();
            } else {
                WaitMessage();
            }

            do_end_of_frame_stuff();
        }
    }

    return msg.wParam;
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -