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

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

Вернуться   forum.boolean.name > Программирование игр для компьютеров > Blitz3D > 2D-программирование

2D-программирование Вопросы, касающиеся двумерного программирования

Ответ
 
Опции темы
Старый 18.02.2012, 13:10   #16
shybovycha
ПроЭктировщик
 
Аватар для shybovycha
 
Регистрация: 27.05.2007
Сообщений: 110
Написано 40 полезных сообщений
(для 33 пользователей)
Ответ: Нужна помощь с готоми

Сообщение от AVL Посмотреть сообщение
if (бот_идет) and (впереди_по_ходу_движения_бота_здание) then бот_поворачивает_пока_впереди_не_будет_свободно
Уж лучше задачкой "лабиринт" - боты не будут зря проникать в заведомо тупики

Уважаемый ТС, рассказываю максимально детально:

1) есть у вас карта. Разбейте ее на клетки размером с игроков (зомби/гг/союзники) - сделайте матрицу размерами M*N, где M = map_width / player_size, N = map_height / player_size, player_size = (player_width > player_height) ? player_width : player_height.

2) Заполните эту матрицу следующим образом: если в клетке A[i][j] препятствие - A[i][j] = -1; иначе - A[i][j] = 0.

3) Возьмите клетку в тупике (так нужно) и сделайте ее некоей start_cell{x, y}.

4) Примените волновой алгоритм: задайте некую очередь q = {start_cell}. И переменную index = 1. В цикле "пока очередь не пуста" выполняем следующее:
а) current_cell = q.shift();
б) A[current_cell.x][current_cell.y] = index;
в) index = index + 1;
г) "если клетка A[i + 1][j] проходима - добавляем ее в очередь"
д) "если клетка A[i - 1][j] проходима - добавляем ее в очередь"
е) "если клетка A[i][j + 1] проходима - добавляем ее в очередь"
ж) "если клетка A[i][j - 1] проходима - добавляем ее в очередь"

*условие "если клетка проходима" равносильно "если в клетке число 0"

Таким образом получаем "лабиринт", заполненный либо числом -1, либо натуральным числом. Так, чтобы из клетки A'(x1, y1) добраться в клетку B'(x2, y2) необходимо:

а) выбрать "обратное направление хода" - от клетки с большим числом в матрице до клетки с меньшим числом в матрице. То есть, если A[x1][y1] > A[x2][y2], то искать путь будем от B' к A'.

б) начиная с клетки с большим числом в матрице, начинаем искать путь (алгоритм идентичен волновому):
  1. очередь q = { start_cell }; очередь path = { };
  2. while (!q.empty())
  3. c = q.shift()
  4. path.push(c)
  5. if (A[c.x + 1][c.y] < A[c.x][c.y]) q.push({c.x + 1, c.y})
  6. if (A[c.x - 1][c.y] < A[c.x][c.y]) q.push({c.x - 1, c.y})
  7. if (A[c.x][c.y + 1] < A[c.x][c.y]) q.push({c.x, c.y + 1})
  8. if (A[c.x][c.y - 1] < A[c.x][c.y]) q.push({c.x, c.y - 1})
В результате получим реверсивный путь - от точки назначения к точке исходной позиции. Заметьте, если исходной позиции соответствует большее число в матрице, то путь не реверсивен. Иначе - "разворачиваем" массив/очередь path.

А потом все просто - в path у вас будет набор пар (x, y) - по ним можно определить, куда (в центр какой клетки) направить тот или иной спрайт =)
(Offline)
 
Ответить с цитированием
Старый 18.02.2012, 13:11   #17
shybovycha
ПроЭктировщик
 
Аватар для shybovycha
 
Регистрация: 27.05.2007
Сообщений: 110
Написано 40 полезных сообщений
(для 33 пользователей)
Ответ: Нужна помощь с готоми

Сообщение от Nikich Посмотреть сообщение

От гта 1 прямо вид сверху. So close...

Вот взяли и испугали парня. Его интересовало векторное перемещение, а вы ему алгоритмами А* и Дейкстры голову забили. Люди добрые, нельзя же так.
Товарища интересовали коллизии/обход препятствий
(Offline)
 
Ответить с цитированием
Старый 18.02.2012, 13:33   #18
Nikich
Бывалый
 
Регистрация: 22.12.2011
Сообщений: 844
Написано 150 полезных сообщений
(для 275 пользователей)
Ответ: Нужна помощь с готоми

Коллизия как раз решается векторным перемещением, обход препятствий его не интересовал. Можете ещё раз перечитать его посты.
(Offline)
 
Ответить с цитированием
Старый 18.02.2012, 15:18   #19
DarkInside
Разработчик
 
Аватар для DarkInside
 
Регистрация: 08.08.2011
Сообщений: 505
Написано 191 полезных сообщений
(для 369 пользователей)
Лампочка Ответ: Нужна помощь с готоми

