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

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

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

Ответ
 
Опции темы
Старый 23.03.2020, 21:59   #1
Sikkyboy
AnyKey`щик
 
Регистрация: 22.03.2020
Сообщений: 18
Написано 6 полезных сообщений
(для 11 пользователей)
Эксперименты с box2d

Привет. Я установил себе этот модуль и посмотрел примеры. Обидно, что первый пример с ошибкой, да ещё просто никакой.
В общем, вместо первого примера я придумал замену.

Framework BaH.Box2D

Import BRL.StandardIO
Import BRL.LinkedList
Import BRL.GLMax2D

Const WORLD_WIDTH:Float=700
Const WORLD_HEIGHT:Float=500

Local worldAABB:b2AABB = New b2AABB.Create()
worldAABB.SetLowerBound(New b2Vec2.Create(0.0, 0.0))
worldAABB.SetUpperBound(New b2Vec2.Create(WORLD_WIDTH, WORLD_HEIGHT))

Local gravity:b2Vec2 = New b2Vec2.Create(0.0, -10.0)

Local doSleep:Int = True


Local world:b2World = New b2World.Create(worldAABB, gravity, doSleep)

Local groundBodyDef:b2BodyDef = New b2BodyDef
groundBodyDef.SetPosition(New b2Vec2.Create(350.0, 10.0))

Local groundBody:b2Body = world.CreateBody(groundBodyDef)

Local groundShapeDef:b2PolygonDef = New b2PolygonDef
groundShapeDef.SetAsBox(350.0, 10.0)

groundBody.CreateShape(groundShapeDef)

Local bodyDef:b2BodyDef = New b2BodyDef
bodyDef.SetPosition(New b2Vec2.Create(350.0, 400.0))
Local body:b2Body = world.CreateBody(bodyDef)

Local shapeDef:b2PolygonDef = New b2PolygonDef
shapeDef.SetAsBox(10.0, 10.0)
shapeDef.SetDensity(1.0)
shapeDef.SetFriction(0.3)
body.CreateShape(shapeDef)
body.SetMassFromShapes()

Local timeStep:Float = 1.0 / 60.0
Local iterations:Int = 10
Local shape:b2PolygonShape
Local vertices:b2Vec2[]
Local poly:Float[]

Graphics WORLD_WIDTH,WORLD_HEIGHT

While Not KeyHit( KEY_ESCAPE )

	world.DoStep(timeStep, iterations,0)
	Cls()


	shape=b2PolygonShape(body.getShapeList())
	vertices=shape.getVertices()
	poly=New Float[vertices.length*2]
	For Local i:Int = 0 Until vertices.length
			poly[i * 2] = body.getworldpoint(vertices[i]).GetX()
			poly[i * 2 + 1] = WORLD_HEIGHT-body.getWorldpoint(vertices[i]).GetY()
	Next
    
	SetColor(0,0,189)
	DrawPoly(Poly)
	
	shape=b2PolygonShape(groundbody.getShapeList())
	vertices=shape.getVertices()
	poly=New Float[vertices.length*2]
	For Local i:Int = 0 Until vertices.length
			poly[i * 2] = groundbody.getworldpoint(vertices[i]).GetX()
			poly[i * 2 + 1] = WORLD_HEIGHT-groundbody.getWorldpoint(vertices[i]).GetY()
	Next
	
	SetColor(0,239,0)
	DrawPoly(poly)
		
	Flip()

Wend
(Offline)
 
Ответить с цитированием
Старый 24.03.2020, 15:54   #2
mingw
ПроЭктировщик
 
Аватар для mingw
 
Регистрация: 01.01.2016
Сообщений: 138
Написано 71 полезных сообщений
(для 155 пользователей)
Ответ: Эксперименты с box2d

Тут дело в том, что сам модуль box2d писался еще в нулевые года, когда блицмакс был основан на FASM и его версия была древнейшая. С тех пор оригинальный блицмакс давно умер, уступив место новому blitzmax ng. Там произошли кардинальные изменения. Автор модуля просто физически не успевает вносить изменения во все свои модули - у него этих модулей порядка 50. Плюс он же является одним из разработчиков самого BlitzMaxNG.
(Offline)
 
Ответить с цитированием
Эти 2 пользователя(ей) сказали Спасибо mingw за это полезное сообщение:
ABTOMAT (24.03.2020), St_AnGer (24.03.2020)
Старый 24.03.2020, 21:51   #3
Sikkyboy
AnyKey`щик
 
