【问题标题】:Dungeon generator in JqueryJquery中的地牢生成器
【发布时间】:2017-09-04 19:25:18
【问题描述】:

https://www.gamasutra.com/blogs/AAdonaac/20150903/252889/Procedural_Dungeon_Generation_Algorithm.php

我正在尝试做类似 jquery 中的链接之类的事情,但我在实现它时遇到了一些麻烦。

1) 我创建了 10(x) 个不同的矩形并将它们放在画布的中间,它们相互混合在一起 - 没问题

2) 分开房间,让每个房间在画布上找个空的地方——大问题

计划 1:我比较两个房间,如果它们相互接触,则将其中一个以最短的方式移动到另一个的边缘。但是,如果那里已经有房间怎么办?然后我刚刚得到了两个相互接触的新房间......

计划 2:制作一系列空/占用点,并将每个房间移动到一个空的地方。但是我怎么知道要移动的方向,所以所有房间都围绕中心放置?

请帮忙!

试用码:

<canvas id="cnvs" width="500" height="500" style="background-color: #333;"></canvas>

var rooms = [],
  gw = 25, //grid width
  gh = 25; //grid height

//Room
function Room(x,y,w,h){
  this.x = x; this.y = y;
  this.w = w; this.h = h;
  };

//Setup
for(var i=0; i<10; i++){
  var w = Math.floor(2+Math.random()*3),
    h = Math.floor(2+Math.random()*3),
    x = Math.floor(gw/2)-Math.floor(w/2),
    y = Math.floor(gh/2)-Math.floor(h/2),
    room = new Room(x,y,w,h);
  rooms.push(room);
  };

//Draw in canvas
var ctx = $("#cnvs")[0].getContext("2d"),
  sz = 20;
ctx.lineWidth = "2";
ctx.strokeStyle = 'white';

for(var i=0; i<rooms.length; i++){
  ctx.rect(rooms[i].x*sz,rooms[i].y*sz,rooms[i].w*sz,rooms[i].h*sz);
  ctx.stroke();
  };

【问题讨论】:

  • 你能解释一下什么不起作用吗?问题出在哪里?
  • 第 1 步有效,但我对如何执行第 2 步(单独的房间)感到非常困惑。如何像链接一样分隔房间,使没有房间覆盖另一个房间?

标签: jquery html canvas


【解决方案1】:

现在我完成了第 2 步。我认为它可以更优雅,所以请随意使其更智能。

   

var rooms = [],
  grid = [],
  gw = 25, //grid width
  gh = 25; //grid height

//Room
Room = function(x,y,w,h){
  this.x = x; this.y = y;
  this.w = w; this.h = h;
  };

//functions
refreshGrid = function(){
  for(var i=0; i<grid.length; i++){
    for(var j=0; j<grid[i].length; j++) grid[i][j] = -1;
    };
  return;
  };

roomDistance = function(x,y,c){
  if(grid[y][x]==-1 || grid[y][x]>c){
    grid[y][x] = c;
    if(x>0) roomDistance(x-1, y, c+1);
    if(x<gw-1) roomDistance(x+1, y, c+1);
    if(y>0) roomDistance(x, y-1, c+1);
    if(y<gh-1) roomDistance(x, y+1, c+1);
    };
  return;
  };

