forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   2D-программирование (http://forum.boolean.name/forumdisplay.php?f=13)
-   -   2d сетка (http://forum.boolean.name/showthread.php?t=17416)

polopok 23.10.2012 19:00

2d сетка
 
вопрос как реализовать подобную сетку в 2д так чтоб можно было
по координатам мыши вычислить номера ячейки при клике

возможно у вас есть идеи ,предложения по реализации...

polopok 23.10.2012 19:34

Ответ: 2d сетка
 
в принципе всё до чего я додумался ...
вот примеры кода:
Код:

Graphics 800,600 ,32,
SetBuffer BackBuffer()


While Not KeyHit(1)
        Cls
Xoffset# = -10
py =0
For map_pointY = 0 To 12
        py= py+1
        px =0
        Xoffset# = Xoffset# -.5
        For map_pointX# = -6 To 6
                px = px +1
                Color 255,255,255
                Plot  400  + (map_pointX*3.5*Xoffset# )  ,  30+ map_pointY*30
                Text  400  + (map_pointX*3.5*Xoffset# )  ,  30+ map_pointY*30 , px +" "+py
        Next
Next
Flip
Wend
End



другой вариант ;

Код:

Graphics 800,600,32,2
SetBuffer BackBuffer()
x = 20
y = 40
z = 50
z2 =30
k =16
FOV = 400
dist =100
Dim tx(k) : Dim ty(k) : Dim tz(k)

Restore dats
For i = 1 To k
        Read x,y,z
        tx(i)=x
        ty(i)=y
        tz(i)=z
Next
HidePointer
While Not KeyHit(1)
Cls ; Сначала очищаем экран
mx = MouseX()-200 : my= MouseY()

For i=1 To k
 ;  sx = 400+tx(i)*dist/Float(tz(i)+dist)
 ;  sy = 300+ty(i)*dist/Float(tz(i)+dist)

sx = tx(i)*FOV/Float(tz(i)) +400
sy = ty(i)*FOV/Float(tz(i)) -200

x = mx*FOV/Float(200) +400
y = my*FOV/Float(200) -200

Text sx,sy,"."
Text x,y,"+"
;Text xx,yy,"2"
Next

Flip ; Меняем буфер
Wend
End

.dats
Data 0,0,0

Data 0,300,200
Data 20,300,200
Data -20,300,200

Data 20,300,220
Data -20,300,220
Data 0,300,220

Data 20,300,240
Data -20,300,240
Data 0,300,240

Data 20,300,260
Data -20,300,260
Data 0,300,260

Data 20,300,280
Data -20,300,280
Data 0,300,280


Жека 24.10.2012 06:41

Ответ: 2d сетка
 
Я бы использовал функцию, которая проверяет - находится ли точка внутри многоугольника. Каждую ячейку карты представить отдельными четырёхугольниками, задать координаты вершин по формуле, которая даёт ощущение перспективы.
Сама функция проверки у меня есть, если нужна скину.

Jlemyp 24.10.2012 08:30

Ответ: 2d сетка
 
Жека, скинь пожалуста.Мне тужно будет полезна эта функция.

polopok 24.10.2012 10:04

Ответ: 2d сетка
 
Цитата:

Сообщение от Жека (Сообщение 240986)
Я бы использовал функцию, которая проверяет - находится ли точка внутри многоугольника. Каждую ячейку карты представить отдельными четырёхугольниками, задать координаты вершин по формуле, которая даёт ощущение перспективы.
Сама функция проверки у меня есть, если нужна скину.

Да такая функция у меня есть (использую довольно часто ) ,все дело в том ,что сетка неравномерная ...
а так -то конечно .

polopok 24.10.2012 10:07

Ответ: 2d сетка
 
вот ссылка по теме :
http://board.flashkit.com/board/show...-3d-coordinate

увы ,разобраться в том коде никак не могу ,хоть и пытался переписать под blitz

polopok 24.10.2012 11:22

Ответ: 2d сетка
 
Так ! Вот получилось ... единственно X мыши неверно определяется :(
код:
Код:

Graphics 800,600
SetBuffer BackBuffer()


While Not KeyHit(1)
Cls
mx# = MouseX() : my# = MouseY()

For y = 1 To 13
        For x# = -6 To 6
                px# = ( (x*30)+(y*x))
                py# =  y*30
               
               
                If x<6
                Line 400 +px,py , 400 + ( (x+1)*30)+(y*(x+1)),py
                EndIf
                If y<13
                Line 400 +px,py , 400 + ( (x)*30)+((y+1)*(x)) ,(y+1)*30
                EndIf
        ;        Plot 400 + px, py
        ;        Text px ,py , Int(x)
        ;        Text px ,py+10 , y
        Next
Next


        xm# = Floor#( (mx/30)-((my/30)/(mx/30)))
        ym# = Floor#(my/30)

Text 20,20,Int(xm)
Text 20,40,Int(ym)
Flip
Wend
End


polopok 24.10.2012 19:10

Ответ: 2d сетка
 
Ну что ж ,можно праздновать победу . После долгих размышлений (проб и ошибок) ,все-таки нашел решение (правда в правом верхнем и левом нижнем углах ячейки заметно не правильные результаты ,всего несколько пикселов, думаю этим можно пренебречь ) .
Вот выкладываю готовый код:
Код:

Graphics 800,600 ,32,2
SetBuffer BackBuffer()
tile_sizeX = 50
tile_sizeY = 30

ClsColor 34 ,139 ,34 
While Not KeyHit(1)
Cls
mx# = MouseX() : my# = MouseY()

For y = 1 To 11 ;Step 1
        For x# = 1 To 11
                px# = ((x-6)*tile_sizeX )+(y*(x-6))
                py# =  y*tile_sizeY
               
                Color 3 ,35, 3
                If x<11
                Line 400 + px,py , 400 +  ( (x-5)*tile_sizeX )+(y*(x-5)),py
                Text 400 +px+20 ,py+5 , Int(x)
                EndIf
                If y<11
                Line 400 + px,py , 400 +  ( (x-6)*tile_sizeX )+((y+1)*(x-6)) ,(y+1)*tile_sizeY
                Text 400 +px+20 ,py+15 , Int(y)
                EndIf
               
        ;        Plot 400 + px,  py
               
               
        ;        Text 400 + px ,py , (y*x)
        ;        Text 400 +px ,py , px
        Next
Next

        ym# = Floor#(my/tile_sizeY )
        xm# = Floor#(    ( mx-400)/(tile_sizeX+ym+0.5)+6)


                Text mx,my-10,Int(xm) +" : "+Int(ym)
                Text mx,my,"\"

                Text 20,20,"MouseX : "+Int(mx)+" MouseY : "+Int(my)
                Text 20,40,"X : "+Int(xm)
                Text 20,60,"Y : "+Int(ym)
Flip
Wend
End



возможно кому-нибудь пригодится ...

moka 24.10.2012 19:14

Ответ: 2d сетка
 
Реализуй простую сетку без перспективы. А затем x координату для отрисовки линий и вычисления ячейки на которую наводишь умножай на коэффициент перспективы который зависит от Y.
Готово.

polopok 24.10.2012 23:33

Ответ: 2d сетка
 
Цитата:

Сообщение от MoKa (Сообщение 241023)
Реализуй простую сетку без перспективы. А затем x координату для отрисовки линий и вычисления ячейки на которую наводишь умножай на коэффициент перспективы который зависит от Y.
Готово.

Вот что значит правильная идея(подход) ,пара минут и готово решение . :)
Выкладываю то , что получилось
код:
Код:

Graphics 800,600
SetBuffer BackBuffer()
TileSizeX = 40
TileSizeY = 30
fov# = 50
While Not KeyHit(1)
Cls
mx# = MouseX() : my# = MouseY()

        For y = 1 To 11
                For x = -5 To 5
                        ScaleRatio# = fov/(fov+y)
                        px# = x*TileSizeX/ScaleRatio
                        py# = y*TileSizeY
                       
                        If x<5 Then Line 400+px , py ,400+ ((x+1)*TileSizeX/ScaleRatio) , py
                        If y<11 Then Line 400+px , py ,400+ ((x)*TileSizeX/(fov/(fov+(y+1)))) , (y+1)*TileSizeY
        ;                Plot 400+px , py
                Next
        Next       
       
        ym# = Floor#(my/TileSizeY)
        xm# = Floor#((  (mx-400)/ TileSizeX*( (fov/(fov+ym)))+6 ))
       
        If xm<11 And xm >0 And ym <11 And ym >0
                Text mx,my-10,Int(xm)+" : "+Int(ym)
        End If
                Text 20,40,"X : "+Int(xm)
                Text 20,60,"Y : "+Int(ym)       
Flip
Wend
End


Жека 26.10.2012 08:19

Ответ: 2d сетка
 
Цитата:

Сообщение от Jlemyp (Сообщение 240987)
Жека, скинь пожалуста.Мне тужно будет полезна эта функция.

У меня код под блитц макс был изначально, выложу его тоже.
В блитц 3д нельзя в функцию передать массив, поэтому я сделал в примере передачу объекта TArray, содержащего массив (статический, к сожалению).

Blitz3D:
Код:

;создадим квадратный полигон
;1----2
;|    |
;|    |
;4----3
Local poly.TArray = New TArray
poly\array[0] = 0 ;x1
poly\array[1] = 0 ;x2
poly\array[2] = 1
poly\array[3] = 0
poly\array[4] = 1
poly\array[5] = 1
poly\array[6] = 0 ;x4
poly\array[7] = 1 ;y4
poly\count = 8

DebugLog "test (-1,0): "+pointInPoly(poly, -1, 0)
DebugLog "test (0.5,0.5): "+pointInPoly(poly, 0.5, 0.5)
DebugLog "test (0.999,0.999): "+pointInPoly(poly, 0.999, 0.999)
Stop
End


;проверка находится ли точка внутри многоугольника
;многоугольник должен быть выпуклый (вогнутые можно заменить несколькими выпуклыми)
;алгоритм: делается обход отрезков многоугольника по часовой стрелке
;и проверяется - лежит ли точка "справа"(внутри) от каждого из отрезков
Function pointInPoly%(array.TArray, px#, py#)
       
        If(array = Null) Then Return False
       
        Local x1#, y1#, x2#, y2#
        Local koef#, koefA#
        Local k%, cnt% = array\count-1
        Local in = True
        Local sign, sign2
        DebugLog "px,py: "+px+","+py
       
        For k = 0 To cnt Step 2
                x1 = array\array[k]
                y1 = array\array[k+1]
                If(k + 3 < cnt)
                        x2 = array\array[k + 2]
                        y2 = array\array[k + 3]
                Else                ; "замыкаем" с первой точкой
                        x2 = array\array[0]
                        y2 = array\array[1]
                EndIf
               
                sign = Sgn(x2 - x1)
                sign2 = Sgn(px - x1)
               
                DebugLog "x1,y1: "+x1+","+y1
                DebugLog "x2,y2: "+x2+","+y2
               
                ;исключаем деление на ноль
                If(sign = 0)
                        x2 = x2+0.01
                        sign = 1
                EndIf
                If(sign2 = 0)
                        px = px+0.01
                        sign2 = 1
                EndIf
               
                ;коэффициенты наклона отрезков (y = k*x + b)
                koef = (y1 - y2) / (x2 - x1)
                koefA = (y1 - py) / (px - x1)
                DebugLog "koef: "+koef
                DebugLog "koefA: "+koefA
                ;сама проверка: коэффициен наклона проверяемого отрезка должен быть
                ;больше чем отрезка с точкой (px,py) при условии что координаты (x2,y2) и (px,py)
                ;лежат по одну сторону от точки (x1,x2)
                ;если по разные стороны, то наклон исходного должен быть меньше
                If((sign2 = sign And koefA > koef) Or (sign2 <> sign And koefA < koef))
                        in = False
                        Exit
                EndIf
               
        Next
       
        Return in
       
End Function


Type TArray
        Field array#[100]
        Field count%
End Type



BlitzMax:
Код:

Local xy#[] = [0.0,0.0, 1.0,0.0, 1.0,1.0, 0.0,1.0]

DebugLog "test (-1,0): "+pointInPoly(xy, -1, 0)
DebugLog "test (0.5,0.5): "+pointInPoly(xy, 0.5, 0.5)
DebugLog "test (0.999,0.999): "+pointInPoly(xy, 0.999, 0.999)

DebugStop
End


'проверка находится ли точка внутри многоугольника
'многоугольник должен быть выпуклый
'алгоритм: делается обход отрезков многоугольника по часовой стрелке
'и проверяется - лежит ли точка "справа"(внутри) от каждого из отрезков
Function pointInPoly%(xy:Float[], px:Float, py:Float)
       
        If(xy = Null) Then Return
       
        Local x1:Float, y1:Float, x2:Float, y2:Float
        Local koef:Float, koefA:Float
        Local k, cnt = xy.Dimensions()[0]
        Local in = True
        Local sign, sign2
       
        For k = 0 Until cnt Step 2
                x1 = xy[k]
                y1 = xy[k + 1]
                If(k + 3 < cnt)
                        x2 = xy[k + 2]
                        y2 = xy[k + 3]
                Else                ' "замыкаем" с первой точкой
                        x2 = xy[0]
                        y2 = xy[1]
                EndIf
               
                sign = Sgn(x2 - x1)
                sign2 = Sgn(px - x1)
               
                'исключаем деление на ноль
                If(sign = 0)
                        x2:+0.01
                        sign = 1
                EndIf
                If(sign2 = 0)
                        px:+0.01
                        sign2 = 1
                EndIf
               
                'коэффициенты наклона отрезков (y = k*x + b)
                koef = (y1 - y2) / (x2 - x1)
                koefA = (y1 - py) / (px - x1)
               
                'сама проверка: коэффициен наклона проверяемого отрезка должен быть
                'больше чем отрезка с точкой (px,py) при условии что координаты (x2,y2) и (px,py)
                'лежат по одну сторону от точки (x1,x2)
                'если по разные стороны, то наклон исходного должен быть меньше
                If((sign2 = sign And koefA > koef) Or (sign2 <> sign And koefA < koef))
                        in = False
                        Exit
                EndIf
       
        Next
       
        Return in
       
End Function


Можно в "полезные функции" скинуть, наверное.

polopok 16.05.2014 14:42

Ответ: 2d сетка
 
После долгого отсутствия ...
Вот код , переделана математическая часть ,что по моему мнению стало лучше ,как читабельно ,так и в понимании .Думаю код будет полезен .

Код:

;
Const ttx = 40 , tty = 30 , KolvoBlock= 13 , GrX = 330 , GrY = 50
Dim MapX(KolvoBlock,KolvoBlock) ,  MapY(KolvoBlock,KolvoBlock) ,MapCenterX(KolvoBlock,KolvoBlock) ,  MapCenterY(KolvoBlock,KolvoBlock) ,map(KolvoBlock,KolvoBlock)

Graphics 800,600,32,2
SetBuffer BackBuffer()

For y = 0 To KolvoBlock
        For x = 0 To KolvoBlock
                px# =( x-5)*(ttx+(y)) ;-5
                py# = y*tty
                pcx# =(( x-5)*(ttx+y)) +(ttx/2+(y/2))
                pcy# =y*(tty)+tty/2
               
                MapX(x,y) = px
                MapY(x,y) = py
               
                If y<KolvoBlock And x<KolvoBlock Then
                        MapCenterX(x,y) = pcx
                        MapCenterY(x,y) = pcy       
                EndIf       
        Next
Next
;Origin 200,100
ClsColor 150,150,150
While Not KeyHit(1)
Cls
mx# = MouseX() : my# = MouseY()
        ty = Int(Floor( (my-GrY )/tty ))
        tx = Int(Floor( ((mx-GrX ) / (ttx+(ty)))) +5 );
Draw()

;Line mx-100,0,mx-100,500
If tx>=0 And tx < KolvoBlock And ty>=0 And ty<KolvoBlock Then
Text  GrX *0.5-100,GrY +KolvoBlock*tty+10 ,tx+" : "+ty
EndIf
Flip
Wend
End

Function DrawBackgraund()

End Function

Function Draw()
        Rect 5,5,790, GrY +KolvoBlock*tty+25,0
For y = 0 To KolvoBlock
        For x = 0 To KolvoBlock
                Plot GrX +MapCenterX(x,y),GrY +MapCenterY(x,y)
                Line GrX +MapX(x,0) , GrY , GrX +MapX(x,KolvoBlock) ,GrY +KolvoBlock*tty
                Line GrX +MapX(0,y) ,GrY +MapY(0,y) ,GrX +MapX(KolvoBlock,y) ,GrY +MapY(KolvoBlock,y)
        Next
Next
End Function


polopok 25.05.2014 17:32

Ответ: 2d сетка
 
Теперь значение перспективы можно задавать(менять) колесом мыши ,а так же некое подобие скролинга зажав ЛКМ.

Код:

time = CreateTimer(60)
Global  fov# = -10 ,GrX# = 330 , GrY# = 50,tx,ty
Const ttx = 40 , tty = 30 , KolvoBlock= 13
Dim MapX(KolvoBlock,KolvoBlock) ,  MapY(KolvoBlock,KolvoBlock) ,MapCenterX(KolvoBlock,KolvoBlock) ,  MapCenterY(KolvoBlock,KolvoBlock) ,map(KolvoBlock,KolvoBlock)

Graphics 800,600,32,2
SetBuffer BackBuffer()


;Origin 200,100
ClsColor 150,150,150
While Not KeyHit(1)
Cls
mx# = MouseX() : my# = MouseY()

fov = fov- MouseZSpeed() * 0.1
If MouseDown(1) Then
GrX = 800-mx
GrY = 250-my
FlushMouse()
EndIf
       
WaitTimer(time)       
        ty = Int(Floor( (my-GrY )/(tty+fov) ))
        tx = Int(Floor( ((mx-GrX ) / (ttx+(ty+fov)))) +5 );

For y = 0 To KolvoBlock
        For x = 0 To KolvoBlock
                px# =( x-5)*(ttx+(y+fov)) ;-5
                py# = y*(tty+fov)
                pcx# =(( x-5)*(ttx+(y+fov))) +(ttx/2+(y/2+fov/2))
                pcy# =y*(tty+fov)+(tty+fov)/2
               
                MapX(x,y) = px
                MapY(x,y) = py
               
                If y<KolvoBlock And x<KolvoBlock Then
                        MapCenterX(x,y) = pcx
                        MapCenterY(x,y) = pcy       
                EndIf       
        Next
Next
Draw()

;Line mx-100,0,mx-100,500
If tx>=0 And tx < KolvoBlock And ty>=0 And ty<KolvoBlock Then
Text  GrX *0.5-100,GrY +KolvoBlock*tty+10 ,tx+" : "+ty
EndIf       
Flip
Wend
FreeTimer timer
End

Function DrawBackgraund()

End Function

Function Draw()
        Rect 5,5,790, GrY +KolvoBlock*tty+25,0
For y = 0 To KolvoBlock
        For x = 0 To KolvoBlock
                Plot GrX +MapCenterX(x,y),GrY +MapCenterY(x,y)
                Line GrX +MapX(x,0) , GrY , GrX +MapX(x,KolvoBlock) ,GrY +KolvoBlock*(tty+fov)
                Line GrX +MapX(0,y) ,GrY +MapY(0,y) ,GrX +MapX(KolvoBlock,y) ,GrY +MapY(KolvoBlock,y)
        Next
Next
End Function


moka 25.05.2014 20:35

Ответ: 2d сетка
 
Вот бы такие прототипы в на JS писали, тогда код для блица (который не стоит тут у доброй половины форумчан) имел бы хоть какую-то пользу, т.к. можно было бы запустить в веб броузере демку сразу же, а не пропустить пост, т.к. это "блиц", а он уже мёртв.

polopok 25.05.2014 21:19

Ответ: 2d сетка
 
Думаю не стоит так переживать , тут главное формулы правильные вывести ,а там можно под любой язык или среду переписать.
Признаться пишу от безделия , а так хоть мозг не атрафируется и чтоб труды не пропали даром выкладываю сюда.


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

vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot