Skip to main content

High-performance creative engine (Win32/OpenGL/Python)

Project description

jwarol

Движок на C++ для 2D-игр на Python. Win32 API + сырой OpenGL (и X11 на Linux). Включено: рендеринг, шейдеры, текстуры, физика, звук .wav, игровые объекты, шифрование ассетов.

Возможности

Функция Описание
Window Создание окна с OpenGL-контекстом (Win32 / X11)
Shader Компиляция GLSL-шейдеров из строк или отдельных .glsl файлов
Renderer Рендеринг прямоугольников и текстур через GPU
Texture Загрузка PNG/JPG/BMP, процедурные текстуры, наложение
Input Клавиатурный ввод (GetAsyncKeyState)
Camera Следование за игроком, скроллинг мира, smooth-камера
Sprite/Animation Спрайт-листы, анимация по кадрам, генерация анимаций
DetailGroup Группа деталей — батч-рендеринг тысяч объектов без просадки FPS
Physics Verlet-интеграция, гравитация, коллизии, типы тел
Sound Воспроизведение .wav (winmm)
Object/Player/Character/GUI/Detail Система игровых объектов
Texture.encrypt Шифрование текстур для скомпилированных игр
Clock Замер дельта-тайма
Vec2/Rect 2D-математика

Установка

pip install jwarol

Быстрый старт

import jwarol as jl

jl.init_graphics()
win = jl.Window(800, 600, "Hello jwarol")
renderer = jl.Renderer(800, 600)

while win.is_open:
    win.poll_events()
    win.clear(0.1, 0.1, 0.2)

    renderer.draw_rect(100, 100, 200, 150, 1.0, 0.3, 0.5)
    renderer.draw_rect(350, 200, 100, 100, 0.2, 0.7, 1.0)

    win.swap_buffers()

Текстуры

# Загрузка из файла (PNG/JPG/BMP на Windows, BMP на Linux)
tex = jl.Texture("sprite.png")

# Процедурная текстура из пикселей (RGBA)
import struct
w, h = 64, 64
pixels = bytearray()
for y in range(h):
    for x in range(w):
        pixels.extend([255, 0, 0, 255])  # красный пиксель
tex = jl.Texture(w, h, bytes(pixels), 4)

# Рисование с текстурой
renderer.draw_texture(tex, 100, 100, 200, 200)

# Текстура с прозрачностью
renderer.draw_texture(tex, 100, 100, 200, 200, alpha=0.5)

# Спрайт из tileset'а (draw_texture_ex)
renderer.draw_texture_ex(tileset, 0, 0, 32, 32, 0, 0, 32, 32)

# Умная загрузка всех текстур из папки
textures = jl.Texture.load_all("assets/textures/")

# Наложение текстур
combined = tex.overlay(other_tex, 10, 10, alpha=0.7)

Физика

world = jl.World()
world.gravity = 980.0

# Verlet-точки
p = world.add_point(400, 100)  # падает вниз

# Физические тела (прямоугольники)
body = world.add_body(300, 0, 50, 50, jl.BodyType.DYNAMIC)
static = world.add_body(0, 650, 800, 50, jl.BodyType.STATIC)

# Исключение из физики
body.enabled = False  # не участвует в симуляции

# Шаг физики
dt = clock.tick()
world.step(dt)

# Чтение позиции
x, y = body.pos.x, body.pos.y

Ввод и время

input = jl.Input()
clock = jl.Clock()

while win.is_open:
    dt = clock.tick()
    input.update()

    if input.is_down(ord('W')): pass      # клавиша зажата
    if input.is_pressed(ord(' ')): pass   # только что нажали
    if input.is_released(ord('A')): pass  # только что отпустили

Шейдеры

# Из строк
shader = jl.Shader("""
#version 330 core
layout(location = 0) in vec2 aPos;
void main() { gl_Position = vec4(aPos, 0.0, 1.0); }
""", """
#version 330 core
uniform vec4 uColor;
out vec4 FragColor;
void main() { FragColor = uColor; }
""")
shader.use()

# Из отдельных файлов (любые названия)
shader = jl.Shader.from_file("shaders/vertex.glsl", "shaders/fragment.glsl")
shader = jl.Shader.from_file("custom.vert", "custom.frag")

# Из одного файла с маркерами (#shader vertex / #shader fragment)
shader = jl.Shader.from_single_file("shader.glsl")

# Ошибки обрабатываются без краша:
# - файл не найден → RuntimeError
# - файл пустой → RuntimeError
# - ошибка компиляции → RuntimeError с логом
try:
    s = jl.Shader.from_file("bad.glsl", "empty.glsl")
except RuntimeError as e:
    print("Shader error:", e)

Звук

