vc配合sdl编写多人泡泡堂联机游戏

       花了两天多的时间写了个泡泡堂联机游戏。感觉其实单机版的实现不难,麻烦的是多人联机的实现。

       先说下思路吧,程序分为服务端和客户端。服务端器一个中转作用,但客户端的状态改变,比如用户进入,放下泡泡,移动等时,会发送信息给服务端,服务端收到后会转发给其他客户端。服务端开辟5个线程,等待客户端连接,也就是最多只能连接5个客户端。具体的大家可以看代码:

下面是客户端的:

#include<iostream>
#include<vector>
#include"winsock2.h"
#include "mysocket.cpp"
#include"sdl/sdl.h"
#include"time.h"
#pragma comment(lib,"ws2_32")
using namespace std;
SDL_Surface *screen;
SDL_Surface *play;
SDL_Surface *mplay;
SDL_Surface *ball;
SDL_Surface *ball1;
SDL_Surface *ball2;
int hall[48][64];
struct info{
 int flag;  //1,新用户;2,新子弹;3.用户移动
 int id;
 int x;
 int y;
 int a;
};
struct bb{
 SDL_Rect r;
 int t;
};
struct pp{
 SDL_Rect point;
 int id;
 int port;
};
vector<bb> b;
vector<pp> p;
mysocket sock;
mysocket sock1;
mysocket sock2;
int id;
char ip[20];
void myexit(){
 
}
DWORD WINAPI get(LPVOID l){
 info f;
 while(1){
  memset((void*)&f,0,sizeof(f));
  sock.recv((char*)&f,sizeof(f));
  if(f.flag==1){
   pp p1; 
   p1.id=f.id;
   p1.point.x=f.x;
   p1.point.y=f.y;
   p1.port=9999+f.id;
   p.push_back(p1);
   cout<<f.x<<"  "<<f.y<<endl;
  // cout<<1<<endl;
  }else if(f.flag==2){
   bb b1;
   b1.r.x=f.x;
   b1.r.y=f.y;
   b1.t=100;
   b.push_back(b1);
  }else if(f.flag==3){
   for(int i=0;i<p.size();i++){
    if(f.id==p[i].id){
     p[i].point.x=f.x;
     p[i].point.y=f.y;
    }
   }
  }
 }
  return 0;
}
DWORD WINAPI get1(LPVOID l){

 info f;
 while(1){
  memset((void*)&f,0,sizeof(f));
  sock2.recvfrom((char*)&f,sizeof(f));
  if(f.flag==1){
   pp p1; 
   p1.id=f.id;
   p1.point.x=f.x;
   p1.point.y=f.y;
   p1.port=9999+f.id;
   p.push_back(p1);
   for(int i=0;i<6;i++){
    for(int i1=0;i1<6;i1++){
     hall[p1.point.y/10+i][p1.point.x/10+i1]=0;
    }
   }
  // cout<<f.x<<"  "<<f.y<<endl;
  }else if(f.flag==2){
   bb b1;
   b1.r.x=f.x;
   b1.r.y=f.y;
   b1.t=100;
   //cout<<b1.t;
   b.push_back(b1);
  }else if(f.flag==3){
   for(int i=0;i<p.size();i++){
    if(f.id==p[i].id){
     p[i].point.x=f.x;
     p[i].point.y=f.y;
    }
   }
  }else if(f.flag==4){
   f.id=hall[f.x][f.y];
   //cout<<10005+f.a;
    sock2.sendto((char*)&f,sizeof(f),ip,10005+f.a); 
   // cout<<id;
  }else if(f.flag==5){
   for(int i=0;i<b.size();i++){
    f.flag=5;
    f.id=b[i].t;
    f.x=b[i].r.x;
    f.y=b[i].r.y;
   sock2.sendto((char*)&f,sizeof(f),ip,10005+f.a); 
   }
   f.flag=5;
   f.id=-1;
   f.x=-1;
   f.y=-1;
   sock2.sendto((char*)&f,sizeof(f),ip,10005+f.a); 
   //cout<<1;
  }else if(f.flag==6){
   for(int i=0;i<p.size();i++){
    if(p[i].id==f.id){
     p.erase(p.begin()+i);
     break;
    }
   }
  }
 }
 return 0;
}
int main(int argc, char *argv[]){
 srand(time(0));
 cin>>ip;
// strcpy(ip,"127.0.0.1");
 WSADATA data;
 WORD v=MAKEWORD(2,2);
 WSAStartup(v,&data);
 mysocket s;
 s.init(0);
 s.connect(ip,9999);
 s.recv((char*)&id,sizeof(id));
 int fid=0;
 if(id==0){
  id=1;
  fid=1;
 }
 s.close();
 int port=9999+id;
 sock2.init(1);
 sock2.bind(id+19999);
 pp p1;
 p1.id=id;
 p1.port=port;
 p1.point.x=rand()%550/10*10;
 p1.point.y=rand()%400/10*10;
 p.push_back(p1);
 sock.init(0);
 sock.connect(ip,id+9999);
 info f={1,id,p1.point.x,p1.point.y};
 sock.send((char*)&f,sizeof(f));
 for(int i=0;i<48;i++){
  for(int i1=0;i1<64;i1++){
   hall[i][i1]=1;
  }
 }

 if(fid==1){
 for(i=0;i<50;i++){
a: int x=rand()%48,y=rand()%64;
   if(hall[x][y]==0){
    goto a;
   }else{
    for(int i1=0;i1<4;i1++){
     for(int i2=0;i2<4;i2++){
      if(x+i1<48 && y+i2<64){
       hall[x+i1][y+i2]=0;
      }
     }
    }
   }
 }
 }else{
  info f;
//cout<<id;
  for(int i=0;i<48;i++){
   for(int i1=0;i1<64;i1++){
    sock2.recvfrom((char*)&f,sizeof(f));
   // Sleep(1);
    hall[f.x][f.y]=f.id;
   }
  }
 //cout<<"sx";
  while(1){
   sock2.recvfrom((char*)&f,sizeof(f));
   if(f.id==-1){
    break;
   }
   bb b1;
   b1.r.x=f.x;
   b1.r.y=f.y;
   b1.t=f.id;
   b.push_back(b1);
  }
 }
 SDL_Init(SDL_INIT_EVERYTHING);
 atexit(SDL_Quit);
 screen=SDL_SetVideoMode(640,480,32,SDL_SWSURFACE);
 
 
 CreateThread(0,0,get,0,0,0);
 CreateThread(0,0,get1,0,0,0);
 play=SDL_LoadBMP("1.bmp");
 ball=SDL_LoadBMP("2.bmp");
 ball1=SDL_LoadBMP("3.bmp");
 ball2=SDL_LoadBMP("4.bmp");
 mplay=SDL_LoadBMP("5.bmp");
 for(i=0;i<6;i++){
  for(int i1=0;i1<6;i1++){
   hall[p[0].point.y/10+i][p[0].point.x/10+i1]=0;
  }
 }
 while(1){
  Uint8 *key=SDL_GetKeyState(0);
  if(key[SDLK_UP]){
   if(p[0].point.y-10>=0 && hall[(p[0].point.y-10)/10][p[0].point.x/10]==0 && hall[(p[0].point.y-10)/10][p[0].point.x/10+1]==0 && hall[(p[0].point.y-10)/10][p[0].point.x/10+2]==0){
    p[0].point.y-=10;
    info f={3,id,p[0].point.x,p[0].point.y};
    sock.send((char*)&f,sizeof(f));
   }
  }
  if(key[SDLK_DOWN]){
   if(p[0].point.y+10+30<=480 && hall[(p[0].point.y+30)/10][p[0].point.x/10]==0 && hall[(p[0].point.y+30)/10][p[0].point.x/10+1]==0 && hall[(p[0].point.y+30)/10][p[0].point.x/10+2]==0){
    p[0].point.y+=10;
    info f={3,id,p[0].point.x,p[0].point.y};
    sock.send((char*)&f,sizeof(f));
   }
  }
  if(key[SDLK_LEFT]){
   if(p[0].point.x-10>=0 && hall[p[0].point.y/10][(p[0].point.x-10)/10]==0 && hall[p[0].point.y/10+1][(p[0].point.x-10)/10]==0 && hall[p[0].point.y/10+2][(p[0].point.x-10)/10]==0){
    p[0].point.x-=10;
    info f={3,id,p[0].point.x,p[0].point.y};
    sock.send((char*)&f,sizeof(f));
   }
  }
  if(key[SDLK_RIGHT]){
   if(p[0].point.x+10+30<=640 && hall[p[0].point.y/10][(p[0].point.x+30)/10]==0 && hall[p[0].point.y/10+1][(p[0].point.x+30)/10]==0 && hall[p[0].point.y/10+2][(p[0].point.x+30)/10]==0){
    p[0].point.x+=10;
    info f={3,id,p[0].point.x,p[0].point.y};
    sock.send((char*)&f,sizeof(f));
   }
  }
  if(key[SDLK_SPACE]){
   bb b1;
   b1.r.x=p[0].point.x;
   b1.r.y=p[0].point.y;
   b1.t=100;
   b.push_back(b1);
   info f={2,id,p[0].point.x,p[0].point.y};
   sock.send((char*)&f,sizeof(f));
  }
  SDL_Event event;
  while (SDL_PollEvent(&event))   
        {
   
   switch (event.type)    {
   case SDL_KEYUP:
    // If escape is pressed, return (and thus, quit)
    if (event.key.keysym.sym == SDLK_ESCAPE){
     info f={6,id,0,0};
      sock.send((char*)&f,sizeof(f));
     return 0;
    }
    break;
   case SDL_QUIT:
    info f={6,id,0,0};
      sock.send((char*)&f,sizeof(f));
    return(0);
    break;
   }
  }
  for(i=0;i<48;i++){
   for(int i1=0;i1<64;i1++){
    SDL_Rect r;
    r.x=i1*10;
    r.y=i*10;
    r.h=10;
    r.w=10;
    if(hall[i][i1]==0){
     SDL_FillRect(screen,&r,SDL_MapRGB(screen->format,255,255,0));
    }else{
     SDL_FillRect(screen,&r,SDL_MapRGB(screen->format,100,100,0));
    }
    
   }
  }
  for(i=0;i<b.size();i++){
   if(b[i].t<=0){
    for(int i1=0;i1<3;i1++){
     for(int i2=0;i2<6;i2++){
      if(b[i].r.x/10-i2-1>=0){
       hall[b[i].r.y/10+i1][b[i].r.x/10-i2-1]=0;
       SDL_Rect r;
       r.x=(b[i].r.x/10-i2-1)*10;
       r.y=(b[i].r.y/10+i1)*10;
       r.h=10;
       r.w=10;
       SDL_FillRect(screen,&r,SDL_MapRGB(screen->format,255,100,0));
       SDL_UpdateRect(screen,r.x,r.y,r.w,r.h);
       
      }
     }
    }
    for(i1=0;i1<6;i1++){
     for(int i2=0;i2<3;i2++){
      if(b[i].r.y/10-i1-1>=0){
       hall[b[i].r.y/10-i1-1][b[i].r.x/10+i2]=0;
       SDL_Rect r;
       r.x=(b[i].r.x/10+i2)*10;
       r.y=(b[i].r.y/10-i1-1)*10;
       r.h=10;
       r.w=10;
       SDL_FillRect(screen,&r,SDL_MapRGB(screen->format,255,100,0));
       SDL_UpdateRect(screen,r.x,r.y,r.w,r.h);
      }
     }
    }
    for(i1=0;i1<3;i1++){
     for(int i2=0;i2<6;i2++){
      if(b[i].r.x/10+i2+3<=63){
       hall[b[i].r.y/10+i1][b[i].r.x/10+i2+3]=0;
       SDL_Rect r;
       r.x=(b[i].r.x/10+i2+3)*10;
       r.y=(b[i].r.y/10+i1)*10;
       r.h=10;
       r.w=10;
       SDL_FillRect(screen,&r,SDL_MapRGB(screen->format,255,100,0));
       SDL_UpdateRect(screen,r.x,r.y,r.w,r.h);
      }
     }
    }
    for(i1=0;i1<6;i1++){
     for(int i2=0;i2<3;i2++){
      if(b[i].r.y/10+i1+3<=47){
       hall[b[i].r.y/10+i1+3][b[i].r.x/10+i2]=0;
       SDL_Rect r;
       r.x=(b[i].r.x/10+i2)*10;
       r.y=(b[i].r.y/10+i1+3)*10;
       r.h=10;
       r.w=10;
       SDL_FillRect(screen,&r,SDL_MapRGB(screen->format,255,100,0));
       SDL_UpdateRect(screen,r.x,r.y,r.w,r.h);
      }
     }
    }

     if((p[0].point.x>=b[i].r.x && p[0].point.x<b[i].r.x+30 && p[0].point.y>b[i].r.y-60 && p[0].point.y<b[i].r.y+90)){
      info f={6,id,0,0};
      sock.send((char*)&f,sizeof(f));
      return 0;
     }
     if((p[0].point.x>=b[i].r.x-60 && p[0].point.x<b[i].r.x+90 && p[0].point.y>=b[i].r.y && p[0].point.y<b[i].r.y+30)){
      info f={6,id,0,0};
      sock.send((char*)&f,sizeof(f));
      return 0;
     }
     if((p[0].point.x+30>b[i].r.x && p[0].point.x+30<b[i].r.x+30 && p[0].point.y>b[i].r.y-60 && p[0].point.y<b[i].r.y+90)){
      info f={6,id,0,0};
      sock.send((char*)&f,sizeof(f));
      return 0;
     }
     if((p[0].point.x+30>b[i].r.x-60 && p[0].point.x+30<b[i].r.x+90 && p[0].point.y>b[i].r.y && p[0].point.y<b[i].r.y+30)){
      info f={6,id,0,0};
      sock.send((char*)&f,sizeof(f));
      return 0;
     }
     if((p[0].point.x>b[i].r.x && p[0].point.x<b[i].r.x+30 && p[0].point.y+30>b[i].r.y-60 && p[0].point.y+30<b[i].r.y+90)){
      info f={6,id,0,0};
      sock.send((char*)&f,sizeof(f));
      return 0;
     }
     if((p[0].point.x>b[i].r.x-60 && p[0].point.x<b[i].r.x+90 && p[0].point.y+30>b[i].r.y && p[0].point.y+30<b[i].r.y+30)){
      info f={6,id,0,0};
      sock.send((char*)&f,sizeof(f));
      return 0;
     }
     if((p[0].point.x+30>b[i].r.x && p[0].point.x+30<b[i].r.x+30 && p[0].point.y+30>b[i].r.y-60 && p[0].point.y+30<b[i].r.y+90)){
      info f={6,id,0,0};
      sock.send((char*)&f,sizeof(f));
      return 0;
     }
     if((p[0].point.x+30>b[i].r.x-60 && p[0].point.x+30<b[i].r.x+90 && p[0].point.y+30>b[i].r.y && p[0].point.y+30<b[i].r.y+30)){
      info f={6,id,0,0};
      sock.send((char*)&f,sizeof(f));
      return 0;
     }

    b.erase(b.begin()+i);
    continue;
   }
   b[i].t-=2;
   if(b[i].t>50){
    SDL_BlitSurface(ball,0,screen,&b[i].r);
   }else if(b[i].t>20){
    SDL_BlitSurface(ball2,0,screen,&b[i].r);
   }else{
    SDL_BlitSurface(ball1,0,screen,&b[i].r);
   }
  }
  for(i=0;i<p.size();i++){
   if(i==0){
   SDL_BlitSurface(mplay,0,screen,&p[i].point);
   }else{
   SDL_BlitSurface(play,0,screen,&p[i].point);
   }
  }
 
  SDL_Flip(screen);
  SDL_Delay(80);
 }
 return 0;
}

 

