【像素画板】游戏地图编辑器-uniapp项目开发流程详解

news2025/1/19 23:15:50

嘿,用过像素画板没有哦,相信喜欢绘画的小朋友会对它感兴趣呢,用来绘制像素画非常好看,有没有发现,它是可以用来绘制游戏地图的,是不是很好奇,来一起看看吧。

像素画板,也叫像素画的绘图工具,可绘制游戏素材,也是游戏地图编辑器

文章目录

  • 游戏地图
  • 创建项目
  • 初始页面
  • 画板页面
    • 初始化数据
    • 初始化画布
    • 触摸操作
    • 绘制逻辑
  • 运行项目
    • 像素画
    • 迷宫地图

游戏地图

有个案例,绘制的游戏地图在以下两个游戏中都有用到,可以看一看这两篇文章

  • 地下迷宫游戏-微信小程序开发流程详解

创建项目

这里用HBuilderX开发工具来创建一个uniapp项目,

例如项目名填写uniapp_map_edit,依次选择如下图
在这里插入图片描述

  • 选择新建uni-app项目
  • 使用默认模板
  • Vue版本选择 3

初始页面

这时项目是自动创建好的,找一找初始页面,

页面文件在项目里/pages/index.index.vue,打开文件修改布局,

要在<template>...</template>标签中修改布局

布局结果显示如下图
在这里插入图片描述

可以看到,页面使用了表单组件form

  • 一个滑块slider,设置画板像素宽度,也就是列数;
  • 一个多行输入框textarea,这里放置输出的地图数据,可直接修改,复制;
  • 三个按钮button,见名知意,什么用途不用多说吧

点击编辑地图数据按钮,就会跳转到画板页面了,

要在<script>...</script>标签中去写页面跳转javascript逻辑代码,很简单,自己能做出来,这里就不讲

画板页面

这个画板页面文件是没有的,需要自己创建一个,

创建页面文件在项目里/pages/game/game.vue

然后打开,同样是在<template>标签中修改,写好布局,显示页面如下图
在这里插入图片描述

从页面上看,布局中只用了一个canvas,和复选框,还有7个迷你按钮组件,

  • 复选框checkbox-groupcheckbox是控制是否显示绘制网格线的;
  • 7个迷你按钮button size="mini",从中选择一个像素来绘制,每个像素点表示不同的颜色;
  • 像素点可以表示数字,例如0,1,2,3,4...e,f
  • 游戏地图是用字节数字来表示的,占用内存少;

初始化数据

同样也是在<script>标签里去写逻辑代码

写好初始化逻辑,代码如下,

const app = getApp()
export default {
	data() {
		return {
			isShowGrids: true, //是否显示网格
			//所有按钮数据:文本,数值,颜色
			buttons: [{
					text: '0',
					value: '0',
					color: 'transparent'
				},
				//...
				{
					text: '6',
					value: '6',
					color: '#909399'
				},
			],
			currentKey: '1' //定义选择的按钮,如不同的画笔按钮
		};
	},
	/** 页面加载完毕会执行到这里 */
	onReady() {
		let {
			map, //地图数据
			cols //列数
		} = app.getMapData() //获取初始页面保存好的数据
		this.cols = cols
		//执行加载初始化方法
		this.load(map)
	},
	methods:{
		//...
		onTouchStart(e){...},
		onTouchMove(e){...},
		onTouchEnd(e){...},
	}
}

data()方法返回的是页面布局中使用到的数据,

做到这里,上面的画布页面就会显示好底部的一排按钮了,

如果显示效果不一样,就要调整布局对应样式,就在<style>...</style>标签中写CSS样式,

初始化画布

还有就是画布,现在还没有显示出来,继续写初始化画布代码,

methods里写加载的load(map)方法,代码如下

load(map) {
	const {
		cols
	} = this
	uni.createSelectorQuery().select('#' + canvasId).fields({
		size: true
	}, res => {
		//定义画布数据
		this.canvasData = {
			canvas: {
				width: res.width,
				height: res.height
			},
			ctx: uni.createCanvasContext(canvasId)
		};
		//调用初始化画布方法
		this.initCanvas(map, cols || 24)
	}).exec()
},

同样的,调用的initCanvas(map, cols)方法也是在methods里面写,代码如下

