使用【码上掘金】开发一个穿越类小游戏

1,730 阅读11分钟

我正在参加掘金社区游戏创意投稿大赛团队赛,详情请看:游戏创意投稿大赛
我正在参加 码上掘金体验活动,详情:show出你的创意代码块

先上一下效果,希望能吸引到大家

1650173354(1).png
猪八戒拜师孙悟空打败沙悟净的剧情您看过么???
如果您感兴趣不妨看一下我是怎么实现的
在线体验地址:code.juejin.cn/pen/7087376…

前言

前几天,在某小视频app上看到了一个挺有意思的视频。大致的内容就是up主假设自己穿越到不同的世界线中。然后根据自己预制的剧情,随机西游记的任务编写剧情。正巧掘金出了一个码上掘金,我们就使用码上掘金实现做一个穿越类小游戏

如何使用【码上掘金】

  1. 我们登录掘金账号之后,访问这个地址:code.juejin.cn/ 然后点击左侧的【新建代码片段】-【新建空白片段】,进入【码上掘金】的个人程序开发页面
  2. 我们看一下开发页面有哪些东西 1650174067(1).png
  3. 项目名称
  4. html开发区域
  5. 样式开发区域
  6. js开发区域
  7. 布局设置区域
  8. 编译运行按钮
  9. 保存按钮
  10. 发布按钮
  11. 预览区域 话不多说,我们开始开发

功能开发

源代码

我先把所有代码贴出来,大家可以复制到自己对应的开发页面
MarkUp

<div id="app">
  <div id="home">
    欢迎体验【穿越人生】游戏。<br />
    在本游戏中,您将体验不同时间线中的人生。<br />
    如果您准备好了,<a href="#" id="toChooseGame">点我开始游戏</a>
  </div>
  <div id="chooseGame">
    请选择世界:<select id="play_word_select"></select>
    请选择剧本类型:<select id="play_type_select"></select>
    <a href="#" id="generate_play">就决定是这样了</a>
  </div>
  <div id="content">
  </div>
</div>

Style
注意,这里选择Less编译

#app{
  text-align: center;
  #chooseGame {
  display: none;
  }
}

Script

