Извините, ничего не найдено.

Не расстраивайся! Лучше выпей чайку!
Регистрация
Справка
Календарь

Вернуться   forum.boolean.name > Программирование в широком смысле слова > Алгоритмика

Алгоритмика Об алгоритмах вообще; методы, обсуждения способов решения

Ответ
 
Опции темы
Старый 23.04.2012, 04:54   #1
Halk-DS
Разработчик
 
Аватар для Halk-DS
 
Регистрация: 09.08.2006
Адрес: Украина
Сообщений: 431
Написано 65 полезных сообщений
(для 53 пользователей)
Пишем свой LinePick для своего Minecraft

Привет форумчане, спешу поделится полезным опытом. Недавно пытался написать алгоритм собственного пика(Camera Pick) для игры похожей на Майнкрафт. Оказалось это сложней чем я рассчитывал, но все же это вышло. Поэтому хочу описать свой метод для посторонних людей с похожими целями. Также хочу добавить моя статья написана с целью помочь разобраться тем, кто не знает как это реализовать, если у вас есть лучшие методы, то я жду от вас либо конструктивной критики, либо помощи в улучшении моей статейки, либо свою собственную статью.

К читающему есть пара требований. Элементарное понимание функций среды программирования, что такое вектор и хоть немного тригонометрии.

И так. Начнем с теории. В моем случае мир 3-х мерный и каждый кубик имеет размер 1х1х1 то есть каждый персонаж имеет координаты X#,Y#,Z# - и все они с типа Float с плавающей запятой. Сделав для координат позиции: Floor(X#),Floor(Y#),Floor(Z#) - мы отбрасываем дробовую часть и узнаем адрес клетки в мире. Поэтому все у кого масштаб кубика не ровен 1х1х1 обрели себя на вечный гемор, и советую перейти на единичные размеры кубика, в случае если это не будет перечить каким либо вашим собственным идеям, или задумкам. Также есть следующее. В меру ограниченности моей карты мне весьма удобно держать все кубики не в октодереве, а в массиве размеры которого равны размерам карты. То есть скорей всего в этих методах у нас с вами может быть различие, но всегда вы сможете подумать и модернизировать свой алгоритм под свою ситуацию. А я постараюсь описать саму логику алгоритма а не его код для копипаста. Поэтому не пытайтесь скопировать какой либо код, без должного понимания у вас ничего не получится. Я же в свою очередь попробую как можно нагляднее изобразить принцип алгоритма. Что б было проще соображать, для начала попробуем рассматривать ситуацию как 2д сетку, а потом переведем все в 3д.
Допустим есть у нас такая вот ситуация в игре, типочек смотрит на камень и пытается его копнуть: (важные точки для алгоритма отмечены)


