2016-08-04 1 views
1

J'essaye de sélectionner tous les hexagones dans une portée donnée. Cependant, je reçois des résultats étranges tout en implémentant ce code trouvé sur page de Amit Patel.Sélection d'hexagones à proximité autour d'un hexagone

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

C'est ce que j'ai jusqu'à présent:

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

Je suppose que la boucle contraint besoin de me un peu modifiée et utiliser des valeurs dx, dy.

<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>

Répondre

0

Il suffit de prendre les coordonnées x, y, z et recherche alors tous les champs à l'un de ces calculs:

  1. z est const, x est plus/moins 1, y est moins/plus 1
  2. x est const, z est plus/moins 1, y est moins/plus 1
  3. y est const, z est plus/moins 1, x est moins/plus 1

Cela devrait être tous les voisins

Exemple: Classé 0, 1, -1 (x, y, z)

  1. z est const et x est plus/moins 1 => [ -1, 2, -1], [1, 0, -1]
  2. x est const et z est plus/moins 1 => [0, 2, -2], [0, 0, 0]
  3. y est const et z est plus/moins 1 => [1, 1, -2], [-1, 1, 0]

Pour une recherche plus rapide, vous pouvez stocker vos cellules à l'intérieur d'un objet comme celui-ci:

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; 
     } 
    } 
} 

Ensuite, vous pouvez accéder aux cellules par là coordonnées:

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

quoi? Je ne semble pas comprendre .. pourquoi devrais-je besoin de faire un autre tableau rempli d'objets? Chaque hex est stocké dans un tableau et possède une propriété 'neighbors' qui comprend tous les hexs environnants, et ils contiennent tous une coordonnée de cellule. Mon exemple fonctionne partiellement, il suffit d'apporter de légères modifications aux contraintes de la boucle. – Alexus

+0

Oh, maintenant je vois ton problème. Mes calculs font la même chose que la boucle avec une distance de 1. – Marcus