const play_word = [
  { name: "西游记", word: "xi_you_ji" },
  { name: "三国演义", word: "san_guo_yan_yi" },
  { name: "水浒传", word: "shui_hu_zhuan" },
  { name: "红楼梦", word: "hong_lou_meng" }
]
const play_peoples = {
  xi_you_ji: [
    "唐僧", "孙悟空", "猪八戒", "沙悟净", "小白龙敖烈", "菩提祖师", "玉皇大帝", "千里眼", "顺风耳", "太上老君", "武曲星君", "托塔天王", "巨灵神", "二郎神", "梅山六兄弟", "四海龙王", "十殿阎王", "土地", "镇元子大仙", "灵吉菩萨", "观音菩萨", "普贤菩萨", "文殊菩萨", "北方真武大帝", "接引佛祖", "燃灯古佛", "白雄尊者", "十八罗汉", "五百阿难", "三千揭蒂", "寅将军", "熊山君", "特处士", "刘伯钦", "黑熊怪", "凌虚子", "白衣秀士", "虎先锋", "黄风怪", "白骨精", "黄袍怪", "宝象国国王", "宝象国公主", "金角大王", "银角大王", "九尾老狐狸", "狐阿七大王", "巴山虎", "倚海龙", "精细鬼", "伶俐虫", "狮猁怪", "乌鸡国国王", "乌鸡国王后", "乌鸡国太子", "红孩儿", "小鼍龙", "虎鹿羊三力大仙", "灵感大王", "青兕怪(青牛精)", "女儿国国王", "蝎子精", "六耳猕猴", "铁扇公主", "牛魔王", "玉面狐狸"
  ],
  san_guo_yan_yi: [
    "荀彧", "荀攸", "贾诩", "郭嘉", "程昱", "戏志才", "刘晔", "蒋济", "陈群", "华歆", "钟繇", "满宠", "董昭", "王朗", "崔琰", "毛玠", "杜畿", "田畴", "王修", "杨修", "辛毗", "杨阜", "田豫", "王粲", "蒯越", "张继", "杜袭", "枣祗",

    "任峻", "陈矫", "郗虑", "桓玠", "丁仪", "丁廙", "司马朗", "韩暨", "韦康", "邴原", "赵俨", "娄圭", "贾逵", "陈琳", "司马懿", "张辽", "徐晃", "夏侯惇", "夏侯渊", "庞德", "张郃", "李典", "乐进", "典韦", "曹洪", "曹仁", "曹彰",

    "曹纯", "于禁", "许褚", "吕虔", "李通", "文聘", "臧霸", "郭淮", "钟会", "邓艾", "曹休", "张燕", "张绣", "朱灵", "路昭", "史涣", "韩浩", "王凌", "孙礼", "秦朗", "郑文", "夏侯尚", "毌丘俭", "诸葛诞",
    "孙乾", "简雍", "糜竺", "糜芳", "庞统", "法正", "许靖", "马良", "徐庶", "陈震", "杨仪", "费祎", "蒋琬", "孟优", "黄皓", "诸葛亮", "关羽", "张飞", "马超", "黄忠", "赵云", "魏延", "关平", "周仓", "关兴", "张苞", "陈到",

    "李严", "姜维", "廖化", "马谡", "马岱", "陈式", "雷铜", "吴兰", "王平", "任夔", "张翼", "马忠", "张南", "冯习", "傅佥", "关索",
    "陆逊", "张昭", "张紘", "鲁肃", "虞翻", "顾雍", "诸葛谨", "诸葛恪", "陆凯", "骆统", "周鲂", "周瑜", "吕蒙", "甘宁", "太史慈", "程普", "黄盖", "韩当", "周泰", "蒋钦", "丁奉", "徐盛", "陈武", "凌操", "凌统", "潘璋", "朱然", "孙桓", "马忠", "孙韶", "朱桓", "夏恂", "周平", "全琮", "于诠",
    "张角", "何进", "董卓", "袁绍", "吕布", "袁术", "刘表", "刘璋", "马腾", "张鲁", "韩遂", "公孙瓒", "韩馥", "刘岱", "王匡", "张邈", "孔伷", "陶谦", "鲍信", "桥瑁", "袁遗", "孔融", "张超", "张杨", "刘度", "赵范", "金旋", "韩玄",
    "董承", "王子服", "李儒", "陈宫", "田丰", "沮授", "审配", "许攸", "郭图", "逢纪", "辛评", "荀谌", "辛毗", "陈登", "蒯良", "王累", "韩胤", "沮鹄", "杨弘", "阎象", "蒯越", "伍孚", "李傕", "郭汜", "颜良", "文丑", "潘凤",

    "俞涉", "武安国", "穆顺", "华雄", "牛辅", "张济", "樊稠", "胡轸", "胡车儿", "李肃", "高顺", "张任", "高览", "曹性", "闵纯", "纪灵", "马休", "马铁", "高览", "袁谭", "袁熙", "袁尚", "高干", "麴义", "吕翔", "吕旷",
    "韩猛", "淳于琼", "焦触", "张南", "马延", "雷薄", "张勋", "陈纪", "桥蕤", "郝萌", "侯成", "宋宪", "魏续", "成廉", "蔡瑁", "张允", "黄祖", "苏飞", "吕公", "侯选", "程银", "李堪", "张横", "梁兴", "成宜", "马玩", "杨秋"
  ],
  shui_hu_zhuan: [
    "宋江", "卢俊义", "吴用", "公孙胜", "关胜", "林冲", "秦明", "呼延灼", "花荣", "柴进", "李应", "朱仝", "鲁智深", "武松", "董平", "张清", "杨志", "徐宁", "索超", "戴宗", "刘唐", "李逵", "史进", "穆弘", "雷横", "李俊", "阮小二", "张横", "阮小五", "张顺", "阮小七", "杨雄", "石秀", "解珍", "解宝", "燕青", "朱武", "黄信", "孙立", "宣赞", "郝思文", "韩滔", "彭玘", "单廷珪", "魏定国", "萧让", "裴宣", "欧鹏", "邓飞", "燕顺", "杨林", "凌振", "蒋敬", "吕方", "郭盛", "安道全", "皇甫端", "王英", "扈三娘", "鲍旭", "樊瑞", "孔明", "孔亮", "项充", "李衮", "金大坚", "马麟", "童威", "童猛", "孟康", "侯健", "陈达", "杨春", "郑天寿", "陶宗旺", "宋清", "乐和", "龚旺", "丁得孙", "穆春", "曹正", "宋万", "杜迁", "薛永", "施恩", "李忠", "周通", "汤隆", "杜兴", "邹渊", "邹润", "朱贵", "朱富", "蔡福", "蔡庆", "李立", "李云", "焦挺", "石勇", "孙新", "顾大嫂", "张青", "孙二娘", "王定六", "郁保四", "白胜", "时迁", "段景住"
  ],
  hong_lou_meng: [
    "贾珍", "尤氏", "茄官", "银蝶儿", "万儿", "来升", "喜儿", "寿儿", "栓儿", "贾惜春", "入画", "彩屏", "彩儿", "贾蓉", "秦可卿", "瑞珠", "宝珠", "焦大", "王兴", "潘又安",
    "贾母", "鸳鸯", "文官", "琥珀", "蕊珠", "翡翠", "玻璃", "傻大姐", "鹦鹉", "贾赦", "邢夫人", "秋桐", "费婆子", "王善保家的(陪房)", "贾政", "王夫人", "金钏", "玉钏", "彩霞", "彩云", "彩鸾", "绣鸾", "绣凤", "小霞", "周瑞", "周瑞家的(陪房)",
    "贾宝玉", "袭人(蕊珠)", "晴雯", "麝月", "秋纹", "碧痕", "春燕", "四儿", "芳官", "茜雪", "佳蕙", "坠儿", "檀云", "绮霰", "良儿", "媚人", "墨雨", "紫绡", "李嬷嬷(奶母)", "宋嬷嬷", "茗烟", "扫红", "锄药", "伴鹤", "李贵", "扫花", "引泉", "挑云", "双瑞", "双寿",
    "贾琏", "王熙凤", "平儿", "小红", "丰儿", "彩明", "彩哥", "来旺妇(凤姐陪房)", "昭儿", "旺儿", "隆儿", "兴儿", "庆儿", "善姐", "王信", "林之孝", "林之孝家的", "赵嬷嬷(贾琏奶母)", "贾元春", "抱琴", "青芸", "琴韵",
    "贾迎春", "司棋", "绣橘", "莲花儿", "柱儿妈(奶母)", "柱儿媳妇", "王善保家的(司棋姥姥)", "贾探春", "侍书", "艾官", "翠墨", "小蝉", "贾惜春", "入画", "彩屏", "彩儿", "李纨", "素云", "碧月", "林黛玉", "雪雁", "紫鹃(鹦哥)", "春纤", "藕官", "王妈妈(奶母)", "王子腾", "史湘云", "翠缕(缕儿)", "葵官", "周奶妈", "薛姨妈", "同喜", "同贵", "薛宝钗", "莺儿", "文杏", "蕊官", "薛蟠", "夏金桂", "宝蟾", "小舍儿", "香菱(甄英莲)", "臻儿", "薛蝌",
    "邢岫烟", "篆儿", "薛宝琴", "小螺", "豆官(豆童)"
  ],
}
const play_type = [
  { name: "玄幻", type: "xuan_huan" },
  { name: "武侠", type: "wu_xia" },
  { name: "都市", type: "du_shi" },
  { name: "官斗", type: "guan_dou" },
]
const play_plot = {
  "xuan_huan": [
    "从小和你青梅竹马的人是:",
    "你的幼年师傅是:",
    "因你经脉尽废,侮辱你的人是:",
    "他的出现使你有了天灵根,这个人是:",
    "你被超级大宗看上了,掌门竟然是:",
    "你在宗门里遇到了你的意中人,这个人是:",
    "你为了拯救世界,要打败的人是:",
    "在这个人的帮助下,你成功拯救了世界:",
    "你拯救了世界,诸天皆知你的名,你是:"
  ],
  "wu_xia": [
    "小时候整天跟在你后边的跟班是:",
    "你们一起参加了武当派的入门筛选,这个人是:",
    "在武当派,你遇到了你的初恋,这个人是:",
    "你被同门暗算,掉落山崖。暗算你的人是:",
    "你在涯底遇到了绝世高手,这个人是:",
    "勤练神功,终有所成,你用神功打败的第一个人是:",
    "参加武林大会比武,你遇到了你的羁绊。这个人是:",
    "你在比武大会决赛对手是:",
    "你成为了武林至尊。有人因嫉生恨,勾结外邦来犯。这个人是:",
    "在这个人的帮助下,你成功打败了敌军:",
    "你扶大厦之将倾,事成后归隐田园,你是:"
  ],
  "du_shi": [
    "今年你毕业了,和你一起租房的人是:",
    "你在这个人的帮助下取得了第一桶金:",
    "你在2021年买了中概互联网的基金,推荐人是:",
    "你参加了一档创业真人秀节目,你的导师是:",
    "你画的饼又大又圆,获得了这个人的投资:",
    "投资非常成功,你觉得要和这个人一起分享你的喜悦:",
    "你被最信任的人背叛了,这个人是:",
    "你一无所有,辛亏有这个人的帮助才能吃一顿饱饭:",
    "你拿着拾破烂换的两元钱,在这个人的彩票站中了一个小目标:",
    "你被外星人选中,在这个人的哀求下,外星人给了你光刻机技术:",
    "你将光刻机技术以股代捐贡献给兔子家,青史留名,你是:"
  ],
  "guan_dou": [
    "你和这个人一起参加乡试。这个人是:",
    "你参加了殿试,最终靠才学打败了这个人:",
    "黄河决堤。你救灾有功,得到了这个人的举荐:",
    "你在朝中正义直言,得罪了这个人:",
    "因为救这个人,你被圣人呵斥:",
    "天下大旱,圣人派你和这个人救灾:",
    "这个人德不配位,你抢了敌对势力的肥缺:",
    "圣人游玩失踪,局势风云变幻。这个人隐隐有得位之势:",
    "最终这个人发动政变,在朝堂夺势成功:",
    "上位者无能昏庸,这个人和你协议起事:",
    "在这个人的帮助下,你取得了大宝:",
    "千古一帝,万事留名,你是:"
  ],
}
const dom = document

