Metadata-Version: 2.4
Name: jwarol
Version: 0.14.2
Summary: High-performance creative engine (Win32/OpenGL/Python)
Home-page: https://github.com/r9441887-collab/jwarol-code-new
Author: jwarol-team
Author-email: r9441887@gmail.com
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: C++
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: license-file
Dynamic: requires-python
Dynamic: summary

# jwarol

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

## Возможности

| Функция | Описание |
|---------|----------|
| **Window** | Окно с OpenGL-контекстом (Win32 / X11) + glViewport |
| **Shader** | GLSL-шейдеры из строк/файлов, проверка ошибок, move-семантика |
| **Renderer** | 2D-рендеринг с ортографической проекцией, камерой, culling |
| **Texture** | PNG/JPG/BMP (WIC), процедурные, наложение, шифрование |
| **Input** | Клавиатурный ввод (Win32 GetAsyncKeyState / X11 XQueryKeymap) |
| **Camera** | Следование за объектом, zoom, smooth-интерполяция |
| **Sprite/Animation** | Спрайт-листы, покадровая анимация |
| **DetailGroup** | Батч-рендеринг тысяч объектов за 1 draw call |
| **AnimatedSprite2D** | Скелетная 2D-анимация из Blender |
| **Physics** | Verlet-интеграция, гравитация, коллизии, STATIC/DYNAMIC/KINEMATIC |
| **Sound** | .wav через winmm (Windows) |
| **GameObjects** | Object, Player, Character, GUI, Detail с рабочими draw/update |
| **PyInstaller Build** | Сборка игры в .exe |

## Установка

```bash
pip install jwarol
```

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

```bash
python setup.py build
```

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

```python
import jwarol as jl

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()
```

## Текстуры

```python
tex = jl.Texture("sprite.png")

# Процедурная текстура
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, alpha=0.5)
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)
```

## Физика

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

body = world.add_body(300, 0, 50, 50, jl.BodyType.DYNAMIC)
static = world.add_body(0, 650, 800, 50, jl.BodyType.STATIC)
# STATIC-тела не двигаются при коллизиях

world.step(dt)
x, y = body.pos.x, body.pos.y
```

## Ввод и время

```python
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
```

## Шейдеры

```python
shader = jl.Shader("#version 330 core\n...", "#version 330 core\n...")
shader.use()

shader = jl.Shader.from_file("vertex.glsl", "fragment.glsl")
shader = jl.Shader.from_single_file("shader.glsl")

# Ошибки компиляции → RuntimeError с логом
try:
    s = jl.Shader.from_file("bad.glsl", "empty.glsl")
except RuntimeError as e:
    print("Shader error:", e)
```

## Камера

```python
cam = jl.Camera(800, 600)
cam.follow(player)
cam.smooth = 0.1
cam.zoom = 2.0  # приближение

cam.update(dt)
cam.apply_to(renderer)
```

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

```python
sheet = jl.Texture("player_walk.png")
sprite = jl.Sprite()
sprite.set_texture(sheet, 4, 2)

anim = jl.Animation()
anim.from_range(0, 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)
```

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

```python
details = jl.DetailGroup()
details.add(100, 200, 32, 32, 1.0, 0.5, 0.0, 0.8)

tileset = jl.Texture("tileset.png")
details.set_texture(tileset, 4, 4)
details.add_frame(100, 100, 32, 32, 0, 0)

details.set_max_distance(500)
details.draw(cam.x, cam.y, 800, 600)
```

## Скелетная анимация (AnimatedSprite2D)

```python
hero = jl.AnimatedSprite2D.from_blender("character.json", "character.png")
hero.play("idle")
hero.anim_loop = True

while win.is_open:
    dt = clock.tick()
    hero.update(dt)
    hero.draw(renderer, player.x, player.y, scale=1.0)
```

### Программное создание скелета

```python
skel = jl.SkeletonData()
skel.add_bone("root")
skel.add_bone("body", 0)
skel.add_bone("head", 1)
skel.add_bone("arm_l", 1)
skel.add_bone("arm_r", 1)

skel.bones[1].y = -30
skel.bones[2].y = -30
skel.bones[3].x = -20
skel.bones[4].x = 20

walk = jl.SkeletalAnimation()
walk.name = "walk"
walk.duration = 1.0
walk.loop = True

track = jl.BoneTrack()
track.bone_index = 3
kf1 = jl.BoneKeyframe(); kf1.time = 0.0; kf1.rotation = -30
kf2 = jl.BoneKeyframe(); kf2.time = 0.5; kf2.rotation = 30
kf3 = jl.BoneKeyframe(); kf3.time = 1.0; kf3.rotation = -30
track.keyframes = [kf1, kf2, kf3]
walk.tracks = [track]

sprite = jl.AnimatedSprite2D()
sprite.skeleton = skel
sprite.add_animation(walk)
sprite.set_texture(jl.Texture("character.png"))
sprite.play("walk")
# В цикле:
sprite.update(dt)
sprite.draw(renderer, x, y)
```

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

```python
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 = jl.GUI(10, 10, 200, 30)
gui.text = "Score: 0"

detail = jl.Detail(500, 400, 16, 16)
detail.alpha = 0.5
```

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

```python
jl.Texture.encrypt("sprite.png", "my_secret_key")
tex = jl.Texture.load_encrypted("sprite.png.enc", "my_secret_key")
# Расшифровка в памяти, без временного файла
```

## Сборка в .exe (PyInstaller)

```bash
python build_exe.py game.py
python build_exe.py game.py --onefile --icon icon.ico --name "MyGame"
python build_exe.py game.py --assets assets/ --console
```

Результат в папке `dist/`.

## Структура проекта

```
jwarol/
├── include/           # C++ заголовки
│   ├── Window.hpp     # Окно (Win32 / X11)
│   ├── Shader.hpp     # GLSL-шейдеры (move-семантика, деструктор)
│   ├── Renderer.hpp   # 2D-рендерер (ортографическая проекция)
│   ├── Texture.hpp    # Текстуры (PNG/JPG/BMP/WIC)
│   ├── Input.hpp      # Клавиатурный ввод (Win32 / X11)
│   ├── Physics.hpp    # Verlet-физика (STATIC fix)
│   ├── Sound.hpp      # WAV-звук (winmm)
│   ├── Camera.hpp     # Камера с follow + zoom
│   ├── Sprite.hpp     # Спрайты и анимация
│   ├── DetailGroup.hpp# Батч-рендеринг
│   ├── Anim2D.hpp     # Скелетная 2D-анимация
│   ├── GameObject.hpp # Игровые объекты
│   ├── Math.hpp       # Vec2, Rect, Mat3
│   ├── Clock.hpp      # Дельта-таймер
│   └── GLFunctions.hpp# OpenGL-функции (кросс-платформа)
├── src/               # C++ исходники
├── tools/
│   └── blender_export.py
├── build_exe.py       # PyInstaller сборщик
├── setup.py
└── README.md
```

## Репозиторий

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

## Лицензия

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