2016-08-04 35 views
1

Ich versuche, alle Hexes in einem bestimmten Bereich auszuwählen. Allerdings bekomme ich merkwürdige Ergebnisse, während ich diesen Code in Amit Patels page implementiert habe.Auswahl in der Nähe von Hexen um ein Hex

var results = [] 
for each -N ≤ dx ≤ N: 
    for each max(-N, -dx-N) ≤ dy ≤ min(N, -dx+N): 
     var dz = -dx-dy 
     results.append(cube_add(center, Cube(dx, dy, dz))) 

Das ist, was ich bisher habe:

var center = this._cel.copy(hex.coords); 
    var dx = range - center.q; 
    var dy = range - center.r; 

    var results = []; 

    for (var q = -range; q <= dx; q++) { 
     var r1 = Math.max(-range, -q - range); 
     var r2 = Math.min(range, -q + range); 
     for (var r = r1; r <= r2; r++) { 
      //console.log(q, r, -q-r) 
      var c = new Cell(q, r, -q-r) 
      results.push(c.add(center)); 
     } 
    } 

Ich nehme an, dass die Schleife ein wenig mich zwingt müssen geändert und die Verwendung der dx, dy-Werte machen.

<body> 
 
\t <canvas width="420px" height="420px" id="myCanvas" style="margin:0; padding:0; border:1px solid #d3d3d3;"></canvas> 
 
</body> 
 

 
<script id="hexagon"> 
 
