richlib: simple API on top of raylib
This commit is contained in:
parent
c3d018c830
commit
de89790bff
2 changed files with 378 additions and 0 deletions
328
raylib/richlib/__init__.py
Executable file
328
raylib/richlib/__init__.py
Executable file
|
@ -0,0 +1,328 @@
|
||||||
|
""" Richlib, simple access to Raylib
|
||||||
|
"""
|
||||||
|
__version__ = '0.1'
|
||||||
|
|
||||||
|
from ..dynamic import ffi, raylib as rl
|
||||||
|
from ..colors import *
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
data_dir = ""
|
||||||
|
|
||||||
|
camera = ffi.new("struct Camera3D *")
|
||||||
|
camera.position = (0.0, 100, 100)
|
||||||
|
camera.target = (0.0, 0.0, 0.0)
|
||||||
|
camera.up = (0, 1, 0)
|
||||||
|
camera.fovy = 45
|
||||||
|
camera.type = rl.CAMERA_PERSPECTIVE
|
||||||
|
|
||||||
|
mod = sys.modules['__main__']
|
||||||
|
|
||||||
|
|
||||||
|
class Vector(list):
|
||||||
|
@property
|
||||||
|
def x(self):
|
||||||
|
return self[0]
|
||||||
|
|
||||||
|
@x.setter
|
||||||
|
def x(self, value):
|
||||||
|
self[0] = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def y(self):
|
||||||
|
return self[1]
|
||||||
|
|
||||||
|
@y.setter
|
||||||
|
def y(self, value):
|
||||||
|
self[1] = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def z(self):
|
||||||
|
return self[2]
|
||||||
|
|
||||||
|
@z.setter
|
||||||
|
def z(self, value):
|
||||||
|
self[2] = value
|
||||||
|
|
||||||
|
|
||||||
|
def make_color(c):
|
||||||
|
if isinstance(c, str):
|
||||||
|
return globals()[c.upper()]
|
||||||
|
else:
|
||||||
|
return c
|
||||||
|
|
||||||
|
|
||||||
|
def clear(color=BLACK):
|
||||||
|
rl.ClearBackground(color)
|
||||||
|
|
||||||
|
|
||||||
|
class Shape:
|
||||||
|
@property
|
||||||
|
def color(self):
|
||||||
|
return self._color
|
||||||
|
|
||||||
|
@color.setter
|
||||||
|
def color(self, value):
|
||||||
|
if isinstance(value, str):
|
||||||
|
self._color = globals()[value.upper()]
|
||||||
|
else:
|
||||||
|
self._color = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def pos(self):
|
||||||
|
return self._pos
|
||||||
|
|
||||||
|
@pos.setter
|
||||||
|
def pos(self, value):
|
||||||
|
self._pos = Vector(value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def wire_color(self):
|
||||||
|
return self._wire_color
|
||||||
|
|
||||||
|
@wire_color.setter
|
||||||
|
def wire_color(self, value):
|
||||||
|
if isinstance(value, str):
|
||||||
|
self._wire_color = globals()[value.upper()]
|
||||||
|
else:
|
||||||
|
self._wire_color = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def x(self):
|
||||||
|
return self.pos.x
|
||||||
|
|
||||||
|
@x.setter
|
||||||
|
def x(self, value):
|
||||||
|
self.pos.x = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def y(self):
|
||||||
|
return self.pos.y
|
||||||
|
|
||||||
|
@y.setter
|
||||||
|
def y(self, value):
|
||||||
|
self.pos.y = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def z(self):
|
||||||
|
return self.pos.z
|
||||||
|
|
||||||
|
@z.setter
|
||||||
|
def z(self, value):
|
||||||
|
self.pos.z = value
|
||||||
|
|
||||||
|
|
||||||
|
class Box(Shape):
|
||||||
|
def __init__(self, position, size, color=RED, wires=True, wire_color=DARKGRAY):
|
||||||
|
self.pos = position
|
||||||
|
self.size = size
|
||||||
|
self.color = color
|
||||||
|
self.wire_color = wire_color # make_color(wire_color)
|
||||||
|
self.wires = wires
|
||||||
|
|
||||||
|
# def __getattr__(self, item):
|
||||||
|
# return self.pos.item
|
||||||
|
#
|
||||||
|
# def __setattr__(self, key, value):
|
||||||
|
# self.pos.key = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def size(self):
|
||||||
|
return self._size
|
||||||
|
|
||||||
|
@size.setter
|
||||||
|
def size(self, value):
|
||||||
|
print("setting size ", value, type(value))
|
||||||
|
self._size = Vector(value)
|
||||||
|
|
||||||
|
def get_bounding_box(self):
|
||||||
|
return (
|
||||||
|
(
|
||||||
|
self.pos.x - self.size.x / 2,
|
||||||
|
self.pos.y - self.size.y / 2,
|
||||||
|
self.pos.z - self.size.z / 2,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
self.pos.x + self.size.x / 2,
|
||||||
|
self.pos.y + self.size.y / 2,
|
||||||
|
self.pos.z + self.size.z / 2,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def draw(self):
|
||||||
|
rl.DrawCubeV(self.pos, self.size, self.color)
|
||||||
|
if self.wires:
|
||||||
|
rl.DrawCubeWiresV(
|
||||||
|
self.pos, self.size, self.wire_color
|
||||||
|
)
|
||||||
|
|
||||||
|
def check_collision(self, other):
|
||||||
|
if isinstance(other, Sphere):
|
||||||
|
r = rl.CheckCollisionBoxSphere(
|
||||||
|
self.get_bounding_box(), other.pos, other.radius
|
||||||
|
)
|
||||||
|
return r
|
||||||
|
elif isinstance(other, Box):
|
||||||
|
return rl.CheckCollisionBoxes(self.get_bounding_box(), other.get_bounding_box())
|
||||||
|
elif isinstance(other, Actor):
|
||||||
|
return self.check_collision(other.collision_sphere)
|
||||||
|
|
||||||
|
|
||||||
|
class Sphere(Shape):
|
||||||
|
def __init__(self, position, radius, color=RED, wires=True, wire_color=DARKGRAY):
|
||||||
|
self.pos = position
|
||||||
|
self.radius = radius
|
||||||
|
self.color = color
|
||||||
|
self.wire_color = wire_color
|
||||||
|
self.wires = wires
|
||||||
|
|
||||||
|
def draw(self):
|
||||||
|
rl.DrawSphere(self.pos, self.radius, self.color)
|
||||||
|
if self.wires:
|
||||||
|
rl.DrawSphereWires(self.pos, self.radius, 32, 32, self.wire_color)
|
||||||
|
|
||||||
|
def check_collision(self, other):
|
||||||
|
if isinstance(other, Sphere):
|
||||||
|
return rl.CheckCollisionSpheres(
|
||||||
|
self.pos, self.radius, other.pos, other.radius
|
||||||
|
)
|
||||||
|
elif isinstance(other, Box):
|
||||||
|
return rl.CheckCollisionBoxSphere(
|
||||||
|
other.get_bounding_box(), self.pos, self.radius
|
||||||
|
)
|
||||||
|
elif isinstance(other, Actor):
|
||||||
|
return self.check_collision(other.collision_sphere)
|
||||||
|
|
||||||
|
|
||||||
|
class Actor(Shape):
|
||||||
|
def __init__(self, model_file, position=Vector([0, 0, 0]), collision_radius=1, texture_file="",
|
||||||
|
rotation_axis=Vector([0, 1, 0]), rotation_angle=0, scale=Vector([1, 1, 1]), color=WHITE, wires=False,
|
||||||
|
wire_color=DARKGRAY):
|
||||||
|
#super().__init__(position, collision_radius, color, wires, wire_color)
|
||||||
|
|
||||||
|
self.pos = position
|
||||||
|
self.color = color
|
||||||
|
self.wire_color = wire_color
|
||||||
|
self.wires = wires
|
||||||
|
|
||||||
|
self.model_file = model_file
|
||||||
|
if texture_file == "":
|
||||||
|
texture_file = model_file + "_diffuse"
|
||||||
|
self.texture_file = texture_file
|
||||||
|
self.scale = scale
|
||||||
|
self.rotation_axis = rotation_axis
|
||||||
|
self.rotation_angle = rotation_angle
|
||||||
|
self.collision_radius = collision_radius
|
||||||
|
self.collision_sphere = Sphere(position, collision_radius, RED)
|
||||||
|
|
||||||
|
self.loaded = False
|
||||||
|
|
||||||
|
def load_data(self):
|
||||||
|
self.loaded = True
|
||||||
|
print("*** DATA_DIR=", data_dir)
|
||||||
|
self.model = rl.LoadModel((data_dir + self.model_file + '.obj').encode('utf-8'))
|
||||||
|
texture = rl.LoadTexture((data_dir + self.texture_file + '.png').encode('utf-8'))
|
||||||
|
self.model.materials[0].maps[rl.MAP_DIFFUSE].texture = texture
|
||||||
|
|
||||||
|
def calc_bounding_box(self):
|
||||||
|
bb = rl.MeshBoundingBox(self.model.meshes[0])
|
||||||
|
|
||||||
|
bb.min.x *= self.scale.x
|
||||||
|
bb.min.y *= self.scale.y
|
||||||
|
bb.min.z *= self.scale.z
|
||||||
|
bb.max.x *= self.scale.x
|
||||||
|
bb.max.y *= self.scale.y
|
||||||
|
bb.max.z *= self.scale.z
|
||||||
|
|
||||||
|
bb.min.x += self.pos.x
|
||||||
|
bb.min.y += self.pos.y
|
||||||
|
bb.min.z += self.pos.z
|
||||||
|
bb.max.x += self.pos.x
|
||||||
|
bb.max.y += self.pos.y
|
||||||
|
bb.max.z += self.pos.z
|
||||||
|
return bb
|
||||||
|
|
||||||
|
def calc_collision_sphere(self):
|
||||||
|
centre_x = (self.bounding_box.max.x + self.bounding_box.min.x)/2
|
||||||
|
centre_y = (self.bounding_box.max.y + self.bounding_box.min.y)/2
|
||||||
|
centre_z = (self.bounding_box.max.z + self.bounding_box.min.z)/2
|
||||||
|
sphere = Sphere((centre_x, centre_y, centre_z), self.collision_radius, RED)
|
||||||
|
return sphere
|
||||||
|
|
||||||
|
def draw(self):
|
||||||
|
if not self.loaded:
|
||||||
|
self.load_data()
|
||||||
|
self.bounding_box = self.calc_bounding_box()
|
||||||
|
self.collision_sphere = self.calc_collision_sphere()
|
||||||
|
rl.DrawModelEx(self.model, self.pos, self.rotation_axis, self.rotation_angle, self.scale, self.color)
|
||||||
|
if self.wires:
|
||||||
|
rl.DrawBoundingBox(self.bounding_box, self.wire_color)
|
||||||
|
self.collision_sphere.draw()
|
||||||
|
|
||||||
|
def check_collision(self, other):
|
||||||
|
return self.collision_sphere.check_collision(other)
|
||||||
|
|
||||||
|
def run():
|
||||||
|
screen_width = 800
|
||||||
|
screen_height = 450
|
||||||
|
title = "RayLibPyZero"
|
||||||
|
|
||||||
|
if hasattr(mod, "WIDTH"):
|
||||||
|
screen_width = mod.WIDTH
|
||||||
|
|
||||||
|
if hasattr(mod, "HEIGHT"):
|
||||||
|
screen_height = mod.HEIGHT
|
||||||
|
|
||||||
|
if hasattr(mod, "TITLE"):
|
||||||
|
title = mod.TITLE
|
||||||
|
|
||||||
|
if hasattr(mod, "DATA_DIR"):
|
||||||
|
global data_dir
|
||||||
|
data_dir = mod.DATA_DIR
|
||||||
|
|
||||||
|
rl.SetConfigFlags(rl.FLAG_VSYNC_HINT + rl.FLAG_MSAA_4X_HINT)
|
||||||
|
|
||||||
|
rl.InitWindow(screen_width, screen_height, title.encode('utf-8'))
|
||||||
|
|
||||||
|
rl.SetTargetFPS(60)
|
||||||
|
|
||||||
|
if hasattr(mod, "CAMERA"):
|
||||||
|
rl.SetCameraMode(camera, mod.CAMERA)
|
||||||
|
|
||||||
|
if hasattr(mod, "init"):
|
||||||
|
mod.init()
|
||||||
|
|
||||||
|
while not rl.WindowShouldClose():
|
||||||
|
if hasattr(mod, "update"):
|
||||||
|
mod.update()
|
||||||
|
rl.UpdateCamera(camera)
|
||||||
|
if rl.IsKeyPressed(rl.KEY_F):
|
||||||
|
rl.ToggleFullscreen()
|
||||||
|
if rl.IsKeyPressed(rl.KEY_ESCAPE):
|
||||||
|
rl.Exit()
|
||||||
|
rl.BeginDrawing()
|
||||||
|
rl.BeginMode3D(camera[0])
|
||||||
|
if hasattr(mod, "draw3d"):
|
||||||
|
mod.draw3d()
|
||||||
|
rl.EndMode3D()
|
||||||
|
if hasattr(mod, "draw2d"):
|
||||||
|
mod.draw2d()
|
||||||
|
if hasattr(mod, "draw"):
|
||||||
|
mod.draw()
|
||||||
|
rl.EndDrawing()
|
||||||
|
rl.CloseWindow()
|
||||||
|
|
||||||
|
|
||||||
|
class Keyboard:
|
||||||
|
def __getattr__(self, kname):
|
||||||
|
# return is a reserved word, so alias enter to return
|
||||||
|
if kname == 'enter':
|
||||||
|
kname = 'return'
|
||||||
|
kname = kname.upper()
|
||||||
|
if not kname.startswith("KEY_"):
|
||||||
|
kname = "KEY_" + kname
|
||||||
|
|
||||||
|
return rl.IsKeyDown(getattr(rl, kname))
|
||||||
|
|
||||||
|
|
||||||
|
keyboard = Keyboard()
|
50
test_richlib.py
Normal file
50
test_richlib.py
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
from raylib.richlib import *
|
||||||
|
|
||||||
|
WIDTH=800
|
||||||
|
HEIGHT=640
|
||||||
|
#CAMERA=CAMERA_FIRST_PERSON
|
||||||
|
DATA_DIR="examples/models/resources/models/"
|
||||||
|
|
||||||
|
player = Box((0, 10, 20), (10, 20, 10), GREEN)
|
||||||
|
enemy_box = Box((-40, 10, 0), (20, 20, 20), (70,70,70))
|
||||||
|
enemy_sphere = Sphere((40, 15, 0), 15, 'gray')
|
||||||
|
castle = Actor("castle", collision_radius=15)
|
||||||
|
castle.z=-50
|
||||||
|
castle.scale.y=2
|
||||||
|
castle.scale.x=1
|
||||||
|
castle.scale.z=1
|
||||||
|
|
||||||
|
#def init():
|
||||||
|
# set_camera_mode(camera, CAMERA_FIRST_PERSON)
|
||||||
|
|
||||||
|
def update():
|
||||||
|
if keyboard.right:
|
||||||
|
player.pos.x += 2
|
||||||
|
elif keyboard.left:
|
||||||
|
player.pos.x -= 2
|
||||||
|
elif keyboard.down:
|
||||||
|
player.pos.z += 2
|
||||||
|
elif keyboard.up:
|
||||||
|
player.pos.z -= 2
|
||||||
|
|
||||||
|
if player.check_collision(enemy_box) or player.check_collision(enemy_sphere) or player.check_collision(castle):
|
||||||
|
player.color = RED
|
||||||
|
else:
|
||||||
|
player.color = GREEN
|
||||||
|
|
||||||
|
|
||||||
|
def draw3d():
|
||||||
|
rl.ClearBackground(WHITE)
|
||||||
|
enemy_box.draw()
|
||||||
|
enemy_sphere.draw()
|
||||||
|
player.draw()
|
||||||
|
castle.draw()
|
||||||
|
rl.DrawGrid(10, 10)
|
||||||
|
|
||||||
|
|
||||||
|
def draw2d():
|
||||||
|
rl.DrawText(b"Move player with cursors to collide", 220, 40, 20, GRAY)
|
||||||
|
rl.DrawFPS(10, 10)
|
||||||
|
|
||||||
|
|
||||||
|
run()
|
Reference in a new issue