想画一个沙漠掘金游戏地图

想画一个沙漠掘金游戏地图

    • 沙漠掘金
    • 生成一个地图
      • html
      • js

沙漠掘金

沙漠掘金是一个企业培训课程游戏,规则大致是:

  1. 玩家从大本营出发,到达矿山掘金后返回,如果规定的天数未回来,则失败,如果回来,则算成功,按照挖取到的金子排名。
  2. 玩家携带一定量的食物、水,具有一定的负重。
  3. 地图分为:村庄、大本营、沙漠、王陵、大山。玩家可以在村庄和大本营补给,大本营、王陵会有特殊事件,大山可以挖到金子,沙漠地区则会遭遇高温和沙尘暴。
  4. 不同的地区和日期会有不同的天气:晴天、高温、沙尘暴。不同的天气消耗的水和食物不同。
  5. 出发可以携带道具:指南针和帐篷。但是会占用负重。

这个游戏有多个版本,大致的游戏内容都一样。

生成一个地图

从网上能找到好多地图,奈何不会P图,还想地图能动态生成,就写一个吧。

效果:

在这里插入图片描述

这里使用js的canvas生成。

具体生成逻辑:把一个画布分成一定数量的小格子,然后随机出固定个数的地图原点,遍历所有小格子,一遍一遍往原点上堆积,形成固定数量的区域。

html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Canvas</title><script src="./js/aa.js"></script><style>canvas{position: absolute;top: 100;left: 100;}#msg{display: inline-block;width: 200px;}</style>
</head>
<body><span>地图块数:</span><input type="number" id="nums"/><button onclick="generate()">开始生成</button><div id="msg"></div><div class="container"><canvas id="canvas" width="100" height="100" style="background-color: bisque;"></canvas></div>
</body></html>

js