roomFit = function(x,y,w,h){
  var tmp = true;
  if( x+w>=gw ) tmp = false;
    else if( y+h>=gh ) tmp = false;
      else {
        for(var i=y; i<y+h; i++){
          for(var j=x;j<x+w; j++){
            if( grid[i][j]<0 ) tmp = false;
            };
          };
  return tmp;
  };

blockSpaces = function(w,h){
  for(var i=0; i<rooms.length; i++){
    var rx = rooms[i].x,
      ry = rooms[i].y,
      rw = rooms[i].w,
      rh = rooms[i].h;
    if(rx+rw<gw) rw = rw+1;
    if(rx>0){ rx = rx-1; rw = rw+1; };
    if(ry+rh<gh) rh = rh+1;
    if(ry>0){ ry = ry-1; rh = rh+1; };
    for(var j=0;j<rh; j++){
      for(var k=0;k<rw; k++){
        grid[ry+j][rx+k] = -1;
        };
      };
    };
  for(var i=0; i<grid.length; i++){
    for(var j=0;j<grid[i].length; j++){
      if( roomFit(j,i,w,h)==false ) grid[i][j] = -1;
      };
    };
  };

findPlace = function(room){
  var x=0, y=0, c=-1;
  for(var i=0; i<grid.length; i++){
    for(var j=0;j<grid[i].length; j++){
      if(grid[i][j]>=0 && (c==-1 || grid[i][j]<c) ){
        c = grid[i][j];
        x= j;
        y = i;
        };
      };
    };
  room.x = x;
  room.y = y;
  };

//Setup
for(var i=0; i<gh; i++){
  var arr = [];
  for(var j=0; j<gw; j++) arr.push(0);
  grid.push(arr);
  };

for(var i=0; i<15; i++){
  var w = Math.floor(2+Math.random()*3),
    h = Math.floor(2+Math.random()*3),
    x = Math.floor(gw/2)-Math.floor(w/2),
    y = Math.floor(gh/2)-Math.floor(h/2);
  refreshGrid();
  roomDistance(x,y,0);
  blockSpaces(w,h);
  var room = new Room(x,y,w,h);
  findPlace(room);
  rooms.push(room);
  };

//Draw in canvas
var ctx = $("#cnvs")[0].getContext("2d"),
  sz = 20;
ctx.beginPath();
ctx.lineWidth = '1';
ctx.strokeStyle = '#666';
for(var i=0; i<gh; i++){ ctx.moveTo(0,i*sz); ctx.lineTo(gw*sz,i*sz); };
for(var i=0; i<gw; i++){ ctx.moveTo(i*sz,0); ctx.lineTo(i*sz,gh*sz); };
ctx.stroke();

ctx.beginPath();
ctx.lineWidth = "2";
ctx.strokeStyle = '#fff';
for(var i=0; i<rooms.length; i++){ ctx.rect(rooms[i].x*sz,rooms[i].y*sz,rooms[i].w*sz,rooms[i].h*sz); ctx.stroke(); };
&lt;canvas id="cnvs" width="500" height="500" style="background-color: #333;"&gt;&lt;/canvas&gt;

【讨论】:

    【解决方案2】:

    我认为这样更好:

    //global variables
    var rooms = [],
    	gw = 35, //grid width
    	gh = 35; //grid height
    
    //Room
    Room = function(){
    	var w = Math.floor(2+Math.random()*4),
    		h = Math.floor(2+Math.random()*4),
    		x = Math.floor(gw/3+Math.random()*gw/3)-Math.floor(w/2),
    		y = Math.floor(gh/3+Math.random()*gw/3)-Math.floor(h/2),
    		grid = [];
    
    	//create grid with -1
    	grid = [];
    	for(var i=0; i<gh; i++){
    		grid.push([]);
    		for(var j=0; j<gw; j++) grid[grid.length-1].push(-1);
    		};
    
    	//Fill grid with distances
    	this.gridDistance = function(x1,y1,c){
    		if(grid[y1][x1]==-1 || grid[y1][x1]>c){
    			grid[y1][x1] = c;
    			if(x1>0) this.gridDistance(x1-1, y1, c+1);
    			if(x1<gw-1) this.gridDistance(x1+1, y1, c+1);
    			if(y1>0) this.gridDistance(x1, y1-1, c+1);
    			if(y1<gh-1) this.gridDistance(x1, y1+1, c+1);
    			};
    		return;
    		};
    	this.gridDistance(x,y,0);
    
    	//block rooms and rooms border
    	for(var i=0; i<rooms.length; i++){
    		var x1 = rooms[i].x, y1 = rooms[i].y, w1 = rooms[i].w, h1 = rooms[i].h;
    		if(x1+w1<gw) w1 = w1+1;
    		if(x1>0){ x1 = x1-1; w1 = w1+1; };
    		if(y1+h1<gh) h1 = h1+1;
    		if(y1>0){ y1 = y1-1; h1 = h1+1; };
    		for(var j=0;j<h1; j++){
    			for(var k=0;k<w1; k++){
    				grid[y1+j][x1+k] = -1;
    				};
    			};
    		};
    
    	//block spaces where room cant fit
    	for(var i=0; i<grid.length; i++){
    		for(var j=0;j<grid[i].length; j++){
    			var tmp = false;
    			if( i+h>=gh ) tmp = true;
    			else if( j+w>=gw ) tmp = true;
    			else {
    				for(var k=i; k<i+h; k++){
    					for(var l=j;l<j+w; l++){
    						if( grid[k][l]<0 ) tmp = true;
    						};
    					};
    				};
    			if(tmp) grid[i][j] = -1;
    			};
    		};
    
    	//find shortest distance to fitable space
    	var x1=0, y1=0, c=-1;
    	for(var i=0; i<grid.length; i++){
    		for(var j=0;j<grid[i].length; j++){
    			if(grid[i][j]>=0 && (c==-1 || grid[i][j]<c) ){
    				c = grid[i][j];
    				x1= j;
    				y1 = i;
    				};
    			};
    		};
    	
    	this.gridDistance = undefined;
    
    	this.x = x1; this.y = y1;
    	this.w = w; this.h = h;
    	};
    
    //Setup
    for(var i=0; i<25; i++){
    	var room = new Room();
    	rooms.push(room);
    	};
    
    $('body').append('ok');
    
    //Draw in canvas
    var ctx = $("#cnvs")[0].getContext("2d"),
    	sz = 20;
    ctx.beginPath();
    ctx.lineWidth = '1';
    ctx.strokeStyle = '#666';
    for(var i=0; i<gh; i++){ ctx.moveTo(0,i*sz); ctx.lineTo(gw*sz,i*sz); };
    for(var i=0; i<gw; i++){ ctx.moveTo(i*sz,0); ctx.lineTo(i*sz,gh*sz); };
    ctx.stroke();
    
    ctx.beginPath();
    ctx.lineWidth = "2";
    ctx.strokeStyle = '#fff';
    for(var i=0; i<rooms.length; i++){ ctx.rect(rooms[i].x*sz,rooms[i].y*sz,rooms[i].w*sz,rooms[i].h*sz); ctx.stroke(); };

    【讨论】:

      猜你喜欢
      • 2014-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-27
      • 2020-09-19
      • 2019-06-29
      • 1970-01-01
      相关资源
      最近更新 更多