Пример #1
0
void bufferPlayerBow(Player *p, QuadBuffer *qb) {
  Data *data;
  Quad *q;
  float height;
  float ex, ey, sx, sy;
  int bdist;
  float white[] = { 1.0, 1.0, 1.0, 1.0 };

  data = p->data;
  height = data->trail_height;
  if(height <= 0) return;

  q = getNextQuad(qb);
  q->type = QUAD_COLOR;
  glShadeModel(GL_SMOOTH);

  if(PLAYER_IS_ACTIVE(p)  && game2->settingsCache.show_model == 1) {
    q->type |= QUAD_TEXTURE | QUAD_TEX_MODULATE | QUAD_ALPHA_TEST;
    q->texture_id = game->screen->textures[TEX_TRAIL];
  }

  bdist = (game2->settingsCache.show_model) &&
	   PLAYER_IS_ACTIVE(p) ? 2 : 3;

  sx = getSegmentEndX(data->trail, data, 0);
  sy = getSegmentEndY(data->trail, data, 0);

  ex = getSegmentEndX(data->trail, data, bdist);
  ey = getSegmentEndY(data->trail, data, bdist);

  /* hacked texture coordinates to avoid bleeding on some cards */
#define ONE 0.98
#define ZERO 0.02
  q_setColor4fv(q, 0, white);
  q_setTexCoord2f(q, 0, ZERO, ZERO);
  q_setVertex3f(q, 0, sx, sy, 0.0);

  q_setColor4fv(q, 1, white);
  q_setTexCoord2f(q, 1, ZERO, ONE);
  q_setVertex3f(q, 1, sx, sy, height);

  q_setColor4fv(q, 2, p->pColorDiffuse);
  q_setTexCoord2f(q, 2, ONE, ONE);
  q_setVertex3f(q, 2, ex, ey, height);

  q_setColor4fv(q, 3, p->pColorDiffuse);
  q_setTexCoord2f(q, 3, ONE, ZERO);
  q_setVertex3f(q, 3, ex, ey, 0.0);

}
Пример #2
0
void doCrashPlayer(GameEvent *e) {
	int j;

	Audio_CrashPlayer(e->player);
	Audio_StopEngine(e->player);

	for(j = 0; j < game->players; j++) 
		if(j != e->player && PLAYER_IS_ACTIVE(&(game->player[j])))
			game->player[j].data->score++;

	game->player[e->player].data->speed = SPEED_CRASHED;
}
Пример #3
0
void bowGeometry(Player *pPlayer, PlayerVisual *pV,
								 TrailMesh *pMesh, int *pvOffset, int *piOffset) {
	Data *pData = pPlayer->data;
	segment2 s;
	int bdist = PLAYER_IS_ACTIVE(pPlayer) ? 2 : 3;
	int i;
	int vOffset = *pvOffset; int iOffset = *piOffset;

	s.vStart.v[0] = getSegmentEndX( pData, 0 );
	s.vStart.v[1] = getSegmentEndY( pData, 0 );
	s.vDirection.v[0] = getSegmentEndX( pData, bdist ) - s.vStart.v[0];
	s.vDirection.v[1] = getSegmentEndY( pData, bdist ) - s.vStart.v[1];

	for(i = 0; i < 10; i++) {
		float t = i * 1.0f / 10;
		float fTop = sqrtf(1 - t*t);
		float fFloor = (t < 0.6f) ? 0 : 0.5f * (t - 0.6f);
		if(fTop < 0.3f) fTop = 0.3f;
		
		storeVertex(pMesh, vOffset, &s, t, 
								fFloor * pPlayer->data->trail_height, 
								fTop * pPlayer->data->trail_height, 
								DECAL_WIDTH, 0);
		storeColor(pMesh, vOffset, pV, COLOR_BRIGHT);
		vOffset += 2;
		if(i) {
			storeIndices(pMesh, iOffset, vOffset - 4);
			iOffset += 6;
		}
	}
	storeVertex(pMesh, vOffset, &s, 1, 
							0.2f * pData->trail_height, 0.3f * pData->trail_height, 
							DECAL_WIDTH, 0);
	storeColor(pMesh, vOffset, pV, COLOR_CYCLE);
	vOffset += 2;
	storeIndices(pMesh, iOffset, vOffset - 4);

	pMesh->iUsed += iOffset - *piOffset;
	*piOffset = iOffset;
	*pvOffset = vOffset;
}
Пример #4
0
void keyGame(int state, int k, int x, int y)
{
  int i;

	if(state == SYSTEM_KEYSTATE_DOWN) {
		switch (k) {
			/* case 'q': SystemExit(); return; */
		case 27:
			game->pauseflag = PAUSE_GAME_SUSPENDED;
			nebu_System_ExitLoop(RETURN_GAME_ESCAPE);
			return;
		case ' ':
			game->pauseflag = PAUSE_GAME_SUSPENDED;
			nebu_System_ExitLoop(RETURN_GAME_PAUSE);
			return;
		case SYSTEM_KEY_F1: changeDisplay(0); return;
		case SYSTEM_KEY_F2: changeDisplay(1); return;
		case SYSTEM_KEY_F3: changeDisplay(2); return;
		case SYSTEM_KEY_F4: changeDisplay(3); return;

		// somehow, this breaks the 'keys' array, and saving
		// at the end of the game fails
		// case SYSTEM_KEY_F5: saveSettings(); return;

		case SYSTEM_KEY_F10: nextCameraType(); return;
		case SYSTEM_KEY_F11: doBmpScreenShot(gScreen); return;
		case SYSTEM_KEY_F12: doPngScreenShot(gScreen); return;

		case SYSTEM_KEY_F6: console_Seek(-1); return;
		case SYSTEM_KEY_F7: console_Seek(1); return;
    /* toggle lighting
  case SYSTEM_KEY_F6: 
      setSettingi("light_cycles", !game->settings->light_cycles);
      return;
    */
		}
	}
	for( i = 0; i < game->players; i++) {
		if(PLAYER_IS_ACTIVE(&game->player[i]) &&
			 !game->player[i].ai->active) {
			int key;
			if(state == SYSTEM_KEYSTATE_DOWN) { 
				scripting_RunFormat("return settings.keys[%d].left", i + 1);
				scripting_GetIntegerResult( &key );
				if(key == k) {
					createEvent(i, EVENT_TURN_LEFT);
					return;
				}
				scripting_RunFormat("return settings.keys[%d].right", i + 1);
				scripting_GetIntegerResult( &key );
				if(key == k) {
					createEvent(i, EVENT_TURN_RIGHT);
					return;
				}
			}
			// deal with glance keys
			scripting_RunFormat("return settings.keys[%d].glance_left", i + 1);
			scripting_GetIntegerResult( &key );
			if(key == k) {
				if(state == SYSTEM_KEYSTATE_DOWN) {
					// printf("glance left down\n");
					game->player[i].camera->movement[CAM_PHI_OFFSET] = PI / 2.0f;
				}	else {
					// printf("glance left up\n");
					game->player[i].camera->movement[CAM_PHI_OFFSET] = 0;
				}
				return;
			}
			// deal with glance keys
			scripting_RunFormat("return settings.keys[%d].glance_right", i + 1);
			scripting_GetIntegerResult( &key );
			if(key == k) {
				if(state == SYSTEM_KEYSTATE_DOWN) {
					// printf("glance right down\n");
					game->player[i].camera->movement[CAM_PHI_OFFSET] = - PI / 2.0f;
				} else {
					// printf("glance right up\n");
					game->player[i].camera->movement[CAM_PHI_OFFSET] = 0;
				}
				return;
			}
			// boost
			scripting_RunFormat("return settings.keys[%d].boost", i + 1);
			scripting_GetIntegerResult( &key );
			if(key == k) {
				if(state == SYSTEM_KEYSTATE_DOWN) {
					// printf("boost down\n");
					if(game->player[i].data->booster > getSettingf("booster_min"))
						game->player[i].data->boost_enabled = 1;
				} else {
					// printf("boost up\n");
					game->player[i].data->boost_enabled = 0;
				}
				return;
			}
			// wallbuster
			scripting_RunFormat("return settings.keys[%d].bust", i + 1);
			scripting_GetIntegerResult( &key );
			if(key == k) {
				if(state == SYSTEM_KEYSTATE_DOWN) {
					// printf("wall_buster down\n");
					if(game->player[i].data->wall_buster > getSettingf("wall_buster_min"))
						game->player[i].data->wall_buster_enabled = 1;
				} else {
					// printf("wall_buster up\n");
					game->player[i].data->wall_buster_enabled = 0;
				}
				return;
			}
		}
	}
	if(state == SYSTEM_KEYSTATE_DOWN) {
		displayMessage(TO_STDERR, "key '%s' (%d) is not bound", 
									 SystemGetKeyName(k), k);
	}
}
Пример #5
0
void Game_Idle(void) {
  List *l;
  List *p;
  int i;
  int dt;
  int t;

	switch(game2->mode) {
	case GAME_SINGLE:
#ifdef RECORD
	case GAME_SINGLE_RECORD:
#endif
		/* check for fast finish */
    
		if (gSettingsCache.fast_finish == 1) {
			int factors[4] = { 4, 6, 12, 25 };
			int threshold[4] = { 0, 300, 600, 800 };
			int factor = 1;
			for(i = 0; i < 4; i++) {
				if(game2->rules.grid_size > threshold[i])
					factor = factors[i];
			}
			for (i = 0; i < game->players; i++) {
				if (game->player[i].ai->active != AI_COMPUTER &&
						gPlayerVisuals[i].exp_radius < EXP_RADIUS_MAX) {
					factor = 1;
				}
			}
			dt = game2->time.dt * factor;
		} else { 
			dt = game2->time.dt;
		}

		while(dt > 0) {
			if(dt > PHYSICS_RATE) t = PHYSICS_RATE;
			else t = dt;

			/* run AI */
			for(i = 0; i < game->players; i++)
				if(game->player[i].ai != NULL)
					if(game->player[i].ai->active == AI_COMPUTER &&
						 PLAYER_IS_ACTIVE(&game->player[i])) {
						doComputer(i, 0);
					}

			/* process any outstanding events (turns, etc) */
			for(p = &(game2->events); p->next != NULL; p = p->next) {
				if(processEvent((GameEvent*) p->data)) return;
			}

			/* free events */
			p = game2->events.next;
			while(p != NULL) {
				l = p;
				p = p->next;
				free(l);
			}
			game2->events.next = NULL;

			l = doMovement(1, t); /* this can generate new events */
			if(l != NULL) {
				for(p = l; p->next != NULL; p = p->next) {
					if(processEvent((GameEvent*) p->data));
				}

			}
			/* free list  */
			p = l;
			while(p != NULL) {
				l = p;
				p = p->next;
				free(l);
			}
			dt -= PHYSICS_RATE;
		}
		break;
#ifdef RECORD
	case GAME_PLAY_NETWORK:
		/* fall through to GAME_PLAY */
	case GAME_PLAY:
		getEvents(); 
		l = doMovement(0, game2->time.dt); /* this won't generate new events */
		if(l != NULL) {
			fprintf(stderr, "something is seriously wrong - ignoring events\n");
		}
		break;
#endif /* RECORD */
	}
    
	doCameraMovement();
	doRecognizerMovement();
}
Пример #6
0
/* game_loop() has been turned into a SDL based loop.
   The code for one iteration of the original game_loop is
   in game_loop_iter. */
