Ejemplo n.º 1
0
/*
 * Set up the required initial conditions for a match, and switch to playing state
 */
void start_game()
{
	/* Seed the RNG */
	srand(TCNT1);

	/* Load in the sprites */
	reticule_SPR = reticule(0);

	/* Generate and draw a level */
	clear_screen();
	free((void*) level_map);
	level_map = generate_flat(WIDTH, 129);	
	if(level_map != NULL)
		draw_level(level_map, SILVER, 0, WIDTH - 1);
	
	/* Set up the players in the field */
	playersX = malloc(players * sizeof(int16_t));
	playersY = malloc(players * sizeof(int16_t));
	players_HP = malloc(players * sizeof(uint8_t));
	if(playersX == NULL || playersY == NULL || players_HP == NULL)
	{
		display_string("Out of memory error!");
		return;
	}
	uint8_t i;
	for(i = 0; i < players; i++)
	{
		playersX[i] = (i + 1) * WIDTH / (players + 1);
		playersY[i] = 120;
		players_HP[i] = MAX_PLAYER_HP;

		free_sprite(player_SPR);
		player_SPR = botleft(i);
		fill_sprite(player_SPR, playersX[i], playersY[i], HEIGHT_NO_UI, WIDTH);
	}

	/* Pick a random player to ... go last
	 * First call to start_turn will cycle to next player. Poor sod. */
	current_player = rand() % players;

	reticuleX = (playersX[current_player] + (RETICULE_DISTANCE * ml_cos(position))/100);
	reticuleY = (playersY[current_player] + (RETICULE_DISTANCE * ml_sin(position))/100);

	/* Initialise movement variables */
	direction = 0;
	launch_speed = 0;

	/* Draw the UI */
	display_string_xy("POWER:", POWER_LABEL_X, POWER_LABEL_Y);
	fill_rectangle(power_outline, WHITE);
	fill_rectangle(power_empty, BLACK);
	display_string_xy("WIND:", WIND_LABEL_X, WIND_LABEL_Y);
	fill_rectangle(wind_outline, WHITE);
	fill_rectangle(wind_empty, BLACK);

	/* Start the first player's turn */
	start_turn();
}
Ejemplo n.º 2
0
static int prepare_sprite_surfaces(int fd, int sprite_width, int sprite_height,
				   uint32_t num_surfaces, uint32_t *sprite_handles,
				   uint32_t *sprite_stride, uint32_t *sprite_size,
				   int tiled)
{
	uint32_t                        bytes_per_pixel = sizeof(uint32_t);
	uint32_t                        *sprite_fb_ptr;
	int                             i;

	if (bytes_per_pixel != sizeof(uint32_t)) {
		printf("Bad bytes_per_pixel for sprite: %d\n", bytes_per_pixel);
		return -EINVAL;
	}

	if (tiled) {
		int                         v;

		/* Round the tiling up to the next power-of-two and the
		 * region up to the next pot fence size so that this works
		 * on all generations.
		 *
		 * This can still fail if the framebuffer is too large to
		 * be tiled. But then that failure is expected.
		 */

		v = sprite_width * bytes_per_pixel;
		for (*sprite_stride = 512; *sprite_stride < v; *sprite_stride *= 2)
			;

		v = *sprite_stride * sprite_height;
		for (*sprite_size = 1024*1024; *sprite_size < v; *sprite_size *= 2)
			;
	} else {
		/* Scan-out has a 64 byte alignment restriction */
		*sprite_stride = (sprite_width * bytes_per_pixel + 63) & ~63;
		*sprite_size = *sprite_stride * sprite_height;
	}

	for (i = 0; i < num_surfaces;  i++) {
		// Create the sprite surface
		sprite_handles[i] = gem_create(fd, *sprite_size);

		if (tiled)
			gem_set_tiling(fd, sprite_handles[i], I915_TILING_X, *sprite_stride);

		// Get pointer to the surface
		sprite_fb_ptr = gem_mmap(fd,
				sprite_handles[i], *sprite_size,
				PROT_READ | PROT_WRITE);

		if (sprite_fb_ptr != NULL) {
			// Fill with checkerboard pattern
			fill_sprite(sprite_width, sprite_height, *sprite_stride, i, sprite_fb_ptr);

			munmap(sprite_fb_ptr, *sprite_size);
		} else {
			i--;
			while (i >= 0) {
				gem_close(fd, sprite_handles[i]);
				i--;
			}
		}
	}

	return 0;
}
Ejemplo n.º 3
0
/*
 * Main function to run one tick of the game
 */
