Что нового

3D Лабиринт с шаром (AutoIt3 + C)

FlatX007

Tattoo!
Сообщения
201
Репутация
35
3D Лабиринт с шаром (AutoIt3 + C)

Гибрид из AutoIt3 и нативной C DLL. AutoIt рулит логикой и окном, а C делает всю графику через рейкастинг напрямую в пиксельный буфер. Никаких сторонних движков.

Как устроено

Два уровня:

1. AutoIt3 (maze_ball.au3) — мозг игры. Обрабатывает клавиатуру, считает физику шара (инерция, отскоки), создаёт окно и крутит игровой цикл.

2. C DLL (maze_rc.c) — графический движок. Рейкастинг (псевдо-3D как в Wolfenstein), рисует небо с солнцем, пол с тенями, стены. Шар рендерится как 3D-сфера с текстурой и бликами.

Как AutoIt рисует 3D

Сам AutoIt для 3D не годится, поэтому обходим через сырой пиксельный буфер:

- В AutoIt создаём DllStruct — массив на 307200 пикселей (640x480).
- Передаём указатель на эту память в C DLL.
- C заполняет буфер цветами — вся математика на полной скорости процессора.
- Когда кадр готов, AutoIt вызывает StretchDIBits из Windows API — копирует буфер прямо в окно.

Что умеет

Освещение — солнце на юге, тени от стен падают на север. Плавные градиенты через мульти-сэмплинг, ambient occlusion у оснований стен.

Физика — у шара есть инерция, он катится сам после разгона и замедляется трением. При ударе о стену отскакивает под углом отражения. Камера сама доворачивается в коридор после поворота.

Сборка и запуск

1. Поставить MinGW (gcc).
2. Запустить build_maze.bat — соберёт mazeball_rc.dll и 32-битную версию.
3. Запустить maze_ball.au3 через AutoIt3.

Управление: стрелки вверх/вниз — разгон/торможение, влево/вправо — поворот (в тупике стрейф), Q или Esc — выход.
 

Вложения

  • 2026-03-09_01-33-31.png
    2026-03-09_01-33-31.png
    51.9 КБ · Просмотры: 3
  • maze_ball.au3
    17.5 КБ · Просмотры: 2
  • AutoIt3.7z
    75.9 КБ · Просмотры: 3

Prog

Продвинутый
Сообщения
645
Репутация
81
Когда кадр готов, AutoIt вызывает StretchDIBits из Windows API — копирует буфер прямо в окно.
То есть без аппаратного ускорения. На топовой видеокарте и встроенной в процессор будет работать с одинаковой производительностью...
Сам AutoIt для 3D не годится
Из него нельзя вызывать функции OpenGL, которые к тому же аппаратно ускорены?
 
Автор
F

FlatX007

Tattoo!
Сообщения
201
Репутация
35
да можно OpenGL,DirectX ... autoit вообще не предназначен для отрисовки графики, но всегда есть исключения.
Мы его используем как программу для запуска, забиваем гвозди микроскопом, на больше чем 2 -3 fps Autoit не способен.
Не хотел выкладывать - https://autoit-script.ru/threads/pacman-privet-iz-igrovyx-avtomatov-chistyj-gdi.29485/
 

Prog

Продвинутый
Сообщения
645
Репутация
81
на больше чем 2 -3 fps Autoit не способен.
GDI / GDI+ не для игр.
Если посмотреть код pacman то видно что при каждом выводе кадра рисуется все. Если рисовать только то что изменилось, это немного ускорит работу и добавит FPS.

3D графика формируется не так. Вместо того чтобы каждый раз все рисовать с нуля, создаются 3D объекты состоящие из сеток (основа объекта), текстур (оболочки над сеткой) и др. Это все загружается в видеокарту (не зря же в ней столько памяти) и вместо того чтобы грузить проц рисованием каждого кадра, сообщаем видеокарте какой объект где расположить, а дальше карта сама все высчитывает и формирует картинку. Чтобы это достичь нужно вместо GDI / GDI+ использовать DirectX или OpenGL - специальные API для взаимодействия с видеокартой.
Код с официального форума
Код:
Global Const $GL_VERSION_1_1 = 1
Global Const $PFD_TYPE_RGBA = 0
Global Const $PFD_MAIN_PLANE = 0
Global Const $PFD_DOUBLEBUFFER = 1
Global Const $PFD_DRAW_TO_WINDOW = 4
Global Const $PFD_SUPPORT_OPENGL = 32
Global Const $GL_PROJECTION = 0x1701
Global Const $GL_COLOR_BUFFER_BIT = 0x00004000
Global Const $GL_LINES = 0x0001


Global $gui = GUICreate("Simple OpenGL Example", 350, 350)
GUISetBkColor(0x000000)
GUISetOnEvent(-3, "Quit")

Global $dc
EnableOpenGL($gui, $dc)
glMatrixMode($GL_PROJECTION)
glViewport(0, 0, 350, 350)

GUISetState(@SW_SHOW)

Global $a, $m

