Пример #1
0
void Sound_setup(void) {
  printf("[sound] initializing sound\n");

  Audio_Init();
  Sound_loadFX();
  Sound_setFxVolume(getSettingf("fxVolume"));
  Sound_reloadTrack();
  Sound_setMusicVolume(getSettingf("musicVolume"));
  Audio_Start();
}
Пример #2
0
void drawHUD(Player *p, PlayerVisual *pV) {
	char temp[1024];
	char pause_message[128];
	float pause_color[3];

	getPauseString(pause_message, pause_color);

	glDisable(GL_DEPTH_TEST);
	glDepthMask(GL_FALSE);
	rasonly(&pV->display);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	/*
		drawHud: parameters
		- Viewport Width
		- Viewport Height
		- Score (or -1 if disabled)
		- AI status ("computer player" or "")
		- Speed digital (absolute value)
		- Speed analog (1 for default speed, > 1 during acceleration)
		- Booster value (between 0 and 1)
		- fps
		- pause message
		- pause message r,g,b colors
	*/

	sprintf(temp, "drawHUD(%d, %d, %d, \"%s\", %f, %f, %f, %f, %d, \"%s\", %f, %f, %f)",
		pV->display.vp_w, pV->display.vp_h,
		gSettingsCache.show_scores ? p->data->score : -1,
		gSettingsCache.show_ai_status ?
		(p->ai->active ? "AI_COMPUTER" : "") : "",
		p->data->speed,
		p->data->speed / (2 * game2->rules.speed),
		p->data->booster / getSettingf("booster_max"),
		p->data->wall_buster / getSettingf("wall_buster_max"),
		getFPS(),
		pause_message,
		pause_color[0],
		pause_color[1],
		pause_color[2]
		);

	glScalef(pV->display.vp_w / 1024.0f, pV->display.vp_w / 1024.0f, 1.0f);
	// fprintf(stderr, "%s\n", temp);
	scripting_Run(temp);

	glDisable(GL_BLEND);
	glDepthMask(GL_TRUE);
	glEnable(GL_DEPTH_TEST);
}
Пример #3
0
void initData(void) {
	/* lasttime = SystemGetElapsedTime(); */
	game->pauseflag = PAUSE_GAME_RUNNING;

	game2->rules.speed = getSettingf("speed");
	game2->rules.eraseCrashed = getSettingi("erase_crashed");
	game2->rules.grid_size = getSettingi("grid_size");

	game2->grid.width = game2->rules.grid_size;
	game2->grid.height = game2->rules.grid_size;

	/* time management */
	game2->time.lastFrame = 0;
	game2->time.current = 0;
	game2->time.offset = SystemGetElapsedTime();
	/* TODO: fix that */
	game2->players = game->players;
	/* event management */
	game2->events.next = NULL;
	/* TODO: free any old events that might have gotten left */

  resetVideoData();
	resetPlayerData();

  initWalls();
}
Пример #4
0
void video_LoadLevel(void) {
    printf("[status] load/reload video data\n");

    if(gWorld)
        video_FreeLevel(gWorld);
    gWorld = video_CreateLevel();
    if(gWorld->scalable)
        video_ScaleLevel(gWorld, getSettingf("grid_size"));
}
Пример #5
0
void checkSettings(void) {
  /* sanity check: speed */
  if(getSettingf("speed") <= 0) {
    fprintf(stderr, "[gltron] sanity check failed: speed = %.2ff\n",
	    getSettingf("speed"));
    setSettingf("speed", 6.0);
    fprintf(stderr, "[gltron] reset speed: speed = %.2f\n",
	    getSettingf("speed"));
  }
#ifndef NEW_LEVEL
  if(getSettingi("grid_size") % 8) {
    fprintf(stderr, "[gltron] sanity check failed: grid_size %% 8 != 0: "
	    "grid_size = %d\n", getSettingi("grid_size"));
    setSettingi("grid_size", 240);
    fprintf(stderr, "[gltron] reset grid_size: grid_size = %d\n",
	    getSettingi("grid_size"));
  }
#endif
}
Пример #6
0
static float getReflectivity() {
	float reflectivity = getSettingf("reflection");
	if(reflectivity < 0)
		reflectivity = getVideoSettingf("reflection");

	// need stencil for reflections
	if(gSettingsCache.use_stencil == 0)
		reflectivity = 0;
	return reflectivity;
}
Пример #7
0
int applyBooster(int player, int dt) {
	Data *data = game->player[player].data;
	if(data->booster > 0 && data->boost_enabled) {
		float boost = getSettingf("booster_use") * dt / 1000.0f;
		if(boost > data->booster) {
			boost = data->booster;
			data->boost_enabled = 0;
		}
		data->speed += boost;
		data->booster -= boost;
		return 1;
	}
	else {
		float booster_max = getSettingf("booster_max");
		if(data->booster < booster_max) {
			data->booster += getSettingf("booster_regenerate") * dt / 1000.0f;
			if(data->booster > booster_max)
				data->booster = booster_max;
		}
		return 0;
	}
}
Пример #8
0
void updateSettingsCache(void) {
  /* cache lua settings that don't change during play */
  gSettingsCache.use_stencil = getSettingi("use_stencil");
  gSettingsCache.show_scores = getSettingi("show_scores");
  gSettingsCache.show_ai_status = getSettingi("show_ai_status");
  gSettingsCache.ai_level = getSettingi("ai_level");
  gSettingsCache.show_fps = getSettingi("show_fps");
  gSettingsCache.show_console = getSettingi("show_console");
  gSettingsCache.softwareRendering = getSettingi("softwareRendering");
  gSettingsCache.line_spacing = getSettingi("line_spacing");
  gSettingsCache.alpha_trails = getSettingi("alpha_trails");
  gSettingsCache.antialias_lines = getSettingi("antialias_lines");
  gSettingsCache.turn_cycle = getSettingi("turn_cycle"); 
  gSettingsCache.light_cycles = getSettingi("light_cycles"); 
  gSettingsCache.lod = getSettingi("lod"); 
  gSettingsCache.fov = getSettingf("fov"); 

  gSettingsCache.show_floor_texture = getVideoSettingi("show_floor_texture");
  gSettingsCache.show_skybox = getVideoSettingi("show_skybox"); 
  gSettingsCache.show_wall = getVideoSettingi("show_wall");
  gSettingsCache.stretch_textures = getVideoSettingi("stretch_textures"); 
  gSettingsCache.show_decals = getVideoSettingi("show_decals");

  gSettingsCache.show_impact = getSettingi("show_impact");
  gSettingsCache.show_glow = getSettingi("show_glow"); 
  gSettingsCache.show_recognizer = getSettingi("show_recognizer");

  gSettingsCache.fast_finish = getSettingi("fast_finish");
  gSettingsCache.fov = getSettingf("fov");
  gSettingsCache.znear = getSettingf("znear");
  gSettingsCache.camType = getSettingi("camType");
  gSettingsCache.playEffects = getSettingi("playEffects");
  gSettingsCache.playMusic = getSettingi("playMusic");
	gSettingsCache.map_ratio_w = getSettingf("map_ratio_w");
	gSettingsCache.map_ratio_h = getSettingf("map_ratio_h");

	scripting_GetGlobal("clear_color", NULL);
  scripting_GetFloatArrayResult(gSettingsCache.clear_color, 4);
}
Пример #9
0
Файл: init.c Проект: Zoxc/gltron
void initConfiguration(int argc, const char *argv[])
{
  /* load some more defaults from config file */
	runScript(PATH_SCRIPTS, "config.lua");
	runScript(PATH_SCRIPTS, "artpack.lua");
	
  /* go for .gltronrc (or whatever is defined in RC_NAME) */
  {
    char *path;
    path = getPossiblePath(PATH_PREFERENCES, RC_NAME);
    if (path != NULL) {
      if (fileExists(path)) {
        printf("[status] loading settings from %s\n", path);
	      scripting_RunFile(path);
      } else {
	      printf("[error] cannot load %s from %s\n", RC_NAME, path);
      }
      free(path);
    }
    else {
      printf("[fatal] can't get valid pref path for %s\n", RC_NAME);
      exit(1); // something is seriously wrong
    }
  }
	
	if(!isSetting("version") || getSettingf("version") < 0.70f) {
		/* load some more defaults from config file */
		runScript(PATH_SCRIPTS, "config.lua");
		runScript(PATH_SCRIPTS, "artpack.lua");
		printf("[warning] old config file found, overriding using defaults\n");
	}
	// check if config is valid
	scripting_GetGlobal("save_completed", NULL);
	if(scripting_IsNilResult()) {
		runScript(PATH_SCRIPTS, "config.lua");
		runScript(PATH_SCRIPTS, "artpack.lua");
		printf("[warning] defunct config file found, overriding using defaults\n");
	}
		
	setSettingf("version", 0.70f);

  /* parse any comandline switches overrinding the loaded settings */
  parse_args(argc, argv);

  /* sanity check some settings */
  checkSettings();
	
  /* intialize the settings cache, remember to do that everytime you
     change something */
  updateSettingsCache();
}
Пример #10
0
void resetPlayerData(void) {
  int i;
  Data *data;
  AI *ai;
  int not_playing = 0;

  int *startIndex;
  startIndex = malloc( game->players * sizeof(int) );
  randomPermutation(game->players, startIndex);

  for(i = 0; i < game->players; i++) {
    float startpos[][2] = { 
			{ 0.5, 0.25 }, { 0.75, 0.5 }, { 0.5, 0.75 }, { 0.25, 0.5 }
    };
		float x, y;

    data = game->player[i].data;
    ai = game->player[i].ai;
    /* init ai */

		switch(i) {
		case 0: ai->active = getSettingi("ai_player1"); break;
		case 1: ai->active = getSettingi("ai_player2"); break;
		case 2: ai->active = getSettingi("ai_player3"); break;
		case 3: ai->active = getSettingi("ai_player4"); break;
		default:
			fprintf(stderr, "[error] player index #%d not caught!\n", i);
			ai->active = AI_NONE;
		}
		ai->tdiff = 0;

		/* arrange players in circle around center */

		/* randomize position on the grid */
		x = startpos[ startIndex[i] ][0] * getSettingi("grid_size");
		y = startpos[ startIndex[i] ][1] * getSettingi("grid_size");
		/* randomize starting direction */
		data->dir = trand() & 3;
		/* data->dir = startdir[i]; */
		data->last_dir = data->dir;

		/* if player is playing... */
		if(ai->active != AI_NONE) {
			data->speed = getSettingf("speed");
			data->booster = getSettingf("booster_max");
			data->boost_enabled = 0;
			data->trail_height = TRAIL_HEIGHT;
		} else {
			data->speed = SPEED_GONE;
			data->trail_height = 0;
			not_playing++;
		}
		// data->trail = data->trails;
		data->trailOffset = 0;

		data->trails[ data->trailOffset ].vStart.v[0] = x;
		data->trails[ data->trailOffset ].vStart.v[1] = y;
		
		data->trails[ data->trailOffset ].vDirection.v[0] = 0;
		data->trails[ data->trailOffset ].vDirection.v[1] = 0;

		{
			int camType;
			Camera *cam = game->player[i].camera;
			camType = (game->player[i].ai->active == AI_COMPUTER) ? 
				CAM_CIRCLE : gSettingsCache.camType;
			initCamera(cam, data, camType);
		}
	}

	free(startIndex);

	game->running = game->players - not_playing; /* not everyone is alive */
	/* printf("starting game with %d players\n", game->running); */
	game->winner = -1;
}
int c_update_audio_volume(lua_State *L) { 
	Sound_setMusicVolume(getSettingf("musicVolume"));
	Sound_setFxVolume(getSettingf("fxVolume"));
	return 0;
}
Пример #12
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);
	}
}
Пример #13
0
void Input_Idle(void) {
	SystemSetJoyThreshold( getSettingf("joy_threshold") );
}
Пример #14
0
void Sound_play(void) {
  Audio_SetMusicVolume(getSettingf("musicVolume"));
  Audio_PlayMusic();
  return;
}
Пример #15
0
  void Audio_Idle(void) { 
    // iterate over all the players and update the engines
    if(sample_engine->IsPlaying()) {
      for(int i = 0; i < PLAYERS; i++) {
				Player *p;
				Sound::Source3D *p3d;
				float x, y;
				p3d = players[i];
				p = game->player + i;
				getPositionFromIndex(&x, &y, i);
				p3d->_location = Vector3(x, y, 0);
				float V = p->data->speed;

				int dt = game2->time.current - p->data->turn_time;
				if(dt < TURN_LENGTH) {
					float t = (float)dt / TURNLENGTH;

					float vx = (1 - t) * dirsX[p->data->last_dir] +
						t * dirsX[p->data->dir];
					float vy = (1 - t) * dirsY[p->data->last_dir] +
						t * dirsY[p->data->dir];
					p3d->_velocity = Vector3(V * vx, V * vy, 0);
				} else {
					p3d->_velocity = Vector3(V * dirsX[p->data->dir], 
																	 V * dirsY[p->data->dir], 
																	 0);
				}
				if(i == 0) {
					if(p->data->boost_enabled) {
						( (Sound::SourceEngine*) p3d )->_speedShift = 1.2f;
					} else {
						( (Sound::SourceEngine*) p3d )->_speedShift = 1.0f;
					}
					( (Sound::SourceEngine*) p3d )->_pitchShift =
						p->data->speed / getSettingf("speed");
				}
						
#if 0
				if(i == 0) {
					if( dt < TURNLENGTH ) {
						float t = (float)dt / TURNLENGTH;
						float speedShift = ( 1 - t ) * 0.4 + t * 0.3;
						float pitchShift = ( 1 - t ) * 0.9 + t * 1.0;
						( (Sound::SourceEngine*) p3d )->_speedShift = speedShift;
						( (Sound::SourceEngine*) p3d )->_pitchShift = pitchShift;
					} else {
						( (Sound::SourceEngine*) p3d )->_speedShift = 0.3;
						( (Sound::SourceEngine*) p3d )->_pitchShift = 1.0;
					}
				}
#endif
      }
    }

    if(sample_recognizer->IsPlaying()) {
      if (gSettingsCache.show_recognizer) {
				vec2 p, v;
				getRecognizerPositionVelocity(&p, &v);
				// recognizerEngine->_location = Vector3(p.x, p.y, RECOGNIZER_HEIGHT);
				recognizerEngine->_location = Vector3(p.v[0], p.v[1], 10.0f);
				recognizerEngine->_velocity = Vector3(v.v[0], v.v[1], 0);
      }
    }

		if(music && !music->IsPlaying()) {
			// check if music is enabled. if it is, advance to
			// next song
			if(gSettingsCache.playMusic) {
				scripting_Run("nextTrack()");
			}
		}

    Sound::Listener& listener = sound->GetListener();

    listener._location = Vector3(game->player[0].camera->cam);
		Vector3 v1 = Vector3(game->player[0].camera->target);
		Vector3 v2 = Vector3(game->player[0].camera->cam);
    listener._direction = v1 - v2;
      
    // listener._location = players[0]->_location;
    // listener._direction = players[0]->_velocity;
    listener._velocity = players[0]->_velocity;

    listener._up = Vector3(0, 0, 1);

    sound->SetMixMusic(gSettingsCache.playMusic);
    sound->SetMixFX(gSettingsCache.playEffects);
    sound->Idle();
  }