Регистрация: 22.03.2020
Сообщений: 18
Написано 6 полезных сообщений
(для 11 пользователей)
Ответ: Эксперименты с box2d

Разобрался с рендером по умолчанию. Он описан в файле "render.bmx". Исполюзуется для отладочного изображения. При разработке программ очень необходим. Я написал два примера с рендером по умолчанию. Что-бы они запустились их нужно создать в папке BlitzMax\mod\bah.mod\box2d.mod\examples( render.bmx там лежит, или указать полный путь к нему при импорте).
Первый пример повторяет пример из первого сообщения, однако не нужно самому перебирать вершины форм - это сделает рендер и нарисует.

Framework BaH.Box2D

Import BRL.StandardIO
Import BRL.LinkedList


Import BRL.FreeTypeFont
Import "render.bmx"

Const WORLD_WIDTH:Float=700
Const WORLD_HEIGHT:Float=500

Local worldAABB:b2AABB = New b2AABB.Create()
worldAABB.SetLowerBound(New b2Vec2.Create(0.0, 0.0))
worldAABB.SetUpperBound(New b2Vec2.Create(WORLD_WIDTH, WORLD_HEIGHT))

Local gravity:b2Vec2 = New b2Vec2.Create(0.0, -10.0)

Local doSleep:Int = True

Local world:b2World = New b2World.Create(worldAABB, gravity, doSleep)
Local m_debugDraw:b2DebugDraw = New debugDraw
m_debugDraw.SetFlags(5)
xScale=1
yScale=1
world.SetWarmStarting(1)
world.SetContinuousPhysics(1)

world.SetDebugDraw(m_debugDraw)

Local groundBodyDef:b2BodyDef = New b2BodyDef
groundBodyDef.SetPosition(New b2Vec2.Create(350.0, 10.0))

Local groundBody:b2Body = world.CreateBody(groundBodyDef)

Local groundShapeDef:b2PolygonDef = New b2PolygonDef
groundShapeDef.SetAsBox(350.0, 10.0)

groundBody.CreateShape(groundShapeDef)

Local bodyDef:b2BodyDef = New b2BodyDef
bodyDef.SetPosition(New b2Vec2.Create(350.0, 400.0))
Local body:b2Body = world.CreateBody(bodyDef)

Local shapeDef:b2PolygonDef = New b2PolygonDef
shapeDef.SetAsBox(10.0, 10.0)
shapeDef.SetDensity(1.0)
shapeDef.SetFriction(0.3)
body.CreateShape(shapeDef)
body.SetMassFromShapes()

Local timeStep:Float = 1.0 / 60.0
Local iterations:Int = 10

Graphics WORLD_WIDTH,WORLD_HEIGHT
SetOrigin(0,WORLD_HEIGHT)
While Not KeyHit( KEY_ESCAPE )
	
	Cls()
	world.DoStep(timeStep, iterations,8)
	world.Validate()
	Flip()

Wend
Во втором примере можно гонять шарик стрелочками( очень медленно).

Framework BaH.Box2D

Import BRL.StandardIO
Import BRL.LinkedList


Import BRL.FreeTypeFont
Import "render.bmx"

Const WORLD_WIDTH:Float=700
Const WORLD_HEIGHT:Float=500

Local worldAABB:b2AABB = New b2AABB.Create()
worldAABB.SetLowerBound(New b2Vec2.Create(0.0, 0.0))
worldAABB.SetUpperBound(New b2Vec2.Create(WORLD_WIDTH, WORLD_HEIGHT))

Local gravity:b2Vec2 = New b2Vec2.Create(0.0, -10.0)

Local doSleep:Int = True