Вот тебе пример, тут и коллизии, и пики, чтобы определить, есть ли препятствие впереди и обойти его. CodeArchive тебе в помощь.
;use these globals to get the collision point between a circle and a line. 
Global LineCollisionX#
Global LineCollisionY#

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

;Create lines at screen edges
LineNew(0,0,800,0)
LineNew(800,0,800,600)
LineNew(0,600,800,600)
LineNew(0,0,0,600)

;Create two Circles
CircleNew(100,100,20,0.4,0.2)
CircleNew(200,100,50,-0.2,0.3)

event=0
cline.cline=Null
Repeat
	Cls
		
	If MouseHit(2)
		
		CircleNew(Rnd(200,600),Rnd(100,500),Rnd(10,40),Rnd(-2,2),Rnd(-2,2))
	
	EndIf
	
	Select event
	
		Case 0
			If MouseHit(1)
				x1#=MouseX()
				y1#=MouseY()
				event=1
				cline=LineNew(x1#,y1#,x1+10,y1)
			EndIf
		Case 1
					
			LineRecalc(cline,x1,y1,MouseX(),MouseY())
			If MouseHit(1)
				event=0
			EndIf
		
	
	End Select
	
	;Update and draw stuff
	CircleUpdate()
	PoofUpdate()

	CircleDraw()
	LineDraw()
	PoofDraw()
			
	Text 400,10,"2D Collision Example by Jeppe Nielsen 2004",1,0
	Text 400,30,"Left mouse button to create lines",1,0
	Text 400,50,"Right mouse button to create more circles",1,0
	
	Flip
	
Until KeyDown(1)
End

Type cline

	Field x1#,y1#,x2#,y2#,nx#,ny#,ux#,uy#

End Type

Function LineNew.cline(x1#,y1#,x2#,y2#)

	l.cline=New cline
	
	LineRecalc(l,x1#,y1#,x2#,y2#)
	
	Return l

End Function

Function LineRecalc(l.cline,x1#,y1#,x2#,y2#)

	l\x1=x1
	l\y1=y1
	l\x2=x2
	l\y2=y2

	dx#=l\x2-l\x1
	dy#=l\y2-l\y1
	
	d#=Sqr(dx*dx+dy*dy)
	If d#<0.0001
		d#=0.0001
	EndIf
	
	l\ux=dx/d
	l\uy=dy/d
	
	l\nx#=l\uy
	l\ny#=-l\ux

End Function

Function LineDraw()

For l.cline=Each cline
	
	Color 255,255,255
	Line l\x1,l\y1,l\x2,l\y2
	
	Color 255,255,0
	;Draw normal
	xm#=(l\x1+l\x2)/2.0
	ym#=(l\y1+l\y2)/2.0
	Line xm,ym,xm+l\nx*10,ym+l\ny*10
	
Next

End Function

;Global LineCollisionX#
;Global LineCollisionY#

;Returns the shortest distance from a point to a line
;Use LineCollisionX and LineCollisionY to get the collision point.
Function LineDistance#(l.cline,x#,y#)

	dx#=l\x2-l\x1
	dy#=l\y2-l\y1
	
	d#=Sqr(dx*dx+dy*dy)
	
	px#=l\x1-x#
	py#=l\y1-y#
	
	dist#=(dx*py-px*dy) / d
	
	LineCollisionX=x#-l\nx*dist#
	LineCollisionY=y#-l\ny*dist#
		
	Return Abs(dist#)
	
End Function

;Returns true if a point collides with a line within range r
Function LineCollide(l.cline,x#,y#,r#)
	
	dx1#=x-(l\x1-l\ux*r)
	dy1#=y-(l\y1-l\uy*r)
	
	d#=Sqr(dx1*dx1+dy1*dy1)
	
	dx1=dx1/d
	dy1=dy1/d
	
	dx2#=x-(l\x2+l\ux*r)
	dy2#=y-(l\y2+l\uy*r)
	
	d#=Sqr(dx2*dx2+dy2*dy2)
	
	dx2=dx2/d
	dy2=dy2/d
	
	dot1#=dx1*l\ux+dy1*l\uy
	dot2#=dx2*l\ux+dy2*l\uy
	
	Return ((dot1#>=0 And dot2#<=0) Or (dot1#<=0 And dot2#>=0)) And (LineDistance(l,x,y)<=r)
	
End Function

Type circle

	Field x#,y#,vx#,vy#
	
	Field vel#

	Field r#

End Type

Function CircleNew.circle(x#,y#,r#=50,vx#=0,vy#=0)
	
	c.circle=New circle
	c\x=x
	c\y=y
	c\r=r
	c\vx=vx
	c\vy=vy
	
	CirclePlace(c)
	
	Return c
End Function

Function CirclePlace(c.circle,w#=800,h#=600)
	
	num=0
	While CirclePlaceTest(c,c\x,c\y)=False And num<1000
	
		c\x=Rnd(w)
		c\y=Rnd(h)
	
		num=num+1
	
	Wend
	
End Function

;Returns true if a circle can be placed, it doesn?t collide with any other circles or lines
Function CirclePlaceTest(c.circle,x#,y#)

	For cc.circle=Each circle
		If cc<>c
			dx#=cc\x-c\x
			dy#=cc\y-c\y
			d#=Sqr(dx*dx+dy*dy)
			If d<(c\r+cc\r)
		
				Return False
				
			EndIf
		EndIf
	Next

	For l.cline=Each cline

		If LineCollide(l,c\x,c\y,c\r)
				
			Return False
					
		EndIf

	Next

Return True

End Function

;draw circles
Function CircleDraw()

Color 0,0,255
For c.circle=Each circle
	
	rh#=c\r*2

	Oval c\x-c\r,c\y-c\r,rh,rh

Next


End Function

Function CircleUpdate()

For c.circle=Each circle

	;Calculate total velocity
	c\vel#=Sqr(c\vx*c\vx+c\vy*c\vy)
	
	;collision against other circles
	For cc.circle=Each circle
		;do not test against itself
		If cc<>c
			;vector from one circle to another
			dx#=cc\x-c\x
			dy#=cc\y-c\y
			d#=Sqr(dx*dx+dy*dy)
			;check of distance is smaller than the two circle?s radii together
			If d<(c\r+cc\r)
		
				;make the vector a unit vector (length=1), multiply it with the circle?s
				;total velocity, to get the new motion vector
				c\vx=(-dx#/d) * c\vel
				c\vy=(-dy#/d) * c\vel
			
			EndIf
		EndIf
	Next
	
	;collision agains lines
	For l.cline=Each cline

		;Check if circle collides with a line
		If LineCollide(l,c\x,c\y,c\r)
		
			;create a mark, where the circle has colliede with the line
			PoofNew(LineCollisionX,LineCollisionY)
				
			;Get the dot product between the circles motion vector and the line?s normal vector
			dot#=c\vx*l\nx+c\vy*l\ny	
			
			;Calculate the circle?s new motion vector
			c\vx=c\vx-2.0*l\nx*dot
			c\vy=c\vy-2.0*l\ny*dot
					
		EndIf

	Next
	
	;add velocity to position
	c\x=c\x+c\vx
	c\y=c\y+c\vy
	
	;Wrap to screen boundaries
	If c\x>GraphicsWidth()
		c\x=0
	EndIf
	
	If c\y>GraphicsHeight()
		c\y=0
	EndIf

	If c\x<0
		c\x=GraphicsWidth()
	EndIf	
	
	If c\y<0
		c\y=GraphicsHeight()
	EndIf
Next

End Function

Type poof

	Field x,y
	
	Field age#
	
	Field maxage
	
End Type

Function PoofNew.poof(x,y,age#=20)
	
	p.poof=New poof
	
	p\x=x
	p\y=y
	p\maxage=age
	
	Return p
End Function

Function PoofUpdate()

For p.poof=Each poof
	p\age=p\age+1

	If p\age>=p\maxage
	
		Delete p
		
	EndIf

Next

End Function

Function PoofDraw()

For p.poof=Each poof
			
	pah=p\age*0.5
		
	Oval p\x-pah,p\y-pah,p\age,p\age,0
		
Next

End Function

Graphics 800,600,0,2

linex1#= 7
liney1# = 20
linex2#= 371
liney2# = 350

circlex#= 300
circley# = 200
circler# = 70

Line linex1, liney1, linex2, liney2
Oval circlex-circler, circley-circler, circler*2, circler*2

If LineToCircle( linex1, liney1, linex2, liney2, circlex, circley, circler) Then
	Text 10,100, "Collided."
Else
	Text 10,100, "Not collided."
End If 



WaitKey



Function LineToCircle( lx1#, ly1#, lx2#, ly2#, cx#, cy#, r#)

dx# = lx2 - lx1
dy# = ly2 - ly1
ld# = Sqr((dx*dx) + (dy*dy))
lux# = dx / ld
luy# = dy / ld
lnx# = luy
lny# = -lux
dx1# = cx - (lx1 - lux*r)
dy1# = cy - (ly1 - luy*r)
d# = Sqr((dx1*dx1) + (dy1*dy1))
dx1 = dx1 / d
dy1 = dy1/ d
dx2# = cx - (lx2 + lux * r)
dy2# = cy - (ly2 + luy*r)
d = Sqr((dx2*dx2) + (dy2*dy2))
dx2 = dx2  / d
dy2 = dy2 / d
dot1# = (dx1 * lux) + (dy1 * luy)
dot2# = (dx2 * lux) + (dy2 * luy)
px#=lx1-cx
py#=ly1-cy
distsq# = Abs((dx * py - px * dy)  / ld )

;You can get point of collision using these two variables (make them global)
;LineColX# = cx - lnx * sqr(distsq) 
;LineColY# = cy - lny * sqr(distsq)


Return (( dot1>=0 And dot2<=0) Or (dot1<=0 And dot2>=0)) And (distsq <= r)


End Function
(Offline)
 
Ответить с цитированием
Ответ


Опции темы

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

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


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


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