366 lines
9.1 KiB
Python
Executable file
366 lines
9.1 KiB
Python
Executable file
""" Richlib, simple access to Raylib
|
|
"""
|
|
__version__ = '0.1'
|
|
|
|
from ..static import ffi, rl, prl
|
|
#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
|
|
|
|
@property
|
|
def w(self):
|
|
return self[3]
|
|
|
|
@w.setter
|
|
def w(self, value):
|
|
self[3] = value
|
|
|
|
class Color(list):
|
|
def __init__(self, s):
|
|
if isinstance(s, str):
|
|
super().__init__(globals()[s.upper()])
|
|
else:
|
|
super().__init__(s)
|
|
if len(self) == 3:
|
|
self.append(255)
|
|
|
|
@property
|
|
def r(self):
|
|
return self[0]
|
|
|
|
@r.setter
|
|
def r(self, value):
|
|
self[0] = value
|
|
|
|
@property
|
|
def g(self):
|
|
return self[1]
|
|
|
|
@g.setter
|
|
def g(self, value):
|
|
self[1] = value
|
|
|
|
@property
|
|
def b(self):
|
|
return self[2]
|
|
|
|
@b.setter
|
|
def b(self, value):
|
|
self[2] = value
|
|
|
|
@property
|
|
def a(self):
|
|
return self[3]
|
|
|
|
@a.setter
|
|
def a(self, value):
|
|
self[3] = value
|
|
|
|
|
|
def clear(color=BLACK):
|
|
rl.ClearBackground(Color(color))
|
|
|
|
|
|
class Shape:
|
|
@property
|
|
def color(self):
|
|
return self._color
|
|
|
|
@color.setter
|
|
def color(self, value):
|
|
self._color = 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):
|
|
self._wire_color = 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
|
|
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):
|
|
#print("draw color ",self.color)
|
|
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()
|