let windowWidth;
let windowHeight;
let canvas;
// 数量dom
let nd;
let nn;
let ss = 5;
// 消息dom
let md;
let ctx;
// 画布宽带
let width;
// 画布高度
let height;
// 地图块之间的间隔
let gap = 1;
// 地图块大小
let tw = 5;
// 地图区域数量
let nums;
// 行数
let rn;
// 列数
let cn;
// 地图左右边距
let pw;
// 地图上下边距
let ph;
// 地图
let maps;
async function init() {windowWidth = window.innerWidth;windowHeight = window.innerHeight;width = windowWidth - 100 * 2;height = windowHeight - 100 * 2;cn = Math.floor((width + gap)/(tw + gap));rn = Math.floor((height + gap)/(tw + gap));width = cn * (tw + gap) - gap;height = rn * (tw + gap) - gap;pw = (windowWidth - width)/2;ph = (windowHeight - height)/2;canvas = document.getElementById('canvas');ctx = canvas.getContext('2d');canvas.style.top = ph + 'px';canvas.style.left = pw + 'px';canvas.width = width;canvas.height = height;let start = Date.now();await createMap();let end = Date.now();console.log(`计算图形耗时:${(end - start - nn*ss)/1000}s`);render(maps);}
/*** 随机一个数* @param {Number} min 下限* @param {Number} max 上限 * @returns */
function random(min, max) {if (max == min) {return min;}return Math.floor(Math.random() * (max - min + 1)) + min;
}
/*** 随机颜色*/
function getRandomHexColor() {  function getRandomHexDigit() {return Math.floor(Math.random() * 16).toString(16);  }  return `#${getRandomHexDigit()}${getRandomHexDigit()}${getRandomHexDigit()}${getRandomHexDigit()}${getRandomHexDigit()}${getRandomHexDigit()}`;  
}
/*** 创建地图* @returns 地图*/
async function createMap() {maps = [];nn = 0;console.log(`地图数量:${nums}`);let all = [];for (let i = 0; i < rn; i++) {for (let j = 0; j < cn; j++) {all.push({i: i,j: j});}}// 先随机出减去首尾的剩余节点let indexArr = new Array(all.length - 2).fill(0).map((item, index) => index + 1);for(let i = 0; i < nums; i++) {let index = random(0, indexArr.length - 1);let item = indexArr[index];indexArr.splice(index, 1);maps.push({i: all[item].i,j: all[item].j,links: [],start: false,end: false,color: getRandomHexColor(),type: 'shamo'});}// 标记区域类型,c村庄、皇陵、绿洲// 最靠近中间的两个点,标记为皇陵和绿洲// 远离中间的点,靠近大本营横坐标的一侧,随机出1/5,最小为1,也可以没有,的区域为村庄let center = { i: Math.floor(rn / 2), j: Math.floor(cn / 2) };let juliOrder = maps.filter(it => it.type == 'shamo');function getDir(p1, p2) {return Math.sqrt(Math.pow(Math.abs(p1.i - p2.i), 2) + Math.pow(Math.abs(p1.j - p2.j), 2));}juliOrder.sort((a, b) => {return getDir(a, center) - getDir(b, center);});// if (juliOrder.length > 2) {juliOrder[0].type = 'huangling';juliOrder[1].type = 'lvzhou';}// 随机出村庄juliOrder = juliOrder.slice(2);if (juliOrder.length > 0) {if (juliOrder.length < nums/5) {juliOrder.forEach(it => it.type = 'cunzhuang');} else {let nn = Math.floor(nums/5);for(let i = 0; i < nn; i++) {let item = juliOrder[juliOrder.length - i - 1];item.type = 'cunzhuang';}}}// 尝试扩充let copyAll = [...all].filter(item => !maps.find(map => map.i === item.i && map.j === item.j));let ijMap = copyAll.reduce((x,y) => {x[y.i + '_' + y.j] = y;return x;}, {});let msg = '';while (Object.keys(ijMap).length) {msg = `剩余节点数量:${Object.keys(ijMap).length}`;console.log(msg);renderMsg(msg);nn++;await sleep(ss);for (let i = 0; i < maps.length; i++) {let map = maps[i];let ps = [{i:map.i,j:map.j}, ...map.links];// 找到一个边界点let ks = ps;let kss = [];for(let k = 0; k < ks.length; k++) {// 四个位置,上下左右let dirs = [{i: 1, j: 0},{i: -1, j: 0},{i: 0, j: -1},{i: 0, j: 1}];kss.push(...dirs.map(dir => ({i: ks[k].i+dir.i, j: ks[k].j+dir.j})));}kss = kss.filter(p => p.i >= 0 && p.i < rn && p.j >= 0 && p.j < cn && ijMap[p.i + '_' + p.j]);if(!kss.length) {continue;}let dir = kss[random(0, kss.length - 1)];let key = dir.i + '_' + dir.j;let p = ijMap[key];if (p) {map.links.push(p);delete ijMap[key];}}}return Promise.resolve();
}
/*** 渲染出地图* @param {Object} maps 地图数据*/
function render(maps) {console.log('渲染地图', maps);let colorMap = maps.reduce((x,y) => {x[y.i + '_' + y.j] = y.color;y.links.forEach(p => {x[p.i + '_' + p.j] = y.color;});return x;}, {});ctx.clearRect(0, 0, width, height);for (let i = 0; i < rn; i++) {for (let j = 0; j < cn; j++) {ctx.fillStyle = colorMap[i + '_' + j] || '#fff';ctx.fillRect(j * (tw + gap), i * (tw + gap), tw, tw);}}
}
/*** 生成地图*/
function generate() {init();
}
function renderMsg(msg) {md.textContent = msg;
}
function sleep(time) {return new Promise(resolve => setTimeout(resolve, time));
}document.addEventListener('DOMContentLoaded', function() {nd = document.getElementById('nums');md = document.getElementById('msg');nd.value = nums = random(15, 50);nd.addEventListener('change', function() {let value = this.value;if (this.value <= 0) {value = 1;} else if (this.value > 100) {value = 100;}nd.value = nums = parseInt(value);});
});

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/7168.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【Java爬虫的淘宝寻宝记】—— 淘宝商品类目的“藏宝图”

