Yanıtlar:
Bu resme bir göz atın
Gördüğünüz gibi, x, y dikdörtgen koordinat sistemini altıgen olana eşlemek için nispeten sezgisel bir yol var.
"Düzgün" düzensiz altıgenler, yani her iki yönde orantısız olarak ölçeklendirilmiş normal altıgenlerden elde edilen altıgenler veya altıgenler içine yerleştirilmiş altıgenler hakkında konuşabiliriz (rotasyon-kesme yok).
Doğrultucu bir altıgen, daire içine alan dikdörtgenin yüksekliği ve genişliği ile yazıya dökülen dikdörtgenin genişliği ile tanımlanabilir. (W, W, h)
Altıgen indeksi bulmanın en kolay yolu, alanı aşağıdaki gibi bölümlendirmektir:
Dikdörtgen genişliği w + (W - w) / 2 = (w + W) / 2, yüksekliği h / 2; yeşil dikdörtgenin genişliği (Ww) / 2'dir. Noktanın hangi dikdörtgenin içine düştüğünü bulmak kolaydır:
u ve v, i, j dikdörtgeninde noktanın nerede olduğunu gösteren hatırlatma koordinatlarıdır: w'yi kullanarak yeşil alanda (u <(Ww) / 2) olup olmadığımızı söyleyebiliriz.
eğer yeşil alandaysak altıgenin üst veya alt yarısında olup olmadığımızı bilmemiz gerekir: i ve j'nin her ikisi de eşitse veya her ikisi de tekse, üst yarıyız; aksi takdirde alt yarıyız.
Her iki durumda da, u ve v'yi değiştirmek 0 ve 1 arasında değişmektedir:
eğer alt yarıdayız ve v <u
veya
eğer üst yarıdaysak ve (1-v)> u
o zaman ben birer birer azalırız
İ i yatay altıgen indeks (sütun) ve j / 2 tamsayısının dikey altıgen indeks (satır) olduğunu görmek için garip ise j'yi bir azaltmalıyız.
Düzenli altıgenlerin altı eksen simetrisi vardır, ancak altıgenlerinizin yalnızca iki simetri eksenine sahip olduğunu varsayacağım ( yani, tüm açılar tam olarak 60 derece değildir). Mutlaka sizinki tam simetriye sahip olmadığı için değil, başka biri için yararlı olabileceği için.
İşte bir altıgenin parametreleri. Merkezi O
, en geniş genişliği, 2a
yüksekliği 2b
ve üst kenarının uzunluğu 2c
.
Y ^
|
____|____
/ b | |\
/ | | \
/ | | \
---(-------+---+---)------>
\ O| c / a X
\ | /
\____|____/
|
Bu, orijini sol alt altıgenin ortasında olacak şekilde satır / sütun düzenidir. Kurulumunuz farklıysa, (x,y)
bu duruma geri dönmek için koordinatlarınızı çevirin veya örneğin -y
yerine kullanın y
:
col 0
| col 1
| | col 2
| | |
__ | __ __ __ __
/ \__/ \__/ \__/ \__/ \__
\__/ \__/ \__/ \__/ \__/ \
/ \__/ \__/ \__/ \__/ \__/
\__/ \__/ \__/ \__/ \__/ \
/ \__/ \__/ \__/ \__/ \__/_ _ line 2
\__/ \__/ \__/ \__/ \__/ \ _ _ _ line 1
/ .\__/ \__/ \__/ \__/ \__/_ _ line 0
\__/ \__/ \__/ \__/ \__/
Aşağıdaki kod size altıgen içeren noktanın satırını ve sütununu verecektir (x,y)
:
static void GetHex(float x, float y, out int row, out int column)
{
// Find out which major row and column we are on:
row = (int)(y / b);
column = (int)(x / (a + c));
// Compute the offset into these row and column:
float dy = y - (float)row * b;
float dx = x - (float)column * (a + c);
// Are we on the left of the hexagon edge, or on the right?
if (((row ^ column) & 1) == 0)
dy = b - dy;
int right = dy * (a - c) < b * (dx - c) ? 1 : 0;
// Now we have all the information we need, just fine-tune row and column.
row += (column ^ row ^ right) & 1;
column += right;
}
Yukarıdaki kodun bu IdeOne çalıştırmasında mükemmel altıgenler çizdiğini kontrol edebilirsiniz .
Muhtemelen kutucuklar arasındaki tıklamaları kaldırmanıza gerek yoktur. Yani, aralarında mantıksal olarak olmaması gereken bir şeyle dolu geniş bir alandan bahsetmediğiniz sürece, fayanslar arasındaki boşlukların da tıklanabilir olmasına izin verirseniz, zarar vermez ve hatta oyuncuya yardımcı olabilir. tıklayın. (Diyelim ki altıgenler, aralarında insanlar gibi tıklanabilir diğer şeyler olan büyük bir haritada bulunan şehirlerdir)
Yukarıdakileri yapmak için, tüm altıgenlerin merkezlerini çizebilir ve ardından tüm altıgenlerin düzlemine tıklandığında fareye en yakın olanı bulabilirsiniz. Mozaik altıgenler düzlemindeki en yakın merkez her zaman üzerinde gezindiğiniz merkezle aynı olacaktır.
Benzer bir soruyu, aynı hedeflerle birlikte, Stack Overflow üzerinde, rahatlık için burada tekrar göndereceğim: (NB - tüm kod Java ile yazılmış ve test edilmiştir)
Bu resim altıgen bir ızgaranın sol üst köşesini gösterir ve üst üste yerleştirilmiş mavi kare bir ızgaradır. Bir noktanın içinde hangi karelerin içinde olduğunu bulmak kolaydır ve bu da hangi altıgenin de kabaca bir yaklaşımını sağlar. Altıgenlerin beyaz kısımları, kare ve altıgen ızgaranın aynı koordinatları nerede paylaştığını, altıgenlerin gri kısımları ise nerede olmadığını gösterir.
Çözüm artık bir noktanın hangi kutuda olduğunu bulmak, daha sonra noktanın üçgenlerden herhangi birinde olup olmadığını kontrol etmek ve gerekirse cevabı düzeltmek kadar basit.
private final Hexagon getSelectedHexagon(int x, int y)
{
// Find the row and column of the box that the point falls in.
int row = (int) (y / gridHeight);
int column;
boolean rowIsOdd = row % 2 == 1;
// Is the row an odd number?
if (rowIsOdd)// Yes: Offset x to match the indent of the row
column = (int) ((x - halfWidth) / gridWidth);
else// No: Calculate normally
column = (int) (x / gridWidth);
Bu noktada, noktamızın bulunduğu kutunun satırına ve sütununa sahibiz, daha sonra, noktamızın yukarıdaki altıgenlerden birinde olup olmadığını görmek için noktamızı altıgenin iki üst kenarına karşı test etmemiz gerekiyor:
// Work out the position of the point relative to the box it is in
double relY = y - (row * gridHeight);
double relX;
if (rowIsOdd)
relX = (x - (column * gridWidth)) - halfWidth;
else
relX = x - (column * gridWidth);
Göreli koordinatlara sahip olmak bir sonraki adımı kolaylaştırır.
Yukarıdaki görüntüde olduğu gibi, noktamızın y değeri > mx + c ise , noktamızın çizginin üstünde olduğunu ve bizim durumumuzda, mevcut satırın ve sütunun üstündeki ve solundaki altıgen olduğunu biliyoruz. Java'daki koordinat sisteminin, her zaman matematikte olduğu gibi sol altta değil, ekranın sol üstünde 0'dan başladığını, dolayısıyla sol kenar için kullanılan negatif gradyan ve sağ için kullanılan pozitif gradyan olduğunu unutmayın.
// Work out if the point is above either of the hexagon's top edges
if (relY < (-m * relX) + c) // LEFT edge
{
row--;
if (!rowIsOdd)
column--;
}
else if (relY < (m * relX) - c) // RIGHT edge
{
row--;
if (rowIsOdd)
column++;
}
return hexagons[column][row];
}
Yukarıdaki örnekte kullanılan değişkenlerin hızlı bir açıklaması:
m eğimdir , dolayısıyla m = c / halfWidth
Bu SebastianTroy'un cevabına bir zeyilname. Bir yorum olarak bırakacaktım ama henüz yeterli üne sahip değilim.
Burada açıklandığı gibi bir eksenel koordinat sistemi uygulamak istiyorsanız: http://www.redblobgames.com/grids/hexagons/
Kodda küçük bir değişiklik yapabilirsiniz.
Onun yerine
// Is the row an odd number?
if (rowIsOdd)// Yes: Offset x to match the indent of the row
column = (int) ((x - halfWidth) / gridWidth);
else// No: Calculate normally
column = (int) (x / gridWidth);
bunu kullan
float columnOffset = row * halfWidth;
column = (int)(x + columnOffset)/gridWidth; //switch + to - to align the grid the other way
Bu, koordinatın (0, 2) doğrudan (0, 0) altında olmak yerine (0, 0) ve (0, 1) ile aynı çapraz sütunda olmasını sağlar.
Tüm altıgenleriniz aynı oranlarda ve yerleştirme kullanılarak yapılırsa, çarpışmalar için bir tür yer paylaşımı kullanabilirsiniz,
Ardından, tek yapmanız gereken çarpışma görüntüsünü altıgeninizin olduğu yere yerleştirmek, fare konumunu sol köşeye göre almak ve göreli konumun pikselinin beyaz OLMAMASI (yani bir çarpışma olduğu anlamına gelir).
Kod (test edilmedi):
bool IsMouseTouchingHexagon(Vector2 mousePosition, Vector2 hexagonPosition,
Rectangle hexagonRectangle, Texture2D hexagonImage)
{
Vector2 mousePositionToTopLeft = mousePosition - hexagonPosition;
// We make sure that the mouse is over the hexagon's rectangle.
if (mousePositionToTopLeft.X >= 0 && mousePositionToTopLeft.X < hexagonRectangle.Width &&
mousePositionToTopLeft.Y >= 0 && mousePositionToTopLeft.Y < hexagonRectangle.Height)
{
// Where "PixelColorAt" returns the color of a pixel of an image at a certain position.
if (PixelColorAt(hexagonImage, mousePositionToTopLeft) == Color.White)
{
// If the color is not white, we are colliding with the hexagon
return true;
}
}
// if we get here, it means that we did not find a collision.
return false;
}
Tüm sürecin performansını artırmak için önceden bir dikdörtgen çarpışma kontrolü yapabilirsiniz (tüm altıgen görüntünüzün).
Kavramın anlaşılması ve uygulanması oldukça basittir, ancak yalnızca altıgenleriniz aynı olduğunda çalışır. Sadece bir dizi olası altıgen boyutunuz varsa da işe yarayabilir, bu da birden fazla çarpışma katmanına ihtiyacınız olacağı anlamına gelir.
Eğer çok daha eksiksiz ve tekrar kullanılabilir ne çok basit bir çözüm bulmak eğer (gerçekten çarpışmayı bulmak için matematik kullanarak) ama bence kesinlikle denemeye değer.
Üzerinde bir makale var Oyun Programlama Gems 7 adlandırılan Bees ve Oyuncular için: Altıgen Fayans Kolu nasıl tam olarak neye ihtiyacınız olacağını.
Ne yazık ki şu anda yanımda kitabımın bir kopyası yok, aksi halde biraz tarif edebilirdim.