Local world:b2World = New b2World.Create(worldAABB, gravity, doSleep)
Local m_debugDraw:b2DebugDraw = New debugDraw
m_debugDraw.SetFlags(131)
xScale=1
yScale=1

world.SetWarmStarting(1)
world.SetContinuousPhysics(1)

world.SetDebugDraw(m_debugDraw)

Local groundBodyDef:b2BodyDef = New b2BodyDef
groundBodyDef.SetPosition(New b2Vec2.Create(350.0, 10.0))

Local groundBody:b2Body = world.CreateBody(groundBodyDef)

Local groundShapeDef:b2PolygonDef = New b2PolygonDef
groundShapeDef.SetAsBox(350.0, 10.0)

groundBody.CreateShape(groundShapeDef)

Local bodyDef:b2BodyDef = New b2BodyDef
bodyDef.SetPosition(New b2Vec2.Create(350.0, 400.0))
Local body:b2Body = world.CreateBody(bodyDef)

Local shapeDef:b2PolygonDef = New b2PolygonDef
shapeDef.SetAsBox(10.0, 10.0)
shapeDef.SetDensity(1.0)
shapeDef.SetFriction(0.3)
body.CreateShape(shapeDef)
body.SetMassFromShapes()

Local circ:b2CircleDef = New b2CircleDef
		circ.SetDensity(0.002)
		circ.SetRadius(10)
		circ.SetFriction(0.8)

		
Local circbody:b2BodyDef= New b2BodyDef
		'circbody.SetAllowSleep(False)
		circbody.SetPosition(New b2Vec2.Create(100.0,100.0))
		
Local		Wheel:b2Body = world.CreateBody(circbody)
		Wheel.CreateShape(circ)
		Wheel.SetMassFromShapes()

Local timeStep:Float = 1.0 / 60.0
Local iterations:Int = 10

Graphics WORLD_WIDTH,WORLD_HEIGHT

SetOrigin(0,WORLD_HEIGHT)
SetColor(0,255,0)

While Not KeyHit( KEY_ESCAPE )
	
	Cls()


	world.DoStep(timeStep, iterations,8)
	world.Validate()
	If KeyDown (KEY_RIGHT) Then Wheel.applyTorque(-500.0)
	If KeyDown (KEY_LEFT) Then Wheel.applyTorque(500.0)

	
	Flip()

Wend
А теперь о неприятной засаде. Рендер всегда импортируется именно в две строчки
Import BRL.FreeTypeFont
Import "render.bmx"
В файле рендера есть зумирование в 8 раз! Поэтому через глобальные настройки рендера в своём проекте нужно убрать зумирование, вот так
xScale=1
yScale=1
Но это ещё не всё. Почему-то рендеру надо задовать смещение в ширину мира(или экрана, надо проверить, так как у меня ширина мира равна ширине экрана).
SetOrigin(0,WORLD_HEIGHT)
Иначе он неправильно выводит объекты.
Надо ещё включить рендер! Командой
Рендер.SetFlags(Флаги)
где флаги совмещаются по OR
Флаги

e_shapeBit = 0x0001, ///< draw shapes
e_jointBit = 0x0002, ///< draw joint connections
e_coreShapeBit = 0x0004, ///< draw core (TOI) shapes
e_aabbBit = 0x0008, ///< draw axis aligned bounding boxes
e_obbBit = 0x0010, ///< draw oriented bounding boxes
e_pairBit = 0x0020, ///< draw broad-phase pairs
e_centerOfMassBit = 0x0040, ///< draw center of mass frame
e_controllerBit = 0x0080, ///< draw controllers

Последний раз редактировалось Sikkyboy, 25.03.2020 в 00:04.
(Offline)
 