While 1


    glViewport(0, 0, 400 - $a / 5, 400 - $a / 5)
    $a += 10
    If $a > 1750 Then $a = 0


    glClear($GL_COLOR_BUFFER_BIT)

    glPopMatrix()
    glPushMatrix()

    $m -= .5
    glRotated($m, 0, 0, 1)

    glBegin($GL_LINES)

    glColor3f(0, 1, 0)
    glVertex2d(-.5, -.5)
    glColor3f(1, 0, 0)
    glVertex2d(-.5, .5)

    glColor3f(0, 1, 0)
    glVertex2d(-.5, -.5)
    glColor3f(1, 0, 0)
    glVertex2d(.75, -.5)

    glColor3f(1, 0, 0)
    glVertex2d(.75, -.5)
    glColor3f(0, 1, 0)
    glVertex2d(.75, .5)


    glColor3f(0, 1, 0)
    glVertex2d(.75, .5)
    glColor3f(1, 0, 0)
    glVertex2d(-.5, .5)
    glEnd()

    SwapBuffers($dc)

    Sleep(10)

WEnd


Func EnableOpenGL($hwnd, ByRef $hDC)

    Local $pfd = DllStructCreate("short nSize;" & _
            "short nVersion;" & _
            "dword dwFlags;" & _
            "byte  iPixelType;" & _
            "byte  cColorBits;" & _
            "byte  cRedBits;" & _
            "byte  cRedShift;" & _
            "byte  cGreenBits;" & _
            "byte  cGreenShift;" & _
            "byte  cBlueBits;" & _
            "byte  cBlueShift;" & _
            "byte  cAlphaBits;" & _
            "byte  cAlphaShift;" & _
            "byte  cAccumBits;" & _
            "byte  cAccumRedBits;" & _
            "byte  cAccumGreenBits;" & _
            "byte  cAccumBlueBits;" & _
            "byte  cAccumAlphaBits;" & _
            "byte  cDepthBits;" & _
            "byte  cStencilBits;" & _
            "byte  cAuxBuffers;" & _
            "byte  iLayerType;" & _
            "byte  bReserved;" & _
            "dword dwLayerMask;" & _
            "dword dwVisibleMask;" & _
            "dword dwDamageMask;")

    Local $h_dc = DllCall("user32.dll", "hwnd", "GetDC", "hwnd", $hwnd)

    DllStructSetData($pfd, "nSize", DllStructGetSize($pfd))
    DllStructSetData($pfd, "nVersion", $GL_VERSION_1_1)
    DllStructSetData($pfd, "dwFlags", BitOR($PFD_DRAW_TO_WINDOW, $PFD_SUPPORT_OPENGL, $PFD_DOUBLEBUFFER))
    DllStructSetData($pfd, "iPixelType", $PFD_TYPE_RGBA)
    DllStructSetData($pfd, "cColorBits", 24)
    DllStructSetData($pfd, "cDepthBits", 32)
    DllStructSetData($pfd, "iLayerType", $PFD_MAIN_PLANE)

    DllOpen("gdi32.dll")
    DllOpen("opengl32.dll")

    Local $iFormat = DllCall("gdi32.dll", "int", "ChoosePixelFormat", "hwnd", $h_dc[0], "ptr", DllStructGetPtr($pfd))

    Local $iSetFormat = DllCall("gdi32.dll", "int", "SetPixelFormat", "hwnd", $h_dc[0], "int", $iFormat[0], "ptr", DllStructGetPtr($pfd))

    Local $h_cont = DllCall("opengl32.dll", "hwnd", "wglCreateContext", "hwnd", $h_dc[0])

    Local $iRet = DllCall("opengl32.dll", "int", "wglMakeCurrent", "int", $h_dc[0], "int", $h_cont[0])

    $hDC = $h_dc[0]

    Return 1

EndFunc   ;==>EnableOpenGL


Func glColor3f($red, $green, $blue)
    DllCall("opengl32.dll", "none", "glColor3f", "float", $red, "float", $green, "float", $blue)
EndFunc   ;==>glColor3f


Func glVertex2d($x, $y)
    DllCall("opengl32.dll", "none", "glVertex2d", "double", $x, "double", $y)
EndFunc   ;==>glVertex2d

Func glClear($mask)
    DllCall("opengl32.dll", "none", "glClear", "uint", $mask)
EndFunc   ;==>glClear


Func glBegin($mode)
    DllCall("opengl32.dll", "none", "glBegin", "uint", $mode)
EndFunc   ;==>glBegin


Func glViewport($x, $y, $width, $height)
    DllCall("opengl32.dll", "none", "glViewport", "int", $x, "int", $y, "int", $width, "int", $height)
EndFunc   ;==>glViewport

Func glEnd()
    DllCall("opengl32.dll", "none", "glEnd")
EndFunc   ;==>glEnd


Func glMatrixMode($mode)
    DllCall("opengl32.dll", "none", "glMatrixMode", "uint", $mode)
EndFunc   ;==>glMatrixMode


Func glPopMatrix()
    DllCall("opengl32.dll", "none", "glPopMatrix")
EndFunc   ;==>glPopMatrix


Func glPushMatrix()
    DllCall("opengl32.dll", "none", "glPushMatrix")
EndFunc   ;==>glPushMatrix


Func glRotated($angle, $x, $y, $z)
    DllCall("opengl32.dll", "none", "glRotated", "double", $angle, "double", $x, "double", $y, "double", $z)
EndFunc   ;==>glRotated

Func SwapBuffers($hDC)
    DllCall("gdi32.dll", "int", "SwapBuffers", "hwnd", $hDC)
EndFunc   ;==>SwapBuffers


Func Quit()
    Exit
EndFunc
 
Автор темы Похожие темы Форум Ответы Дата
I Разработка ботов 2
Верх