HTML5 GAME的可滚动板应该使用SVG或Canvas

时间:2018-06-06 13:31:54

标签: javascript css svg canvas game-engine

我希望创建一个涉及平铺板的简单网页游戏。我有一个svg的集合为每个方块的背景(即一个用于草,一个用于石头,一个用于污垢等)。我还有svg用于将在背景上方的图层上显示的项目(例如树木,木头,剑)。

我有一个内存数据库,其中包含每个方块的背景以及它是否包含哪个项目。

我希望能够:
*放大或缩小
*向左或向右滚动
*向上或向下晃动 *项目显示在该方格的背景上方

只需要在最新版本的现代浏览器中使用

最佳方法是什么:

1。有一个画布对象。获取当前缩放,最顶部的XY,画布宽度和画布高度。循环通过内存数据库中的方块,并在正确的位置打印相应的SVG。每次滚动或缩放都会重新打印整个电路板。

2。有一个div。获取当前缩放,最顶部的XY,画布宽度和画布高度。循环通过内存数据库中的方块,并在正确的位置创建SVG。

每次棋盘滚动时,当SVG变得可见时添加它们,在棋盘移动时删除SVG。以适当的金额翻译所有现有的SVG。

每次电路板根据新的缩放级别放大或缩小所有现有SVG时。

3。我不知道的第三种方法。

1 个答案:

答案 0 :(得分:0)

enter image description here

以下示例使用两个模块svg来加载图像(任何图像格式都可以使用)&处理平移,缩放和处理的板渲染。它还提供了一个onClick事件,它将为您提供一个描述已被单击的图块的对象。