Ответить с цитированием
Старый 01.04.2020, 07:46   #4
Sikkyboy
AnyKey`щик
 
Регистрация: 22.03.2020
Сообщений: 18
Написано 6 полезных сообщений
(для 11 пользователей)
Ответ: Эксперименты с box2d

Разобрался с рендером по умолчанию. Для правильного вывода нужно задавать смещение в высоту экрана(окна).
Пример(Для работы примеров нужно скопировать в папку проекта render.bmx из BlitzMax\mod\bah.mod\box2d.mod\examples):
Framework BaH.Box2D

Import BRL.StandardIO
Import BRL.LinkedList


Import BRL.FreeTypeFont
Import "render.bmx"

Const WORLD_WIDTH:Float=400
Const WORLD_HEIGHT:Float=300

Global worldAABB:b2AABB = New b2AABB.Create()
worldAABB.SetLowerBound(New b2Vec2.Create(0.0, 0.0))
worldAABB.SetUpperBound(New b2Vec2.Create(WORLD_WIDTH, WORLD_HEIGHT))

Global gravity:b2Vec2 = New b2Vec2.Create(0.0, -10.0)

Global doSleep:Int = True

Global world:b2World = New b2World.Create(worldAABB, gravity, doSleep)
Local m_debugDraw:b2DebugDraw = New debugDraw
m_debugDraw.SetFlags(131)
xScale=1
yScale=1

world.SetWarmStarting(1)
world.SetContinuousPhysics(1)

world.SetDebugDraw(m_debugDraw)

Local groundBodyDef:b2BodyDef = New b2BodyDef
groundBodyDef.SetPosition(New b2Vec2.Create(200, 10.0))

Local groundBody:b2Body = world.CreateBody(groundBodyDef)

Local groundShapeDef:b2PolygonDef = New b2PolygonDef
groundShapeDef.SetAsBox(200.0, 10.0)
'groundShapeDef.setFriction(1)
groundBody.CreateShape(groundShapeDef)

Local cd:b2CircleDef = New b2CircleDef
cd.SetRadius(2.0)
cd.SetDensity(1.0)

Local restitution:Float[] = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5,0.6,0.7,0.8,0.9,1.0]

Local j:Int=0

For Local i:Int = 0 Until 77

Local bd:b2BodyDef = New b2BodyDef
			bd.SetPositionXY(10 + 5.0 * i, 200.0)

			Local body:b2Body = world.CreateBody(bd)
			If i<11 Then
			j=i
			Else
			j=i-11*(Int(Float(i)/11.0))
			EndIf
			
			cd.SetRestitution(restitution[j])
			body.CreateShape(cd)
			body.SetMassFromShapes()
Next


Local timeStep:Float = 1.0 / 60.0
Local iterations:Int = 10

Const SCREEN_WIDTH:Float=700
Const SCREEN_HEIGHT:Float=500
Graphics SCREEN_WIDTH,SCREEN_HEIGHT
SetOrigin(0,SCREEN_HEIGHT)
While Not KeyHit( KEY_ESCAPE )
	
	Cls()
	world.DoStep(timeStep, iterations,8)
	world.Validate()
	Flip()

Wend
На основе материала https://habr.com/ru/post/199064/
сделал капсулу коллизий (хотя в материале не капсула, а прямоугольник) и управление как у платформера:

Framework BaH.Box2D
Import BRL.StandardIO
Import BRL.LinkedList
Import BRL.FreeTypeFont
Import "render.bmx"

SuperStrict

Const WORLD_WIDTH:Float=70
Const WORLD_HEIGHT:Float=50

Global worldAABB:b2AABB = New b2AABB.Create()
worldAABB.SetLowerBound(New b2Vec2.Create(0.0, 0.0))
worldAABB.SetUpperBound(New b2Vec2.Create(WORLD_WIDTH, WORLD_HEIGHT))

Global gravity:b2Vec2 = New b2Vec2.Create(0.0, -10.0)
Global doSleep:Int = True

Global world:b2World = New b2World.Create(worldAABB, gravity, doSleep)

Local m_debugDraw:b2DebugDraw = New debugDraw
m_debugDraw.SetFlags(131)
xScale=10
yScale=10
world.SetWarmStarting(1)
world.SetContinuousPhysics(1)
world.SetDebugDraw(m_debugDraw)

Local groundBodyDef:b2BodyDef = New b2BodyDef
groundBodyDef.SetPosition(New b2Vec2.Create(35, 1.0))
Local groundBody:b2Body = world.CreateBody(groundBodyDef)
Local groundShapeDef:b2PolygonDef = New b2PolygonDef
groundShapeDef.SetAsBox(35.0, 1.0)
groundShapeDef.setFriction(1)
groundBody.CreateShape(groundShapeDef)

Local leftBodyDef:b2BodyDef = New b2BodyDef
leftBodyDef.SetPosition(New b2Vec2.Create(1, 25.0))
Local leftBody:b2Body = world.CreateBody(leftBodyDef)
Local boundShapeDef:b2PolygonDef = New b2PolygonDef
boundShapeDef.SetAsBox(1.0, 24.0)
boundShapeDef.SetFriction(0.0)

leftBody.CreateShape(boundShapeDef)

Local rightBodyDef:b2BodyDef = New b2BodyDef
rightBodyDef.SetPosition(New b2Vec2.Create(69, 25.0))
Local RightBody:b2Body = world.CreateBody(rightBodyDef)
rightBody.CreateShape(boundShapeDef)

Global cd:b2CircleDef = New b2CircleDef
cd.SetRadius(0.35)
cd.SetDensity(0.3)
cd.setrestitution(0.0)
cd.setfriction(0.8)

Local corpusShapeDef:b2PolygonDef = New b2PolygonDef
corpusShapeDef.SetAsBox(0.357, 0.65)
corpusShapeDef.setrestitution(0.0)
corpusShapeDef.setDensity(0.3)

Global bd:b2BodyDef = New b2BodyDef
bd.SetPositionXY(35.0, 15.0)
bd.setfixedRotation(1)
bd.setissleeping(0)
Global body:b2Body = world.CreateBody(bd)
body.CreateShape(corpusShapeDef)
cd.setlocalposition(New b2Vec2.Create(0.0,0.65))
body.CreateShape(cd)
cd.setlocalposition(New b2Vec2.Create(0.0,-0.65))
Global bottom:b2Shape = body.CreateShape(cd)
body.SetMassFromShapes()

Global OnSurface:Int=0

Type MyContactListener Extends b2ContactListener

Rem
Method Add(point:b2ContactPoint)
If(point.getShape1()=bottom Or point.getShape2()=bottom) Then OnSurface=1
End Method
End Rem

Method Persist(point:b2ContactPoint) 
If(point.getShape1()=bottom Or point.getShape2()=bottom) Then OnSurface=1
End Method


Method Remove(point:b2ContactPoint) 
OnSurface=0
End Method

End Type

world.setContactListener( New MyContactListener)


Local timeStep:Float = 1.0 / 60.0
Local iterations:Int = 10

Const SCREEN_WIDTH:Float=700
Const SCREEN_HEIGHT:Float=500
Graphics SCREEN_WIDTH,SCREEN_HEIGHT
SetOrigin(0,SCREEN_HEIGHT)
While Not KeyHit( KEY_ESCAPE )
Local Velocity:b2Vec2=body.getlinearvelocity()
	
	If(KeyDown(KEY_RIGHT)) Then
	body.wakeup()
	If Velocity.getx()<10 Then
	Velocity.setx(10.0)
	body.setlinearVelocity(Velocity)
	EndIf
	EndIf
	
	If(KeyDown(KEY_LEFT)) Then
	body.wakeup()
	If Velocity.getx()>-10 Then
	Velocity.setx(-10.0)
	body.setlinearVelocity(Velocity)
	EndIf
	EndIf
	
	If(KeyDown(KEY_UP)) Then
	'body.getcontactlist()
	body.wakeup()
	If OnSurface= 1 Then
	Velocity.sety(10.0)
	body.setlinearVelocity(Velocity)
	OnSurface=0
	EndIf
	EndIf
	
	Cls()
	world.DoStep(timeStep, iterations,8)
	world.Validate()
	Flip()

Wend
Для стабильной работы нужно правильно реализовывать ContactListener, а также делать радиус входящих в капсулу окружностей чуть меньшим чем ширина прямоугольного корпуса капсулы.

Последний раз редактировалось Sikkyboy, 01.04.2020 в 14:18. Причина: Стабилизировал работу второго примера
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
Эмиль (21.05.2020)
Ответ


Опции темы

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

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


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


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