dom.getElementById("toChooseGame").onclick = function () {
  dom.getElementById("home").style.display = "none";
  dom.getElementById("chooseGame").style.display = "block";
  let play_word_select = dom.getElementById("play_word_select")
  play_word.forEach(item => {
    play_word_select.add(new Option(item.name, item.word))
  })
  let play_type_select = dom.getElementById("play_type_select")
  play_type.forEach(item => {
    play_type_select.add(new Option(item.name, item.type))
  })
}
dom.getElementById("generate_play").onclick = function () {
  let word = dom.getElementById("play_word_select").value;
  let type = dom.getElementById("play_type_select").value;
  let content = dom.getElementById("content")
  let generate_word = "欢迎来到新的世界线<br />";
  content.innerHTML = generate_word
  let startIndex = 0
  //从word取人,从type取剧情
  let timer = setInterval(() => {
    generate_word += play_plot[type][startIndex] + play_peoples[word][getRndInteger(1, play_peoples[word].length)] + "<br />"
    content.innerHTML = generate_word
    startIndex += 1
    if (startIndex === play_plot[type].length) {
      clearInterval(timer);
    }
  }, 500)
}
function getRndInteger(min, max) {
  return Math.floor(Math.random() * (max - min)) + min;
}

实现思路

因为我没有尝试过引入Vue或者React等js库,所以我全部使用原生开发的,下面我介绍一下实现的思路和步骤

