基于websocket实现双人联机俄罗斯方块游戏,逻辑思路整理如下

  • 思路整理
    • 1.游戏开始,双方都收到start消息,同时调用start方法
    • 2.start方法中,调用game.init方法,同时发送init消息给server,server收到后会转发给另一个游戏玩家
    • 3.另一个游戏玩家在remote.js中接收init,会驱动对方去调用start方法(next消息同init消息)
  • 整体代码
    • local.js
    • remote.js
    • wsServer.js
    • script.js

思路整理

1.游戏开始,双方都收到start消息,同时调用start方法

socket.on('start', function () {document.getElementById('waiting').inneHTML = '';start();});

2.start方法中,调用game.init方法,同时发送init消息给server,server收到后会转发给另一个游戏玩家

 game.init(doms, type, dir);socket.emit('init', {type: type,dir: dir});bindKeyEvent();var t = generateType();var d = generateDir();game.performNext(t, d);socket.emit('next', {type: t,dir: d})
//wsServer.js中 server收到消息
socket.on('init', function (data) {// 接收消息后,将其匹配给另一个socketif (socket.clientCount % 2 == 0) {socketMap[socket.clientCount - 1].emit('init', data);} else {socketMap[socket.clientCount + 1].emit('init', data);}
});

3.另一个游戏玩家在remote.js中接收init,会驱动对方去调用start方法(next消息同init消息)