function Point(pos) { 
 
    this.x = 0; 
 
\t this.y = 0; 
 
\t if(typeof(pos) !== "undefined"){ 
 
\t \t this.x = pos[0]; 
 
\t \t this.y = pos[1]; 
 
\t } 
 
}; 
 

 
function Cell(_q, _r, _s){ //// direction /// 
 
\t this.q = _q; 
 
\t this.r = _r; 
 
\t this.s = _s; 
 
\t this._hashID = null; 
 
\t this.generateHashID(); 
 
} 
 

 
Cell.prototype = { 
 
\t constructor: Cell, 
 
\t add: function(d){ 
 
\t \t this.q += d.q; 
 
\t \t this.r += d.r; 
 
\t \t this.s += d.s; 
 
\t \t this.generateHashID(); 
 
\t \t return this; 
 
\t }, 
 
\t copy: function(c){ 
 
\t \t this.set(c.q, c.r, c.s); 
 
\t \t return this; 
 
\t }, 
 
\t set: function(_q, _r, _s){ 
 
\t \t this.q = _q; 
 
\t \t this.r = _r; 
 
\t \t this.s = _s; 
 
\t \t this.generateHashID(); 
 
\t \t return this; 
 
\t }, 
 
\t generateHashID: function(){ 
 
\t \t this._hashID = this.q+"."+this.r+"."+this.s; 
 
\t }, 
 
\t getHashID: function(){ 
 
\t \t return this._hashID; 
 
\t }, 
 
\t round: function(){ 
 
\t \t var q = Math.trunc(Math.round(this.q)); 
 
\t \t var r = Math.trunc(Math.round(this.r)); 
 
\t \t var s = Math.trunc(Math.round(this.s)); 
 
\t \t var q_diff = Math.abs(q - this.q); 
 
\t \t var r_diff = Math.abs(r - this.r); 
 
\t \t var s_diff = Math.abs(s - this.s); 
 
\t \t if (q_diff > r_diff && q_diff > s_diff){ 
 
\t \t \t q = -r - s; 
 
\t \t }else if (r_diff > s_diff){ 
 
\t \t \t r = -q - s; 
 
\t \t }else{ 
 
\t \t \t s = -q - r; 
 
\t \t } 
 
\t \t 
 
\t \t return this.set(q, r, s); 
 
\t } 
 
} 
 

 
var Hex = function(coords, l_){ //// [axial], [cartesian] , layout 
 
\t this.coords = new Cell(coords[0], coords[1], coords[2]); 
 
\t 
 
\t this.content = -2; 
 
\t 
 
\t this.pos = this.coords; //// set primary coorinate type /// 
 
\t 
 
\t this.neighbors = []; 
 
\t 
 
\t this.layout = l_; 
 
\t this.corners = []; 
 
\t 
 
\t this.center = this.get_center_p(); 
 
\t 
 
\t //this.id = this.generate_id(cart_coord); 
 

 
\t this.colors = { 
 
\t \t "base" : { 
 
\t \t \t filling : "#008844", 
 
\t \t \t border : "#FFDD88", 
 
\t \t }, 
 
\t \t "selected": { 
 
\t \t \t filling: "#00cc00" 
 
\t \t }, 
 
\t \t "hovered": { 
 
\t \t \t filling: "#006600" 
 
\t \t }, 
 
\t \t "path" : { 
 
\t \t \t filling: "#80ff00" 
 
\t \t }, 
 
\t \t "obstacle" : { 
 
\t \t \t filling: "#86592d" 
 
\t \t }, 
 
\t \t "neighbor": { 
 
\t \t \t filling: "#ffbf00" 
 
\t \t } 
 
\t } 
 
\t 
 
\t this.states = { 
 
\t \t "selected" : false, 
 
\t \t "hovered" : false, 
 
\t \t "isPath": false, 
 
\t \t "isObstacle": false, 
 
\t \t "isNeighbor": false 
 
\t } 
 

 
\t this.generate_corners(); 
 
}; 
 

 
Hex.prototype = { 
 
\t constructor: Hex, 
 

 
\t get_corner_offset: function(corner){ 
 
\t \t var angle = 2.0 * Math.PI * (corner + this.layout.orientation.start_angle)/6; 
 
\t \t return new Point([ size.x * Math.cos(angle), size.y * Math.sin(angle) ]); 
 
\t }, 
 
\t 
 
\t generate_corners: function(h){ 
 
\t \t var offset = null, angle = 0; 
 
\t \t var size = this.layout.size; 
 
\t \t for (var i = 0; i < 6; i++) { 
 
\t \t \t angle = 2.0 * Math.PI * (i + this.layout.orientation.start_angle)/6; 
 
\t \t \t offset = new Point([ size.x * Math.cos(angle), size.y * Math.sin(angle)]); 
 
\t \t \t 
 
\t \t \t this.corners.push( 
 
\t \t \t \t new Point([ this.center.x + offset.x, this.center.y + offset.y ]) 
 
\t \t \t); 
 
\t \t } 
 
\t }, 
 
\t 
 
\t draw: function(ctx){ 
 
\t \t var points = this.corners; 
 
\t \t ctx.beginPath(); 
 
\t \t ctx.moveTo(points[0].x, points[0].y); 
 
\t \t for(var i = 1; i < points.length; i++){ 
 
\t \t \t var p = points[i]; 
 
\t \t \t ctx.lineTo(p.x, p.y); 
 
\t \t } 
 
\t \t ctx.closePath(); 
 
\t \t //// fill Hex /// 
 
\t \t if(this.checkState("selected")){ 
 
\t \t \t ctx.fillStyle = this.colors.selected.filling; 
 
\t \t }else if( this.checkState("hovered")){ 
 
\t \t \t ctx.fillStyle = this.colors.hovered.filling; 
 
\t \t }else if( this.checkState("isPath")){ 
 
\t \t \t ctx.fillStyle = this.colors.path.filling; 
 
\t \t }else if( this.checkState("isNeighbor")){ 
 
\t \t \t ctx.fillStyle = this.colors.neighbor.filling; 
 
\t \t }else if( this.checkState("isObstacle")){ 
 
\t \t \t ctx.fillStyle = this.colors.obstacle.filling; 
 
\t \t }else{ 
 
\t \t \t ctx.fillStyle = this.colors.base.filling; 
 
\t \t } 
 
\t \t ctx.fill(); 
 
\t \t //// draw border /// 
 
\t \t ctx.lineWidth = 1; 
 
\t \t ctx.strokeStyle = "#19334d"; 
 
\t \t ctx.stroke(); 
 
\t \t 
 
\t \t this.draw_coords(ctx); 
 
\t \t 
 
\t \t this.draw_center_point(ctx); 
 
\t }, 
 
\t 
 
\t add_neighbor: function(neighbor){ 
 
\t \t this.neighbors.push(neighbor); 
 
\t }, 
 
\t 
 
\t show_neighbors: function(){ 
 
\t \t for(var nb = 0, nb_l = this.neighbors.length; nb < nb_l; nb++){ 
 
\t \t \t this.neighbors[nb].changeState("isNeighbor", true); 
 
\t \t } 
 
\t }, 
 
\t 
 
\t hide_neighbors: function(){ 
 
\t \t for(var nb = 0, nb_l = this.neighbors.length; nb < nb_l; nb++){ 
 
\t \t \t this.neighbors[nb].changeState("isNeighbor", false); 
 
\t \t } 
 
\t }, 
 
\t 
 
\t draw_coords: function(ctx){ 
 
\t \t var text = this.coords.q+" : "+ this.coords.s; 
 
\t \t var text_z = this.coords.r; 
 
\t \t var metrics1 = ctx.measureText(text); 
 
\t \t var metrics2 = ctx.measureText(text_z); 
 
\t \t var w1 = metrics1.width; 
 
\t \t var w2 = metrics2.width; 
 
\t \t var h = 8; 
 
\t \t ctx.font = h+'pt Calibri bold'; 
 
\t \t ctx.textAlign = 'center'; 
 
\t \t ctx.fillStyle = '#FFFFFF'; 
 
\t \t ctx.fillText(text, this.center.x, this.center.y + (h/2) - 5); 
 
\t \t ctx.fillText(text_z, this.center.x, this.center.y + (h/2) + 7); 
 
\t }, 
 
\t 
 
\t get_center_p: function(){ 
 
\t \t var M = this.layout.orientation; 
 
\t \t var x = (M.f0 * this.pos.q + M.f1 * this.pos.r) * this.layout.size.x; 
 
\t \t var y = (M.f2 * this.pos.q + M.f3 * this.pos.r) * this.layout.size.y; 
 
\t \t return new Point([ 
 
\t \t \t x + this.layout.origin.x, 
 
\t \t \t y + this.layout.origin.y 
 
\t \t ]); 
 
\t }, 
 
\t 
 
\t draw_center_point: function(ctx){ 
 
\t \t ctx.beginPath(); 
 
\t \t ctx.lineWidth="1"; 
 
\t \t ctx.fillStyle="red"; 
 
\t \t ctx.arc(this.center.x , this.center.y , 2, 0 ,2*Math.PI); 
 
\t \t ctx.closePath(); 
 
\t \t ctx.stroke(); 
 
\t \t ctx.fill(); 
 
\t }, 
 
\t 
 
\t generate_id: function(coords){ 
 
\t \t return parseInt(coords[0]+''+coords[1]); 
 
\t }, 
 
\t 
 
\t checkState: function(state){ 
 
\t \t return this.states[ state ]; 
 
\t }, 
 
\t 
 
\t changeState: function(state , value){ 
 
\t \t this.states[ state ] = value; 
 
\t }, 
 
\t 
 
\t trigger: function(ev_name){ 
 
\t \t if(this.events[ ev_name ]){ 
 
\t \t \t this.events[ ev_name ].call(this); 
 
\t \t } 
 
\t }, 
 
\t 
 
\t setContent: function(type){ 
 
\t \t this.content = type; 
 
\t \t this.changeState("isObstacle" , true); 
 
\t }, 
 
\t 
 
\t hover: function(){ 
 
\t \t if(! this.checkState("isPath")){ 
 
\t \t \t this.trigger("hover"); 
 
\t \t } 
 
\t }, 
 
\t 
 
\t clear_hover: function(){ 
 
\t \t if(! this.checkState("isPath")){ 
 
\t \t \t this.trigger("clear_hover"); 
 
\t \t } 
 
\t }, 
 
\t 
 
\t select: function(){ 
 
\t \t this.trigger("select"); 
 
\t \t //this.show_neighbors(); 
 
\t }, 
 
\t 
 
\t unselect: function(){ 
 
\t \t this.trigger("unselect"); 
 
\t }, 
 
\t 
 
\t events: { 
 
\t \t select: function(){ 
 
\t \t \t this.changeState("selected", true); 
 
\t \t \t this.changeState("hovered", false); 
 
\t \t }, 
 
\t \t unselect: function(){ 
 
\t \t \t this.changeState("selected", false); 
 
\t \t }, 
 
\t \t hover: function(){ 
 
\t \t \t this.changeState("hovered", true); 
 
\t \t }, 
 
\t \t clear_hover: function(){ 
 
\t \t \t this.changeState("hovered", false); 
 
\t \t } 
 
\t } 
 
}; 
 

 

 
</script> 
 

 
<script id="grid"> 
 

 
var Grid = function(size, hex_size, origin, ctx_pos, layout_type){ 
 
\t this.size = size; 
 
\t this.grid_r = size/2; 
 
\t 
 
\t this.layout_type = layout_type; 
 
\t this.layout = this.set_layout(this.layout_types[this.layout_type], hex_size, origin); 
 
\t 
 
\t this.hexes = []; 
 
\t 
 
\t this.hovered = [null, null]; //// [cur, prev] /// 
 
\t this.selected = [null, null]; ///// [cur , prev] /// 
 
\t 
 
\t this.dots = []; 
 
\t 
 
\t this._list = []; 
 
\t this._cel = new Cell(); 
 
\t 
 
\t this._directions = [new Cell(+1, 0, -1), new Cell(+1, -1, 0), new Cell(0, -1, +1), 
 
\t \t \t \t \t \t new Cell(-1, 0, +1), new Cell(-1, +1, 0), new Cell(0, +1, -1)]; 
 
\t 
 
\t this.generate(); 
 
\t this.add_neighbors(); 
 
\t 
 
\t this.mouse = new Point(); 
 
\t this.mouse_events(new Point(ctx_pos)); 
 
} 
 

 
Grid.prototype = { 
 
\t constructor: Grid, 
 
\t layout_types: { 
 
\t \t "pointy": [ 
 
\t \t \t [ Math.sqrt(3.0), Math.sqrt(3.0)/2.0, 0.0, 3.0/2.0], //// 2x2 forward matrix 
 
\t \t \t [ Math.sqrt(3.0)/3.0, -1.0/3.0, 0.0, 2.0/3.0], ///// 2x2 inverse matrix 
 
\t \t \t 0.5 
 
\t \t ], //// starting angle in multiples of 60° ///// 
 
\t \t "flat": [ 
 
\t \t \t [3.0/2.0, 0.0, Math.sqrt(3.0)/2.0, Math.sqrt(3.0)], //// 2x2 forward matrix 
 
\t \t \t [2.0/3.0, 0.0, -1.0/3.0, Math.sqrt(3.0)/3.0], ///// 2x2 inverse matrix 
 
\t \t \t 1.0 
 
\t \t ] 
 
\t }, 
 
\t set_layout: function(orn_type , hex_s_, ogn_ ){ 
 
\t \t return { 
 
\t \t \t orientation: this.set_orientation(orn_type), ///// orientation type /// 
 
\t \t \t size: new Point([ hex_s_ , hex_s_ ]), ///// hex size /// 
 
\t \t \t origin: new Point(ogn_) //// Grid center ///// 
 
\t \t } 
 
\t }, 
 

 
\t set_orientation: function(opts){ /// [0] : forward_matrix, [1] : inverse_matrix, [2] : starting_angle 
 
\t \t return { 
 
\t \t \t f0: opts[0][0], f1: opts[0][1], f2: opts[0][2], f3: opts[0][3], b0: opts[1][0], b1: opts[1][1], b2: opts[1][2], b3: opts[1][3], start_angle: opts[2] 
 
\t \t } 
 
\t }, 
 
\t 
 
\t get_hex_at_p: function(p){ //// point /// 
 
\t \t var M = this.layout.orientation; 
 
\t \t var pt = new Point([ (p.x - this.layout.origin.x)/this.layout.size.x, (p.y - this.layout.origin.y)/this.layout.size.y ]); 
 
\t \t var q = M.b0 * pt.x + M.b1 * pt.y; 
 
\t \t var r = M.b2 * pt.x + M.b3 * pt.y; 
 
\t \t var c = this._cel.set(q, r, -q-r); 
 
\t \t return c.round(); 
 
\t }, 
 
\t 
 
\t generate: function(){ 
 
\t \t var n_hex = null; 
 
\t \t for (var q = -this.grid_r; q <= this.grid_r; q++) { 
 
\t \t \t var r1 = Math.max(-this.grid_r, -q - this.grid_r); 
 
\t \t \t var r2 = Math.min(this.grid_r, -q + this.grid_r); 
 
\t \t \t for (var r = r1; r <= r2; r++) { 
 
\t \t \t \t n_hex = new Hex([ q, r, -q-r ], this.layout); 
 
\t \t \t \t this.hexes[ n_hex.coords.getHashID() ] = n_hex; 
 
\t \t \t } 
 
\t \t } 
 
\t }, 
 
\t 
 
\t _selectHexesInRange: function(hex, range){ 
 
\t \t var center = this._cel.copy(hex.coords); 
 
\t \t var dx = range - center.q; 
 
\t \t var dy = range - center.r; 
 
\t \t 
 
\t \t var results = []; 
 
\t \t for (var q = -range; q <= dx; q++) { 
 
\t \t \t var r1 = Math.max(-range, -q - range); 
 
\t \t \t var r2 = Math.min(range, -q + range); 
 
\t \t \t for (var r = r1; r <= r2; r++) { 
 
\t \t \t \t var c = new Cell(q, r, -q-r) 
 
\t \t \t \t results.push(c.add(center)); 
 
\t \t \t } 
 
\t \t } 
 
\t \t 
 
\t \t for(var h in results){ 
 
\t \t \t if(typeof(this.hexes[results[h].getHashID()]) !== "undefined"){ 
 
\t \t \t \t this.hexes[results[h].getHashID()].select() 
 
\t \t \t } 
 
\t \t } 
 
\t \t //console.log(results) 
 
\t }, 
 
\t 
 
\t hex_corner_offset : function (corner) { 
 
\t \t var size = this.layout.size; 
 
\t \t var angle = 2.0 * Math.PI * (this.layout.orientation.start_angle - corner)/6; 
 
\t \t return new Point([size.x * Math.cos(angle), size.y * Math.sin(angle)]); 
 
\t }, 
 
\t 
 
\t point_add : function(p, q) { 
 
\t \t return new Point([p.x + q.x, p.y + q.y]); 
 
\t }, 
 

 
\t add_neighbors: function(){ 
 
\t \t var nbor = null, hex = null; 
 
\t \t for(var h in this.hexes){ 
 
\t \t \t hex = this.hexes[h]; 
 
\t \t \t var i, n, l = this._directions.length; 
 
\t \t \t this._list.length = 0;//// reset array /// 
 
\t \t \t for (i = 0; i < l; i++) { 
 
\t \t \t \t this._cel.copy(hex.coords); 
 
\t \t \t \t this._cel.add(this._directions[i]); 
 
\t \t \t \t n = this.hexes[ this._cel.getHashID() ]; 
 
\t \t \t \t if (typeof(n) == "undefined") { ///// if doesn't exists //// 
 
\t \t \t \t \t this._list.push(null); 
 
\t \t \t \t \t continue; 
 
\t \t \t \t } 
 
\t \t \t \t this._list.push(n); 
 
\t \t \t } 
 
\t \t \t 
 
\t \t \t hex.neighbors = this._list.slice(); //// take copy of the array //// 
 
\t \t } 
 
\t }, 
 
\t 
 
\t draw: function(ctx){ 
 
\t \t for(var h in this.hexes){ 
 
\t \t \t this.hexes[h].draw(ctx); 
 
\t \t } 
 
\t }, 
 
\t 
 
\t checkCollisions: function(){ 
 
\t \t var h_pos = this.get_hex_at_p(this.mouse); 
 
\t \t var hex = this.hexes[ h_pos.getHashID() ]; 
 
\t \t if(typeof(hex) !== "undefined"){ 
 
\t \t \t if(this.hovered[0] == null){ //// cur 
 
\t \t \t \t this.hovered[0] = hex; 
 
\t \t \t \t this.hovered[0].hover(); 
 
\t \t \t }else{ 
 
\t \t \t \t this.hovered[1] = this.hovered[0]; 
 
\t \t \t \t this.hovered[0] = hex; 
 
\t \t \t \t if(this.hovered[0].coords._hashID != this.hovered[1].coords._hashID){ 
 
\t \t \t \t \t this.hovered[1].clear_hover(); 
 
\t \t \t \t \t this.hovered[1] = null; 
 
\t \t \t \t } 
 
\t \t \t } 
 
\t \t \t this.hovered[0].hover(); 
 
\t \t } 
 
\t }, 
 
\t 
 
\t mouse_events: function(ctx_pos){ 
 
\t \t var self = this; 
 
\t \t 
 
\t \t window.addEventListener('mousemove', function(e){ 
 
\t \t \t self.mouse.x = (e.clientX - ctx_pos.x); 
 
\t \t \t self.mouse.y = (e.clientY - ctx_pos.y); 
 
\t \t }); 
 
\t \t 
 
\t \t window.addEventListener('mousedown', function(e){ 
 
\t \t \t //console.log("neighbors : ",self.hovered[0].neighbors) 
 
\t \t \t self._selectHexesInRange(self.hovered[0], 2); 
 
\t \t }); 
 
\t } 
 
} 
 
