Esempio n. 1
0
void android_main(android_app *app) {
    app_dummy();

    asset_manager = app->activity->assetManager;

    user_data p = {};
    p.texture_buffer = (uint8_t *)malloc(4 * 960 * 540);
    strcpy(p.app_name, "org.nxsy.ndk_handmade");
    app->userData = &p;

    app->onAppCmd = on_app_cmd;
    app->onInputEvent = on_input_event;
    uint64_t counter;
    uint start_row = 0;
    uint start_col = 0;

    game_memory m = {};
    m.PermanentStorageSize = 64 * 1024 * 1024;
    m.TransientStorageSize = 64 * 1024 * 1024;
    p.total_size = m.PermanentStorageSize + m.TransientStorageSize;
    p.game_memory_block = calloc(p.total_size, sizeof(uint8));
    m.PermanentStorage = (uint8 *)p.game_memory_block;
    m.TransientStorage =
        (uint8_t *)m.PermanentStorage + m.TransientStorageSize;

#ifdef HANDMADE_INTERNAL
    m.DEBUGPlatformReadEntireFile = debug_read_entire_file;
#endif

    thread_context t = {};

    game_input input[2] = {};
    p.new_input = &input[0];
    p.old_input = &input[1];

    int monitor_refresh_hz = 60;
    real32 game_update_hz = (monitor_refresh_hz / 2.0f); // Should almost always be an int...
    long target_nanoseconds_per_frame = (1000 * 1000 * 1000) / game_update_hz;

    while (++counter) {
        timespec start_time = {};
        clock_gettime(CLOCK_MONOTONIC_RAW, &start_time);

        game_controller_input *old_keyboard_controller = GetController(p.old_input, 0);
        game_controller_input *new_keyboard_controller = GetController(p.new_input, 0);
        *new_keyboard_controller = {};
        new_keyboard_controller->IsConnected = true;
        for (
                uint button_index = 0;
                button_index < ArrayCount(new_keyboard_controller->Buttons);
                ++button_index)
        {
            new_keyboard_controller->Buttons[button_index].EndedDown =
                old_keyboard_controller->Buttons[button_index].EndedDown;
        }

        int poll_result, events;
        android_poll_source *source;

        while((poll_result = ALooper_pollAll(0, 0, &events, (void**)&source)) >= 0)
        {
            source->process(app, source);
        }

        switch (poll_result)
        {
            case ALOOPER_POLL_WAKE:
            {
                __android_log_print(ANDROID_LOG_INFO, p.app_name, "poll_result was ALOOPER_POLL_WAKE");
                break;
            }
            case ALOOPER_POLL_CALLBACK:
            {
                __android_log_print(ANDROID_LOG_INFO, p.app_name, "poll_result was ALOOPER_POLL_CALLBACK");
                break;
            }
            case ALOOPER_POLL_TIMEOUT:
            {
                //__android_log_print(ANDROID_LOG_INFO, p.app_name, "poll_result was ALOOPER_POLL_TIMEOUT");
                break;
            }
            case ALOOPER_POLL_ERROR:
            {
                __android_log_print(ANDROID_LOG_INFO, p.app_name, "poll_result was ALOOPER_POLL_ERROR");
                break;
            }
            default:
            {
                __android_log_print(ANDROID_LOG_INFO, p.app_name, "poll_result was %d", poll_result);
                break;
            }
        }

        p.new_input->dtForFrame = target_nanoseconds_per_frame / (1024.0 * 1024 * 1024);

        hh_process_events(app, p.new_input, p.old_input);

        game_offscreen_buffer game_buffer = {};
        game_buffer.Memory = p.texture_buffer;
        game_buffer.Width = 960;
        game_buffer.Height = 540;
        game_buffer.Pitch = 960 * 4;
        game_buffer.BytesPerPixel = 4;

        GameUpdateAndRender(&t, &m, p.new_input, &game_buffer);
        draw(app);

        timespec end_time = {};
        clock_gettime(CLOCK_MONOTONIC_RAW, &end_time);

        end_time.tv_sec -= start_time.tv_sec;
        start_time.tv_sec -= start_time.tv_sec;

        int64_t time_taken = ((end_time.tv_sec * 1000000000 + end_time.tv_nsec) -
            (start_time.tv_sec * 1000000000 + start_time.tv_nsec));

        int64_t time_to_sleep = 33 * 1000000;
        if (time_taken <= time_to_sleep)
        {
            timespec sleep_time = {};
            sleep_time.tv_nsec = time_to_sleep - time_taken;
            timespec remainder = {};
            nanosleep(&sleep_time, &remainder);
        }
        else
        {
            if (counter % 10 == 0)
            {
                __android_log_print(ANDROID_LOG_INFO, p.app_name, "Skipped frame!  Took %" PRId64 " ns total", time_taken);
            }
        }

        game_input *temp_input = p.new_input;
        p.new_input = p.old_input;
        p.old_input = temp_input;
    }
}
Esempio n. 2
0
int main(int argc, char *args[])
{
#if _WIN32
	// NOTE(nathan): Set the windows schedular granularity to 1ms
	// so that our SDL_Delay() and be more granular

	// SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); 
	// NOTE(nathan): This seems to give a more consistant result than above
	timeBeginPeriod(1);
#if _DEBUG
	HWND console = GetConsoleWindow();
	if(console != 0)
	MoveWindow(console, -900, 100, 700, 800, TRUE);
#endif
#endif
	SDL_Init(SDL_INIT_EVERYTHING);

	// NOTE(nathan): This also initializes the window_with and window_height
	WindowData window_data = { };
	window_data.target_width = 1920;
	window_data.target_height = 1080;

	FixViewport(1280, 720, &window_data);

	SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
	//SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
	//SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 4);

	SDL_Window *window = SDL_CreateWindow(
		"Banana",
		SDL_WINDOWPOS_CENTERED,
		SDL_WINDOWPOS_CENTERED,
		window_data.width, window_data.height,
		SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL);

	// ToggleFullScreen(window);
	SDL_ShowCursor(SDL_DISABLE);
	// OutputSystemInfo();
	SDL_GLContext glContext = SDL_GL_CreateContext(window);
	glewExperimental = GL_TRUE;
	if (glewInit() != GLEW_OK) Error("glewInit");

	// Goes stuttery if we turn on vsync
	SDL_GL_SetSwapInterval((int)window_data.vsync);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glEnable(GL_CULL_FACE);
	glCullFace(GL_BACK);
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

	bool running = true;
	SDL_Event e;

	uint32 gameUpdateHz = 60;
	float32 targetSecondsPerFrame = 1.0f / (float32)gameUpdateHz;

	perfCountFreq = SDL_GetPerformanceFrequency();
	uint64 lastCounter = GetWallClock();

	GameMemory game_memory = { 0 };
	game_memory.size = Megabytes(64);
	game_memory.memory = SDL_malloc(game_memory.size);

	EditorMemory editor_memory = { 0 };
	editor_memory.size = Megabytes(64);
	editor_memory.memory = SDL_malloc(editor_memory.size);

	RenderContext render_context = {};
	render_context.diffuse = CreateShader("assets/shaders/diffuse.vert", "assets/shaders/diffuse.frag");
	InitializeContext(&render_context);

	VoxelRenderContext voxel_render_context = {};
	voxel_render_context.diffuse = CreateShader("assets/shaders/voxels.vert", "assets/shaders/voxels.frag");
	InitializeVoxelContext(&voxel_render_context);

	InputData input = { };
	input.window = window;

	UIContext ui_context = { 0 };
	ui_context.input = &input;
	ui_context.render_context = &render_context;

	Mode mode = MODE_GAME;

	bool game_paused = false;

	while (running)
	{
		while (SDL_PollEvent(&e))
		{
			if (e.type == SDL_QUIT)
				running = false;
			if (e.type == SDL_WINDOWEVENT)
			{
				if (e.window.event == SDL_WINDOWEVENT_RESIZED)
				{
					FixViewport((int)e.window.data1, (int)e.window.data2, &window_data);
				}
			}
			if (e.type == SDL_KEYDOWN)
			{
				SDL_Scancode key = e.key.keysym.scancode;
				input.keyboard_state[key] = true;
				if (key == SDL_SCANCODE_ESCAPE)
					running = false;
				if (key == SDL_SCANCODE_F12)
					window_data.vsync = !window_data.vsync;
				if (key == SDL_SCANCODE_F11)
					ToggleFullScreen(window, &window_data);
				if (key == SDL_SCANCODE_F10)
				{
					if (mode == MODE_GAME)
					{
						game_paused = true;
						mode = MODE_EDITOR;
					}
					else
					{
						mode = MODE_GAME;
						game_paused = false;
					}
				}
			}
			if (e.type == SDL_KEYUP)
			{
				SDL_Scancode key = e.key.keysym.scancode;
				input.keyboard_state[key] = false;
			}
			if (e.type == SDL_MOUSEMOTION)
			{
				input.mouse_pos.x = (((float)window_data.target_width / (float)window_data.vp_width) 
					* ((float)e.motion.x - window_data.vp_x));
				input.mouse_pos.y = (((float)window_data.target_height / (float)window_data.vp_height) 
					* ((float)e.motion.y - window_data.vp_y));
			}
			if (e.type == SDL_MOUSEBUTTONDOWN)
			{
				if (e.button.button == SDL_BUTTON_LEFT)
					input.mb_left = true;
				if (e.button.button == SDL_BUTTON_RIGHT)
					input.mb_right = true;
				if (e.button.button == SDL_BUTTON_MIDDLE)
					input.mb_middle = true;
			}
			if (e.type == SDL_MOUSEBUTTONUP)
			{
				if (e.button.button == SDL_BUTTON_LEFT)
					input.mb_left = false;
				if (e.button.button == SDL_BUTTON_RIGHT)
					input.mb_right = false;
				if (e.button.button == SDL_BUTTON_MIDDLE)
					input.mb_middle = false;
			}
		}

		float32 delta = 1.0f / (float32)gameUpdateHz;

		GameUpdateAndRender(&game_memory, &input, &render_context, &voxel_render_context, 
			&window_data, game_paused, delta);

		uint64 workCounter = GetWallClock();
		float32 workSecondsElapsed = GetSecondsElapsed(lastCounter, workCounter);
		// Dont include this in frametime
		if (mode == MODE_EDITOR)
			EditorUpdateAndRender(&editor_memory, &input, &render_context, &ui_context, delta);

		float32 secondsElapsedForFrame = workSecondsElapsed;
		if (secondsElapsedForFrame < targetSecondsPerFrame)
		{
			uint32 sleepMS = (uint32)((1000.0f * (targetSecondsPerFrame - secondsElapsedForFrame)) - 1);
			if (sleepMS > 0)
				SDL_Delay(sleepMS);
			while (secondsElapsedForFrame < targetSecondsPerFrame)
			{
				secondsElapsedForFrame = GetSecondsElapsed(lastCounter, GetWallClock());
			}
		}
		else
		{
			// Error("Missed Frame Rate");
		}

		uint64 endCounter = GetWallClock();
		float64 msPerFrame = 1000.0f * GetSecondsElapsed(lastCounter, endCounter);
		lastCounter = endCounter;

		// Debug Render
		BeginRenderer(&render_context);

		std::string s = "FRAMETIME " + std::to_string(msPerFrame) + " VSYNC " + std::to_string(window_data.vsync);
		RenderString(&render_context, 40.0f, 40.0f, s.c_str(), 0.0f);


		EndRenderer();

		SDL_GL_SwapWindow(window);
		input.prev_keyboard_state = input.keyboard_state;
		input.mb_left_prev = input.mb_left;
		input.mb_right_prev = input.mb_right;
		input.mb_middle_prev = input.mb_middle;
	}
	UnloadContext(&render_context);
	UnloadVoxelContext(&voxel_render_context);
	SDL_free(game_memory.memory);

	SDL_GL_DeleteContext(glContext);
	SDL_DestroyWindow(window);
	SDL_Quit();
	return(0);
}
Esempio n. 3
0
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	LPSTR lpCmdLine, int nCmdShow)
{
	GameState gameState = {};
	gameState.RenderState = 0;
	gameState.State = 1;
	gameState.PlayerX = 200.0;
	gameState.PlayerY = 450.0;

	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
	glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

	GLFWwindow* window = glfwCreateWindow(gameState.ScreenWidth, gameState.ScreenHeight, "Neighbors", NULL, NULL);
	glfwMakeContextCurrent(window);

	glewExperimental = GL_TRUE; 

	glewInit();
	glGetError();

	glfwSetKeyCallback(window, processWindowsCallback);

	// OpenGL configuration
	glViewport(0, 0, gameState.ScreenWidth, gameState.ScreenHeight); // Where in the window to render.
	glEnable(GL_CULL_FACE);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	// Load shaders
	ResourceManager::LoadShader("shaders/sprite.vs", "shaders/sprite.frag", nullptr, "sprite");
	// Configure shaders
	glm::mat4 projection = glm::ortho(0.0f, static_cast<GLfloat>(gameState.ScreenWidth),
		static_cast<GLfloat>(gameState.ScreenHeight), 0.0f, -1.0f, 1.0f);
	ResourceManager::GetShader("sprite").Use().SetInteger("image", 0);
	ResourceManager::GetShader("sprite").SetMatrix4("projection", projection);
	// Set render-specific controls
	Renderer = new SpriteRenderer(ResourceManager::GetShader("sprite"));
	AnimateRenderer = new AnimatedSpriteRenderer(ResourceManager::GetShader("sprite"));
	// Load textures
	ResourceManager::LoadTexture("textures/download.png", GL_TRUE, "face");
	ResourceManager::LoadTexture("textures/download.jpg", GL_TRUE, "other");
	ResourceManager::LoadTexture("textures/grass.png", GL_TRUE, "grass");
	ResourceManager::LoadTexture("textures/floor.png", GL_TRUE, "floor");
	ResourceManager::LoadTexture("textures/back_wall.png", GL_TRUE, "backwall");
	ResourceManager::LoadSpriteSheet("textures/sonic.png", GL_TRUE, "sonic");

	RenderList List;

	/* Loop until the user closes the window */
	while (!glfwWindowShouldClose(window))
	{
		// Clear IsDowns to false for incoming input and update WasDown's.
		for (int ButtonIndex = 0; ButtonIndex < ArrayCount(GlobalInput.Controller.Buttons); ButtonIndex++)
		{
			GlobalInput.Controller.Buttons[ButtonIndex].WasDown = GlobalInput.Controller.Buttons[ButtonIndex].IsDown;
			GlobalInput.Controller.Buttons[ButtonIndex].IsDown = false;
		}

		// Controller input handeling.
		if (glfwJoystickPresent(GLFW_JOYSTICK_1))
		{
			int countButtons;
			const unsigned char *button = glfwGetJoystickButtons(GLFW_JOYSTICK_1, &countButtons);
			for (int i = 0; i < countButtons; i++)
			{
				if (button[i] == GLFW_PRESS)
				{
					GlobalInput.Controller.Buttons[i].IsDown = true;
				}
			}

			int countAxes;
			const float *axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1, &countAxes);
			for (int i = 0; i < countAxes; i++)
			{
				GlobalInput.Controller.Axes[i] = axes[i];
			}
		}

		/* Poll for and process events */
		glfwPollEvents();
		if (gameState.State == 0)
			glfwSetWindowShouldClose(window, 1);

		/* Render here */

		GameUpdateAndRender(&gameState, &GlobalInput, &List);

		float cameraPosX = gameState.PlayerX - 500;
		float cameraPosY = gameState.PlayerY - 400;

		glm::mat4 projection = glm::ortho(cameraPosX, cameraPosX + static_cast<GLfloat>(gameState.ScreenWidth),
			cameraPosY + static_cast<GLfloat>(gameState.ScreenHeight), cameraPosY, -1.0f, 1.0f);
		ResourceManager::GetShader("sprite").Use().SetInteger("image", 0);
		ResourceManager::GetShader("sprite").SetMatrix4("projection", projection);

		glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);

		while (!List.isEmpty)
		{
			RenderObject * obj = List.Pop();
			Renderer->DrawSprite(ResourceManager::GetTexture(obj->name),
				obj->position, obj->scale, 0.0f, obj->color);
			free(obj);
		}

		AnimateRenderer->DrawSprite(ResourceManager::GetSpriteSheet("sonic"), glm::vec2(cameraPosX, cameraPosY), glm::vec2(64, 72), 0.0f, glm::vec3(1.0f, 1.0f, 1.0f), gameState.RenderState);

		/* Swap front and back buffers */
		glfwSwapBuffers(window);
	}

	glfwTerminate();
	return 0;
}