<!doctype html>
<html>
	<head>
		<meta charset="utf-8">
		<style>
			body {
				background-color: black;
			}
			
			canvas {
				display: block;
				margin: 30px auto 0px auto;
				border: solid 1px white;
				border-radius: 10px;
			}
		</style>
	</head>
	<body>
		<canvas id="canvas"></canvas>
		<script type="application/javascript">
		
		var svg = function() {
		
			"use strict";
			
			var svgImages = [];
			var areImagesLoaded = true;
			var isPageLoaded = false;
			
			addEventListener("load",function() { isPageLoaded = true; isFinished(); });
			
			var exports = {
				onload: function() {},
				request: null,
				get: null
			};
			
			function isFinished() {
				if (isPageLoaded && areImagesLoaded) {
					exports.onload();
				}
			}
			
			function onSvgError() {
				this.isDone = true;
				console.warn("SVG " + this.src + " failed to load.");
			}
			
			function onSvgLoaded() {
				this.isDone = true;
				
				for (var id in svgImages) {
					if (!svgImages[id].isDone) {
						return;
					}
				}
				
				areImagesLoaded = true;
				isFinished();
			}
			
			function request(id,path) {
				if (svgImages[id]) {
					return;
				}
				
				areImagesLoaded = false;
				
				var img = document.createElement("img");
				
				img.onerror = onSvgError;
				img.onload = onSvgLoaded;
				img.isDone = false;
				img.id = id;
				img.src = path;
				
				svgImages[id] = img;
			}
			
			function get(id) {
				return svgImages[id];
			}
		
			exports.request = request;
			exports.get = get;
			
			return exports;
		
		}();
		
		var board = function() {
		
			"use strict";
			
			var canvasWidth = 0;
			var canvasHeight = 0;
			var canvas = null;
			var ctx = null;
			var frameRequested = false;
			
			var tileWidth = 0;
			var tileHeight = 0;
			var tileTypes = [];
			
			var boardWidth = 0;
			var boardHeight = 0;
			var board = [];
			var hasInitialized = false;
			
			var camera = {
				x: 0.0,
				y: 0.0,
				zoom: 1.0
			};
			
			function mapToBoard(x,y) {
				var invZoom = 1.0 / camera.zoom;
				
				return [
					(x - (canvasWidth >> 1)) * invZoom - camera.x,
					(y - (canvasHeight >> 1)) * invZoom - camera.y
				];
			}
			
			var isMouseDragging = false;
			var mouseStartX = 0;
			var mouseStartY = 0;
			var mouseLastX = 0;
			var mouseLastY = 0;
			
			var tileEvent = {
				background: "",
				foreground: "",
				x: 0,
				y: 0
			};
			
			function onTileSelected(e) {
				
			}
			
			function onMouseDown(e) {
				isMouseDragging = true;
			
				var bounds = canvas.getBoundingClientRect();
				
				mouseStartX = mouseLastX = e.clientX - bounds.left;
				mouseStartY = mouseLastY = e.clientY - bounds.top;
			}
			
			function onMouseUp(e) {
				isMouseDragging = false;
				
				var bounds = canvas.getBoundingClientRect()
				var x = e.clientX - bounds.left - mouseStartX;
				var y = e.clientY - bounds.top - mouseStartY;
				var l = Math.sqrt(x * x + y * y);
				
				if (l < 2.0) {
					[x,y] = mapToBoard(e.clientX - bounds.left,e.clientY - bounds.top);
					
					if (x > 0 && y > 0 && x < boardWidth * tileWidth && y < boardHeight * tileHeight) {
						x = (x / tileWidth) | 0;
						y = (y / tileHeight) | 0;
						
						var tile = board[x + y * boardWidth];
						
						tileEvent.background = tile.background;
						tileEvent.foreground = tile.foreground;
						tileEvent.x = x;
						tileEvent.y = y;
					} else {
						tileEvent.background = "";
						tileEvent.foreground = "";
						tileEvent.x = -1;
						tileEvent.y = -1;
					}
				
					onTileSelected(tileEvent);
				}
			}
			
			function onMouseMove(e) {
				if (hasInitialized && isMouseDragging) {
					var bounds = canvas.getBoundingClientRect();
					var x = e.clientX - bounds.left;
					var y = e.clientY - bounds.top;
					
					camera.x += (x - mouseLastX) / camera.zoom;
					camera.y += (y - mouseLastY) / camera.zoom;
					
					mouseLastX = x;
					mouseLastY = y;
					
					requestDraw();
				}
			}
			
			function onWheel(e) {
				if (Math.sign(e.deltaY) === -1) {
					camera.zoom *= 1.1;
				} else {
					camera.zoom *= 0.9;
				}
				
				requestDraw();
			}
			
			function draw() {
				ctx.fillStyle = "gray";
				ctx.fillRect(-canvasWidth >> 1,-canvasHeight >> 1,canvasWidth,canvasHeight);
				
				var _tileWidth = tileWidth * camera.zoom;
				var _tileHeight = tileHeight * camera.zoom;
				var _ox = camera.x * camera.zoom;
				var _oy = camera.y * camera.zoom;
				var _x = _ox;
				var _y = _oy;
				
				for (var x = 0; x <boardWidth; ++x) {
					for (var y = 0; y < boardHeight; ++y) {
						var index = x + y * boardWidth;
						var tile = board[index];
						var background = tileTypes[tile.background];
						var foreground = tileTypes[tile.foreground];
						
						if (background) {
							ctx.drawImage(
								background,
								_x,
								_y,
								_tileWidth,
								_tileHeight
							);
						}
						
						if (foreground) {
							ctx.drawImage(
								foreground,
								_x,
								_y,
								_tileWidth,
								_tileHeight
							);
						}
						
						_y += _tileHeight;
					}
					
					_y = _oy;
					_x += _tileWidth;
				}
				
				frameRequested = false;
			}
			
			function requestDraw() {
				if (!frameRequested) {
					frameRequested = true;
					requestAnimationFrame(draw);
				}
			}
			
			return {
				BACKGROUND: 0,
				FOREGROUND: 1,
			
				set canvas(canvasID) {
					if (!hasInitialized) {
						canvas = document.getElementById(canvasID);
						canvas.onmousedown = onMouseDown;
						canvas.onmouseup = onMouseUp;
						canvas.onmousemove = onMouseMove;
						canvas.onwheel = onWheel;
						ctx = canvas.getContext("2d");
					}
				},
				
				set canvasWidth(w) {
					if (!hasInitialized && canvas) {
						canvasWidth = canvas.width = w;
					}
				},
				
				set canvasHeight(h) {
					if (!hasInitialized && canvas) {
						canvasHeight = canvas.height = h;
					}
				},
				
				set tileWidth(w) {
					if (!hasInitialized) {
						tileWidth = w;
					}
				},
				
				set tileHeight(h) {
					if (!hasInitialized) {
						tileHeight = h;
					}
				},
				
				set width(w) {
					if (!hasInitialized) {
						boardWidth = w;
					}
				},
				
				set height(h) {
					if (!hasInitialized) {
						boardHeight = h;
					}
				},
				
				set onTileSelected(callback) {
					onTileSelected = callback;
				},
				
				get width() {
					return boardWidth;
				},
				
				get height() {
					return boardHeight;
				},
				
				get onTileSelected() {
					return onTileSelected;
				},
				
				defineTileTypes: function(types) {
					if (types.length % 2 !== 0) {
						return;
					}
				
					for (var i = 0; i < types.length; i += 2) {
						var id = types[i];
						var img = types[i + 1];
						
						tileTypes[id] = img;
					}
				},
				
				init: function() {
					camera.x = -(boardWidth >> 1) * tileWidth;
					camera.y = -(boardHeight >> 1) * tileHeight;
					ctx.translate(canvasWidth >> 1,canvasHeight >> 1);
				
					board.length = boardWidth * boardHeight;
					
					for (var i = 0; i < board.length; ++i) {
						board[i] = {
							background: "",
							foreground: ""
						};
					}
					
					hasInitialized = true;
					requestAnimationFrame(draw);
				},
				
				set: function(type,id,x,y) {
					if (hasInitialized
					&& tileTypes[id]
					&& x > -1 
					&& x < boardWidth
					&& y > -1
					&& y < boardHeight) {
						var index = x + y * boardWidth;
						
						if (type === this.BACKGROUND) {
							board[index].background = id;
						} else {
							board[index].foreground = id;
						}
						
						requestDraw();
					}
				}
			};
		
		}();
		
		void function() {
		
			"use strict";
			
			svg.request("grass","https://i.stack.imgur.com/CkvU7.png");
			svg.request("water","https://i.stack.imgur.com/an6a5.png");
			
			svg.onload = function() {
				board.canvas = "canvas";
				board.canvasWidth = 180;
				board.canvasHeight = 160;
				
				board.tileWidth = 25;
				board.tileHeight = 25;
				
				board.width = 20;
				board.height = 20;
				
				board.defineTileTypes([
					"GRASS",svg.get("grass"),
					"WATER",svg.get("water")
				]);
				
				board.init();
				
				for (var x = 0; x < board.width; ++x) {
					for (var y = 0; y < board.height; ++y) {
						board.set(board.BACKGROUND,"WATER",x,y);
						
						if (Math.random() > 0.2) {
							board.set(board.BACKGROUND,"GRASS",x,y);
						} else {
							board.set(board.BACKGROUND,"WATER",x,y);
						}
					}
				}
			}
			
			board.onTileSelected = function(e) {
				if (e.background === "GRASS") {
           board.set(board.BACKGROUND,"WATER",e.x,e.y);
        } else {
           board.set(board.BACKGROUND,"GRASS",e.x,e.y);
        }
			}
			
		}();
		
		</script>
	</body>
</html>
&#13;
&#13;
&#13;