</script> 
 

 
<script id="main"> 
 
var c_el = document.getElementById("myCanvas"); 
 
var ctx = c_el.getContext("2d"); 
 

 
var nGrid = new Grid(6, 25, [ c_el.width/2, c_el.height/2 ], [c_el.getBoundingClientRect().left, c_el.getBoundingClientRect().top], "pointy"); 
 

 
function animate(){ 
 
\t window.requestAnimationFrame(animate); 
 
\t ctx.clearRect(0, 0, c_el.width, c_el.height); 
 
\t nGrid.checkCollisions(); 
 
\t nGrid.draw(ctx); 
 
} 
 

 
animate(); 
 
</script>

Antwort

0

nehmen einfach die Koordinaten x, y, z und dann alle Felder eines dieser Berechnungen suchen:

  1. z const ist, x plus/minus 1, y ist minus/plus 1
  2. xist const, z ist plus/minus 1, y ist minus/plus 1
  3. y ist const, z ist plus/minus 1, x ist minus/plus 1

Diese sollten alle Nachbarn

Beispiel: abgelegt 0, 1, -1 (x, y, z)

  1. z const und x plus/minus 1 => [ -1, 2, -1], [1, 0, -1]
  2. x ist const und z ist plus/minus 1 => [0, 2, -2], [0, 0, 0]
  3. y ist const und z ist plus/minus 1 => [1, 1, -2], [-1, 1, 0]

