view linda.c @ 19:8ab79a86aa73

*** empty log message ***
author gongo
date Sat, 04 Nov 2006 09:13:06 +0000
parents 6910aeb52843
children a1908b83f8fa
line wrap: on
line source

/*
 * $Id$
 */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <libps2.h>
#include <ps2util.h>

#include "car.h"
#include "game.h"
#include "lindaapi.h"

#define CLIENT_MAX 2
#define LINDA_ASK_ID 65535
#define LINDA_HOST "firefly.cr.ie.u-ryukyu.ac.jp"

extern CarPtr car_init(int);
extern void gFont_SetString(char *, int, int);
extern void gFont_SetStringInt(int, int, int);
extern void carNode_append(CarPtr);
extern Game game;
extern FILE *main_fp;

static GAME_STATE common_state = GAME_WAIT;
static  int my_id;

typedef struct car_info {
    GAME_STATE state;
    FMATRIX position;
    int car_id;
    int course_id;
    int create_flg;
} CarInfo, *CarInfoPtr;

static CarPtr linda_carlist[CLIENT_MAX+1];
static CarInfo jiki;
static int linda_seq[CLIENT_MAX+1];

static void
linda_enemy_update(int id, CarPtr enemy, CarInfoPtr tpl)
{
    int i,j;

    if (id == 1 || tpl->state == GAME_GOAL) {
	common_state = tpl->state;
	game.course_id = tpl->course_id;
    }

    if (enemy && (common_state == GAME_MAIN || common_state == GAME_GOAL)) {
	for (i=0; i<4; i++) {
	    for (j=0; j<4; j++) {
		enemy->body->transfer[i][j] = tpl->position[i][j];
	    }
	}

	/* 敵は相対位置で */
	enemy->body->transfer[3][0] -= game.jiki->location[0];
	enemy->body->transfer[3][1] -= game.jiki->location[1];
	enemy->body->transfer[3][2] -= game.jiki->location[2];
	enemy->body->transfer[3][3] = 1;
    }
}

/*
 * 位置が同じなら1を返す。
 * もっと良い比較方法があるんでは...
 */
static int
linda_jiki_compareLocation()
{
    float x,y,z;
    double d;

    if (common_state == GAME_MAIN || common_state == GAME_GOAL) {
	x = jiki.position[3][0] - game.jiki->location[0];
	y = jiki.position[3][1] - game.jiki->location[1];
	z = jiki.position[3][2] - game.jiki->location[2];
	d = sqrt(x*x+y*y+z*z);

	if (d < 1.0) {
	    return 1;
	} else {
	    return 0;
	}
    } else {
	return 1;
    }
}

/*
 * 自機情報が更新されていなければ
 * 0を返す(psx_outしない)
 */
static int
linda_jiki_compare()
{
    if ((jiki.car_id == game.car_id) &&
	(jiki.course_id == game.course_id) &&
	(jiki.create_flg == ((game.jiki) ? 1:0)) &&
	(jiki.state == common_state) &&
	(linda_jiki_compareLocation())) {
	return 0;
    } else {
	return 1;
    }
}

static void
linda_jiki_update()
{
    int i,j;

    jiki.car_id     = game.car_id;
    jiki.course_id  = game.course_id;
    jiki.create_flg = (game.jiki) ? 1 : 0;
    jiki.state      = common_state;

    if (common_state == GAME_MAIN || common_state == GAME_GOAL) {
	for (i=0; i<3; i++) {
	    for (j=0; j<4; j++) {
		jiki.position[i][j]
		    = game.jiki->body->transfer[i][j];
	    }
	}
	jiki.position[3][0] = game.jiki->location[0];
	jiki.position[3][1] = game.jiki->location[1];
	jiki.position[3][2] = game.jiki->location[2];
	jiki.position[3][3] = 1;
    }
}

