[Pixel Drawing Board] Game Map Editor-Detailed explanation of uniapp project development process

Hey, have you ever used a pixel drawing board? I believe that children who like painting will be interested in it. It is very nice to use to draw pixel paintings. Have you found out that it can be used to draw game maps? Are you curious? Come and join us. Let's see.

Pixel drawing board, also called pixel drawing drawing tool, can draw game materials and is also a game map editor.

game map

There is a case where the game map drawn is used in the following two games. You can take a look at these two articles.

Create project

Here we useHBuilderX development tool to create a uniapp project,

For example, fill in the project nameuniapp_map_edit, and select the following picture in sequence
Insert image description here

  • SelectNew uni-app project
  • UseDefault template
  • Vue versionSelection 3

Initial page

At this time, the project is automatically created. Look for the initial page.

The page file is in the project/pages/index/index.vue, open the file to modify the layout,

To modify the layout in<template>...</template> tag

The layout result is displayed as shown below
Insert image description here

You can see that the page uses form componentsform,

  • A sliderslider, sets the pixel width of the artboard, that is, the number of columns;
  • A multi-line input boxtextarea, where the output map data is placed and can be directly modified and copied;
  • Three buttonsbutton, you know the meaning by name, no need to say more about its purpose

Click the edit map data button and you will jump to the drawing board page.

You need to write the page jump logic code in the<script>...</script> tag. It is very simple. You can do it yourself, so I won’t go into it herejavascript

Artboard page

This artboard page file does not exist, you need to create one yourself.

Create page file in project/pages/game/game.vue,

Then open it, also modify it in the <template> tag, write the layout, and display the page as shown below
Insert image description here

From the page, only one canvas and 复选框 are used in the layout, and there are 7 more迷你按钮 components,

  • The checkboxcheckbox-group and checkbox control whether to display and draw grid lines;
  • 7 mini buttonsbutton size="mini", select a pixel to draw, each pixel represents a different color;
  • pixels can represent numbers, such as0,1,2,3,4...e,f;
  • The game map is represented by byte numbers and takes up less memory;

Initialization data

Also write logic code in<script> tag

Write the initialization logic, the code is as follows,

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()The method returns the data used in the page layout.

After doing this, the canvas page above will display the bottom row of buttons.

If the display effect is different, you need to adjust the corresponding style of the layout, just write the CSS style in the <style>...</style> tag,

Initialize canvas

There is also the canvas, which is not displayed yet. Continue to write the code to initialize the canvas.

Write the loading method inmethods, the code is as followsload(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()
},

Similarly, the calledinitCanvas(map, cols) method is also written inmethods, the code is as follows

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()
},

Touch operation

After the canvas is displayed, touch drawing must be implemented.

Looking at the previous code, there are the following three methods, which are methods for calling start, move, and end events of touch. They are implemented in this method.

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

The component in the layoutcanvas needs to add the three methods above for attribute association binding

When the user touches the canvas, just draw a point on the canvas. The code is as follows

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

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

How to draw pixels is implemented by calling the touch move method. The code is as follows

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();
},

This touch movement method can realize continuous drawing of pixels, just like drawing a line.

Here is the following code in the touch end method:

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

This touch end method is optional. If you implement multi-touch, you need to write it.

Draw logic

Do you know why it is called the redraw method? It is implemented using refresh logic.

Drawing methodredraw(), the code is as follows, wipe it clean first, and then draw it

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)
},

See if the above method is very simple and easy to understand?

Run the project

At this point, the pixel drawing board applet project is basically ready. It can be compiled and run. Next, let’s see the effect.

pixel art

If you want to use it as a pixel drawing board, take a look at the one the author drew randomlyErha, as shown below,
Insert image description here

This is a pixel painting. Is it good-looking? (^o^);
If you are interested in painting, just imagine it and it will look good

If the adjusted pixels are too fine, or there are too many grid columns, it will be difficult to control.

In this way, you need to use two fingers to touch the operation. The logic of multi-touch operation in the project is a bit complicated.

The operation is to hold down the drawing board with one finger and drag with another finger. You will find that the pixel you pressed is dragged out. Just continue dragging to the specified position. This will result in accurate drawing.

maze map

If you want to use it to draw game maps, such as maze maps, the running effect animation is as follows:
Please add image description

The last button at the bottom is the preview image function added by the author in the project, which can be saved as an image;
After drawing, return to the initial page, and you can see the exported map displayed. data,

From the picture above, you can see the drawn and exported string of numbers. Click the copy map data button, and then paste it into the small game program you wrote to use as a new level map.

You can also draw 2D pixel people, pixel maps, tile maps, etc. You can use everything you can think of.

For example, to add a new game map tounderground maze game project, the usage is the same as the following code

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

The exported map data is very long. When pasting, just remove the extra string of numbers 0 at the end.

If you want the project source code, click here to view and download, or directly click here to search: Pixel Artboard , please feel free to download from this blog site, thank you for your support!

You may not be able to see it on your mobile phone, please use a computer browser to view it instead.

Please add image description

Guess you like

Origin blog.csdn.net/zs1028/article/details/134723783