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

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

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

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

Ответ
 
Опции темы
Старый 17.07.2018, 22:09   #1
FlameSword
AnyKey`щик
 
Аватар для FlameSword
 
Регистрация: 06.03.2015
Сообщений: 10
Написано 2 полезных сообщений
(для 5 пользователей)
Стрелка 3D объект в 2D рамке - Делюсь кодом!

Итак, недавно меня мучил вопрос: "Как сделать простой HUD для простой игры?" - в голове пролетела идея сделать простые уголки вокруг объектов, с которыми можно будет взаимодействовать в игровой вселенной.

Потом я столкнулся с вопросом: "Как узнать координаты левого-верхнего и правого-нижнего угла 3D объекта на 2D скрине?" - все казалось просто - CameraProject. Но эта функция могла указывать лишь на средину меша, в то время, как мне нужны были углы, с учетом формы, размера меша и положения камеры относительно его.

Долго думая у меня зародилась альтернативная идея: запихнуть в объект квад, который постоянно смотрит вперед (в камеру) и сохраняет размеры меша объекта. Тут я решил использовать PointEntity(квад,камера) - но я не учел тот факт, что эта функция влияет на энтити, а не на меш. Поэтому когда я пытался получить координаты вершин квада (которые и должны были стать вершинами рамки), столкнулся с тем, что они не меняются.

Я решил написать собственную функцию-аналог РоintEntity, только чтобы она влияла на меш. Написать - не написал, зато благодаря архиву кода от LLI.T.A.L.K.E.R нашел какую-то набор функций для односюрфейсных частиц, в основе которых простые квады. Там использовался до сих пор не понятный для меня способ применения векторов TFormVector. Мне сложно было понять суть управления этой функцией, так как она часто выдавала непредсказуемый для меня результат. Но в конце концов сверив расположение точек квада и подогнав под них функцию я добился нужного результата.

Хоть порой эта рамка (скобочки) иногда ведет себя не так, как задумывалось, я рад результатом

Сначала сделал с FastImage, но потом переделал под чистый Блиц, чтобы можно было сразу скопировать в новый проект и проверить самому.

Вот код:

;Рамка вокруг объекта на 'чистом' (для удобства) Блитце!
AppTitle "B3D GUI/HUD test"

Graphics3D 800,600,32,2

Global FL_Pitch#,FL_Yaw#,FL_Roll#
Global FL_XSpeed#,FL_YSpeed#,FL_ZSpeed#
Global speed#=0.05
Global gw#=GraphicsWidth()
Global gh#=GraphicsHeight()
Global frame=CreateQuad(); Пока один глобальный квад.

HideEntity frame

;===Рисуем ГУЙ/ХУД/ХЗ===
outline=CreateImage(24,24)
SetBuffer ImageBuffer(outline)
	Color 0,0,0
	Rect 0,0,22,22,1
	Color 255,0,255
	Line 1,1,9,1
	Line 1,1,1,9
	Line 1,22,9,22
	Line 1,22,1,14
	Line 22,1,14,1
	Line 22,1,22,9
	Line 22,22,22,14
	Line 22,22,14,22
	
cross=CreateImage(16,16)
SetBuffer ImageBuffer(cross)
	Color 0,0,0
	Rect 0,0,23,23,1
	Color 255,0,0
	Line 8,0,8,16
	Line 0,8,16,8
;============
SetBuffer BackBuffer()
MaskImage outline,0,0,0
MaskImage cross,0,0,0

cam=CreateCamera()
CameraClsColor cam, 40, 40, 40
PositionEntity cam,0,0,-3

lit=CreateLight()
RotateEntity lit,60,45,0

cube=CreateCube()
EntityPickMode cube,2 

fnt=LoadFont("courier new",20)
SetFont fnt

HidePointer

sx#=1
sy#=1

While Not KeyHit(1)

	; Простое управление размерами меша, дабы проверить, будет ли это отслеживаться квадом и ХУДом.
	If KeyHit(203) Then sx=2 Else sx=1
	If KeyHit (205) Then sx=0.5
	If KeyHit(200) Then sy=2 Else sy=1
	If KeyHit (208) Then sy=0.5
	ScaleMesh cube,sx,sy,1
	
	CameraPick(cam,MouseX(),MouseY())

	If MouseHit(2) Then MoveMouse gw,gh
	If MouseDown(2)
		FreeLook (cam)	
	EndIf
	
	RenderWorld
			If MouseDown (2)
				DrawImage (cross,(gw/2)+8,(gh/2)+8)
			Else
				DrawImage (cross,MouseX()+8,MouseY()+8)
			EndIf
			UpdateFrame(cam,cube,outline)
			Color 0,255,0
			Text 5,10,"Entity Scale: "+MeshWidth(cube)
			Text 5,30,"Use [ARROWS] to scale cube"
			Text 5,50,"Hold [2nd MOUSE BUTTON]+[WASD] to rotate camera and fly"
			Text 5,gh-20,"Mesh in HUD frame test on 'clean' Blitz3D"
	UpdateWorld
	FlushMouse
	Flip
Wend
ClearWorld
End

;Эту ф-цию переписал и подогнал из примера 'SingleSurface particles' 
;Она заставляет квад вести себя как спрайт.
Function SpriteMesh(ent,cam)
Local surf=GetSurface(ent,1)
Local x#=EntityX(ent)
Local y#=EntityY(ent)
Local z#=EntityZ(ent)
TFormPoint x,y,z,0,cam

If TFormedZ#()>0
	; Вот, чесно говоря, до сих пор не умею пользоваться векторами. Благо, еще остались примеры.
	;topleft
	TFormVector -1,-1,0,cam,0 
	VertexCoords surf,0,x+TFormedX#(),y+TFormedY#(),z+TFormedZ#()
	;topright
	TFormVector -1,1,0,cam,0 
	VertexCoords surf,1,x+TFormedX#(),y+TFormedY#(),z+TFormedZ#()
	;bottomright
	TFormVector 1,-1,0,cam,0 
	VertexCoords surf,2,x+TFormedX#(),y+TFormedY#(),z+TFormedZ#()
	;bottomleft
	TFormVector 1,1,0,cam,0 
	VertexCoords surf,3,x+TFormedX#(),y+TFormedY#(),z+TFormedZ#()
EndIf

End Function

; Эта ф-ция регулирует размеры рамки и отрисовывает наши границы рамки
Function UpdateFrame(cam,ent,img)
	Local surf=GetSurface(frame,CountSurfaces(frame))
	Local vx1#,vy1#
	Local vx2#,vy2#
	; Тут благодаря CameraProject вытащил координаты вершин квада
	CameraProject cam,VertexX(surf,0),VertexY(surf,0),VertexZ(surf,0)
	vx1=ProjectedX():vy1=ProjectedY()
	CameraProject cam,VertexX(surf,3),VertexY(surf,3),VertexZ(surf,3)
	vx2=ProjectedX():vy2=ProjectedY()
	
	DrawImageRect (img,vx1-12,vy2-12,0,0,12,12)
	DrawImageRect (img,vx2,vy1,12,12,12,12)
	DrawImageRect (img,vx1-12,vy1,0,12,12,12)
	DrawImageRect (img,vx2,vy2-12,12,0,12,12)
	
	PositionEntity frame,EntityX(ent),EntityY(ent),EntityZ(ent)
	SpriteMesh (frame,cam); Изначально использовал PointEntity, но это была большая ошибка
	If MeshWidth(ent)<>MeshWidth(frame) Then ScaleMesh frame,MeshWidth(ent)/2,MeshHeight(ent)/2,MeshDepth(ent)/2
End Function

; Собсна квад.
Function CreateQuad(x#=0,y#=0,z#=0,scale#=1)
	mesh=CreateMesh()
	Local surf=CreateSurface(mesh)
	AddVertex (surf, -1,0,1,0,0,0)
	AddVertex (surf,1,0,1,1,0,1)
	AddVertex (surf,-1,0,-1,0,1,1)
	AddVertex (surf,1,0,-1,1,1,1)
	AddTriangle (surf,0,1,2)
	AddTriangle (surf,3,2,1)
	UpdateNormals(mesh) 
	PositionEntity mesh,x#,y#,z#
	ScaleEntity mesh, scale#,scale#,scale#
	Return mesh
End Function

; Весьма распрастраненная ф-ция свободного перемещения камеры (WASD+МЫШЬ)
Function FreeLook(FL_Cam)
	FL_Pitch#=FL_Pitch#+(MouseYSpeed()*0.02)
	FL_Pitch#=FL_Pitch#/1.2
	FL_Yaw#=FL_Yaw#+-(MouseXSpeed()*0.02)
	FL_Yaw#=FL_Yaw#/1.2
	MoveMouse (GraphicsWidth()/2,GraphicsHeight()/2)
	FL_ZSpeed#=FL_ZSpeed#+Float(KeyDown(17)-KeyDown(31))*speed# ; W & S
	FL_ZSpeed#=FL_ZSpeed#/1.14
	FL_XSpeed#=FL_XSpeed#+Float(KeyDown(32)-KeyDown(30))*speed# ; A & D
	FL_XSpeed#=FL_XSpeed#/1.14
	FL_YSpeed#=FL_YSpeed#+Float(KeyDown(19)-KeyDown(33))*speed# ; R & F
	FL_YSpeed#=FL_YSpeed#/1.14
	FL_Roll#=(FL_Yaw#*speed#)-(FL_XSpeed#*1.7)
	MoveEntity FL_Cam,FL_XSpeed#,FL_YSpeed#+Abs(FL_Roll#*FL_XSpeed#)/50,FL_ZSpeed#
	Local cp#=EntityPitch(FL_Cam,True)+FL_Pitch#
	If cp<-89 Then cp=-89
	If cp>89 Then cp=89
	RotateEntity FL_Cam,cp,EntityYaw(FL_Cam)+FL_Yaw#,FL_Roll#
End Function


Функции еще можно сто раз переделать под любые нужды и под любые библиотеки для большей производительности и графония.

Это еще не все! Продолжу использовать вместе с FastImage или Xors3D. Хочу добавить плавное появление с увеличением и плавным изменением цвета (чтобы покрасивее было), при наведении курсора на нужный объект, плюс режимы взаимодействия с объектом (игровая механика, основана на физике).
__________________
В этом мире нет ничего невозможного.
(Offline)
 
Ответить с цитированием
Эти 4 пользователя(ей) сказали Спасибо FlameSword за это полезное сообщение:
ABTOMAT (18.07.2018), Arton (18.07.2018), St_AnGer (18.07.2018), Tiranas (13.08.2018)
Старый 13.08.2018, 04:11   #2
Tiranas
AnyKey`щик
 
Регистрация: 11.10.2017
Сообщений: 7
Написано 0 полезных сообщений
(для 0 пользователей)
Ответ: 3D объект в 2D рамке - Делюсь кодом!

Не споря, статья хорошая, автору +++.
Но что мешает использовать спрайты с текстурой уголков и виртуальные точки? Я так делал.
__________________
Человек это или баг, или заложенное специально программное яйцо.
(Offline)
 
Ответить с цитированием
Старый 13.08.2018, 18:48   #3
Arton
Быдлокодер
 
Аватар для Arton
 
Регистрация: 05.07.2009
Адрес: Проспит
Сообщений: 4,521
Написано 1,979 полезных сообщений
(для 4,734 пользователей)
Ответ: 3D объект в 2D рамке - Делюсь кодом!

Сообщение от Tiranas Посмотреть сообщение
Не споря, статья хорошая, автору +++.
Но что мешает использовать спрайты с текстурой уголков и виртуальные точки? Я так делал.
Если именно спрайты, то в Blitz3D лучше не надо, а так надо свой огород городить.
(Offline)
 
Ответить с цитированием
Ответ


Опции темы

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

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


Часовой пояс GMT +1, время: 07:34.


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