Важно помнить что на самом деле у каждой точки по 3 координаты. Я для схематики и простоты наглядного примера я использую только 2.
Теперь опишу нужные точки:
Source(x1#,z1#)-Точная позиция начальной точки, в нашем случае это точная точка камеры.
Dest(x2#,z2#)-Точка которая находится на расстоянии на которое персонаж может копать (DiggingRange)
p1(p1x%,P1z%)-Теперь несколько важных точек которые мы можем узнать так: p1x%=Floor(X1#) P1z%=Ceil(Z1#)
p2(p2x%,P2z%)-p2x%=Ceil(x1#) P2z%=Ceil(Z1#)
p3(p3x%,P3z%)-p3x%=Ceil(x1#) P3z%=Floor(Z1#)
p4(p4x%,P4z%)-p4x%=Floor(X1#) P4z%=Floor(Z1#)
p5(p5x#,p5z#)-неизвестная нам пока точка, которая находится в месте на которое мы ткнули мышкой.
Координаты этой точки должны быть аналогом блицевским PickedX#(),PickedY#(),PickedZ#()
Как я и говорил, в случае если ваш стандарт кубика не 1х1х1 - нужно будит все переделывать под свой масштаб(просто вызовом Floor(X1#) мы не получим координаты нужной точки, как в прочем и другими такими вызовами), и код будет другим, но думаю написать это не должно составить труда. А точки Source(x1#,z1#) и Dest(x2#,z2#) образуют собой вектор Vector(Vx#,Vz#) где:
Vx#=x2#-x1#
Vz#=z2#-z1#

Сразу опишу функцию, что б было понятно какие данные являются входными: Function Pick%(X1#,Z1#,Vx#,Vz#) - другими словами аналог блицовскому LinePick. Располагая данными выше опишу сам алгоритм по шагам опираясь на этот рисунок:


Проверить блок под номером 1 - проще простого, мы на нем стоим и знаем его координаты, делаем адрес блока: Floor(X#),Floor(Y#),Floor(Z#) и если он пуст - продолжаем работу. Методом перебора 2, 3 и т.д. кубов и постоянно сверяемся пустые ли они, а если нет, возвращаем их оканчивая работу функции. Вся соль заключается в том, как располагая точками выше определить какие кубы проткнул вектор?
Начнем с того, что б узнать какую из сторон куба номер 1 проткнул вектор. Есть 4 варианта левую, правую, переднюю, заднюю (вид сверху, поэтому верхнюю и нижнюю пока что игнорим) присваиваем сторонам соответственные индексы:
1-лево
2-право
3-перед
4-зад
(пока что делаем это только в уме).
При помощи If Then Else делаем весьма сложное разветвление.
If VZ>0
    
If VX>0
        
;В этой ситуации теоретически возможны 2 варианта.
        ;
Вектор проткнет либо передлибо право
    
Else
        If 
VX=0
            
;Тут он точно проткнет только перед
        
Else
            ;
Передили лево
        
EndIf
    EndIf
Else
    If 
VZ=0
        
If VX>0
            
;Точно только право
        
Else
            If 
VX=0
                
;Ничего не проткнет
            
Else
                ;
Точно только лево
            
EndIf
        EndIf
    Else
        If 
VX>0
            
;Правоили низ
        
Else
            If 
VX=0
                
;Только низ
            
Else
                ;
Левоили низ.
            EndIf
        EndIf
    EndIf
EndIf 
Теперь мы сделали все возможные варианты (кроме верхней и нижней сторон, но пока отложим их). Теперь стоя в этом тупике, на нужно определить намного меньше чем раньше, какую из ДВУХ сторон проткнет вектор, а не из ЧЕТЫРЕХ возможных. Вот теперь нам на помощь и приходят точки:
p1(p1x%,P1z%) где p1x%=Floor(X1#) P1z%=Ceil(Z1#)
p2(p2x%,P2z%) где p2x%=Ceil(x1#) P2z%=Ceil(Z1#)
p3(p3x%,P3z%) где p3x%=Ceil(x1#) P3z%=Floor(Z1#)
p4(p4x%,P4z%) где p4x%=Floor(X1#) P4z%=Floor(Z1#)
В каждой из выше возможных ситуаций нам нужна лишь 1 из 4-х точек. И каждый раз эта точка будет той, что стоит между 2 теоретически возможными сторонами. Пример:
Возможно вектор проткнет либо перед, либо право - нужна верхняя правая точка что соответствует точке p2(p2x%,P2z%)
п.с. В нашем случае как на рисунках нам именно эта точка и нужна. Переменные и Vx#>0, и Vz#>0

Теперь располагая информацией выше можем свести алгоритм до использования только этих переменных
Source(x1#,z1#)
Vector(Vx#,Vz#)
p2(p2x%,P2z%)
Попробую изобразить рисунком данный пример:


Серым цветом закрашена зона где вектор не когда не окажется при Vx#>0 и Vz#>0
Вы должны понимать, что в ситуации, когда вектор проткнет либо зад, либо лево (Vx#<0 и Vz#<0) - ситуация будет другой, и нужна будет уже точка не p2(p2x%,P2z%), а точка p4(p4x%,P4z%). Другими словами в точке Source(x1#,z1#) пространство делится на 4 области двумя перпендикулярами какие проходят параллельно осям OX и OZ. Отсюда и строятся предположения, какие возможные стороны будут проткнуты.

Далее превращаем Source(x1#,z1#) и p2(p2x%,P2z%) в новый вектор EdgeVector(eVx#,eVz#)
eVx#=p2x%-x1#
eVz#=P2z%-z1#
И смотрим:


Что б узнать наверняка, какую сторону проткнет вектор, нужно узнать косинус угла вектора. Попробую сделать сложный рисунок. Надеюсь вы его поймете:


Теперь прокомментирую происходящее.
У нас есть 3 точки Source(x1#,z1#) p2(p2x%,P2z%) Dest(x2#,z2#)
Которые создали 2 вектора Vector(Vx#,Vz#) и EdgeVector(eVx#,eVz#)
В математике есть кроме Декартовой сис-мы координат еще и полярная. В ней каждая точка имеет 2 компонента. Пример: Point(Lenght,Angle) Lenght-длинна вектора который соединяет точку с началом координат (0,0) Angle-угол, на который повернут вектор. У нас в алгоритме будет использовано нечто подобное. Как видно я на круге отложил 2 точки. Эти точки показывают угол на который повернут каждый вектор. Осталось найти косинус угла каждого вектора. Если косинус Vector(Vx#,Vz#) больший за косинус EdgeVector(eVx#,eVz#), значит вектор проткнет правую сторону. Если наоборот, то переднюю. Формула что б узнать косинус угла вектора:
п.с. Не знаю как по русски сказать "Скалярный" короче когда вектор множишь на вектор и выходит одно число.
Скалярное воспроизведении векторов разделено на воспроизведение их модулей равно косинусу угла между ними. За этой формулой находим косинус угла между векторами и сравниваем их.
Вот необходимые данные:

Вот решение:

Вот попробую анимационно изобразить роботу этой части алгоритма:


Думаю все логично и понятно. Теперь когда мы знаем сторону куба которую проткнет вектор мы сможем вычислить нашу загадочную точку p5(p5x#,p5z#), которая как я говорил имеет координаты служащие аналогом блицевским PickedX#(),PickedY#(),PickedZ#(). Найти мы ее можем потому, что она лежит на прямой концом и началом которой являются точки Source(x1#,z1#) и Dest(x2#,z2#), а зная какой стороне куба принадлежит эта точка мы будем знать одну из координат этой точки.
Если пробита правая сторона куба Известная координата будет p5x#=p2x%
Если пробита верхняя сторона куба известная координата будет p5z#=P2z%
Найти недостающие координаты мы можем при помощи не сложных уравнений:
Тут и пригодится элементарные знания математики, что б вывести из следующих формул необходимые:
(X2-X1)/Vx=(Y2-Y1)/Vy
(X2-X1)/Vx=(Z2-Z1)/Vz
(Y2-Y1)/Vy=(Z2-Z1)/Vz

Например нам известно, что вектор проткнул правую сторону. Формулы должны выглядеть так:
p5x#=p2x%
p5y#=VY*(p5x-X1)/VX+Y1
p5Z#=VZ*(p5y-Y1)/VY+Z1

Вот теперь почти все готово. Единственное про что мы забыли это посчитать это не протыкает ли вектор верх, или низ куба. Делается это примерно также как и с другими сторонами. После этого мы зацикливаем функцию, и делаем в нужный момент выход из нее.

Излагаю свой код функции, но он еще не на 100% отлажен. Хотя пробовал в деле, кубики в моей игре он уже рубать способен, отладка идет в сторону, что б при ее помощи вычислять передвижение персонажа по локации.
п.с. Когда доделаю до 100-процентного конца обновлю код.

;Описываем переменныекакие мы будем использовать вне функции
Global PickX#
Global PickY#
Global PickZ#
Global PickVx#
Global PickVy#
Global PickVz#

Function Pick%(PointX#,PointY#,PointZ#,VectorX#=0,VectorY#=0,VectorZ#=0)
    
Local CosAngle#,CosEdgeVector#
    
Local PointVectorX#,PointVectorZ#,PointVectorY#
    
Local Side=0
    Local X2
#,Y2#,Z2#
    
Local X#=PointX
    
Local Y#=PointY
    
Local Z#=PointZ
    
Local VX#=VectorX
    
Local VY#=VectorY
    
Local VZ#=VectorZ
    
    
Repeat
    

    
:Если вектор вообще не выходит из куба (слишком короткий) - выходим из функции.
    If 
Floor(X+VX)=Floor(X) And Floor(Y+VY)=Floor(Y) And Floor(Z+VZ)=Floor(Z)
        
PickX=X+VX
        PickY
=Y+VY
        PickZ
=Z+VZ
        PickVx
=VX
        PickVy
=VY
        PickVz
=VZ
        
Return World(Floor(X),Floor(Y),Floor(Z))
    EndIf

        If 
VZ>0
            
If VX>0
                CosAngle
=VX/(Sqr(VX^2+VZ^2)*1.0)
                
PointVectorX=Ceil(X)-X
                PointVectorZ
=Ceil(Z)-Z
                CosEdgeVector
=PointVectorX/(Sqr(PointVectorX^2+PointVectorZ^2))
                If 
CosAngle>CosEdgeVector
                    
;=========================================================================Right side
                    Side
=2
                
Else
                    ;=========================================================================
Front side
                    Side
=5
                
EndIf
            Else
                If 
VX=0
                    
;=========================================================================Front side
                    Side
=5
                
Else
                    
CosAngle=VX/(Sqr(VX^2+VZ^2)*1.0)
                    
PointVectorX=Floor(X)-X
                    PointVectorZ
=Ceil(Z)-Z
                    CosEdgeVector
=PointVectorX/(Sqr(PointVectorX^2+PointVectorZ^2))
                    If 
CosAngle<CosEdgeVector
                        
;=========================================================================Left side
                        Side
=1
                    
Else
                        ;=========================================================================
Front side
                        Side
=5
                    
EndIf
                EndIf
            EndIf
        Else
            If 
VZ=0
                
If VX>0
                    
;=========================================================================Right side
                    Side
=2
                
Else
                    If 
VX=0
                        Side
=0
                    
Else
                        ;=========================================================================
Left side
                        Side
=1
                    
EndIf
                EndIf
            Else
                If 
VX>0
                    CosAngle
=VX/(Sqr(VX^2+VZ^2)*1.0)
                    
PointVectorX=Ceil(X)-X
                    PointVectorZ
=Floor(Z)-Z
                    CosEdgeVector
=PointVectorX/(Sqr(PointVectorX^2+PointVectorZ^2))
                    If 
CosAngle>CosEdgeVector
                        
;=========================================================================Right side
                        Side
=2
                    
Else
                        ;=========================================================================
Back side
                        Side
=6
                    
EndIf
                Else
                    If 
VX=0
                        
;=========================================================================Back side
                        Side
=6
                    
Else
                        
CosAngle=VX/(Sqr(VX^2+VZ^2)*1.0)
                        
PointVectorX=Floor(X)-X
                        PointVectorZ
=Floor(Z)-Z
                        CosEdgeVector
=PointVectorX/(Sqr(PointVectorX^2+PointVectorZ^2))
                        If 
CosAngle<CosEdgeVector
                            
;=========================================================================Left side
                            Side
=1
                        
Else
                            ;=========================================================================
Back side
                            Side
=6
                        
EndIf
                    EndIf
                EndIf
            EndIf
        EndIf
        
;
Теперькогда мы определили какую сторону пробивает векторопределимне пробивает ли он верх или низ?


        If 
VY<>0
            
If VY>0
                Select True
                    
Case Side=Or Side=2
                        CosAngle
=VX/(Sqr(VX^2+VY^2)*1.0)
                        
PointVectorY=Ceil(Y)-Y
                        
If Side=1
                            PointVectorX
=Floor(X)-X
                            CosEdgeVector
=PointVectorX/(Sqr(PointVectorX^2+PointVectorY^2)*1.0)
                            If 
CosAngle>CosEdgeVector
                            
;=========================================================================Up side
                                Side
=3
                            
EndIf
                        Else
                            
PointVectorX=Ceil(X)-X
                            CosEdgeVector
=PointVectorX/(Sqr(PointVectorX^2+PointVectorY^2)*1.0)
                            If 
CosAngle<CosEdgeVector
                            
;=========================================================================Up side
                                Side
=3
                            
EndIf
                        EndIf
                    Case 
Side=Or Side=6
                        CosAngle
=VZ/(Sqr(VZ^2+VY^2)*1.0)
                        
PointVectorY=Ceil(Y)-Y
                        
If Side=5
                            PointVectorZ
=Ceil(Z)-Z
                            CosEdgeVector
=PointVectorZ/(Sqr(PointVectorZ^2+PointVectorY^2)*1.0)
                            If 
CosAngle<CosEdgeVector
                            
;=========================================================================Up side
                                Side
=3
                            
EndIf
                        Else
                            
PointVectorZ=Floor(Z)-Z
                            CosEdgeVector
=PointVectorZ/(Sqr(PointVectorZ^2+PointVectorY^2)*1.0)
                            If 
CosAngle>CosEdgeVector
                            
;=========================================================================Up side
                                Side
=3
                            
EndIf
                        EndIf
                    Case 
Side=0
                        
;=========================================================================Up side
                        Side
=3
                End Select
            
Else
                
Select True
                    
Case Side=Or Side=2
                        CosAngle
=VX/(Sqr(VX^2+VY^2)*1.0)
                        
PointVectorY=Floor(Y)-Y
                        
If Side=1
                            PointVectorX
=Floor(X)-X
                            CosEdgeVector
=PointVectorX/(Sqr(PointVectorX^2+PointVectorY^2)*1.0)
                            If 
CosAngle>CosEdgeVector
                            
;=========================================================================Down side
                                Side
=4
                            
EndIf
                        Else
                            
PointVectorX=Ceil(X)-X
                            CosEdgeVector
=PointVectorX/(Sqr(PointVectorX^2+PointVectorY^2)*1.0)
                            If 
CosAngle<CosEdgeVector
                            
;=========================================================================Down side
                                Side
=4
                            
EndIf
                        EndIf
                    Case 
Side=Or Side=6
                        CosAngle
=VZ/(Sqr(VZ^2+VY^2)*1.0)
                        
PointVectorY=Floor(Y)-Y
                        
If Side=5
                            PointVectorX
=Ceil(Z)-Z
                            CosEdgeVector
=PointVectorZ/(Sqr(PointVectorZ^2+PointVectorY^2)*1.0)
                            If 
CosAngle<CosEdgeVector
                            
;=========================================================================Down side
                                Side
=4
                            
EndIf
                        Else
                            
PointVectorX=Floor(Z)-Z
                            CosEdgeVector
=PointVectorZ/(Sqr(PointVectorZ^2+PointVectorY^2)*1.0)
                            If 
CosAngle>CosEdgeVector
                            
;=========================================================================Down side
                                Side
=4
                            
EndIf
                        EndIf
                    Case 
Side=0
                        
;=========================================================================Down side
                        Side
=4
                End Select
            
EndIf
        Else
            If 
Side=Return 0
        
EndIf
        
;
Зная точную сторону вычисляем точку пика

        Select Side
            
Case 1
                X2
=Floor(X)-.001
                Y2
=VY*(X2-X)/VX+Y
                Z2
=VZ*(Y2-Y)/VY+Z
                VX
=VX-(X2-X)
                
VY=VY-(Y2-Y)
                
VZ=VZ-(Z2-Z)
                
X=X2
                Y
=Y2
                Z
=Z2
            
Case 2
                X2
=Ceil(X)+.001
                Y2
=VY*(X2-X)/VX+Y
                Z2
=VZ*(Y2-Y)/VY+Z
                VX
=VX-(X2-X)
                
VY=VY-(Y2-Y)
                
VZ=VZ-(Z2-Z)
                
X=X2
                Y
=Y2
                Z
=Z2
            
Case 3
                Y2
=Ceil(Y)+.001
                Z2
=VZ*(Y2-Y)/VY+Z
                X2
=VX*(Z2-Z)/VZ+X
                VX
=VX-(X2-X)
                
VY=VY-(Y2-Y)
                
VZ=VZ-(Z2-Z)
                
X=X2
                Y
=Y2
                Z
=Z2
            
Case 4
                Y2
=Floor(Y)-.001
                Z2
=VZ*(Y2-Y)/VY+Z
                X2
=VX*(Z2-Z)/VZ+X
                VX
=VX-(X2-X)
                
VY=VY-(Y2-Y)
                
VZ=VZ-(Z2-Z)
                
X=X2
                Y
=Y2
                Z
=Z2
            
Case 5
                Z2
=Ceil(Z)+.001
                X2
=VX*(Z2-Z)/VZ+X
                Y2
=VY*(X2-X)/VX+Y
                VX
=VX-(X2-X)
                
VY=VY-(Y2-Y)
                
VZ=VZ-(Z2-Z)
                
X=X2
                Y
=Y2
                Z
=Z2
            
Case 6
                Z2
=Floor(Z)-.001
                X2
=VX*(Z2-Z)/VZ+X
                Y2
=VY*(X2-X)/VX+Y
                VX
=VX-(X2-X)
                
VY=VY-(Y2-Y)
                
VZ=VZ-(Z2-Z)
                
X=X2
                Y
=Y2
                Z
=Z2
            
Default
                
RuntimeError "Something wrong!!!"
        
End Select
        

            
;Если наткнулись на твердую породу или чтото еще выходим из функции.
            If 
World(Floor(X),Floor(Y),Floor(Z))<>0
                PickX
=X
                PickY
=Y
                PickZ
=Z
                PickVx
=X-PointX
                PickVy
=Y-PointY
                PickVz
=Z-PointZ
                
Return World(Floor(X),Floor(Y),Floor(Z))
            EndIf
        
    
Forever
    
End 
Function 


В математической стороне реализации мне помог друг (с)Мостепанюк Вова

Последний раз редактировалось Hulk-DS, 23.04.2012 в 17:42.
(Offline)
 
Ответить с цитированием
Эти 11 пользователя(ей) сказали Спасибо Halk-DS за это полезное сообщение:
ABTOMAT (23.04.2012), den (23.04.2012), Gector (23.04.2012), Harter (23.04.2012), impersonalis (25.04.2012), nil0q (24.04.2012), Nuprahtor (23.04.2012), pax (23.04.2012), Randomize (23.04.2012), Reks888 (23.04.2012), St_AnGer (23.04.2012)
Старый 23.04.2012, 11:14   #2
pax
Unity/C# кодер
 
Аватар для pax
 
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений
(для 5,323 пользователей)
Ответ: Пишем свой LinePick для своего Minecraft

Сообщение от Hulk-DS Посмотреть сообщение
в случае если ваш стандарт кубика не 1х1х1 - нужно будит все переделывать под свой масштаб(просто вызовом Floor(X1#) мы не получим координаты нужной точки, как в прочем и другими такими вызовами), и код будет другим, но думаю написать это не должно составить труда.
Собственно перед расчетами все координаты поделить на размер клетки, а после домножить. (Привести в единичную систему)


В коде есть -.001 и +.001, т.е. с каждой итерацией будет расти ошибка?
__________________
Blitz3d to Unity Wiki
(Offline)
 
Ответить с цитированием
Эти 2 пользователя(ей) сказали Спасибо pax за это полезное сообщение:
Harter (23.04.2012), Hulk-DS (23.04.2012)
Старый 23.04.2012, 11:35   #3
ABTOMAT
Ференька
 
Аватар для ABTOMAT
 
Регистрация: 26.01.2007
Адрес: улица Пушкина дом Колотушкина
Сообщений: 10,741
Написано 5,461 полезных сообщений
(для 15,675 пользователей)
Ответ: Пишем свой LinePick для своего Minecraft

Спасибо, хорошая статья!
Когда писал свой клон тоже хотел сделать свой пик, но всё же сделал проще, чтобы не тратить время: пик был только по текущему чанку (либо если игрок у границы - то ещё и по соседнему, т.е. максимум по 4), но ты всё же собрался и сделал православно! Обязательно прочитаю потом внимательно.
__________________
Мои проекты:
Анальное Рабство
Зелёный Слоник
Дмитрий Маслов*
Различие**
Клюква**

* — в стадии разработки
** — в стадии проектирования
Для проектов в стадии проектирования приведены кодовые имена

(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
Hulk-DS (23.04.2012)
Старый 23.04.2012, 12:02   #4
Nuprahtor
Элита
 
Аватар для Nuprahtor
 
Регистрация: 26.07.2008
Сообщений: 1,972
Написано 1,095 полезных сообщений
(для 3,923 пользователей)
Ответ: Пишем свой LinePick для своего Minecraft

Это хорошая статья.
Когда можно будет погонять .exe пример?
(Offline)
 
Ответить с цитированием
Старый 23.04.2012, 12:43   #5
ffinder
Дэвелопер
 
Аватар для ffinder
 
Регистрация: 10.09.2007
Сообщений: 1,442
Написано 793 полезных сообщений
(для 1,460 пользователей)
Ответ: Пишем свой LinePick для своего Minecraft

Сделав для координат позиции: Floor(X#),Floor(Y#),Floor(Z#) - мы узнаем адрес клетки в мире.
лучше говорить что делает функция - отбрасывает дробную часть числа.
в разных языках/фреймворках функции же по-разному могут называться.

сразу видно, что украинский твой родной язык
наочнее, припустим
нагляднее, допустим/пусть

В математике есть кроме Декартовой сис-мы координат еще и афинная.
полярная система координат.

Теперь главное:
анимированное изображение метода - офигительное, маладца!
сразу стала понятна суть.
(Offline)
 
Ответить с цитированием
Эти 3 пользователя(ей) сказали Спасибо ffinder за это полезное сообщение:
HolyDel (23.04.2012), Hulk-DS (23.04.2012), impersonalis (25.04.2012)
Старый 23.04.2012, 12:45   #6
Igor
Мастер
 
Аватар для Igor
 
Регистрация: 03.05.2010
Адрес: Подмосковье
Сообщений: 1,218
Написано 438 полезных сообщений
(для 790 пользователей)
Ответ: Пишем свой LinePick для своего Minecraft

А может, искать пересечения луча не с кубиками, а с плоскостями? Потом их округлять и получать кубик.
(Берём много плоскостей - параллельных XOY, XOZ, YOZ и отличающихся на целое число третьей координатой. Ищем точки пересечений. Потом у этих точек округляем координаты и получаем положение кубика)
__________________
О¯О ¡¡¡ʁɔvʎнdǝʚǝdǝu dиW
(Offline)
 
Ответить с цитированием
Старый 23.04.2012, 17:19   #7
Halk-DS
Разработчик
 
Аватар для Halk-DS
 
Регистрация: 09.08.2006
Адрес: Украина
Сообщений: 431
Написано 65 полезных сообщений
(для 53 пользователей)
Ответ: Пишем свой LinePick для своего Minecraft

Сообщение от pax Посмотреть сообщение
Собственно перед расчетами все координаты поделить на размер клетки, а после домножить. (Привести в единичную систему)
В коде есть -.001 и +.001, т.е. с каждой итерацией будет расти ошибка?
Собственно да. Есть немного говнокода. Это можно немного подумать и исправить, но оч сильно хотелось использовать функцию в деле, поэтому пришлось поторопится. Как я и писал, еще немного позднее попробую подправить код и этот недостаток попробую учесть.
п.с. При дальности пика куба в 10 клеток(это уже неиграбельный параметр) погрешность становится в 0.01. Имхо заметно только нам с вами

Сообщение от Nuprahtor Посмотреть сообщение
Это хорошая статья.
Когда можно будет погонять .exe пример?
Я хочу эту функцию применить при перерасчете передвижения игрока. (копать он уже может). Редактор тоже есть. Короче пара мелочей и буду выкладывать. (надеюсь в пределах этой недели будет.)

Сообщение от Igor Посмотреть сообщение
А может, искать пересечения луча не с кубиками, а с плоскостями? Потом их округлять и получать кубик.
(Берём много плоскостей - параллельных XOY, XOZ, YOZ и отличающихся на целое число третьей координатой. Ищем точки пересечений. Потом у этих точек округляем координаты и получаем положение кубика)
Идей и теорий куча, вопрос в том кто возьмется за их реализацию? А потом еще и сумеет качественно поделится этим с народом. Была еще одна идея похожа на эту. Вектор проходящий через грань представляется как вектор принадлежащий прямой. Точка Dest(x2,y2,z2) - просто как точка (в нашем случае это был конец вектора). Должно было высчитывается смещение точки относительно прямой и по переменной смещения находилась проткнутая сторона куба и т.д. Но мне с косинусом угла чот больше понравилось.


Ну а за полурусский язык простите, с чем словарь в мозилле справляется так и выкладываю
Ошибки вроде подправил.
Нашел главный баг. Не предусмотрено деление на ноль практически везде. Омг
(Offline)
 
Ответить с цитированием
Ответ


Опции темы

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


Часовой пояс GMT +4, время: 13:10.


vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot
Style crйe par Allan - vBulletin-Ressources.com