# Из папки
sound = jl.Sound("assets/sounds/effect.wav")
sound.play()
sound.set_volume(500)  # 0-1000
sound.stop()

# Быстрое воспроизведение без создания объекта
jl.Sound.play_file("assets/sounds/click.wav")

Камера

cam = jl.Camera(800, 600)

# Следование за игроком (с плавностью)
cam.follow(player)
cam.smooth = 0.1  # 0 = мгновенно, 1 = очень плавно

# Применить к рендереру перед отрисовкой
cam.update(dt)
cam.apply_to(renderer)

# Все draw_rect/draw_texture теперь сдвинуты камерой
# Объекты за экраном не рисуются (FPS не проседает)
renderer.draw_rect(0, 0, 2000, 2000, 0.2, 0.2, 0.3)  # большой мир

Спрайты и анимация

# Загрузка спрайт-листа (одна картинка с кадрами)
sheet = jl.Texture("player_walk.png")  # 4 колонки x 2 строки = 8 кадров

sprite = jl.Sprite()
sprite.set_texture(sheet, 4, 2)  # 4 колонки, 2 строки

# Анимация из последовательности кадров
anim = jl.Animation()
anim.from_range(0, 3)  # кадры 0,1,2,3
anim.speed = 0.1       # сек/кадр
anim.loop = True
sprite.set_animation(anim)

# В игровом цикле
sprite.update(dt)
sprite.draw_at(renderer, player.x, player.y, 64, 64)

# Генерация простых анимаций
idle = jl.Animation.generate("idle", 8)
walk = jl.Animation.generate("walk", 8)
run = jl.Animation.generate("run", 8)

# Рендерер сам обрезает невидимые объекты
renderer.set_camera(cam.x, cam.y)
renderer.is_visible(x, y, w, h)  # проверка видимости вручную

Группа деталей (DetailGroup)

Тысячи мелких объектов без просадки FPS — все рендерятся за один draw call.

details = jl.DetailGroup()

# Добавить кучу деталей
for i in range(10000):
    details.add(i * 10, i * 5, 4, 4, 1.0, 0.5, 0.0, 0.8)

# В игровом цикле — всё одним пакетом
details.draw(cam.x, cam.y, 800, 600)

# Если хочешь ПРОСАДКУ FPS — отключи culling
details.set_culling(False)   # рисует ВСЁ, даже за экраном
details.set_culling(True)    # по умолчанию — рисует только видимое

Игровые объекты

# Базовый объект
obj = jl.Object(100, 100, 64, 64)
obj.active = True
obj.set_texture(texture)

# Игрок
player = jl.Player(400, 300, 32, 32)
player.speed = 250.0

# Персонаж
char = jl.Character(200, 200, 32, 48)
char.hp = 100

# GUI-элемент
gui = jl.GUI(10, 10, 200, 30)
gui.text = "Score: 0"

# Мелкая деталь
detail = jl.Detail(500, 400, 16, 16)
detail.alpha = 0.5

Шифрование текстур

# Зашифровать текстуру (создаёт .enc файл)
jl.Texture.encrypt("sprite.png", "my_secret_key")

# Загрузить зашифрованную текстуру
tex = jl.Texture.load_encrypted("sprite.png.enc", "my_secret_key")

Сборка из исходников

# Windows (MSVC)
python setup.py build

# Linux (GCC)
python setup.py build

Репозиторий

https://github.com/r9441887-collab/jwarol-code-new

Лицензия

MIT License — Руслан (r9441887@gmail.com)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

jwarol-0.11.0.tar.gz (19.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

jwarol-0.11.0-cp312-cp312-win_amd64.whl (197.6 kB view details)

Uploaded CPython 3.12Windows x86-64

File details

Details for the file jwarol-0.11.0.tar.gz.

File metadata

  • Download URL: jwarol-0.11.0.tar.gz
  • Upload date:
  • Size: 19.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.7

File hashes

Hashes for jwarol-0.11.0.tar.gz
Algorithm Hash digest
SHA256 de5420603702aa3eb5e60fb488c325d71f155a18bdfab7b6ba7f51ac511a8583
MD5 458c3326f970c796a32f08bcd12ed8b5
BLAKE2b-256 05c0a6cd3d61039f8f76480ceaa0be6d6eeb5500f6d1d254ad91862d03e35458

See more details on using hashes here.

File details

Details for the file jwarol-0.11.0-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: jwarol-0.11.0-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 197.6 kB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.7

File hashes

Hashes for jwarol-0.11.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 1a3ad44f7d7d0e5c9547fe00bbfce3dc3d3aa76368ea19440fb45e08b4e671ab
MD5 34f8fc135d0b47fc86eed94a2c7945a1
BLAKE2b-256 0abdf923e3b632925d40c518c6b655c7b6254abfcc8c6ee09190812d6362f344

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page