initCanvas(map, cols) {
	const {
		ctx,
		canvas
	} = this.canvasData
	//计算出每个单元格大小
	const size = Math.floor(canvas.width / cols)
	//计算出铺满网格的行数
	const rows = Math.floor(canvas.height / size)
	//...
	const grids = []
	//...
	// 绘制网格,r是行数,c是列数
	for (let r = 0, i = 0; r < rows; r++) {
		for (let c = 0; c < cols; c++, i++) {
			let g = {
				x: c * size + paddingLeft, //位置x paddingLeft是左边距
				y: r * size + paddingTop,
				//...
				v: '0' //像素初始数据
			}
			//...
			grids.push(g)
		}
	}
	//将计算出的数据放到canvasData数据中,下次会读取到
	Object.assign(this.canvasData, {
		grids, //这是网格的数据
		size,
		//...
		rows
	})
	//调用重新绘制方法
	this.redraw()
},

触摸操作

画布显示出来以后,就要实现触摸绘制,

看之前的代码,有如下三个方法,分别是触摸开始,移动,结束事件调用的方法,就在这方法中实现

export default {
	//...
	methods:{
		//...
		onTouchStart(e){...},
		onTouchMove(e){...},
		onTouchEnd(e){...},
	}
}

在布局中的canvas组件需要加上属性关联绑定上面的三个方法

当用户触摸画布时,就在画布中画出一个点就可以了,代码如下

onTouchStart(e) {
	let touch1 = e.touches[0]
	//调用此方法,根据第一个触摸点查找网格中单元格的索引
	let index = this.findGridIndex(touch1);
	//如果没有在网格内,就返回
	if (index < 0) return;
	
	//...这是第二个触摸点,如果有的话,就实现触摸拖动像素点,来达到准确绘制
	let touch2 = e.touches[1]
	//...省略了

	//如果是点击,直接调用触摸移动方法即可,避免重复写
	this.onTouchMove(e)
},

调用触摸移动方法里实现了如何绘制像素点,代码如下

onTouchMove(e) {
	//如果是同时存在两个触摸点,就是拖动操作
	let isMove = e.touches.length > 1
	let touch = isMove ? e.touches[1] : e.touches[0];
	const {
		grids
	} = this.canvasData;
	const {
		currentKey
	} = this;

	if (isMove && this.selectGrids.grid) {
		//...处理拖动操作的
	}

	let index = this.findGridIndex(touch);
	if (index < 0) return;
	let grid = grids[index];

	//...
	//更新指定的像素信息
	Object.assign(grid, {
		v: currentKey,
		color: this.findCurrentColor(currentKey) //将数值转换为按钮对应的颜色方法
	});
	//调用重绘方法
	this.redraw();
},

这个触摸移动方法可以实现连续绘制像素点,就像画一条线,

在触摸结束的方法这里,如下代码,

onTouchEnd(e) {
	if (!e || e.touches.length > 0) return
	//...触摸多点触摸操作的
},

这个触摸结束方法是可有可无的,如果实现多点触摸就要去写

绘制逻辑

知道为什么叫重绘方法吗,它就用刷新逻辑来实现的,

绘制方法redraw(),代码如下,先擦干净,再画上去

redraw() {
	const {
		canvas,
		ctx,
		grids,
		size,
		rows,
		cols
	} = this.canvasData
	const {
		isShowGrids
	} = this
	//擦画板
	ctx.clearRect(0, 0, canvas.width, canvas.height)
	//设置画笔颜色
	ctx.strokeStyle = '#000000'
	ctx.fillStyle = '#ffffff'
	//画背景色,如果想背景透明,就注释掉这一行
	ctx.fillRect(0, 0, canvas.width, canvas.height)
	//定义单元格的一半大小
	let r = size / 2;
	for (let r = 0; r < rows; r++) {
		for (let c = 0; c < cols; c++) {
			let g = grids[r * cols + c]
			ctx.beginPath()
			if (g.v != '0') {
				//画颜色的
				ctx.fillStyle = g.color
				ctx.fillRect(g.x, g.y, size, size)
			} else if (isShowGrids) {
				//画网格的
				ctx.strokeRect(g.x, g.y, size, size)
			}
		}
	}
	//最后调用这个方法就绘制出来了
	ctx.draw(true)
},

看上面的方法是不是很简单,容易理解呢

运行项目

讲到这里,像素画板的小程序项目基本上就算做好了,可以编译运行,接下来看看效果

像素画

想当像素画板用,看看作者随便画的一个二哈,如下图,
在这里插入图片描述

这是像素画,笔者画得好看吗 (^o^);
对画画感兴趣的话,就自己想象画出来也好看的

如果调整的像素太细的话,或者网格列数过多,这是不好控制的,

这样,就要用两个手指触摸操作,项目里实现多点触摸操作逻辑是有点复杂的,