int run_game()
{
	cli();

	/* Movement phase */
	if(game_state == 1)
	{
		/* Move the reticule based on readings from the rotary encoder */
		int16_t newRX = (playersX[current_player] + (RETICULE_DISTANCE * ml_cos(position))/100);
		int16_t newRY = (playersY[current_player] + (RETICULE_DISTANCE * ml_sin(position))/100);
		
		rectangle reticuleOld = {reticuleX - reticule_SPR->width / 2, reticuleX + reticule_SPR->width / 2 - 1, reticuleY - reticule_SPR->height / 2, reticuleY + reticule_SPR->height / 2 - 1};
		draw_background(level_map, SILVER, reticuleOld, HEIGHT_NO_UI, WIDTH);

		//fill_rectangle(reticuleOld, BLACK);
		if(newRX >= 0 && newRX < WIDTH && newRY >= 0 && newRY < HEIGHT)
			fill_sprite(reticule_SPR, newRX, newRY, HEIGHT_NO_UI, WIDTH);
	
		reticuleX = newRX;
		reticuleY = newRY;

		/* Read firing input */
		if (get_switch_long(_BV(SWC)))
		{
			game_state = 3;
			return 0;
		}		

		/* Read directional input.*/
		if (get_switch_rpt(_BV(SWE))) 
		{
			direction = 4;
			free_sprite(player_SPR);
			player_SPR = botright(current_player);
		}
		else if (get_switch_rpt(_BV(SWW)))
		{
			direction = -4;
			free_sprite(player_SPR);
			player_SPR = botleft(current_player);
		}
		else
		{
			direction = 0;
			return 0;
		}

		/* Move the player */
		int16_t newX = playersX[current_player] + direction;
		int16_t newY = ml_min(level_map[newX - PLAYER_WIDTH], level_map[newX + PLAYER_WIDTH - 1]) - PLAYER_HEIGHT;

		int8_t i;
		int8_t player_collision = 0;
		for(i = 0; i < players; i++)
		{
			if(players_HP[i] != 0 && i != current_player && newX >= playersX[i] - PLAYER_WIDTH && newX <= playersX[i] + PLAYER_WIDTH - 1)
			{
				player_collision = 1;
				break;
			}				
		}

		/* Cancel movement if trying to climb to high or off the sides of the screen */
		if(player_collision || playersY[current_player] - newY > MAX_CLIMB_HEIGHT || newX <= PLAYER_WIDTH || newX + PLAYER_WIDTH > WIDTH)
		{
			/* DEBUGGING prints: */
			//display_string_xy("Error\n", 10, 10);
			//ml_printf("Cannot move there... (%u,%u) to (%u,%u)", playersX[0], playersY[0], newX, newY);
			return 0;
		}
		
		rectangle playerOld = {playersX[current_player] - PLAYER_WIDTH, playersX[current_player] + PLAYER_WIDTH - 1, playersY[current_player] - PLAYER_HEIGHT, playersY[current_player] + PLAYER_HEIGHT - 1};

		fill_rectangle(playerOld, BLACK);
		fill_sprite(player_SPR, newX, newY, HEIGHT_NO_UI, WIDTH);
		
		playersX[current_player] = newX;
		playersY[current_player] = newY;
	}
	/* Projectile phase (missile in the air) */
	else if(game_state == 2)
	{
		/* Find the new position of the projectile */
		int16_t newX = projectileX + proVelX/1000;
		int16_t newY = projectileY + proVelY/1000;
		
		rectangle projectileOld = {projectileX, projectileX, projectileY, projectileY};
		fill_rectangle(projectileOld, BLACK);

		/* End turn if projectile goes off the sides of the level */
		if(newX < 0 || newX > WIDTH)
		{
			start_turn();
			return 0;
		}
		
		/* If the new position is in the ground, EXPLODE!
		 * (Also, if off the bottom of the level) */
		if(newY >= level_map[newX] || newY > HEIGHT_NO_UI)
		{
			int i;
			for(i = -EXPLOSION_RADIUS; i <= EXPLOSION_RADIUS; i++)
			{
				/* Make sure that terrain is on screen */
				if(newX + i >= 0 && newX + i < WIDTH)
				{
					uint16_t new_ground_level = newY + ml_sqrt(EXPLOSION_RADIUS * EXPLOSION_RADIUS - i * i);
					if(new_ground_level >= HEIGHT_NO_UI)
						level_map[newX + i] = HEIGHT_NO_UI - 1; //Clamp to bottom of level
					else if(new_ground_level > level_map[newX + i]) //Don't raise the ground level!
						level_map[newX + i] = new_ground_level; 
				}
			}

			draw_level(level_map, SILVER, newX - EXPLOSION_RADIUS, newX + EXPLOSION_RADIUS);

			/* Check players for damage + redraw them */
			for(i = 0; i < players; i++)
			{
				int16_t deltaX = playersX[i] - newX;
				int16_t deltaY = playersY[i] - newY;
				int16_t distance = ml_sqrt(deltaX * deltaX + deltaY * deltaY);
				if(distance < BLAST_RADIUS)
				{
					int16_t damage = ml_clamp(0, players_HP[i], MAX_EXPLOSION_DAMAGE - (distance * MAX_EXPLOSION_DAMAGE / BLAST_RADIUS));
					players_HP[i] -= damage;
				}

				rectangle playerOld = {playersX[i] - PLAYER_WIDTH, playersX[i] + PLAYER_WIDTH - 1, playersY[i] - PLAYER_HEIGHT, playersY[i] + PLAYER_HEIGHT - 1};
				fill_rectangle(playerOld, BLACK);

				/* If the player is still alive, redraw them */
				if(players_HP[i] != 0)
				{
					free_sprite(player_SPR);
					player_SPR = botleft(i);
					playersY[i] = ml_min(level_map[playersX[i] - PLAYER_WIDTH], level_map[playersX[i] + PLAYER_WIDTH - 1]) - PLAYER_HEIGHT;
					fill_sprite(player_SPR, playersX[i], playersY[i], HEIGHT_NO_UI, WIDTH);
				}
			}

			start_turn();
			return 0;
		}	

		rectangle projectileNew = {newX, newX, newY, newY};
		
		/* Continue turn if off top of level, but only draw if projectile onscreen */
		if(newY >= 0)
		{
			fill_rectangle(projectileNew, RED);
		}

		projectileX = newX;
		projectileY = newY;		

		/* Apply gravity and wind */
		proVelY += 500;
		proVelX += (wind_velocity - 10) * 50;
	}
	/* Charging phase */
	else if(game_state == 3)
	{
		/* Increase the launch speed while the fire button is held */
		if (get_switch_state(_BV(SWC)))
		{
			launch_speed++;
			rectangle bar = {POWER_BAR_START, POWER_BAR_START + launch_speed, 231, 236};
			fill_rectangle(bar, WHITE);

			/* Fire once max power is reached */
			if(launch_speed == 100)
				fire_projectile();
		}
		else
		{
			fire_projectile();
		}
	}	
	/* Menu phase */
	else if(game_state == 4)
	{
		if (get_switch_press(_BV(SWE)))
		{
			if(players == 4)
				players = 2;
			else
				players++;
		}
		else if (get_switch_press(_BV(SWW)))
		{
			if(players == 2)
				players = 4;
			else
				players--;
		}

		ml_printf_at("< %u Players >", 5, 115, players);
		
		if (get_switch_long(_BV(SWC)))
		{
			start_game();
		}
	}
	/* End game phase */
	else if(game_state == 5)
	{
		if (get_switch_long(_BV(SWC)))
		{
			start_menu();
		}
	}

	sei();
	
	return 0;
}