572 lines
18 KiB
C
572 lines
18 KiB
C
#include <stdio.h>
|
||
#include <allegro5/allegro_primitives.h>
|
||
|
||
#include "common.h"
|
||
#include "networkgame.h"
|
||
|
||
/************************************************************
|
||
* HANDLING
|
||
***********************************************************/
|
||
|
||
void networkgame_handling(CLIENT_DATA* data)
|
||
{
|
||
if(data->event.current.type == ALLEGRO_EVENT_KEY_DOWN)
|
||
{
|
||
switch (data->event.current.keyboard.keycode)
|
||
{
|
||
case ALLEGRO_KEY_ESCAPE:
|
||
{
|
||
if(!data->keys[ESCAPE])
|
||
{
|
||
data->keys[ESCAPE] = true;
|
||
al_show_mouse_cursor(data->screen.display);
|
||
cl_change_state(data, NETWORKOUT);
|
||
}
|
||
break;
|
||
}
|
||
case ALLEGRO_KEY_LEFT:
|
||
data->keys[LEFT] = true;
|
||
break;
|
||
case ALLEGRO_KEY_RIGHT:
|
||
data->keys[RIGHT] = true;
|
||
break;
|
||
case ALLEGRO_KEY_UP:
|
||
data->keys[UP] = true;
|
||
// cl_select_button(data);
|
||
break;
|
||
case ALLEGRO_KEY_DOWN:
|
||
data->keys[DOWN] = true;
|
||
// cl_select_button(data);
|
||
break;
|
||
case ALLEGRO_KEY_ENTER:
|
||
data->keys[ENTER] = true;
|
||
// networkparty_push_button(data);
|
||
break;
|
||
case ALLEGRO_KEY_SPACE:
|
||
data->keys[SPACE] = true;
|
||
networkgame_fire_bullet(data);
|
||
break;
|
||
case ALLEGRO_KEY_TAB:
|
||
// networkparty_change_selected(data);
|
||
break;
|
||
}
|
||
}
|
||
else if(data->event.current.type == ALLEGRO_EVENT_KEY_UP)
|
||
{
|
||
switch (data->event.current.keyboard.keycode)
|
||
{
|
||
case ALLEGRO_KEY_ESCAPE:
|
||
data->keys[ESCAPE] = false;
|
||
break;
|
||
case ALLEGRO_KEY_LEFT:
|
||
data->keys[LEFT] = false;
|
||
break;
|
||
case ALLEGRO_KEY_RIGHT:
|
||
data->keys[RIGHT] = false;
|
||
break;
|
||
case ALLEGRO_KEY_UP:
|
||
data->keys[UP] = false;
|
||
break;
|
||
case ALLEGRO_KEY_DOWN:
|
||
data->keys[DOWN] = false;
|
||
break;
|
||
case ALLEGRO_KEY_ENTER:
|
||
data->keys[ENTER] = false;
|
||
break;
|
||
case ALLEGRO_KEY_SPACE:
|
||
data->keys[SPACE] = false;
|
||
break;
|
||
}
|
||
}
|
||
else if(data->event.current.type == ALLEGRO_EVENT_MOUSE_AXES)
|
||
{
|
||
// cl_update_list(data);
|
||
// cl_update_button(data);
|
||
}
|
||
else if(data->event.current.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN)
|
||
{
|
||
// networkparty_push_button(data);
|
||
}
|
||
else if(data->event.current.type == ALLEGRO_EVENT_TIMER)
|
||
{
|
||
data->render = true;
|
||
|
||
if(data->keys[UP])
|
||
networkgame_move_ship_up(data);
|
||
else if(data->keys[DOWN])
|
||
networkgame_move_ship_down(data);
|
||
else
|
||
networkgame_reset_ship_animation(data, 1);
|
||
|
||
if(data->keys[LEFT])
|
||
networkgame_move_ship_left(data);
|
||
else if(data->keys[RIGHT])
|
||
networkgame_move_ship_right(data);
|
||
else
|
||
networkgame_reset_ship_animation(data, 2);
|
||
|
||
networkgame_update_explosions(data);
|
||
networkgame_update_comet(data);
|
||
|
||
cl_update_background(data, BG1);
|
||
cl_update_background(data, BG3);
|
||
cl_update_background(data, BG2);
|
||
}
|
||
|
||
networkgame_enet_receive(data);
|
||
}
|
||
|
||
/************************************************************
|
||
* DRAW
|
||
***********************************************************/
|
||
|
||
void networkgame_draw(CLIENT_DATA* data)
|
||
{
|
||
cl_draw_background(data, BG1);
|
||
cl_draw_background(data, BG3);
|
||
cl_draw_background(data, BG2);
|
||
|
||
networkgame_draw_ship(data);
|
||
networkgame_draw_bullet(data);
|
||
networkgame_draw_comet(data);
|
||
networkgame_draw_explosions(data);
|
||
networkgame_draw_statistic(data);
|
||
|
||
networkgame_send_move_ship(data);
|
||
}
|
||
|
||
/************************************************************
|
||
* PROCESSING
|
||
***********************************************************/
|
||
|
||
void networkgame_create_objects(CLIENT_DATA* data)
|
||
{
|
||
CLIENT_OBJECTS* objects = &data->objects;
|
||
int iterator = 0;
|
||
|
||
cl_create_objects(objects, data->network.count_connected, 5 * data->network.count_connected, 15, 5 * data->network.count_connected);
|
||
|
||
for(int i = 0; i < objects->ship_size; i++)
|
||
{
|
||
cl_init_ships(objects, iterator, data->network.users[i].id, 3, 1, 1, 10, 12, 0, 0, 50, 41, 46, data->media.bitmaps[SHIP_R + i]->al_bitmap, 3, 3, 0, 0, 0, 0);
|
||
|
||
for(int j = iterator++ * 5; j < iterator * 5; j++)
|
||
cl_init_bullets(objects, j, data->network.users[i].id, 10, 0, 0);
|
||
}
|
||
|
||
for(int i = 0; i < objects->comet_size; i++)
|
||
cl_init_comets(objects, i, 0, 21, rand() % 2 ? 1 : -1, 35, 35, 0, 0, 2, 96, 96, data->media.bitmaps[COMET]->al_bitmap, 143, 5, 0, 0);
|
||
|
||
for(int i = 0; i < objects->explosion_size; i++)
|
||
cl_init_explosions(objects, i, 8, 1, 0, 0, 1, 128, 128, data->media.bitmaps[EXPLOSION]->al_bitmap, 31, 0, 0);
|
||
}
|
||
|
||
void networkgame_enet_receive(CLIENT_DATA* data)
|
||
{
|
||
ENetEvent event;
|
||
CLIENT_MESSAGE_UPDATE* message;
|
||
|
||
while(enet_host_service(data->enet.client, &event, 0) > 0)
|
||
if(event.type == ENET_EVENT_TYPE_RECEIVE)
|
||
{
|
||
message = (CLIENT_MESSAGE_UPDATE*)event.packet->data;
|
||
|
||
for(int i = 0; i < data->objects.ship_size; i++)
|
||
{
|
||
CLIENT_SHIP* ship = data->objects.ships[i];
|
||
|
||
for(int j = 0; j < 3; j++)
|
||
if(ship->ID == message->ship[j].ID)
|
||
{
|
||
ship->x = message->ship[j].x;
|
||
ship->y = message->ship[j].y;
|
||
ship->lives = message->ship[j].lives;
|
||
ship->score = message->ship[j].score;
|
||
ship->active = message->ship[j].active;
|
||
|
||
for(int k = 0; k < 3; k++)
|
||
{
|
||
CLIENT_USER* user = &data->network.users[k];
|
||
|
||
if(user->id == ship->ID)
|
||
{
|
||
user->command.dx = message->ship[j].dx;
|
||
user->command.dy = message->ship[j].dy;
|
||
}
|
||
}
|
||
|
||
break;
|
||
}
|
||
}
|
||
|
||
for(int i = 0; i < data->objects.bullet_size; i++)
|
||
{
|
||
CLIENT_BULLET* bullet = data->objects.bullets[i];
|
||
|
||
if(message->bullet[i].live && !bullet->live)
|
||
cl_play_sound(data, SAMPLE_SHOT);
|
||
|
||
bullet->ID = message->bullet[i].ID;
|
||
bullet->active = message->bullet[i].active;
|
||
bullet->live = message->bullet[i].live;
|
||
bullet->x = message->bullet[i].x;
|
||
bullet->y = message->bullet[i].y;
|
||
}
|
||
|
||
for(int i = 0; i < data->objects.comet_size; i++)
|
||
{
|
||
CLIENT_COMET* comet = data->objects.comets[i];
|
||
|
||
comet->live = message->comet[i].live;
|
||
comet->x = message->comet[i].x;
|
||
comet->y = message->comet[i].y;
|
||
}
|
||
|
||
for(int i = 0; i < data->objects.explosion_size; i++)
|
||
{
|
||
CLIENT_EXPLOSION* explosion = data->objects.explosions[i];
|
||
|
||
if(message->explosion[i].live)
|
||
{
|
||
if(message->explosion[i].live && !explosion->live)
|
||
cl_play_sound(data, SAMPLE_BOOM);
|
||
|
||
explosion->live = message->explosion[i].live;
|
||
explosion->x = message->explosion[i].x;
|
||
explosion->y = message->explosion[i].y;
|
||
}
|
||
}
|
||
|
||
enet_packet_destroy(event.packet);
|
||
}
|
||
}
|
||
|
||
static void networkgame_send_move_ship(CLIENT_DATA* data)
|
||
{
|
||
if(data->network.command.send)
|
||
{
|
||
CLIENT_GAME_COMMAND command = data->network.command;
|
||
|
||
command.send = false;
|
||
|
||
ENetPacket *packet;
|
||
CLIENT_MESSAGE_GAME message;
|
||
|
||
message.dx = command.dx;
|
||
message.dy = command.dy;
|
||
message.fire = command.fire;
|
||
message.state = STATE_GAME;
|
||
|
||
data->network.command.fire = false;
|
||
|
||
packet = enet_packet_create(&message, sizeof(message), ENET_PACKET_FLAG_RELIABLE);
|
||
enet_peer_send(data->enet.server, 0, packet);
|
||
}
|
||
}
|
||
|
||
/************************************************************
|
||
* SHIP
|
||
***********************************************************/
|
||
|
||
static void networkgame_draw_ship(CLIENT_DATA* data)
|
||
{
|
||
for(int i = 0; i < data->objects.ship_size; i++)
|
||
{
|
||
CLIENT_SHIP* ship = data->objects.ships[i];
|
||
|
||
if(!ship->active) continue;
|
||
|
||
for(int j = 0; j < data->objects.ship_size; j++)
|
||
{
|
||
CLIENT_USER* user = &data->network.users[j];
|
||
|
||
if(user->id == ship->ID)
|
||
{
|
||
if(user->command.dy == -1)
|
||
ship->animation_row = 0;
|
||
else if(user->command.dy == 1)
|
||
ship->animation_row = 2;
|
||
else
|
||
ship->animation_row = 1;
|
||
|
||
if(user->command.dx == -1)
|
||
ship->cur_frame = 2;
|
||
else if(user->command.dx == 1)
|
||
ship->cur_frame = 1;
|
||
else
|
||
ship->cur_frame = 0;
|
||
}
|
||
}
|
||
|
||
int fx = (ship->cur_frame % ship->animation_columns) * ship->frame_width;
|
||
int fy = ship->animation_row * ship->frame_height;
|
||
|
||
al_draw_bitmap_region(ship->image, fx, fy, ship->frame_width, ship->frame_height,
|
||
ship->x - ship->frame_width / 2, ship->y - ship->frame_height / 2, 0);
|
||
}
|
||
}
|
||
|
||
static void networkgame_move_ship_up(CLIENT_DATA* data)
|
||
{
|
||
for(int i = 0; i < data->objects.ship_size; i++)
|
||
{
|
||
CLIENT_SHIP* ship = data->objects.ships[i];
|
||
|
||
if(ship->ID == data->network.user_id)
|
||
{
|
||
ship->animation_row = 0;
|
||
data->network.command.dy = -1;
|
||
data->network.command.send = true;
|
||
}
|
||
}
|
||
}
|
||
|
||
static void networkgame_move_ship_down(CLIENT_DATA* data)
|
||
{
|
||
for(int i = 0; i < data->objects.ship_size; i++)
|
||
{
|
||
CLIENT_SHIP* ship = data->objects.ships[i];
|
||
|
||
if(ship->ID == data->network.user_id)
|
||
{
|
||
ship->animation_row = 2;
|
||
data->network.command.dy = 1;
|
||
data->network.command.send = true;
|
||
}
|
||
}
|
||
}
|
||
|
||
static void networkgame_move_ship_left(CLIENT_DATA* data)
|
||
{
|
||
for(int i = 0; i < data->objects.ship_size; i++)
|
||
{
|
||
CLIENT_SHIP* ship = data->objects.ships[i];
|
||
|
||
if(ship->ID == data->network.user_id)
|
||
{
|
||
ship->cur_frame = 2;
|
||
data->network.command.dx = -1;
|
||
data->network.command.send = true;
|
||
}
|
||
}
|
||
}
|
||
|
||
static void networkgame_move_ship_right(CLIENT_DATA* data)
|
||
{
|
||
for(int i = 0; i < data->objects.ship_size; i++)
|
||
{
|
||
CLIENT_SHIP* ship = data->objects.ships[i];
|
||
|
||
if(ship->ID == data->network.user_id)
|
||
{
|
||
ship->cur_frame = 1;
|
||
data->network.command.dx = 1;
|
||
data->network.command.send = true;
|
||
}
|
||
}
|
||
}
|
||
|
||
static void networkgame_reset_ship_animation(CLIENT_DATA* data, int position)
|
||
{
|
||
for(int i = 0; i < data->objects.ship_size; i++)
|
||
{
|
||
CLIENT_SHIP* ship = data->objects.ships[i];
|
||
|
||
if(ship->ID == data->network.user_id)
|
||
{
|
||
if(position == 1)
|
||
{
|
||
ship->animation_row = 1;
|
||
data->network.command.dy = 0;
|
||
}
|
||
else
|
||
{
|
||
ship->cur_frame = 0;
|
||
data->network.command.dx = 0;
|
||
}
|
||
|
||
data->network.command.send = true;
|
||
}
|
||
}
|
||
}
|
||
|
||
static bool networkgame_dead_ship(CLIENT_DATA* data)
|
||
{
|
||
return data->objects.ships[0]->lives <= 0;
|
||
}
|
||
|
||
/************************************************************
|
||
* BULLET
|
||
***********************************************************/
|
||
|
||
static void networkgame_fire_bullet(CLIENT_DATA* data)
|
||
{
|
||
for(int i = 0; i < data->objects.ship_size; i++)
|
||
{
|
||
CLIENT_SHIP* ship = data->objects.ships[i];
|
||
|
||
if(ship->ID == data->network.user_id && ship->active)
|
||
data->network.command.fire = true;
|
||
}
|
||
}
|
||
|
||
static void networkgame_draw_bullet(CLIENT_DATA* data)
|
||
{
|
||
CLIENT_OBJECTS* objects = &data->objects;
|
||
|
||
for(int i = 0; i < objects->bullet_size; i++)
|
||
{
|
||
CLIENT_BULLET* bullet = objects->bullets[i];
|
||
|
||
if(bullet->live)
|
||
al_draw_filled_circle(bullet->x, bullet->y, 2, al_map_rgb(255, 255, 255));
|
||
}
|
||
}
|
||
|
||
/************************************************************
|
||
* COMET
|
||
***********************************************************/
|
||
|
||
static void networkgame_draw_comet(CLIENT_DATA* data)
|
||
{
|
||
CLIENT_OBJECTS* objects = &data->objects;
|
||
|
||
for(int i = 0; i < objects->comet_size; i++)
|
||
{
|
||
CLIENT_COMET* comet = objects->comets[i];
|
||
|
||
if(comet->live)
|
||
{
|
||
int fx = (comet->cur_frame % comet->animation_columns) * comet->frame_width;
|
||
int fy = (comet->cur_frame / comet->animation_columns) * comet->frame_height;
|
||
|
||
al_draw_bitmap_region(comet->image, fx, fy, comet->frame_width, comet->frame_height,
|
||
comet->x - comet->frame_width / 2, comet->y - comet->frame_height / 2, 0);
|
||
}
|
||
}
|
||
}
|
||
|
||
void networkgame_update_comet(CLIENT_DATA* data)
|
||
{
|
||
CLIENT_OBJECTS* objects = &data->objects;
|
||
|
||
for(int i = 0; i < objects->comet_size; i++)
|
||
{
|
||
CLIENT_COMET* comet = objects->comets[i];
|
||
|
||
if(comet->live)
|
||
{
|
||
if(++comet->frame_count >= comet->frame_delay)
|
||
{
|
||
comet->cur_frame += comet->animation_direction;
|
||
if(comet->cur_frame >= comet->max_frame)
|
||
comet->cur_frame = 0;
|
||
else if(comet->cur_frame <= 0)
|
||
comet->cur_frame = comet->max_frame - 1;
|
||
|
||
comet->frame_count = 0;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/************************************************************
|
||
* EXPLOSION
|
||
***********************************************************/
|
||
|
||
static void networkgame_draw_explosions(CLIENT_DATA* data)
|
||
{
|
||
CLIENT_OBJECTS* objects = &data->objects;
|
||
|
||
for(int i = 0; i < objects->explosion_size; i++)
|
||
{
|
||
CLIENT_EXPLOSION* explosion = objects->explosions[i];
|
||
|
||
if(explosion->live)
|
||
{
|
||
int fx = (explosion->cur_frame % explosion->animation_columns) * explosion->frame_width;
|
||
int fy = (explosion->cur_frame / explosion->animation_columns) * explosion->frame_height;
|
||
|
||
al_draw_bitmap_region(explosion->image, fx, fy, explosion->frame_width, explosion->frame_height,
|
||
explosion->x - explosion->frame_width / 2, explosion->y - explosion->frame_height / 2, 0);
|
||
}
|
||
}
|
||
}
|
||
|
||
void networkgame_update_explosions(CLIENT_DATA* data)
|
||
{
|
||
CLIENT_OBJECTS* objects = &data->objects;
|
||
|
||
for(int i = 0; i < objects->explosion_size; i++)
|
||
{
|
||
CLIENT_EXPLOSION* explosion = objects->explosions[i];
|
||
|
||
if(explosion->live)
|
||
if(++explosion->frame_count >= explosion->frame_delay)
|
||
{
|
||
explosion->cur_frame += explosion->animation_direction;
|
||
if(explosion->cur_frame >= explosion->max_frame)
|
||
{
|
||
explosion->cur_frame = 0;
|
||
explosion->live = false;
|
||
}
|
||
|
||
explosion->frame_count = 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
/************************************************************
|
||
* STATISTIC
|
||
***********************************************************/
|
||
|
||
static void networkgame_draw_statistic(CLIENT_DATA* data)
|
||
{
|
||
ALLEGRO_COLOR color;
|
||
ALLEGRO_COLOR color_text = al_map_rgba_f(0.5, 0.5, 0.5, 0.2);
|
||
ALLEGRO_FONT* font = data->media.fonts[FONT_PS2P30]->al_font;
|
||
|
||
char text[200] = {' ', '\0'};
|
||
char num[5] = {'\0'};
|
||
|
||
for(int i = 0; i < data->objects.ship_size; i++)
|
||
{
|
||
CLIENT_SHIP* ship = data->objects.ships[i];
|
||
CLIENT_USER user;
|
||
|
||
switch(i)
|
||
{
|
||
case 0:
|
||
color = al_map_rgba_f(0.5, 0.0, 0.0, 0.2);
|
||
break;
|
||
case 1:
|
||
color = al_map_rgba_f(0.0, 0.5, 0.0, 0.2);
|
||
break;
|
||
case 2:
|
||
color = al_map_rgba_f(0.5, 0.5, 0.0, 0.2);
|
||
break;
|
||
}
|
||
|
||
for(int j = 0; j < 3; j++)
|
||
if(data->network.users[j].id == ship->ID)
|
||
{
|
||
user = data->network.users[j];
|
||
break;
|
||
}
|
||
|
||
al_draw_text(font, color, al_get_text_width(font, text), 5, 0, user.nickname);
|
||
strcat(text, user.nickname);
|
||
al_draw_text(font, color, al_get_text_width(font, text), 5, 0, " - Ж:");
|
||
strcat(text, " - Ж:");
|
||
al_draw_textf(font, color_text, al_get_text_width(font, text), 5, 0, "%d", ship->lives);
|
||
sprintf(num, "%d", ship->lives);
|
||
strcat(text, num);
|
||
al_draw_text(font, color, al_get_text_width(font, text), 5, 0, " К:");
|
||
strcat(text, " К:");
|
||
al_draw_textf(font, color_text, al_get_text_width(font, text), 5, 0, "%d", ship->score);
|
||
sprintf(num, "%d ", ship->score);
|
||
strcat(text, num);
|
||
}
|
||
}
|
||
|