static void
game_loop()
{
	/* FPS */
	int fps = 0;
	int fps_ema = 0;
	int fps_target = 25;
	const float ema_alpha = 0.003;

	int drag_button = 0;

	unsigned int last_down[3] = {0};
	unsigned int last_click[3] = {0};

	unsigned int current_ticks = SDL_GetTicks();
	unsigned int accum = 0;
	unsigned int accum_frames = 0;

	SDL_Event event;
	gui_event_t ev;

	game_loop_run = 1;
	while (game_loop_run) {
		if (SDL_PollEvent(&event)) {
			switch (event.type) {
			case SDL_MOUSEBUTTONUP:
				if (drag_button == event.button.button) {
					ev.type = GUI_EVENT_TYPE_DRAG_END;
					ev.x = event.button.x;
					ev.y = event.button.y;
					ev.button = drag_button;
					gui_object_handle_event((gui_object_t *)&interface, &ev);

					drag_button = 0;
				}

				ev.type = GUI_EVENT_TYPE_BUTTON_UP;
				ev.x = event.button.x;
				ev.y = event.button.y;
				ev.button = event.button.button;
				gui_object_handle_event((gui_object_t *)&interface, &ev);

				if (event.button.button <= 3 &&
				    current_ticks - last_down[event.button.button-1] < MOUSE_SENSITIVITY) {
					ev.type = GUI_EVENT_TYPE_CLICK;
					ev.x = event.button.x;
					ev.y = event.button.y;
					ev.button = event.button.button;
					gui_object_handle_event((gui_object_t *)&interface, &ev);

					if (current_ticks - last_click[event.button.button-1] < MOUSE_SENSITIVITY) {
						ev.type = GUI_EVENT_TYPE_DBL_CLICK;
						ev.x = event.button.x;
						ev.y = event.button.y;
						ev.button = event.button.button;
						gui_object_handle_event((gui_object_t *)&interface, &ev);
					}

					last_click[event.button.button-1] = current_ticks;
				}
				break;
			case SDL_MOUSEBUTTONDOWN:
				ev.type = GUI_EVENT_TYPE_BUTTON_DOWN;
				ev.x = event.button.x;
				ev.y = event.button.y;
				ev.button = event.button.button;
				gui_object_handle_event((gui_object_t *)&interface, &ev);

				if (event.button.button <= 3) last_down[event.button.button-1] = current_ticks;
				break;
			case SDL_MOUSEMOTION:
				if (drag_button == 0) {
					/* Move pointer normally. */
					interface_set_cursor(&interface, event.motion.x, event.motion.y);
				}

				for (int button = 1; button <= 3; button++) {
					if (event.motion.state & SDL_BUTTON(button)) {
						if (drag_button == 0) {
							drag_button = button;

							ev.type = GUI_EVENT_TYPE_DRAG_START;
							ev.x = event.motion.x;
							ev.y = event.motion.y;
							ev.button = drag_button;
							gui_object_handle_event((gui_object_t *)&interface, &ev);
						}

						ev.type = GUI_EVENT_TYPE_DRAG_MOVE;
						ev.x = event.motion.x;
						ev.y = event.motion.y;
						ev.button = drag_button;
						gui_object_handle_event((gui_object_t *)&interface, &ev);
						break;
					}
				}
				break;
			case SDL_KEYDOWN:
				if (event.key.keysym.sym == SDLK_q &&
				    (event.key.keysym.mod & KMOD_CTRL)) {
					game_loop_quit();
					break;
				}

				switch (event.key.keysym.sym) {
					/* Map scroll */
				case SDLK_UP: {
					viewport_t *viewport = interface_get_top_viewport(&interface);
					viewport_move_by_pixels(viewport, 0, -1);
				}
					break;
				case SDLK_DOWN: {
					viewport_t *viewport = interface_get_top_viewport(&interface);
					viewport_move_by_pixels(viewport, 0, 1);
				}
					break;
				case SDLK_LEFT: {
					viewport_t *viewport = interface_get_top_viewport(&interface);
					viewport_move_by_pixels(viewport, -1, 0);
				}
					break;
				case SDLK_RIGHT: {
					viewport_t *viewport = interface_get_top_viewport(&interface);
					viewport_move_by_pixels(viewport, 1, 0);
				}
					break;

					/* Panel click shortcuts */
				case SDLK_1: {
					panel_bar_t *panel = interface_get_panel_bar(&interface);
					panel_bar_activate_button(panel, 0);
				}
					break;
				case SDLK_2: {
					panel_bar_t *panel = interface_get_panel_bar(&interface);
					panel_bar_activate_button(panel, 1);
				}
					break;
				case SDLK_3: {
					panel_bar_t *panel = interface_get_panel_bar(&interface);
					panel_bar_activate_button(panel, 2);
				}
					break;
				case SDLK_4: {
					panel_bar_t *panel = interface_get_panel_bar(&interface);
					panel_bar_activate_button(panel, 3);
				}
					break;
				case SDLK_5: {
					panel_bar_t *panel = interface_get_panel_bar(&interface);
					panel_bar_activate_button(panel, 4);
				}
					break;

					/* Game speed */
				case SDLK_PLUS:
				case SDLK_KP_PLUS:
					if (game.game_speed < 40) game.game_speed += 1;
					LOGI("main", "Game speed: %u", game.game_speed);
					break;
				case SDLK_MINUS:
				case SDLK_KP_MINUS:
					if (game.game_speed >= 1) game.game_speed -= 1;
					LOGI("main", "Game speed: %u", game.game_speed);
					break;
				case SDLK_0:
					game.game_speed = DEFAULT_GAME_SPEED;
					LOGI("main", "Game speed: %u", game.game_speed);
					break;
				case SDLK_p:
					if (game.game_speed == 0) game_pause(0);
					else game_pause(1);
					break;

					/* Audio */
				case SDLK_s:
					sfx_enable(!sfx_is_enabled());
					break;
				case SDLK_m:
					midi_enable(!midi_is_enabled());
					break;

					/* Misc */
				case SDLK_ESCAPE:
					if (BIT_TEST(interface.click, 7)) { /* Building road */
						interface_build_road_end(&interface);
					} else if (interface.clkmap != 0) {
						interface_close_popup(&interface);
					}
					break;

					/* Debug */
				case SDLK_g:
					interface.viewport.layers ^= VIEWPORT_LAYER_GRID;
					break;
				case SDLK_j: {
					int current = 0;
					for (int i = 0; i < 4; i++) {
						if (interface.player == game.player[i]) {
							current = i;
							break;
						}
					}

					for (int i = (current+1) % 4; i != current; i = (i+1) % 4) {
						if (PLAYER_IS_ACTIVE(game.player[i])) {
							interface.player = game.player[i];
							LOGD("main", "Switched to player %i.", i);
							break;
						}
					}
				}
					break;
				case SDLK_z:
					if (event.key.keysym.mod & KMOD_CTRL) {
						save_game(0);
					}
					break;

				default:
					break;
				}
				break;
			case SDL_QUIT:
				game_loop_quit();
				break;
			}
		}

		unsigned int new_ticks = SDL_GetTicks();
		int delta_ticks = new_ticks - current_ticks;
		current_ticks = new_ticks;

		accum += delta_ticks;
		while (accum >= TICK_LENGTH) {
			game_update();

			/* Autosave periodically */
			if ((game.const_tick % AUTOSAVE_INTERVAL) == 0 &&
			    game.game_speed > 0) {
				int r = save_game(1);
				if (r < 0) LOGW("main", "Autosave failed.");
			}

			/* FPS */
			fps = 1000*((float)accum_frames / accum);
			if (fps_ema > 0) fps_ema = ema_alpha*fps + (1-ema_alpha)*fps_ema;
			else if (fps > 0) fps_ema = fps;

			if ((game.const_tick % (10*TICKS_PER_SEC)) == 0) {
				LOGV("main", "FPS: %i", fps_ema);
			}

			accum -= TICK_LENGTH;
			accum_frames = 0;
		}

		/* Update and draw interface */
		interface_update(&interface);

		interface.flags &= ~BIT(4);
		interface.flags &= ~BIT(7);

		gui_object_redraw((gui_object_t *)&interface, game.frame);

		/* TODO very crude dirty marking algortihm: mark everything. */
		sdl_mark_dirty(0, 0, sdl_frame_get_width(game.frame),
			       sdl_frame_get_height(game.frame));

		/* Swap video buffers */
		sdl_swap_buffers();

		accum_frames += 1;

		/* Reduce framerate to target */
		if (fps_target > 0) {
			int delay = 0;
			if (fps_ema > 0) delay = (1000/fps_target) - (1000/fps_ema);
			if (delay > 0) SDL_Delay(delay);
		}
	}
}
Пример #7
0
void drawCam(int player) {
	int i;
	float up[3] = { 0, 0, 1 };
	Visual *d = & gPlayerVisuals[player].display;
	
	float reflectivity = getReflectivity();
	// compute shadow color based on glocal constant & reflectivity
	for(i = 0; i < 4; i++) 
		gCurrentShadowColor[i] = gShadowColor[i] * (1 - reflectivity);

	glColor3f(0.0, 1.0, 0.0);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	doPerspective(gSettingsCache.fov, (float) d->vp_w / (float) d->vp_h,
		gSettingsCache.znear, box2_Diameter(& game2->level->boundingBox) * 6.5f);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	{
		vec3 vLookAt;
		vec3 vTarget;
		matrix matRotate;

		vec3_Sub(&vLookAt, (vec3*)gPlayerVisuals[player].camera.target, (vec3*)gPlayerVisuals[player].camera.cam);
		vec3_Normalize(&vLookAt, &vLookAt);
		matrixRotationAxis(&matRotate, 90.0f * (float) gPlayerVisuals[player].camera.bIsGlancing, (vec3*)up);
		vec3_Transform(&vLookAt, &vLookAt, &matRotate);
		vec3_Add(&vTarget, (vec3*)gPlayerVisuals[player].camera.cam, &vLookAt);
		doLookAt(gPlayerVisuals[player].camera.cam, (float*)&vTarget, up);
	}

	glDisable(GL_LIGHTING); // initial config at frame start
	glDisable(GL_BLEND); // initial config at frame start

	// disable writes to alpha
	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);

	/* skybox */
	glDepthMask(GL_FALSE);
	glDisable(GL_DEPTH_TEST);

	drawSkybox( box2_Diameter( & game2->level->boundingBox ) * 2.5f );

	glDepthMask(GL_TRUE);
	glEnable(GL_DEPTH_TEST);
	/* skybox done */

	/* floor */ 
	if(reflectivity == 0) {
		// draw floor to fb and stencil (set to 1),
		// using alpha-blending
		// TODO: draw floor alpha to fb
		video_Shader_Setup(& gWorld->floor_shader);
		glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
		glStencilFunc(GL_ALWAYS, 1, 255);
		glEnable(GL_STENCIL_TEST);
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		nebu_Mesh_DrawGeometry( gWorld->floor );
		glDisable(GL_BLEND);
		glDisable(GL_STENCIL_TEST);
		video_Shader_Cleanup(& gWorld->floor_shader);
	} else {
		/* reflections */
		/* first draw reflector to stencil */
		/* and reflector alpha to fb */

		video_Shader_Setup(& gWorld->floor_shader);

		// store only reflector alpha in framebuffer
		glDepthMask(GL_FALSE);
		glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
		glStencilFunc(GL_ALWAYS, 1, 255);
		glEnable(GL_STENCIL_TEST);
		glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
		// glEnable(GL_ALPHA_TEST);
		// glAlphaFunc(GL_GREATER, 0.1f);

		nebu_Mesh_DrawGeometry( gWorld->floor );
		
		// glDisable(GL_ALPHA_TEST);
		glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
		glDepthMask(GL_TRUE);
		glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
		glStencilFunc(GL_EQUAL, 1, 255);

		video_Shader_Cleanup(& gWorld->floor_shader);
		
		/* then draw world & skybox reflected, where stencil is set */
		/* protect the alpha buffer */
		glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);

		isRenderingReflection = 1; // hack: reverse lighting
		glPushMatrix();
		glScalef(1,1,-1);
		glCullFace(GL_FRONT); // reverse culling
		// clip skybox & world to floor plane
		glEnable(GL_CLIP_PLANE0);
		{
			double plane[] = { 0, 0, 1, 0 };
			glClipPlane(GL_CLIP_PLANE0, plane);
		}

		drawSkybox( box2_Diameter( & game2->level->boundingBox ) * 2.5f );
		drawWorld(player);

		glDisable(GL_CLIP_PLANE0);
		glCullFace(GL_BACK);
		glPopMatrix();
		isRenderingReflection = 0; // hack: normal lighting

		/* then blend the skybox into the scene, where stencil is set */
		/* modulate with the destination alpha */
		glDisable(GL_DEPTH_TEST);
		glEnable(GL_BLEND);
		glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA);
		drawSkybox( box2_Diameter( & game2->level->boundingBox ) * 2.5f );
		glDisable(GL_BLEND);
		glEnable(GL_DEPTH_TEST);
		
		/* then blend reflector into the scene */
		glDisable(GL_DEPTH_TEST);
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

		glColor4f(1, 1, 1, 1 - reflectivity);

		glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
		glStencilFunc(GL_ALWAYS, 1, 255);

		video_Shader_Setup(& gWorld->floor_shader);
		nebu_Mesh_DrawGeometry( gWorld->floor );
		video_Shader_Cleanup(& gWorld->floor_shader);

		glDisable(GL_STENCIL_TEST);
		glDisable(GL_BLEND);
		glEnable(GL_DEPTH_TEST);
	}
	/* floor done */

	/* planar shadows */
	glDepthMask(GL_FALSE);
	glDisable(GL_DEPTH_TEST);

	if(reflectivity != 1) // there are no shadows on perfect mirrors
		drawPlanarShadows(player);

	glDepthMask(GL_TRUE);
	glEnable(GL_DEPTH_TEST);
	/* planar shadows done */

	drawWorld(player);

	/* transparent stuff */
	/* draw the glow around the other players: */
	if (gSettingsCache.show_glow == 1) {
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

		for (i = 0; i < game->players; i++)
		{
			if (i != player && PLAYER_IS_ACTIVE(game->player + i))
			{
				drawGlow(&gPlayerVisuals[player].camera, game->player + i, gPlayerVisuals + i,
					d, TRAIL_HEIGHT * 4);
			}
		}
		glDisable(GL_BLEND);
	}
}
Пример #8
0
/* game_loop() has been turned into a SDL based loop.
   The code for one iteration of the original game_loop is
   in game_loop_iter. */
