Mercurial > hg > Members > kono > Cerium
view Renderer/Test/aquarium.cc @ 880:f4bdf2b0d7da
[Renderer/Test/aquarium] sync aquarium (1 bug)
author | kazz <kazz@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 06 Jul 2010 23:37:11 +0900 |
parents | 596009c66065 |
children | c81744aaa3ef |
line wrap: on
line source
#include <stdio.h> #include <string.h> #include <fcntl.h> #include <sys/types.h> #include <sys/mman.h> #include <sys/stat.h> #include <unistd.h> #include "SceneGraphRoot.h" #include "lindaapi.h" #include "aquarium.h" #include "aquarium.pb.h" #define GET_SERIAL_ID 65535 int aquarium::last_player_id = 1; Viewer *aquarium::sgroot; SceneGraphPtr aquarium::parent; linda_t aquarium::linda_addr = { "localhost", 10000 }; int aquarium::linda; int aquarium::serial_id; int aquarium::width; int aquarium::start_x; char *aquarium::xml_file_name; const char *usr_help_str = "Usage: ./aquarium -linda LINDA_SERVER_NAME\n"; void TMend(TaskManager *manager); extern void task_initialize(); extern int init(TaskManager *manager, int argc, char *argv[]); extern Application * application() { return new aquarium(); } static void null_move(SceneGraphPtr node, void *sgroot_, int screen_w, int screen_h) { } static void null_collision(SceneGraphPtr node, void *sgroot_, int screen_w, int screen_h, SceneGraphPtr tree) { } void aquarium::set_position(SceneGraphPtr node, unsigned char *reply) { aqua::Position *pos = new aqua::Position(); pos->ParseFromArray(reply + LINDA_HEADER_SIZE, psx_get_datalength(reply)); node->xyz[0] = pos->x() - start_x; node->xyz[1] = pos->y(); printf("xyz: %f, %f\n", node->xyz[0], node->xyz[1]); delete pos; } static void update_position_move(SceneGraphPtr node, void *sgroot_, int screen_w, int screen_h) { printf("move_xyz: %f, %f\n", node->xyz[0], node->xyz[1]); // LindaServerから座標データを取得してオブジェクトに反映させる。 if (!node->resend_flag || node->seq_rd != node->seq) { unsigned char *reply_rd = psx_reply(node->seq_rd); if (reply_rd != NULL) { aquarium::set_position(node, reply_rd); psx_free(reply_rd); return; } } unsigned char *reply = psx_reply(node->seq); if (reply != NULL) { // aquarium::set_position(node, reply); psx_free(reply); node->seq = psx_wait_rd(aquarium::linda, node->id * 10 + 1); node->resend_flag = true; } else if (node->resend_flag) { node->seq_rd = psx_rd(aquarium::linda, node->id * 10 + 1); node->resend_flag = false; } } SceneGraphPtr create_sg(Viewer *viewer, SceneGraphPtr parent, unsigned char *data, int len, int serial_id) { SceneGraphPtr child = viewer->sgroot->createSceneGraph(); viewer->sgroot->createFromXMLmemory(viewer->sgroot->tmanager, child, (char *)data, len); child->set_move_collision(update_position_move, null_collision); child->id = serial_id; child->seq = psx_wait_rd(aquarium::linda, serial_id * 10 + 1); child->seq_rd = psx_rd(aquarium::linda, serial_id * 10 + 1); child->resend_flag = false; parent->addChild(child); return child; } static void check_new_player_move(SceneGraphPtr node, void *sgroot_, int screen_w, int screen_h) { unsigned char *reply_rd = psx_reply(node->seq_rd); if (reply_rd != NULL) { unsigned char *xml_data = reply_rd + LINDA_HEADER_SIZE; int xml_len = psx_get_datalength(reply_rd); create_sg(aquarium::sgroot, node, xml_data, xml_len, aquarium::last_player_id); psx_free(reply_rd); aquarium::last_player_id++; int tuple_id = aquarium::last_player_id * 10; aquarium::parent->seq_rd = psx_rd(aquarium::linda, tuple_id); } // printf("rd id: %d\n", aquarium::last_player_id); } void * file_map(const char *filename, int *size) { int fd; void *addr; struct stat sb; if ((fd = open(filename, O_RDONLY)) == -1) { fprintf(stderr, "Can't open %s\n", filename); perror(NULL); } if (fstat(fd, &sb) == -1) { fprintf(stderr, "Can't fstat %s\n", filename); perror(NULL); } *size = sb.st_size; addr = mmap(NULL, *size, PROT_READ, MAP_PRIVATE, fd, 0); if (addr == MAP_FAILED) { perror("mmap error\n"); exit(EXIT_FAILURE); } close(fd); return addr; } void callback_free(unsigned char *tuple, void *arg) { psx_free(tuple); } void aquarium::send_position(SceneGraphPtr node) { int pos_id = serial_id * 10 + 1; psx_callback_in(linda, pos_id, callback_free, NULL); aqua::Position *pos = new aqua::Position(); pos->set_x(node->xyz[0] + start_x); pos->set_y(node->xyz[1]); int size = pos->ByteSize(); unsigned char *msg = (unsigned char *) sgroot->manager->allocate(sizeof(char) * size); pos->SerializeToArray(msg, size); // 更新したデータを再度シリアライズ delete pos; psx_out(linda, pos_id, msg, size); } void my_move(SceneGraphPtr node, void *sgroot_, int w, int h) { SceneGraphRoot *sgroot = (SceneGraphRoot *)sgroot_; Pad *pad = sgroot->getController(); int flag = 0; if (pad->right.isHold() || pad->left.isHold()) { if (pad->right.isHold()) { node->xyz[0] += 5.0f; flag = 1; } else if (pad->left.isHold()) { node->xyz[0] -= 5.0f; flag = 1; } } if (pad->down.isHold() || pad->up.isHold() ) { if (pad->down.isHold()) { node->xyz[1] += 5.0f; flag = 1; } else if (pad->up.isHold()) { node->xyz[1] -= 5.0f; flag = 1; } } /* ここで座標を送信 */ if (flag || node->resend_flag) { aquarium::send_position(node); } } void aquarium::create_my_sg(Viewer *viewer, SceneGraphPtr parent, int screen_w, int screen_h) { int size; void *addr = file_map(xml_file_name, &size); SceneGraphPtr sgp = viewer->createSceneGraph(); viewer->createFromXMLmemory(sgp, (char *)addr, size); sgp->set_move_collision(my_move, null_collision); parent->addChild(sgp); int xml_id = serial_id * 10; psx_out(linda, xml_id, (unsigned char *)addr, size); int pos_id = serial_id * 10 + 1; aqua::Position *pos = new aqua::Position(); pos->set_x(0.0f + start_x); pos->set_y(0.0f); unsigned char *msg = (unsigned char *) viewer->manager->allocate(sizeof(unsigned char *) * size); pos->SerializeToArray(msg, size); psx_out(linda, pos_id, (unsigned char *)msg, pos->ByteSize()); delete pos; sgp->seq = 0; sgp->resend_flag = 0; } MainLoopPtr aquarium::init(Viewer *sgroot, int screen_w, int screen_h) { this->sgroot = sgroot; width = screen_w; linda_connect(); // 接続に合わせて serial_id も取得 update_screen_scope(); parent = sgroot->createSceneGraph(); parent->set_move_collision(check_new_player_move, null_collision); create_my_sg(sgroot, parent, screen_w, screen_h); if (serial_id == last_player_id) last_player_id++; int tuple_id = aquarium::last_player_id * 10; parent->seq_rd = psx_rd(linda, tuple_id); sgroot->setSceneData(parent); return sgroot; } void aquarium::linda_connect() { init_linda(); // セレクタの初期化 linda = open_linda_java(linda_addr.hostname, linda_addr.port); // serial_id の取得 int seq = psx_in(linda, GET_SERIAL_ID); unsigned char *data = NULL; do { psx_sync_n(); data = psx_reply(seq); } while (data == NULL); data[LINDA_HEADER_SIZE + psx_get_datalength(data)] = '\0'; serial_id = atoi((char *)data + LINDA_HEADER_SIZE); psx_free(data); printf("Get serial_id: %d\n", serial_id); } void aquarium::update_screen_scope() { int seq = psx_in(linda, 1); unsigned char *data = NULL; do { psx_sync_n(); data = psx_reply(seq); } while (data == NULL); aqua::Width *w = new aqua::Width(); w->ParseFromArray(data + LINDA_HEADER_SIZE, *(int *)(data + LINDA_DATA_LENGTH_OFFSET)); start_x = w->width(); // 現在の全長を取得 w->set_width(start_x + width); // 自分の横幅を足す int size = w->ByteSize(); unsigned char *msg = (unsigned char *) sgroot->manager->allocate(sizeof(char) * size); w->SerializeToArray(msg, size); // 更新したデータを再度シリアライズ delete w; psx_out(linda, 1, msg, size); psx_sync_n(); printf("start_x = %d, width = %d\n", start_x, width); } int TMmain(TaskManager *manager, int argc, char *argv[]) { task_initialize(); manager->set_TMend(TMend); for (int i = 0; i < argc; i++) { if (strcmp(argv[i],"-linda") == 0 && i + 1 <= argc) { aquarium::linda_addr.hostname = argv[i+1]; } else if (strcmp(argv[i],"-port") == 0 && i + 1 <= argc) { aquarium::linda_addr.port = atoi(argv[i+1]); } else if (strcmp(argv[i],"-xml") == 0 && i + 1 <= argc) { aquarium::xml_file_name = argv[i+1]; } } return init(manager, argc, argv); } void TMend(TaskManager *manager) { printf("aquarium end\n"); } /* end */