var bindEvents = function () {socket.on('init', function (data) {// 调用start,接收init消息和传递的参数,实现两个用户相连接(在对方区域中调用了start)start(data.type, data.dir);});socket.on('next', function (data) {// 驱动对方游戏区域也调用performNext函数game.performNext(data.type, data.dir);});}

整体代码

local.js

var Local = function (socket) {// 游戏对象var game;// 时间间隔 200毫秒var INTERVAL = 500;// 定时器var timer = null;// 绑定键盘事件// 时间计数器var timeConut = 0;var time = 0;var bindKeyEvent = function () {document.onkeydown = function (e) {if (e.keyCode == 38) {// 向上game.rotate();socket.emit("rotate");} else if (e.keyCode == 39) {// 向右game.right();socket.emit("right");} else if (e.keyCode == 40) {// 向下game.down();socket.emit("down");} else if (e.keyCode == 37) {// 向左game.left();socket.emit("left");} else if (e.keyCode == 32) {// 空格键game.fall();socket.emit("fall");}};};// 随机生成干扰行var generateBotLine = function (lineNum) {var lines = [];for (var i = 0; i < lineNum; i++) {var line = [];for (var j = 0; j < 10; j++) {line.push(Math.ceil(Math.random() * 2) - 1); // 生成 0 1 随机数}lines.push(line);}return lines;};// 移动var move = function () {timeFunc();// 不能下降再调用if (!game.down()) {// 落下的方块固定game.fixed();socket.emit("fixed");var line = game.checkClear();if (line) {// 行数不为0,则传入addScore函数game.addScore(line);socket.emit("line", line);if (line > 1) {var bottomLines = generataBottomLines(line);socket.emit('bottomLines', bottomLines);}}var gameOver = game.checkGameOver();if (gameOver) {game.gameOver(false);document.getElementById("remote_gameover").innerHTML = "你赢了";socket.emit("lose");stop();} else {var t = generateType();var d = generateDir();game.performNext(t, d);socket.emit("next", {type: t,dir: d,});}} else {socket.emit("down");}};// 计时函数var timeFunc = function () {timeConut = timeConut + 1;if (timeConut == 5) {timeConut = 0;time = time + 1;// 将更新的时间传入界面game.setTime(time);socket.emit("time", time);}};// 随机生成下一个方块var generateType = function () {// 随机生成0-6的整数return Math.ceil(Math.random() * 7) - 1;};// 随机生成旋转次数var generateDir = function () {// 随机生成0-3的整数return Math.ceil(Math.random() * 4) - 1;};// 开始var start = function () {var doms = {gameDiv: document.getElementById("local_game"),nextDiv: document.getElementById("local_next"),timeDiv: document.getElementById("local_time"),scoreDiv: document.getElementById("local_score"),resultDiv: document.getElementById("local_gameover"),};game = new Game();// 定义变量,用websocket将随机方向种类和方向generateType(), generateDir()通过对象形式到init,var type = generateType();var dir = generateDir();game.init(doms, type, dir);socket.emit("init", {type: type,dir: dir,});bindKeyEvent();var t = generateType();var d = generateDir();game.performNext(t, d);socket.emit("next", {type: t,dir: d,});timer = setInterval(move, INTERVAL);};// 结束,关闭计时var stop = function () {if (timer) {clearInterval(timer);timer = null;}document.onkeydown = null;};// 不用导出start了,用socket.on监听start,收到后,通过waiting设置页面显示为空;调用start开始游戏socket.on("start", function () {document.getElementById("waiting").innerHTML = "游戏开始!";start();});socket.on("lose", function () {game.gameOver(true);stop();});socket.on("leave", function () {document.getElementById("local_gameover").innerHTML = "对方掉线啦";document.getElementById("remote_gameover").innerHTML = "已掉线";stop();});socket.on('bottomLines', function (data) {game.addTailLines(data);socket.emit('addTailLines', data);})
};

remote.js

var Remote = function (socket) {var game;var bindEvents = function () {socket.on('init', function (data) {// 调用start,接收init消息和传递的参数,实现两个用户相连接(在对方区域中调用了start)start(data.type, data.dir);});socket.on('next', function (data) {// 驱动对方游戏区域也调用performNext函数game.performNext(data.type, data.dir);});socket.on('rotate', function (data) {// 驱动对方游戏区域也调用performNext函数game.rotate();});socket.on('right', function (data) {// 驱动对方游戏区域也调用performNext函数game.right();});socket.on('left', function (data) {// 驱动对方游戏区域也调用performNext函数game.left();});socket.on('down', function (data) {// 驱动对方游戏区域也调用performNext函数game.down();});socket.on('line', function (data) {// 驱动对方游戏区域也调用performNext函数game.checkClear();game.addScore(data);});socket.on('fall', function (data) {// 驱动对方游戏区域也调用performNext函数game.fall();});socket.on('fixed', function (data) {// 驱动对方游戏区域也调用performNext函数game.fixed();});socket.on('time', function (data) {// 驱动对方游戏区域也调用performNext函数game.setTime(data);});socket.on('lose', function (data) {// 驱动对方游戏区域也调用performNext函数game.gameOver(false);});socket.on('addTailLines', function (data) {// 驱动对方游戏区域也调用performNext函数game.addTailLines(data);});}var start = function (type, dir) {var doms = {gameDiv: document.getElementById('remote_game'),nextDiv: document.getElementById('remote_next'),timeDiv: document.getElementById('remote_time'),scoreDiv: document.getElementById('remote_score'),resultDiv: document.getElementById('remote_gameover')}game = new Game();game.init(doms, type, dir);}bindEvents();
}

wsServer.js

var app = require("http").createServer();
var io = require("socket.io")(app);var PORT = 3000;
// 客户端计数
var clientCount = 0;
// 保存客户端socket
var socketMap = {};
app.listen(PORT);var bindListener = function (socket, event) {socket.on(event, function (data) {if (socket.clientNum % 2 == 0) {if (socketMap[socket.clientNum - 1])socketMap[socket.clientNum - 1].emit(event, data);} else {if (socketMap[socket.clientNum + 1])socketMap[socket.clientNum + 1].emit(event, data);}});
}
io.on("connection", function (socket) {// 用户连接进来后先进行客户加1clientCount++;socket.clientNum = clientCount;socketMap[clientCount] = socket;// 是单数个进来的用户需要等待if (clientCount % 2 == 1) {// 发送wait消息socket.emit("waiting", "等待玩家进入……");} else {if (socketMap[clientCount - 1]) {socket.emit("start");socketMap[(clientCount - 1)].emit("start");} else {socket.emit('leave');}}bindListener(socket, 'init');bindListener(socket, 'next');bindListener(socket, 'rotate');bindListener(socket, 'down');bindListener(socket, 'right');bindListener(socket, 'left');bindListener(socket, 'fall');bindListener(socket, 'fixed');bindListener(socket, 'line');bindListener(socket, 'time');bindListener(socket, 'lose');bindListener(socket, 'bottomLines');bindListener(socket, 'addTailLines');socket.on('disconnect', function () {if (socket.clientNum % 2 == 0) {if (socketMap[socket.clientNum - 1])socketMap[socket.clientNum - 1].emit('leave');} else {if (socketMap[socket.clientNum + 1])socketMap[socket.clientNum + 1].emit('leave');}delete(socketMap[socket.clientNum]);});
});console.log("websocket listening on port" + PORT);

script.js

var socket = io('ws://localhost:3000');
// 创建local对象并调用,传入socket对象
var local = new Local(socket);
var remote = new Remote(socket);socket.on('waiting', function (str) {document.getElementById('waiting').innerHTML = str;
});


前端实现双人联机版俄罗斯方块小游戏2(实现双人联机)相关推荐

  1. 《游戏学习》Java版俄罗斯方块小游戏源码实战

    [Java版俄罗斯方块]     增加保存配置信息到文件的功能,声音设置.显示设置.关卡选择等配置信息在修改后将会保存在jar包同级目录下(以jar相同的文件名+.cfg后缀保存) [菜单选项]    ...

  2. 回归前端学习第26天-实现俄罗斯方块小游戏9(实现单机版,一个计时带干扰的单机版俄罗斯方块小游戏完成)

    最终完善单机版俄罗斯方块小游戏,增加干扰功能--每10秒增加一行 增加干扰功能 game.js中加入addBotLine函数 local.js中加入 增加干扰功能 game.js中加入addBotLi ...

  3. 回归前端学习第22天-实现俄罗斯方块小游戏5(实现单机版1——结合HTML、CSS、JS来搭建界面)

    实现单机版俄罗斯方块小游戏,搭建页面 实现静态基础页面 实现静态基础页面 HTML: <!DOCTYPE html> <html lang="en">< ...

  4. 联机版俄罗斯方块带自动挂机源码

    这是一款联机版俄罗斯方块游戏.共配置了13种方块.支持ai挂机功能.双人比赛,右下角显示对手的进度. 每消除一行,会给对手投递一个停滞蛛网,暂停对手的进度.连续消除多行时,投递停滞蛛网 + 快进,停滞 ...

  5. 用matlab编写的游戏,用matlab编写的俄罗斯方块小游戏

    用matlab编写的俄罗斯方块小游戏 ?function RussiaBlock( varargin ) if nargin == 0 OldHandle = findobj( 'Type', 'fi ...

  6. 使用JavaFx实现的俄罗斯方块小游戏

    使用JavaFx编写一个俄罗斯方块小游戏 一.内容介绍 (1)经典俄罗斯方块基础内容: ①七种四小方块组成的方块(田形.L形.反L形.长条形.Z形.S形): ②填满一排消除,到达顶端结束: ③下一个方 ...

  7. c++ 小游戏_C/C++编程新手入门基础系列:俄罗斯方块小游戏制作源代码

    这篇文章主要为大家详细介绍了C语言实现俄罗斯方块小游戏,具有一定的参考价值,感兴趣的小伙伴们可以参考一下. 1.要先下载一个 graphics.h 的头文件来绘图. 2.初始化窗口:initgraph ...

  8. 基于stm32、0.96寸OLED实现的俄罗斯方块小游戏(详细源码注释)

    概述:本实验基于stm32最小系统.0.96寸OLED(68*128)和摇杆实现一个经典的俄罗斯方块小游戏.项目源码地址:点击下载. 硬件要求: 普通摇杆,两个电位器和一个开关组成,左右摇动控制一个电 ...

  9. Python编写俄罗斯方块小游戏

    俄罗斯方块是俄罗斯人发明的一款休闲类的小游戏,这款小游戏可以说是很多人童年的主打电子游戏了,本文我们使用 Python 来实现这款小游戏. 很多人学习python,不知道从何学起. 很多人学习pyth ...

最新文章

  1. Python单例模式中几种实现及优化方法
  2. AGC002E Candy Piles
  3. 完整的Web应用程序Tomcat JSF Primefaces JPA Hibernate –第2部分
  4. 【计算机网络】Socket
  5. 华中数控hnc一818b_数控车床精确对刀方法总结
  6. 几张动态图弄懂递归,二叉树,二分查找简短算法
  7. Xcode 运行程序,左侧memory 不显示内存
  8. Android--UI控件
  9. 使用Aforge 开发的摄像头,有拍照,录像,设置帧率,分辨率等,以及对视频以及相机等的控制
  10. 射频测试系统软件,射频测试可以不懂测试仪器?“仪器程控系统”软件助你极大提升测试效率...
  11. 【电力电子技术】浅析IR2110自举电路
  12. pdf转换成word转换器免费版哪里下载
  13. 手机变Android麦克风,【工具】手机秒变摄像头及麦克风方法
  14. 今日恐慌与贪婪指数为10 恐慌程度有所上升
  15. 基于Python的新闻聚合网站设计与实现
  16. 高通平台 UART log 开启方法
  17. floyed算法、dijkstra算法、SPFA算法
  18. AXI latency 理解
  19. 【多媒体封装格式详解】---ASF(WMV/WMA)
  20. 斐波那契数列的通项公式

热门文章

  1. npm是什么东西?npm是干什么的
  2. 计算机书籍(必看推荐)
  3. Charle工具详解之实战演练问题分析、https抓包、流量设置、断点配置
  4. Python+Vue计算机毕业设计网上图书商城q3ulr(源码+程序+LW+部署)
  5. 我所理解的开源软件供应链安全
  6. 罗技无法使用计算机上的配置文件,如何解决Logitech键盘多媒体键无法使用的问题?...
  7. C语言基础:求10个数的平均数
  8. [机缘参悟-83]:如何自我前提应对可能的经-济-危-机?
  9. mysql批量导入json_微信小程序云开发---数据库批量导入json文件
  10. Sublime Text格式化Xml