引言&#xff1a; 在淘宝这个广袤的“商品宇宙”中&#xff0c;每一件商品都是一颗璀璨的星球&#xff0c;而商品类目就是连接这些星球的星际航道。今天&#xff0c;我们将派遣一位勇敢的Java爬虫宇航员&#xff0c;去揭开这些星际航道背后的秘密——商品类目。准备好了吗&…

内网穿透-SSF内网穿透反向socks代理之渗透内网thinkphp主机上线msf

1 ssf 简介 Secure Socket Funneling socks正反向代理&#xff0c;linux版较好的免杀 1.1下载地址 https://github.com/securesocketfunneling/ssf 1.2下载编译好的执行文件 https://github.com/securesocketfunneling/ssf/releases/tag/3.0.0 2.环境 kali 攻击机 网卡 桥…

【HarmonyOS】键盘遮挡输入框UI布局处理

【HarmonyOS】键盘遮挡输入框UI布局处理 问题背景&#xff1a; 在开发输入框UI时&#xff0c;特别是登录页面的密码输入框靠下&#xff0c;或者是评论底部的pop弹框。 当我们输入框获得焦点后&#xff0c;键盘自下而上显示&#xff0c;一般情况下会遮挡住我们的UI布局。 导致…

ssm基于BS的仓库在线管理系统的设计与实现+vue

系统包含&#xff1a;源码论文 所用技术&#xff1a;SpringBootVueSSMMybatisMysql 免费提供给大家参考或者学习&#xff0c;获取源码看文章最下面 需要定制看文章最下面 目 录 第一章 绪论 1 1.1 研究背景 1 1.2 研究意义 1 1.3 研究内容 2 第二章 开发环境与技术3 …

QML项目实战:自定义TextField

目录 一.添加模块 import QtQuick.Controls 1.2 import QtQuick.Controls.Styles 1.4 import QtGraphicalEffects 1.15 二.自定义TextField 1.属性设置 2.输入框设置 3.按钮开关 三.效果 1.readonly为false 2.readonly为true 四.代码 一.添加模块 import QtQuick.…

C++ | Leetcode C++题解之第523题连续的子数组和

题目&#xff1a; 题解&#xff1a; class Solution { public:bool checkSubarraySum(vector<int>& nums, int k) {int m nums.size();if (m < 2) {return false;}unordered_map<int, int> mp;mp[0] -1;int remainder 0;for (int i 0; i < m; i) {r…

AFL++实战入门与afl-fuzz流程解析(源码流程图)

简介 本项目为模糊测试的零基础教学,适合了解 pwn 且会使用 Linux 的 gcc、gdb 的读者。模糊测试旨在通过向程序投喂数据使其崩溃,从而获取崩溃样本以寻找程序漏洞。本文前半部分介绍 AFL++ 的 docker 环境配置,帮助读者解决入门时的环境和网络问题; 后半部分全面解析 afl…

Java 网络编程(一)—— UDP数据报套接字编程

概念 在网络编程中主要的对象有两个&#xff1a;客户端和服务器。客户端是提供请求的&#xff0c;归用户使用&#xff0c;发送的请求会被服务器接收&#xff0c;服务器根据请求做出响应&#xff0c;然后再将响应的数据包返回给客户端。 作为程序员&#xff0c;我们主要关心应…

用Python脚本执行安卓打包任务

这个样例是基于windows系统写的python打包安卓的脚本&#xff1a; 一、配置AndroidStudio下的打包任务 1.在Android项目根目录下的build.gradle文件配置生成Release包的任务&#xff1a; task cleanAll(type: Delete) {delete rootProject.buildDirrootProject.subprojects.e…

C++学习笔记----9、发现继承的技巧(六)---- 有趣且令人迷惑的继承问题(7)

6、非公共继承 在前面所有的例子中&#xff0c;父类总是用public关键字列出。你可能会想是否父类也可以是private或protected。实际上&#xff0c;是可以的&#xff0c;但都不像public一样常见。如果不对父类进行访问指示符的指定&#xff0c;对于类来讲就是private继承&#x…