Für eine schnellere Sie Ihre Zellen in einem Objekt wie folgt speichern Suche:

var cells = new Object(); 
for(x=-2; x<3; x++){ 
    cells[x] = new Object(); 
    for(y=-2; y<3; y++){ 
     cells[x][y] = new Object(); 
     for(z=-2; z<3; z++){ 
      cells[x][y][z] = cell; 
     } 
    } 
} 

Dann können Sie die Zellen zugreifen, indem dort Koordinaten:

var x = 0; 
var y = 1; 
var z = -1; 
var neighbors = new Array(); 
neighbors.push(cells[x-1][y+1][z]); 
neighbors.push(cells[x+1][y-1][z]); 
neighbors.push(cells[x][y+1][z-1]); 
neighbors.push(cells[x][y-1][z+1]); 
neighbors.push(cells[x+1][y][z-1]); 
neighbors.push(cells[x-1][y][z+1]); 
+0

was? Ich verstehe das nicht. Warum müsste ich ein weiteres Array mit Objekten füllen? Jedes Hex ist in einem Array gespeichert und hat eine "Nachbarn" -Eigenschaft, die aus allen umgebenden Hexen besteht, und alle enthalten eine Zellkoordinate. Mein Beispiel funktioniert teilweise, es braucht nur eine kleine Änderung der Schleifenbeschränkungen. – Alexus

+0

Oh, jetzt sehe ich dein Problem. Meine Berechnungen machen dasselbe wie die Schleife mit einem Abstand von 1. – Marcus