首页设计

在首页上我们简答介绍一下这个游戏是什么,然后添加一个快递入口,我们通过给a标签设置id标识,通过监听该元素的点击事件我们设置首页的div为display:none,隐藏它

主业务的步骤流程设计

我们在设置完首页display:none之后,下面我们开始分析一下我们的主要渲染流程
在首页disable时初始化世界和剧本选择器->用户选择之后,点击确认时根据选择select的value来生成剧本
我来说一下我的js代码逻辑
1: 首先定义我们的变量

  • play_word:选择的世界 name用来显示,word作为key值来寻找play_peoples中的用户
  • play_peoples:世界线下的人 key就是世界的key,值是世界线下的所有人
    即我选择word之后就可以获取word下的所有人
  • play_type:选择的剧本类型 name用来显示,type作为key值来寻找play_plot下的剧情
  • play_plot:世界线的剧本 key值就是剧本的key,值是该剧本的剧情 2: 我们定义完成自己的变量之后开始编写业务代码
  • 定义通用的dom
const dom = document
  • 监听id为toChooseGame的click事件,点击之后将首页设置为display:none,游戏页面设置为display:block。然后初始化世界和剧本的下拉选
dom.getElementById("toChooseGame").onclick = function () {
  dom.getElementById("home").style.display = "none";
  dom.getElementById("chooseGame").style.display = "block";
  let play_word_select = dom.getElementById("play_word_select")
  play_word.forEach(item => {
    play_word_select.add(new Option(item.name, item.word))
  })
  let play_type_select = dom.getElementById("play_type_select")
  play_type.forEach(item => {
    play_type_select.add(new Option(item.name, item.type))
  })
}
  • 监听生成剧情的按钮,点击之后,根据选择的key值来确认选择的世界和剧本,生成对应的剧情
dom.getElementById("generate_play").onclick = function () {
  let word = dom.getElementById("play_word_select").value;
  let type = dom.getElementById("play_type_select").value;
  let content = dom.getElementById("content")
  let generate_word = "欢迎来到新的世界线<br />";
  content.innerHTML = generate_word
  let startIndex = 0
  //从word取人,从type取剧情
  let timer = setInterval(() => {
    generate_word += play_plot[type][startIndex] + play_peoples[word][getRndInteger(1, play_peoples[word].length)] + "<br />"
    content.innerHTML = generate_word
    startIndex += 1
    if (startIndex === play_plot[type].length) {
      clearInterval(timer);
    }
  }, 500)
}
function getRndInteger(min, max) {
  return Math.floor(Math.random() * (max - min)) + min;
}

结语

我们使用【码上掘金】开发的时候,可能有一些不太熟悉,不过当我们以后如果开发需要简单预览的项目,完全可以不搭建环境,直接在网页上开发,还是挺方便的。建议就是希望【码上掘金】可以设置开发区域隐藏,现在三个div占用的比较小,开发起来不是很方便。