摘要:最近刷了一部電影動物世界,感概原來簡單的剪刀石頭布游戲還可以這么燒腦,強大的數據分析能力對人性心理的靈敏嗅覺等??赐曛箴堄信d致,于是便利用技術,實現了一個動物世界多人對戰系統。
最近刷了一部電影《動物世界》,感概原來簡單的“剪刀石頭布”游戲還可以這么燒腦,強大的數據分析能力、對人性心理的靈敏嗅覺等??赐曛箴堄信d致,于是便利用socket技術,實現了一個“動物世界”多人對戰系統。
游戲背景故事講述的是男主被發小欺騙,欠下了一屁股債,為了償還債務被迫上了一艘賊船,同時上船的還有一批人,大伙兒的狀況都差不多。上船的好處是有機會還清債務并且還可能獲得一筆巨大的財富,這對于在現實世界中已經生活不能自理的人來說,無疑是一次改變人生的機會,而一旦失敗的話,就要被拉去做人體實驗(恐怖如斯)。
上船的人會進行一場賭博,就是我們小時候常玩的“石頭剪刀布”,每人初始時擁有12張卡牌,石頭、剪刀、布各4張,并且擁有3顆星,大家可以找任何一個人作為對手,每人各出一張卡牌,獲勝者將從失敗方拿走一顆星。游戲獲勝條件是手里卡牌全部消耗完并且擁有的星星不少于3顆,反之,若卡牌消耗完且星星少于3顆、或還有卡牌但星星為0,都視為失敗。
后端邏輯我們將利用koa來搭建一個socket服務器,來管理客戶端的消息接受和分發。
主要邏輯:
const io = SocketIO(server) // 建立socket連接 const users = {} // 緩存當前鏈接的用戶 const challengeData = {} // 緩存用戶發起的對戰信息 io.on("connection", socket => { // 客戶端連接后 const id = socket.id // 當前連接的unique標識 socket.emit("connected") // 告訴客戶端已經連接成功 // 接收客戶端的open事件 socket.on("open", name => { // 初始化數據 users[id] = { id, name, // 用戶昵稱 star: 3, // 用戶擁有的星星 stone: 4, // 用戶擁有的“石頭”卡牌數量 scissors: 4, // 用戶擁有的“剪刀”卡牌數量 paper: 4 // 用戶擁有的“布”卡牌數量 } // 通知所有人,當前所有用戶的信息 io.emit("update_users", users) }) // 用戶發起挑戰 socket.on("challenge", data => { // data包括fromCard(發起者出示的卡牌)、toId(被挑戰者的id) data.fromId = id challengeData[id] = data io.to(data.toId).emit("accept_challenge", users[id]) // 告訴對方有人要和你對戰 }) // 發起者取消了挑戰 socket.on("cancel_challenge", () => { io.to(challengeData[id].toId).emit("cancel_challenge") // 告訴對方挑戰已取消 delete challengeData[id] // 刪除緩存的數據 }) // 對方接受挑戰的信息 socket.on("respond_challenge", data => { if (data.accept) { // 接受 let cd = challengeData[data.fromId] cd.toCard = data.toCard // 被挑戰者出示的卡牌 // 雙方卡牌各減少1 users[cd.fromId][cd.fromCard]-- users[cd.toId][cd.toCard]-- let result = getChallengeResult(cd.fromCard, cd.toCard) // 獲得挑戰結果 // 比賽后的星星變更 if (result === 1) { users[cd.fromId].star++ users[cd.toId].star-- } else if (result === -1) { users[cd.fromId].star-- users[cd.toId].star++ } // 告訴挑戰者和被挑戰者,比賽的結果 io.to(cd.fromId).emit("result_challenge", result, users) io.to(cd.toId).emit("result_challenge", -result, users) } else { // 拒絕 io.to(data.fromId).emit("cancel_challenge") // 告訴發起者對方不接受挑戰 } delete challengeData[data.fromId] }) // 比賽勝利 socket.on("success_challenge", () => { // 告訴所有人,有人獲得了勝利 socket.broadcast.emit("success_challenge", users[id]) }) // 斷開連接 socket.on("disconnect", () => { delete users[id] // 廣播用戶已退出 socket.broadcast.emit("update_users", users) }) })前端邏輯
前端使用Vue來進行頁面渲染。
import request from "@/common/request" import tips from "@axe/tips" import modal from "@axe/modal" import Loading from "./components/Loading.vue" /* eslint-disable no-alert */ export default { name: "App", components: { Loading }, data () { return { isConnected: false, id: "", selectedUserId: "", selectedCard: "", users: {}, acceptChallenge: false }; }, computed: { userInfo () { let user = this.users[this.id] || {} return { star: user.star || 0, stone: user.stone || 0, scissors: user.scissors || 0, paper: user.paper || 0 } }, totalInfo () { let info = { stone: 0, scissors: 0, paper: 0 } for (let id in this.users) { let user = this.users[id] info.stone += user.stone || 0 info.scissors += user.scissors || 0 info.paper += user.paper || 0 } return info } }, methods: { handleSelectCard (type) { this.selectedCard = type }, handleSelectUser (id) { if (this.id === id) { tips.show({ content: "不可以挑戰自己哦" }) return } this.selectedUserId = id }, handleChallenge () { if (this.gameover) { tips.show({ content: "游戲已結束,請重新開始" }) return } if (!this.selectedCard) { tips.show({ content: "請挑選卡牌" }) return } if (this.users[this.id][this.selectedCard] <= 0) { tips.show({ content: "這類卡牌已耗盡" }) return } let user = this.users[this.selectedUserId] if (!user) { tips.show({ content: "請挑選對手" }) return } if (user.star <= 0 || (user.stone + user.scissors + user.paper) <= 0) { tips.show({ content: "該用戶已不具備對戰能力了" }) return } if (!this.acceptChallenge) { this.socket.emit("challenge", { fromCard: this.selectedCard, toId: this.selectedUserId }) modal.show({ title: "發起挑戰", content: "等待對方接受中...", confirmText: "取消挑戰" }, t => { if (t === "confirm") { this.socket.emit("cancel_challenge") } }) } else { this.socket.emit("respond_challenge", { accept: true, fromId: this.challengeFromUser.id, toCard: this.selectedCard }) // 重置記錄 this.acceptChallenge = false } } }, mounted () { request({ url: "/api/info" }).then(data => { // 使用ip建立連接,局域網內其他設備也可以訪問 this.socket = window.io.connect("http://" + data.ip + ":" + data.port) this.socket.on("connected", () => { let name = window.prompt("請輸入您優雅高貴的稱呼") if (!name || !name.trim()) { name = this.socket.id } // 告訴服務器,有人進來了 this.socket.emit("open", name) // 已連接 this.id = this.socket.id this.isConnected = true }) this.socket.on("update_users", users => { this.users = users }) // 是否接受挑戰 this.socket.on("accept_challenge", fromUser => { modal.show({ title: "接受挑戰", content: "是否接受來自【" + fromUser.name + "】的挑戰?", confirmText: "接受", cancelText: "拒絕" }, t => { if (t === "confirm") { // 緩存挑戰信息,等待用戶選擇出示的卡牌 this.selectedUserId = fromUser.id this.acceptChallenge = true this.challengeFromUser = fromUser } else { this.socket.emit("respond_challenge", { accept: false, fromId: fromUser.id }) } }) }) this.socket.on("cancel_challenge", () => { this.acceptChallenge = false modal.hide() tips.show({ content: "對方取消了挑戰" }) }) // 監聽對戰結果 this.socket.on("result_challenge", (result, users) => { this.users = users modal.hide() tips.show({ content: result === 0 ? "平局" : (result === 1 ? "你贏了" : "你輸了") }, () => { // 檢測游戲勝利和失敗條件 let user = users[this.id] let cardCount = user.stone + user.scissors + user.paper if (user.star >= 3 && cardCount <= 0) { this.socket.emit("success_challenge") modal.show({ title: "游戲勝利", content: "恭喜你獲得了勝利!", confirmText: "再來一局" }, t => { if (t === "confirm") { window.location.reload() } }) } else if (user.star <= 0 || cardCount <= 0) { this.gameover = true modal.show({ title: "游戲結束", content: user.star <= 0 ? "你已經沒有星星了" : "你已經沒有卡牌了", confirmText: "重新開始" }, t => { if (t === "confirm") { window.location.reload() } }) } }) }) // 接收系統廣播,有人挑戰成功的信息 this.socket.on("success_challenge", user => { window.alert(`恭喜【${user.name}】挑戰成功,戰績(${user.star})顆星`) }) }) } }補充說明
游戲預覽
源碼地址:https://github.com/ansenhuang/node-socket
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/98887.html
摘要:在高度結構化的數據挖掘以及通過分析來評估和改進機器學習模型方面,是國際領先的研究人員。在機器學習里,我并沒有涉及強化學習的內容。這些準備讓讀者了解機器學習能做什么,然后我的書能幫助他們了解機器學習怎么工作。 非商業轉載請注明作譯者、出處,并保留本文的原始鏈接:http://www.ituring.com.cn/art... 訪談對象: Peter Flach,布里斯托大學人工智能教授,...
摘要:在高度結構化的數據挖掘以及通過分析來評估和改進機器學習模型方面,是國際領先的研究人員。在機器學習里,我并沒有涉及強化學習的內容。這些準備讓讀者了解機器學習能做什么,然后我的書能幫助他們了解機器學習怎么工作。 非商業轉載請注明作譯者、出處,并保留本文的原始鏈接:http://www.ituring.com.cn/art... 訪談對象: Peter Flach,布里斯托大學人工智能教授,...
摘要:如果這個場景足夠簡單的話,深度學習并不能表現出相對于其它基于傳統模式識別方法的優勢。這是深度學習目前受到關注的一個非常重要的原因。通過積累大量的數據進行足夠的訓練,基于深度學習的系統可以給出最優規劃。 谷歌和李世石的人機大戰引爆了公眾對于人工智能的關注,也讓基于深度學習的人工智能成為汽車業界關注的重點,那么深度學習在智能駕駛的應用場景下有什么幫助呢?自動駕駛最先出現在美國,而不是歐洲或者日本...
摘要:年新星調查中顯示,越來越流行,其熱度已經逐漸超過了。及其框架位于全球最受歡迎使用最廣泛的技術榜榜首。本文轉載自框架的游戲年流行趨勢英文原文JavaScript 生態系統復雜多變,各種框架讓人眼花繚亂。究竟孰優孰劣,如今的發展趨勢是怎樣的,用人單位又需要怎樣的人才?本文站在一個中立者的角度,客觀分析了當前這場框架的游戲中,JavaScript 的流行趨勢。 Javascript 的生態環境讓我...
閱讀 3674·2021-09-02 15:11
閱讀 4619·2021-08-16 10:47
閱讀 1573·2019-08-29 18:35
閱讀 3054·2019-08-28 17:54
閱讀 2858·2019-08-26 11:37
閱讀 1512·2019-08-23 16:51
閱讀 1820·2019-08-23 14:36
閱讀 1816·2019-08-23 14:21