Пример #16
0
int applyWallAcceleration(int player, int dt) {
	// find distance to enemy walls left & right
	enum { eLeft, eRight, eMax };
	segment2 segments[eMax];

	Data *data = game->player[player].data;
	int dirLeft = (data->dir + 3) % 4;
	int dirRight = (data->dir + 1) % 4;

	float left, right;

	float x, y;
	vec2 vPos;

	int i, j;

	getPositionFromIndex(&x, &y, player);
	vPos.v[0] = x;
	vPos.v[1] = y;

	for(i = 0; i < eMax; i++) {
		vec2Copy(&segments[i].vStart, &vPos);
	}

	segments[eLeft].vDirection.v[0] = dirsX[dirLeft];
	segments[eLeft].vDirection.v[1] = dirsY[dirLeft];
	segments[eRight].vDirection.v[0] = dirsX[dirRight];
	segments[eRight].vDirection.v[1] = dirsY[dirRight];

	left = FLT_MAX;
	right = FLT_MAX;

	for(i = 0; i < game->players; i++) {
		segment2 *wall = game->player[i].data->trails;

		if(i == player)
			continue;
		if(game->player[i].data->trail_height < TRAIL_HEIGHT)
			continue;
		
		for(j = 0; j < game->player[i].data->trailOffset + 1; j++) {
			float t1, t2;
			vec2 v;
			if(segment2_Intersect(&v, &t1, &t2, segments + eLeft, wall) &&
				 t1 > 0 && t1 < left && t2 >= 0 && t2 <= 1)
				left = t1;
			if(segment2_Intersect(&v, &t1, &t2, segments + eRight, wall) &&
				 t1 > 0 && t1 < right && t2 >= 0 && t2 <= 1)
				right = t1;
			wall++;
		}
	}

	{
		float accell_limit = getSettingf("wall_accel_limit");
		if(left < accell_limit || right < accell_limit) {
			float boost = getSettingf("wall_accel_use") * dt / 1000.0f;
			data->speed += boost;
			return 1;
		} else {
			return 0;
		}
	}
}
Пример #17
0
List* doMovement(int mode, int dt) {
  int i;
  List *l = NULL;

  for(i = 0; i < game->players; i++) {
		Data *data = game->player[i].data;
		PlayerVisual *pV = gPlayerVisuals + i;
    if(data->speed > 0) { /* still alive */
			float fs;
			float t;

			// speed boost:
			float deccel = 0;
			if(getSettingf("wall_accel_on") == 1) {
				if(!applyWallAcceleration(i, dt)) {
					deccel = getSettingf("wall_accel_decrease");
				}
				else {
					deccel = -1; // forbid deacceleration for booster
				}
			}
			if(getSettingf("booster_on") == 1) {
				if(!applyBooster(i, dt) && deccel != -1) {
					float d = getSettingf("booster_decrease");
					deccel = d > deccel ? d : deccel;
				} else {
					deccel = -1;
				}
			}
			if(deccel > 0)
				applyDecceleration(i, dt, deccel);

			// if(i == 0)
			// printf("speed: %.2f, boost: %.2f\n", data->speed, data->booster);
				
      fs = 1.0f - SPEED_OZ_FACTOR + SPEED_OZ_FACTOR * 
				cosf(i * PI / 4.0f + 
						(game2->time.current % SPEED_OZ_FREQ) * 
						2.0f * PI / SPEED_OZ_FREQ);

      t = dt / 100.0f * data->speed * fs;
			
			{
				segment2 *current = data->trails + data->trailOffset;
				segment2 movement;
				int crash = 0;
				float x, y;
				
				getPositionFromData(&x, &y, data);
				movement.vStart.v[0] = x;
				movement.vStart.v[1] = y;
				movement.vDirection.v[0] = t * dirsX[data->dir];
				movement.vDirection.v[1] = t * dirsY[data->dir];
				
				current->vDirection.v[0] += t * dirsX[data->dir];
				current->vDirection.v[1] += t * dirsY[data->dir];

				crash = crash || crashTestPlayers(i, &movement);
				crash = crash || crashTestWalls(i, &movement);
			}
    } else { /* already crashed */
      if(game2->rules.eraseCrashed == 1 && data->trail_height > 0)
				data->trail_height -= (dt * TRAIL_HEIGHT) / 1000.0f;
      if(pV->exp_radius < EXP_RADIUS_MAX)
				pV->exp_radius += dt * EXP_RADIUS_DELTA;
      else if (data->speed == SPEED_CRASHED) {
				int winner = -1;

				data->speed = SPEED_GONE;
				game->running--;
				if(game->running <= 1) { /* all dead, find survivor */
					int i, maxSpeed = SPEED_GONE;
					/* create winner event */
					for(i = 0; i < game->players; i++) {
						if(game->player[i].data->speed >= maxSpeed) {
							winner = i;
							maxSpeed = game->player[i].data->speed;
						}
					}
					if(mode) {
            createEvent(winner, EVENT_STOP);
						/* a stop event is the last event that happens */
						return l;
					}
				}
      }
    }      
  }
  return l;
}
Пример #18
0
int getSettingi(const char *name) {
	return (int) getSettingf(name);
}
Пример #19
0
void playerCamera(Player *p, int player) {
	float dest[3];
	float tdest[3];
	float phi, chi, r;
	float x, y;
	int mouse_dx, mouse_dy;
	Camera *cam;
	Data *data;
	/* first, process all movement commands */
	/* that means, check for mouse input mainly */

	/* dt hack: the time since the last frame is not necessarily the game
		time, since the game maybe hasn't started yet, or was paused */
	static int last=0;
	int dt;

	if(game2->time.dt == 0) {
		dt = nebu_Time_GetElapsed() - last;
		last = nebu_Time_GetElapsed();
	} else {
		dt = game2->time.dt;
	}


	cam = &gPlayerVisuals[player].camera;
	data = p->data;
	getPositionFromData(&x, &y, data);

	if(game->pauseflag != PAUSE_GAME_RUNNING || !getSettingi("mouse_lock_ingame"))
	{
		if(cam->type.freedom[CAM_FREE_R]) {
			// mouse buttons let you zoom in/out
			if(gInput.mouse1 == 1)
				cam->movement[CAM_R] += (cam->movement[CAM_R]-CLAMP_R_MIN+1) * dt / 300.0f;
			if(gInput.mouse2 == 1)
				cam->movement[CAM_R] -= (cam->movement[CAM_R]-CLAMP_R_MIN+1) * dt / 300.0f;
			writeCamDefaults(cam, CAM_R);
		}
		nebu_Input_Mouse_GetDelta(&mouse_dx, &mouse_dy);
		if(cam->type.freedom[CAM_FREE_PHI] && mouse_dx != 0) {
			// mouse x axis lets you rotate horizontally
			int sign = getSettingi("mouse_invert_x") ? -1 : 1;
			cam->movement[CAM_PHI] += sign * (- mouse_dx) * MOUSE_CX;
			writeCamDefaults(cam, CAM_PHI);
		}
		if(cam->type.freedom[CAM_FREE_CHI] && mouse_dy != 0) {
			// mouse y axis lets you rotate vertically
			int sign = getSettingi("mouse_invert_y") ? -1 : 1;
			cam->movement[CAM_CHI] += sign * mouse_dy * MOUSE_CY;
			writeCamDefaults(cam, CAM_CHI);
		}
		/* done with mouse movement, now clamp the camera to legal values */
		clampCam(cam);
	}

	phi = cam->movement[CAM_PHI] + cam->movement[CAM_PHI_OFFSET];
	chi = cam->movement[CAM_CHI];
	r = cam->movement[CAM_R];

	/* if the cam is coupled to player movement, change the phi accordingly */
	if(cam->type.coupled) {
		int time = game2->time.current - p->data->turn_time;
		if(time < TURN_LENGTH) {
			int dir, ldir;
			dir = p->data->dir;
			ldir = p->data->last_dir;
			if(dir == 1 && ldir == 2)
				dir = 4;
			if(dir == 2 && ldir == 1)
				ldir = 4;
			phi += ((TURN_LENGTH - time) * camAngles[ldir] + 
				time * camAngles[dir]) / TURN_LENGTH;
		}
		else
			phi += camAngles[p->data->dir];
	}

	/* position the camera */
	dest[0] = x + r * cosf(phi) * sinf(chi);
	dest[1] = y + r * sinf(phi) * sinf(chi);
	dest[2] = r * cosf(chi);

	/* ok, now let's calculate the new camera destination coordinates */
	/* also, perform some camera dependent movement */
	switch(cam->type.type) {
	case CAM_TYPE_CIRCLING: /* Andi-cam */
		cam->movement[CAM_PHI] += CAM_SPEED * game2->time.dt;
		tdest[0] = x;
		tdest[1] = y;
		tdest[2] = B_HEIGHT;
		break;
	case CAM_TYPE_FOLLOW: /* Mike-cam */
	case CAM_TYPE_MOUSE: /* mouse camera */
		tdest[0] = x;
		tdest[1] = y;
		tdest[2] = B_HEIGHT;
		break;
	case CAM_TYPE_COCKPIT: /* 1st person */
		tdest[0] = x + 4.0f * dirsX[ p->data->dir ] + 2.0f * cosf(phi);
		tdest[1] = y + 4.0f * dirsY[ p->data->dir ] + 2.0f * sinf(phi);
		tdest[2] = CAM_COCKPIT_Z;
		dest[0] = x + 4.0f * dirsX[ p->data->dir ] + 0.1f * cosf(phi);
		dest[1] = y + 4.0f * dirsY[ p->data->dir ] + 0.1f * sinf(phi);
		dest[2] = CAM_COCKPIT_Z + 0.1f;
		break;
	case CAM_TYPE_OFFSET: /* AMR-cam */
		{
			static float px[4]= { 0, 0, 0, 0 };
			static float py[4] = { 0, 0, 0, 0 };
			float dx,dy,tx,ty,gs,d;
	
			gs=getSettingf("grid_size");
			tx=(x-gs/2)*(1+15/gs)+gs/2; /* Scale position of cycle */
			ty=(y-gs/2)*(1+15/gs)+gs/2;

			dx=px[player]-tx;
			dy=py[player]-ty;
			d=1.3f * sqrtf(dx*dx+dy*dy); /* Find distance between old viewpoint and scaled cycle pos */
			px[player] = dest[0] = tx + CAM_CIRCLE_DIST * dx/d; /* Set viewpoint a fixed distance from */
			py[player] = dest[1] = ty + CAM_CIRCLE_DIST * dy/d; /* scaled pos, preserving angle */

			dx=(tx-x)*(tx-x); /* find distance between scaled and actual */
			dy=(ty-y)*(ty-y); /* cycle positions... */
			d=sqrtf(dx*dx+dy*dy)/8.0f;
			dest[2] = CAM_CIRCLE_Z-(d*CAM_CIRCLE_Z)/24; /* ...and lift camera when close to cycle */

			tdest[0] = x;
			tdest[1] = y;
			tdest[2] = B_HEIGHT;
		}
		break;
	}
	memcpy(cam->cam, dest, sizeof(cam->cam));
	memcpy(cam->target, tdest, sizeof(cam->target));
}