void
linda_update()
{
    int i;
    int barrier = 1; // バリア同期(?)用
    int connect = 1;
    char* reply;
    CarInfoPtr p = NULL;
    CarPtr car = NULL;

    for (i=1; i<=CLIENT_MAX; i++) {
	reply = psx_reply(linda_seq[i]);
	if (reply) {
	    p = (CarInfoPtr)(reply+LINDA_HEADER_SIZE);

	    if (i != game.play_id) {
		connect++;
		
		car = linda_carlist[i];
		if (common_state == GAME_MAIN && !car && p->create_flg == 1) {
		    car = car_init(p->car_id);
		    carNode_append(car);
		    linda_carlist[i] = car;
		}
		linda_enemy_update(i, car, p);
		if (common_state == p->state) {
		    barrier++;
		}
	    }
	    psx_free(reply);
	    linda_seq[i] = psx_rd(i);
	}
    }

    if (connect == CLIENT_MAX) {
	if (game.state == GAME_WAIT) {
	    gFont_SetString("CONNECT OK!!", 170, 300);
	    if (game.play_id == 1)
		gFont_SetString(" PUSH START ", 170, 400);
	}

	// ごちゃごちゃしてる...
	// なんか無駄な処理がありそうだ
	if (game.play_id == 1) {
	    // 全員のフラグ成立
	    if (common_state == GAME_GOAL) {
		if (game.state == GAME_FINISH) {
		    common_state = game.state;
		} else {
		    game.state = common_state;
		}
	    } else if (barrier == CLIENT_MAX) {
		common_state = game.state;
	    } else {
		game.state = common_state;
	    }
	} else {
	    if (game.state == GAME_GOAL) {
		if (common_state != GAME_FINISH) {
		    common_state = game.state;
		} else {
		    game.state = common_state;
		}
	    } else {
		game.state = common_state;
	    }
	}
    } else {
	if (game.state == GAME_WAIT) {
	    gFont_SetString("WAITING...", 200, 100);
	}
	game.state = common_state;
    }

    if (linda_jiki_compare()) {
#ifdef DEBUG
	// どのタイミングでoutされてるか見る
	// 必要なときだけoutしないと重いですね当然だけど
	//fprintf(main_fp, "psx_out() jiki\n");
#endif
	linda_jiki_update();
	// 無理矢理
	// 古いものを消すだけなんだけど
	// 正しいやり方が他に有るのかな?
	// 実行し続けてると最終的に激重になるので
	// ここら辺に問題が有るのだろうか。
	//	psx_free(psx_reply(psx_in(game.play_id)));
	linda_seq[my_id]=psx_in(game.play_id);
	psx_out(game.play_id, (char*)&jiki, sizeof(CarInfo));
    }
}

static int
get_id()
{
    unsigned char * reply;
    int seq;
    int id;

    //ユーザIDが格納されているTUPLE SpaceのIDへアクセス
    seq = psx_in(LINDA_ASK_ID);

    // IDが取得できるまでループ
    while((reply = psx_reply(seq)) == 0) psx_sync_n();

    id = atoi(reply+LINDA_HEADER_SIZE);
    psx_free(reply);
    return id;
}

void
linda_jikiInfo_init()
{
    int i, j;

    jiki.car_id     = 1;
    jiki.course_id  = 1;
    jiki.create_flg = 0;
    jiki.state      = game.state;

    // malloc16で生成してないからBus errorに
    // ps2_vu0_unit_matrix(jiki.position);
    for (i=0; i<4; i++) {
	for (j=0; j<4; j++) {
	    if (i==j)
		jiki.position[i][j] = 1;
	    else
		jiki.position[i][j] = 0;
	}
    }

    for (i=0; i<CLIENT_MAX+1; i++) {
	linda_carlist[i] = NULL;
    }
}



int
linda_init()
{

    int i;

    start_linda(LINDA_HOST);
    my_id = get_id();

    for (i=1; i<=CLIENT_MAX; i++) {
	if (i == my_id) {
	    psx_out(i, (char*)&jiki, sizeof(CarInfo));
	}
	linda_seq[i] = psx_rd(i);
    }
    psx_sync_n();

    return my_id;
}