Linux服务控制及系统基本加固

一. liunx操作系统的开机引导的过程 1. 开机自检 根据bios的设置&#xff0c;对cpu,内存&#xff0c;显卡&#xff0c;键盘等等设备进行初步检测如果以上检测设备工作正常&#xff0c;系统会把控制权移交到硬盘 总结:检测出包含系统启动操作系统的设备&#xff0c;硬盘&#…

k8s 处理namespace删除一直处于Terminating —— 筑梦之路

问题现象 k8s集群要清理某个名空间&#xff0c;把该名空间下的资源全部删除后&#xff0c;删除名空间&#xff0c;一直处于Terminating状态&#xff0c;无法完全清理掉。 如何处理 为什么要记录下这个处理的步骤&#xff0c;经过查询资料&#xff0c;网上也有各种各样的方法&…

百货零售行业信息化蓝图整体规划方案|165页PPT

文件《百货零售行业信息化蓝图整体规划方案》是一份针对百货零售行业的信息化转型和供应链低碳解决方案的详细规划报告。以下是对报告的主要内容的分析和总结&#xff1a; 1. 项目概况 议程&#xff1a;包括项目概况、蓝图工作汇报、业务方案概览、详细业务方案、下阶段工作计…

SQL,力扣题目571, 给定数字的频率查询中位数

一、力扣链接 LeetCode_571 二、题目描述 Numbers 表&#xff1a; ------------------- | Column Name | Type | ------------------- | num | int | | frequency | int | ------------------- num 是这张表的主键(具有唯一值的列)。 这张表的每一行表示某个数…

move_base

move_base 官方介绍&#xff1a;http://wiki.ros.org/move_base 如果在仿真环境下&#xff0c; sensor source、odometry source 和 sensor transforms 都已提供好&#xff0c;我们只需要完成以下部分&#xff1a; 一、编写导航程序 ①创建 ROS 工作空间 和 pkg 包 mkdir -p …

标签权重的计算方法之贝叶斯平滑

贝叶斯平滑&#xff08;Bayesian Smoothing&#xff09;是一种平滑技术&#xff0c;用于解决评分和标签数据中的样本稀疏性问题。在某些推荐系统或广告点击率预估的场景中&#xff0c;我们可能会遇到标签&#xff08;例如点击次数和曝光次数&#xff09;不均衡的问题&#xff0…

QML项目实战:自定义Switch按钮

目录 一.添加模块 1.QtQuick.Controls 2.1 2.QtGraphicalEffects 1.12 二.自定义Switch 三.标签 四.效果 五.代码 一.添加模块 1.QtQuick.Controls 2.1 QtQuick.Controls 提供了一组预定义的 UI 控件&#xff0c;这些控件可以用于构建现代、响应式的用户界面。它包括按…

【勘误笔记】J-LINK连接不上芯片问题

1. 常见的问题 https://mp.weixin.qq.com/s/Ik1czY0jiUkZK21qmeF-yA#rd 2. 记录问题 烧录的固件起始地址为0x08004000 芯片烧录后导致&#xff0c;后面使用J-LINK怎么样都连接不上&#xff0c; 当时硬件是BOOT 0接地应该是上电进入flash代码有问题 考虑到启动模式 把BOOT 0不…

职场高手揭秘,细节如何左右你的成败与升迁之路

身在职场&#xff0c;每一个人都想得到老板的器重&#xff0c;能不断地加薪、升职&#xff0c;从而获得职场的成功。但你知道&#xff0c;影响一个人职场成功&#xff0c;或者说影响升职加薪的最重要因素是什么吗&#xff1f; 许多人会说那要靠运气&#xff0c;也有人认为工作…

SSM大学生校园交流论坛-计算机设计毕业源码31910

摘 要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了大学生校园交流论坛的开发全过程。通过分析大学生校园交流论坛管理的不足&#xff0c;创建了一个计算机管理大学生校园交流论坛的方案。文章介绍了大学生校园交…