下面是服务端的 :

 

#include<iostream>
#include<vector>
#include"winsock2.h"
#include "mysocket.cpp"
#include"windows.h"
#pragma comment(lib,"ws2_32")
using namespace std;
CRITICAL_SECTION cs;
struct info{
 int flag;  //1,新用户;2,新子弹;3.用户移动,4,地图;5,泡泡;6,用户退出
 int id;
 int x;
 int y;
 int a;
};
struct play{
 int id;
 char ip[20];
 int x;
 int y;
};
vector<play> p;
DWORD WINAPI sendinfo(LPVOID l){
 while(1){
  mysocket ss;
  ss.init(0);
  ss.bind(9999);
  ss.listen();
  mysocket ss1;
  ss.accept(ss1);
  cout<<"sx"<<endl;
  int id;
  if(p.size()==0){
   id=0;
   ss1.send((char*)&id,sizeof(id));
  }else{
   for(int i=1;i<=5;i++){
    int f=0;
    for(int i1=0;i1<p.size();i1++){
     if(p[i1].id==i){
      f=1;
     }
     
    }
    if(f==0){
     id=i;
     break;
    }
   }
   cout<<id;
   ss1.send((char*)&id,sizeof(id));
  }
  ss1.close();
  ss.close();
 }
 return 0;
}
DWORD WINAPI user(LPVOID l){
 int port=(long)l;
 EnterCriticalSection(&cs);
 cout<<port<<endl;
 LeaveCriticalSection(&cs);
init: mysocket s;
 s.init(0);
 s.bind(port);
 s.listen();
 mysocket s1;
 s.accept(s1);
 info f;
 while(1){
  memset((void*)&f,0,sizeof(f));
  s1.recv((char*)&f,sizeof(f));
  if(f.flag==1){
   for(int i=0;i<p.size();i++){
    info f1={1,p[i].id,p[i].x,p[i].y};
    int e=s1.send((char*)&f1,sizeof(f1));
    cout<<p[i].x<<"   "<<p[i].y<<endl;
   }
   cout<<p.size()<<endl;
   if(p.size()>0){
    mysocket s2;
    s2.init(1);
    s2.bind(10005+port-9999);
   // cout<<10005+port-9999;
    // cout<<p[0].ip<<"  "<<p[0].id+19999;
    for(int i=0;i<48;i++){
     for(int i1=0;i1<64;i1++){
      info f2={4,0,i,i1,port-9999};
      s2.sendto((char*)&f2,sizeof(f2),p[0].ip,p[0].id+19999);
      // Sleep(1);
      s2.recvfrom((char*)&f2,sizeof(f2));
     // cout<<f.id;
      // Sleep(1);
      s2.sendto((char*)&f2,sizeof(s2),s1.getaddr(),f.id+19999);
     }
    }
    info f2={5,0,0,0,port-9999};
    s2.sendto((char*)&f2,sizeof(f2),p[0].ip,p[0].id+19999);
    while(1){
     // Sleep(1);
     s2.recvfrom((char*)&f2,sizeof(f2));
     //cout<<f.id;
     // Sleep(1);
     
     s2.sendto((char*)&f2,sizeof(s2),s1.getaddr(),f.id+19999);
     if(f2.id==-1){
      break;
     }
    }
    s2.close();
   }
   info f2={1,f.id,f.x,f.y};
   mysocket s2;
   s2.init(1);
   for(i=0;i<p.size();i++){
    s2.sendto((char*)&f2,sizeof(f2),p[i].ip,p[i].id+19999);
   }
   play p1; 
   p1.id=f.id;
   p1.x=f.x;
   p1.y=f.y;
   sockaddr_in addr;
   int n=sizeof(addr);
   ::getpeername(s1.getsocket(),(sockaddr*)&addr,&n);
  // int peerport=::ntohs(addr.sin_port);
 char *peerip=::inet_ntoa(addr.sin_addr);
 cout<<peerip<<endl;
   strcpy(p1.ip,peerip);
   p.push_back(p1);
  }else if(f.flag==2){
   info f2={2,f.id,f.x,f.y};
   mysocket s2;
   s2.init(1);
   for(int i=0;i<p.size();i++){
    if(p[i].id!=f.id){
    int e= s2.sendto((char*)&f2,sizeof(f2),p[i].ip,p[i].id+19999);
    }
   }
  }else if(f.flag==3){
   //cout<<"sx"<<endl;
   info f2={3,f.id,f.x,f.y};
   mysocket s2;
   s2.init(1);
   for(int i=0;i<p.size();i++){
    if(p[i].id!=f.id){
     s2.sendto((char*)&f2,sizeof(f2),p[i].ip,p[i].id+19999);
    }else{
    p[i].x=f.x;
    p[i].y=f.y;
    }
   }
  }else if(f.flag==6){
   for(int i=0;i<p.size();i++){
    if(p[i].id==f.id){
     p.erase(p.begin()+i);
     break;
    }
   }
   info f2={6,f.id,0,0};
   mysocket s2;
   s2.init(1);
   for(i=0;i<p.size();i++){
    s2.sendto((char*)&f2,sizeof(f2),p[i].ip,p[i].id+19999);
   }
   s.close();
    s1.close();
    cout<<p.size()<<endl;
   goto init;
  }
 }
 return 0;
}
HANDLE t;
main(){
 InitializeCriticalSection(&cs);
 WSADATA data;
 WORD v=MAKEWORD(2,2);
 WSAStartup(v,&data);
 t=CreateThread(0,0,sendinfo,0,0,0);
 for(int i=0;i<5;i++){
  CreateThread(0,0,user,(void*)(10000+i),0,0);
 }
 WaitForSingleObject(t,-1);
 DeleteCriticalSection(&cs);
}

 

       代码写的不是很好,在多线程的处理上有缺陷。测试时发现有时会发生客户端得不到服务端发送数据的情况,可能是我用UDP通信的缘故吧。

       本文有不足之处,还望大家多多指正。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值