static void
game_loop()
{
	/* FPS */
	int fps = 0;
	float fps_ema = 0;
	int fps_target = 25;
	/* TODO: compute alpha dynamically based on frametime */
	const float ema_alpha = 0.07;

	const int frametime_target = 1000 / fps_target; /* in milliseconds */
	int last_frame = SDL_GetTicks();

	int drag_button = 0;

	unsigned int last_down[3] = {0};
	unsigned int last_click[3] = {0};

	unsigned int current_ticks = SDL_GetTicks();
	unsigned int accum = 0;

	SDL_Event event;
	gui_event_t ev;

	game_loop_run = 1;
	while (game_loop_run) {
		while (SDL_PollEvent(&event)) {
			switch (event.type) {
			case SDL_MOUSEBUTTONUP:
				if (drag_button == event.button.button) {
					ev.type = GUI_EVENT_TYPE_DRAG_END;
					ev.x = event.button.x;
					ev.y = event.button.y;
					ev.button = drag_button;
					gui_object_handle_event((gui_object_t *)&interface, &ev);

					drag_button = 0;
				}

				ev.type = GUI_EVENT_TYPE_BUTTON_UP;
				ev.x = event.button.x;
				ev.y = event.button.y;
				ev.button = event.button.button;
				gui_object_handle_event((gui_object_t *)&interface, &ev);

				if (event.button.button <= 3 &&
				    current_ticks - last_down[event.button.button-1] < MOUSE_SENSITIVITY) {
					ev.type = GUI_EVENT_TYPE_CLICK;
					ev.x = event.button.x;
					ev.y = event.button.y;
					ev.button = event.button.button;
					gui_object_handle_event((gui_object_t *)&interface, &ev);

					if (current_ticks - last_click[event.button.button-1] < MOUSE_SENSITIVITY) {
						ev.type = GUI_EVENT_TYPE_DBL_CLICK;
						ev.x = event.button.x;
						ev.y = event.button.y;
						ev.button = event.button.button;
						gui_object_handle_event((gui_object_t *)&interface, &ev);
					}

					last_click[event.button.button-1] = current_ticks;
				}
				break;
			case SDL_MOUSEBUTTONDOWN:
				ev.type = GUI_EVENT_TYPE_BUTTON_DOWN;
				ev.x = event.button.x;
				ev.y = event.button.y;
				ev.button = event.button.button;
				gui_object_handle_event((gui_object_t *)&interface, &ev);

				if (event.button.button <= 3) last_down[event.button.button-1] = current_ticks;
				break;
			case SDL_MOUSEMOTION:
				if (drag_button == 0) {
					/* Move pointer normally. */
					interface_set_cursor(&interface, event.motion.x, event.motion.y);
				}

				for (int button = 1; button <= 3; button++) {
					if (event.motion.state & SDL_BUTTON(button)) {
						if (drag_button == 0) {
							drag_button = button;

							ev.type = GUI_EVENT_TYPE_DRAG_START;
							ev.x = event.motion.x;
							ev.y = event.motion.y;
							ev.button = drag_button;
							gui_object_handle_event((gui_object_t *)&interface, &ev);
						}

						ev.type = GUI_EVENT_TYPE_DRAG_MOVE;
						ev.x = event.motion.x;
						ev.y = event.motion.y;
						ev.button = drag_button;
						gui_object_handle_event((gui_object_t *)&interface, &ev);
						break;
					}
				}
				break;
			case SDL_KEYDOWN:
				if (event.key.keysym.sym == SDLK_q &&
				    (event.key.keysym.mod & KMOD_CTRL)) {
					game_loop_quit();
					break;
				}

				switch (event.key.keysym.sym) {
					/* Map scroll */
				case SDLK_UP: {
					viewport_t *viewport = interface_get_top_viewport(&interface);
					viewport_move_by_pixels(viewport, 0, -1);
				}
					break;
				case SDLK_DOWN: {
					viewport_t *viewport = interface_get_top_viewport(&interface);
					viewport_move_by_pixels(viewport, 0, 1);
				}
					break;
				case SDLK_LEFT: {
					viewport_t *viewport = interface_get_top_viewport(&interface);
					viewport_move_by_pixels(viewport, -1, 0);
				}
					break;
				case SDLK_RIGHT: {
					viewport_t *viewport = interface_get_top_viewport(&interface);
					viewport_move_by_pixels(viewport, 1, 0);
				}
					break;

					/* Panel click shortcuts */
				case SDLK_1: {
					panel_bar_t *panel = interface_get_panel_bar(&interface);
					panel_bar_activate_button(panel, 0);
				}
					break;
				case SDLK_2: {
					panel_bar_t *panel = interface_get_panel_bar(&interface);
					panel_bar_activate_button(panel, 1);
				}
					break;
				case SDLK_3: {
					panel_bar_t *panel = interface_get_panel_bar(&interface);
					panel_bar_activate_button(panel, 2);
				}
					break;
				case SDLK_4: {
					panel_bar_t *panel = interface_get_panel_bar(&interface);
					panel_bar_activate_button(panel, 3);
				}
					break;
				case SDLK_5: {
					panel_bar_t *panel = interface_get_panel_bar(&interface);
					panel_bar_activate_button(panel, 4);
				}
					break;

				case SDLK_TAB:
					if (event.key.keysym.mod & KMOD_SHIFT) {
						interface_return_from_message(&interface);
					} else {
						interface_open_message(&interface);
					}
					break;

					/* Game speed */
				case SDLK_PLUS:
				case SDLK_KP_PLUS:
					if (game.game_speed < 40) game.game_speed += 1;
					LOGI("main", "Game speed: %u", game.game_speed);
					break;
				case SDLK_MINUS:
				case SDLK_KP_MINUS:
					if (game.game_speed >= 1) game.game_speed -= 1;
					LOGI("main", "Game speed: %u", game.game_speed);
					break;
				case SDLK_0:
					game.game_speed = DEFAULT_GAME_SPEED;
					LOGI("main", "Game speed: %u", game.game_speed);
					break;
				case SDLK_p:
					if (game.game_speed == 0) game_pause(0);
					else game_pause(1);
					break;

					/* Audio */
				case SDLK_s:
					sfx_enable(!sfx_is_enabled());
					break;
				case SDLK_m:
					midi_enable(!midi_is_enabled());
					break;

					/* Video */
				case SDLK_f:
					if (event.key.keysym.mod & KMOD_CTRL) {
						sdl_set_fullscreen(!sdl_is_fullscreen());
					}
					break;

					/* Misc */
				case SDLK_ESCAPE:
					if (GUI_OBJECT(&interface.popup)->displayed) {
						interface_close_popup(&interface);
					} else if (interface.building_road) {
						interface_build_road_end(&interface);
					}
					break;

					/* Debug */
				case SDLK_g:
					interface.viewport.layers ^= VIEWPORT_LAYER_GRID;
					break;
				case SDLK_b:
					interface.viewport.show_possible_build = !interface.viewport.show_possible_build;
					break;
				case SDLK_j: {
					int current = 0;
					for (int i = 0; i < 4; i++) {
						if (interface.player == game.player[i]) {
							current = i;
							break;
						}
					}

					for (int i = (current+1) % 4; i != current; i = (i+1) % 4) {
						if (PLAYER_IS_ACTIVE(game.player[i])) {
							interface.player = game.player[i];
							LOGD("main", "Switched to player %i.", i);
							break;
						}
					}
				}
					break;
				case SDLK_z:
					if (event.key.keysym.mod & KMOD_CTRL) {
						save_game(0);
					}
					break;
				case SDLK_F10:
					interface_open_game_init(&interface);
					break;

				default:
					break;
				}
				break;
			case SDL_VIDEORESIZE:
				sdl_set_resolution(event.resize.w, event.resize.h, 0);

				frame_t *screen = sdl_get_screen_frame();
				int width = sdl_frame_get_width(screen);
				int height = sdl_frame_get_height(screen);

				screen_frame.clip.w = width;
				screen_frame.clip.h = height;

				gui_object_set_size((gui_object_t *)&interface, width, height);
				break;
			case SDL_QUIT:
				game_loop_quit();
				break;
			}
		}

		unsigned int new_ticks = SDL_GetTicks();
		int delta_ticks = new_ticks - current_ticks;
		current_ticks = new_ticks;

		/* Update FPS EMA per frame */
		fps = 1000*(1.0 / (float)delta_ticks);
		if (fps_ema > 0) fps_ema = ema_alpha*fps + (1-ema_alpha)*fps_ema;
		else if (fps > 0) fps_ema = fps;

		accum += delta_ticks;
		while (accum >= TICK_LENGTH) {
			game_update();

			/* Autosave periodically */
			if ((game.const_tick % AUTOSAVE_INTERVAL) == 0 &&
			    game.game_speed > 0) {
				int r = save_game(1);
				if (r < 0) LOGW("main", "Autosave failed.");
			}

			/* Print FPS */
			if ((game.const_tick % (10*TICKS_PER_SEC)) == 0) {
				LOGV("main", "FPS: %i", (int)fps_ema);
			}

			accum -= TICK_LENGTH;
		}

		/* Update and draw interface */
		interface_update(&interface);

		gui_object_redraw(GUI_OBJECT(&interface), game.frame);

		/* TODO very crude dirty marking algortihm: mark everything. */
		sdl_mark_dirty(0, 0, sdl_frame_get_width(game.frame),
			       sdl_frame_get_height(game.frame));

		/* Swap video buffers */
		sdl_swap_buffers();

		/* Reduce framerate to target if we finished too fast */
		int now = SDL_GetTicks();
		int frametime_spent = now - last_frame;

		if (frametime_spent < frametime_target) {
			SDL_Delay(frametime_target - frametime_spent);
		}
		last_frame = SDL_GetTicks();
	}
}