Compare commits

..

2 Commits

4 changed files with 245 additions and 5 deletions

27
Diagrams.org Normal file
View File

@ -0,0 +1,27 @@
* The topics
#+begin_src syntree
("Game Programming Fundamentals"
("Math" "_:Data Structures" "_:Algorithms" "_:Linear Algebra")
("Engineering"
("Machine Architecture" "_:CPU Design" "_:Memory Hierarchy" "_:Processes" "_:Concurrency")
"_:Networking"
"_:Compilers"
("Operating Systems" "_:Scheduling" "_:File Systems" "_:Virtual Memory")))
#+end_src
#+RESULTS:
#+begin_example
Game Programming Fundamentals
._________________________________________|_________________________________________.
| |
Math Engineering
.______________|_____________. .________________________________._|________._________________________.
| | | | | | |
.______|______. .____|___. .______|_____. Machine Architecture .____|___. .___|___. Operating Systems
|_____________| |________| |____________| .______________._____|_______.___________. |________| |_______| .____________.|_____________.
Data Structures Algorithms Linear Algebra | | | | Networking Compilers | | |
.____|___. ._______|______. .___|___. .____|____. .____|___. ._____|____. .______|_____.
|________| |______________| |_______| |_________| |________| |__________| |____________|
CPU Design Memory Hierarchy Processes Concurrency Scheduling File Systems Virtual Memory
#+end_example

View File

@ -24,16 +24,18 @@ class Ball:
@dataclass @dataclass
class QNode: class QNode:
aabb: Rect aabb: Rect
points: List = field(default_factory=list) points: List[Tuple[float, float]] = field(default_factory=list)
@dataclass @dataclass
class Quadtree: class Quadtree:
node: QNode node: QNode
subdivided = False subdivided = False
direction: str = ''
nw: Optional['Quadtree'] = None nw: Optional['Quadtree'] = None
ne: Optional['Quadtree'] = None ne: Optional['Quadtree'] = None
sw: Optional['Quadtree'] = None sw: Optional['Quadtree'] = None
se: Optional['Quadtree'] = None se: Optional['Quadtree'] = None
parent: Optional['Quadtree'] = None
@dataclass @dataclass
class World: class World:
@ -51,10 +53,10 @@ def qt_split(qt: Quadtree):
ne = Rect(x + hw, y , hw, hh) ne = Rect(x + hw, y , hw, hh)
sw = Rect(x , y + hh, hw, hh) sw = Rect(x , y + hh, hw, hh)
se = Rect(x + hw, y + hh, hw, hh) se = Rect(x + hw, y + hh, hw, hh)
qt.nw = Quadtree(QNode(nw)) qt.nw = Quadtree(QNode(nw), parent=qt, direction='NW')
qt.ne = Quadtree(QNode(ne)) qt.ne = Quadtree(QNode(ne), parent=qt, direction='NE')
qt.sw = Quadtree(QNode(sw)) qt.sw = Quadtree(QNode(sw), parent=qt, direction='SW')
qt.se = Quadtree(QNode(se)) qt.se = Quadtree(QNode(se), parent=qt, direction='SE')
qt.subdivided = True qt.subdivided = True
def qt_insert(qt: Quadtree, p): def qt_insert(qt: Quadtree, p):
@ -82,6 +84,82 @@ def qt_insert(qt: Quadtree, p):
qt.node.points.append(p) qt.node.points.append(p)
return True return True
def qt_find_nearest_point(qt: Quadtree, point) -> Tuple[float, float]:
closest_point = None
closest_dist = None
last_direction = None
containing_qt = qt
# Find the containing subnode
while containing_qt.subdivided:
if RL.check_collision_point_rec(point, qt.nw.node.aabb):
containing_qt = qt.nw
elif RL.check_collision_point_rec(point, qt.ne.node.aabb):
containing_qt = qt.ne
elif RL.check_collision_point_rec(point, qt.sw.node.aabb):
containing_qt = qt.sw
elif RL.check_collision_point_rec(point, qt.se.node.aabb):
containing_qt = qt.se
while containing_qt.parent is not None:
# If it's greater than 1, then we have a point inside we can compare to
if len(containing_qt.node.points) > 1:
for p in qt.node.points:
if p == point:
continue
if closest_dist is None or RL.vector_2distance(Vec2(*point), Vec2(*p)) < closest_dist:
closest_point = p
last_direction = containing_qt.direction
containing_qt = containing_qt.parent
else:
# If there aren't any other points in here, then we can't create a
# closest_point or a closest_dist. We would have to handle that later on
if not containing_qt.subdivided:
last_direction = containing_qt.direction
containing_qt = containing_qt.parent
else:
# def search_for_nearest(child_qt: Quadtree):
# We have to generalize this code, most likely, because it feels like
# we have to do this recursively until we have exhausted all quadrants
px, py = point
# This is where we check the surrounding nodes and try to discard nodes
if last_direction == 'NW':
xse, yse = containing_qt.se.node.aabb.x, containing_qt.se.node.aabb.y
ne_dist = containing_qt.ne.node.aabb.x - px
if ne_dist < closest_dist:
closest_dist = True
# Now we have to search inside, but we would have to do recursively
pass
sw_dist = containing_qt.sw.node.aabb.y - py
se_dist = RL.vector_2distance(Vec2(*point), Vec2(xse, yse))
assert se_dist >= 0, 'ITS LESS THAN 0!!!!'
if last_direction == 'NE':
xsw, ysw = containing_qt.sw.node.aabb.x, containing_qt.sw.node.aabb.y
nw_dist = px - containing_qt.nw.node.aabb.x
sw_dist = RL.vector_2distance(Vec2(xsw, ysw), Vec2(*point))
assert sw_dist >= 0, 'ITS LESS THAN 0!!!!'
se_dist = containing_qt.se.node.aabb.y - py
if last_direction == 'SW':
xne, yne = containing_qt.ne.node.aabb.x, containing_qt.ne.node.aabb.y
nw_dist = px - containing_qt.nw.node.aabb.x
ne_dist = RL.vector_2distance(Vec2(xne, yne), Vec2(*point))
assert ne_dist >= 0, 'ITS LESS THAN 0!!!!'
se_dist = containing_qt.se.node.aabb.x - px
if last_direction == 'SE':
xnw, ynw = containing_qt.nw.node.aabb.x, containing_qt.nw.node.aabb.y
nw_dist = RL.vector_2distance(Vec2(xnw, ynw), Vec2(*point))
ne_dist = py - containing_qt.nw.node.aabb.y
assert ne_dist >= 0, 'ITS LESS THAN 0!!!!'
sw_dist = px - containing_qt.se.node.aabb.x
last_direction = containing_qt.direction
containing_qt = containing_qt.parent
def construct_quadtree(points): def construct_quadtree(points):
root_node = QNode(Rect(0, 0, screen_width, screen_height)) root_node = QNode(Rect(0, 0, screen_width, screen_height))
qt = Quadtree(root_node) qt = Quadtree(root_node)