实现操作就是用一个手指按住画板,另一个手指去拖动,就会发现按住的像素点拖出来了,继续拖动到指定的位置即可,这就准确绘制了

迷宫地图

要想用来绘制游戏地图,例如迷宫地图,运行效果动图如下,
请添加图片描述

底部最后边的按钮是作者在项目里新加的预览图片功能,可以保存为图片的;
绘制好返回初始页面,可以看到显示导出的地图数据,

从上图中可以看到画出来导出的一串数字,点击复制地图数据按钮,然后粘贴到自己编写的小游戏程序中当新关卡地图用,

还可以绘制出2d像素人,像素地图,瓦片地图等,能想到的你都能用得上吧

例如,给地下迷宫游戏项目添加新的游戏地图,用法同如下代码

// 迷宫地图数据
const mapData1 = {
	map:' 111111111111111111111111101100010001000000000001000101101010101110101111111010101101010100000101000000010101101010111111101011111110101101010000000100010000000001101011101110101111111111101101000101000101000000000101101110101011101111111110101100010001010100010000000101111011111010111010111111101100010100010001010000000001101110101110101011101111111100000101000101000101000001111011101111101110101111101100010100000100000100000001101110111111111111101111101100000100000001000101000001111110101111101110111011111100000101000001010000010001101111101011111011111010101100000001010000010001000101111111111010101110101111101100000000010101000100000001101111101110101111101111101100000100000100000101000001111111111111111110111111111'
	cols: 27
}

导出的地图数据很长很长,粘贴时把后面多出的一串数字0去掉即可

想要项目源码在点这里查看下载,或者直接点这里搜索:像素画板,在本博客站内请放心下载,感谢支持!

可能手机上看不到,请改用电脑浏览器查看

请添加图片描述

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

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

相关文章

DeDeCMS v5.7 SP2 正式版 前台任意用户密码修改(漏洞复现)

1.环境搭建 PHP 5.6 DeDeCMSV5.7SP2 正式版 安装phpstudy&#xff0c;https://www.xp.cn/小皮面板 先启动Apache2.4.39和MySQL5.7.26 如果他会让你下载&#xff0c;点击是就好&#xff01; 让后点击网站—>点击创建网站 域名自己创建&#xff0c;自己取 其他的不变 点击…

iOS 自动签名打包,并用脚本上传appstore

背景&#xff1a; 1&#xff09;测试环境给测试&#xff0c;产品&#xff0c;或者其他业务人员打测试包时&#xff0c;经常存在需要添加设备&#xff0c;不得不重新生成描述文件&#xff0c;手动去更新打包机描述文件配置 2&#xff09;证书&#xff0c;描述文件过期造成打包失…

Session 与 JWT 的对决:谁是身份验证的王者? (上)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

树与二叉树堆:经典OJ题集(2)

目录 二叉树的性质及其问题&#xff1a; 二叉树的性质 问题&#xff1a; 一、对称的二叉树&#xff1a; 题目&#xff1a; 解题思路&#xff1a; 二、另一棵树&#xff1a; 题目&#xff1a; 解题思路&#xff1a; 三、翻转二叉树&#xff1a; 题目&#xff1a;…

windows如何配置java环境变量(java环境变量配置教程)

本文章以Windows为例记录Java环境变量配置详情。 笔者系统为windows10&#xff0c; JDK百度云链接放在文末有需要的可以下载。 当我们下载并安装好JDK后需要配置环境变量&#xff0c;否则无法方便的使用JDK中的工具进行Java源文件的编译及运行&#xff0c;或者其他工具的使用…

numpy知识库:基于numpy绘制灰度直方图

前言 对于灰度图像而言&#xff0c;灰度直方图可以统计灰度图像内各个灰度级出现的次数。 灰度直方图的横坐标是灰度图像中各像素点的灰度级。灰度的数值范围为[0, 255]。因此&#xff0c;如果将图像分为256个灰度级&#xff0c;那么每个灰度级唯一对应一个灰度&#xff1b;如…

分享一个大学生免费的资源网站(含考研资源,竞赛四六级)

今天不小心从其他地方链接到的网站&#xff0c;里面包含考考研资料&#xff0c;四六级相关的资料&#xff0c;重点都是免费的&#xff0c;部分资料可能需要登录或者关注公众号才可见&#xff0c;&#xff0c;网站链接了CSDN 能跳转到CSND, 网站地址 :忠哥资源共享http://jian…

奇技淫巧第9期

今天回顾一下 5~12 月所遇到的零碎知识点。 文章目录 歪门邪道优雅删除“学习资料”快速下载 vscode两种硬盘格式zotero在word中插入参考文献markdown 下划线查看 CPU Linux 命令postgres 无法通过 root 用户操作bash 初学者礼包gitwin 11 edge 浏览器0x80190001 报错 python …

inux基础项目开发1:量产工具——业务系统(七)

前言&#xff1a; 前面我们已经构造出来显示系统、输入系统、文字系统、UI系统、页面系统&#xff0c;这个项目百分之八十需要实现的都已经构建出来了&#xff0c;最后让我们对这个项目进行最后一项系统的搭建&#xff0c;也就是业务系统&#xff0c;说到业务大家应该就知道我们…

软件生命周期四个阶段SDLC

软件产品生命周期&#xff1a;指软件产品研发全部过程、活动和任务的结构框架。 产品的生命周期一般包括四个阶段&#xff1a;引入期、成长期、成熟期和衰退期&#xff0c;在不同的阶段中&#xff0c;市场对产品的反应不同&#xff0c;其销售特点不同&#xff0c;因而产品管理的…

Windows驱动中使用数字签名验证控制设备访问权限

1. 背景 在一般的驱动开发时&#xff0c;创建了符号链接后在应用层就可以访问打开我们的设备并进行通讯。 但我们有时候不希望非自己的进程访问我们的设备并进行交互&#xff0c;虽然可以使用 IoCreateDeviceSecure 来创建有安全描述符的设备&#xff0c;但大数的用户账户为了方…

【理解ARM架构】中断处理 | CPU模式

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《理解ARM架构》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 目录 &#x1f35c;中断&#x1f368;GPIO中断代码实现 &#x1f35c;CPU&#x1f368;CONTROL…

设计模式-结构型模式之装饰者设计模式

文章目录 六、装饰者模式 六、装饰者模式 装饰者模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其结构。它是作为现有的类的一个包装。 装饰类和被装饰类可以独立发展&#xff0c;不会相互耦合&#xff0c;装饰者模…

各大期刊网址

AAAL: http://dblp.uni-trier.de/db/conf/aaai/ CVPR: http://dblp.uni-trier.de/db/conf/cvpr/ NeurlPS:http://dblp.uni-trier.de/db/conf/nips/ ICCV: http://dblp.uni-trier.de/db/conf/iccv/ IJCAL: http://dblp.uni-trier.de/db/conf/ijcal/ 并非原创引…

Linux(12):磁盘配额(Quota)与进阶文件系统管理

磁盘配额&#xff08;Quota&#xff09;的应用与实作 Quota 的一般用途&#xff1a; 针对 www server &#xff0c;例如:每个人的网页空间的容量限制&#xff1b; 针对 mail server&#xff0c;例如:每个人的邮件空间限制。 针对 file server&#xff0c;例如:每个人最大的可用…

【开源】基于Vue+SpringBoot的康复中心管理系统

项目编号&#xff1a; S 056 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S056&#xff0c;文末获取源码。} 项目编号&#xff1a;S056&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 普通用户模块2.2 护工模块2.3 管理员…

详解Spring对Mybatis等持久化框架的整合

&#x1f609;&#x1f609; 学习交流群&#xff1a; ✅✅1&#xff1a;这是孙哥suns给大家的福利&#xff01; ✨✨2&#xff1a;我们免费分享Netty、Dubbo、k8s、Mybatis、Spring...应用和源码级别的视频资料 &#x1f96d;&#x1f96d;3&#xff1a;QQ群&#xff1a;583783…

最大单词数算法分析

题目描述&#xff1a; 算法一&#xff1a; 代码实现&#xff1a; # include<stdio.h> # include<string.h>int main(){//char text[100]"leet code";//char brokenLetters[26]"lt";char text[100]"hello world";char brokenLetters…

28、DS18B20温度传感器

DS18B20介绍 DS18B20是一种常见的数字温度传感器&#xff0c;其控制命令和数据都是以数字信号的方式输入输出&#xff0c;相比较于模拟温度传感器&#xff0c;具有功能强大、硬件简单、易扩展、抗干扰性强等特点 测温范围&#xff1a;-55C 到 125C 通信接口&#xff1a;1-Wire…

常见的线程安全问题及解决

1. 什么是线程安全 线程安全指的是当多个线程同时访问一个共享的资源时&#xff0c;不会出现不确定的结果。这意味着无论并发线程的调度顺序如何&#xff0c;程序都能够按照设计的预期来运行&#xff0c;而不会产生竞态条件&#xff08;race condition&#xff09;或其他并发问…