96
skilltree.py Normal file
View File

@ -0,0 +1,96 @@
import pyray as RL
from pyray import (Rectangle as Rect, Vector2 as Vec2)
import math
import pdb
import random
from typing import Optional, Tuple, List
from dataclasses import dataclass, field
screen_width = 1280
screen_height = 1024
node_width = 200
node_height = 60
node_font_height = 24
default_font = RL.get_font_default()
@dataclass
class Node:
text: str
rect: Rect
@dataclass
class World:
nodes: List[Node]
dragging_node: Optional[Tuple[Node, Tuple[float, float]]] = None
global w
def init():
global w
nodes = [Node("Node1",Rect(50,50,node_width,node_height)),Node("Node2",Rect(150,150,node_width,node_height))]
w = World(nodes)
def player_input():
if RL.is_mouse_button_pressed(0):
w.dragging_node = None
for node in w.nodes:
mouse_pos = RL.get_mouse_position()
if RL.check_collision_point_rec(mouse_pos, node.rect):
w.dragging_node = node, (node.rect.x - mouse_pos.x, node.rect.y - mouse_pos.y)
break
if RL.is_mouse_button_released(0):
w.dragging_node = None
if w.dragging_node:
node, offset_x, offset_y = w.dragging_node[0], *w.dragging_node[1]
mouse_pos = RL.get_mouse_position()
node.rect.x, node.rect.y = mouse_pos.x + offset_x, mouse_pos.y + offset_y
def update():
pass
def draw():
RL.begin_drawing()
RL.clear_background(RL.RAYWHITE)
for node in w.nodes:
rect_offset = Rect(node.rect.x + 2, node.rect.y + 2, node.rect.width, node.rect.height)
RL.draw_rectangle_lines_ex(rect_offset, 2, RL.BLACK)
RL.draw_rectangle_rec(node.rect, RL.WHITE)
RL.draw_rectangle_lines_ex(node.rect, 1, RL.BLACK)
text_width = RL.measure_text(node.text, node_font_height)
pos = Vec2(
node.rect.x + node.rect.width / 2 - text_width / 2,
node.rect.y + node.rect.height / 2 - node_font_height / 2,
)
RL.draw_text_ex(default_font, node.text, pos, node_font_height, 1, RL.BLACK)
node1 = w.nodes[0]
node2 = w.nodes[1]
start_pos = Vec2(node1.rect.x + node1.rect.width // 2, node1.rect.y + node1.rect.height)
end_pos = Vec2(node2.rect.x + node2.rect.width // 2, node2.rect.y)
# RL.draw_line_bezier(start_pos, end_pos, 3, RL.BLUE)
# c1 = start_pos
# c1.x += 50
# c1.y += 50
# c2 = end_pos
# c2.y -= 50
mid_point = RL.vector2_subtract(end_pos, start_pos)
mid_control = RL.vector2_add(mid_point, Vec2(50,50))
points = [start_pos, start_pos, mid_point, mid_control, end_pos, end_pos]
# points = [start_pos, c1, c2, mid_point, end_pos]
RL.draw_spline_bezier_cubic(points, 6, 3, RL.BLUE)
RL.end_drawing()
RL.init_window(screen_width, screen_height, "Skilltree");
RL.set_target_fps(60)
init()
while not RL.window_should_close():
player_input()
update()
draw()

39
starter.py Normal file
View File

@ -0,0 +1,39 @@
import pyray as RL
from pyray import (Rectangle as Rect)
import math
import pdb
import random
from typing import Optional, Tuple, List
from dataclasses import dataclass, field
screen_width = 1280
screen_height = 1024
@dataclass
class World:
pass
def init():
pass
def player_input():
pass
def update():
pass
def draw():
RL.begin_drawing()
RL.clear_background(RL.WHITE)
RL.end_drawing()
RL.init_window(screen_width, screen_height, "Starter");
RL.set_target_fps(60)
init()
while not RL.window_should_close():
player_input()
update()
draw()