Skip to content

Commit

Permalink
Merge pull request #250 from PresentFoxz/master
Browse files Browse the repository at this point in the history
Adding Foxgine to the Arcade!
  • Loading branch information
masonova1 authored Jul 22, 2024
2 parents 147a3e8 + e1a259f commit 9532883
Show file tree
Hide file tree
Showing 6 changed files with 348 additions and 0 deletions.
54 changes: 54 additions & 0 deletions Foxgine/Cam.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
from math import *

class Cam:
def __init__(self, pos=(0, 0, 0), rot=(0, 0)):
self.pos = list(pos)
self.rot = list(rot)
self.style = 0
self.yVel = 0
self.falling = 0

def update(self, dt, buttons, objects):
s = dt * 10

if self.style == 0:
x, y = s * sin(self.rot[1]), s * cos(self.rot[1])
if buttons.buttonU.pressed():
self.pos[0] += x
self.pos[2] += y
if buttons.buttonD.pressed():
self.pos[0] -= x
self.pos[2] -= y
if buttons.buttonL.pressed():
self.pos[0] -= y
self.pos[2] += x
if buttons.buttonR.pressed():
self.pos[0] += y
self.pos[2] -= x

elif self.style == 1:
if buttons.buttonR.pressed():
self.rot[1] += 0.05
if buttons.buttonL.pressed():
self.rot[1] -= 0.05
if buttons.buttonU.pressed():
self.rot[0] += 0.05
if buttons.buttonD.pressed():
self.rot[0] -= 0.05

if buttons.buttonA.justPressed() and self.falling < 1:
print("Jump initiated!")
self.yVel = 0.8

self.yVel -= 0.1
self.pos[1] += self.yVel

if buttons.buttonB.justPressed():
self.style = (self.style + 1) % 2

self.falling += 1

if self.pos[1] <= 1:
self.falling = 0
self.yVel = 0
self.pos[1] = 1
109 changes: 109 additions & 0 deletions Foxgine/Foxgine.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import thumbyButton as buttons
from math import sin, cos, radians
import ujson
from sys import path as syspath
syspath.insert(0, '/Games/Foxgine')
from thumbyGrayscale import display
from Cam import Cam
from Obj3D import Object3D

w, h = 72, 40
cx, cy = w // 2, h // 2
fov = 50
dt = 1 / 30
rendType = 0
gameStart = 0
rendAmt = 2
objects = []

display.setFont("/lib/font3x5.bin", 3, 5, 1)
display.setFPS(30)

cam = Cam((0, 1, -5))
file_path = "/Games/Foxgine/models.txt"

try:
with open(file_path, "r") as file:
fileObjs = ujson.load(file)
except Exception as e:
print(f"Error loading JSON file: {e}")
fileObjs = {}

def makeObjs(fileObjs, rendType):
objMaker = []
objPos = [[0, 0, 0], [0, 0, 5], [0, 1, 0]]
combinedObjs = ["quad", "tri", "test"]

combined_verts = []
combined_polys = []

vert_offset = 0

for i, obj_name in enumerate(combinedObjs):
verts = fileObjs[obj_name]["Verticies"]
polys = fileObjs[obj_name]["Polygons"]
pos = objPos[i]

for vert in verts:
combined_verts.append([vert[0] + pos[0], vert[1] + pos[1], vert[2] + pos[2]])

for poly in polys:
adjusted_poly = [index + vert_offset if isinstance(index, int) else index for index in poly]
combined_polys.append(adjusted_poly)

vert_offset += len(verts)

fileObjs["combined"]["Verticies"] = combined_verts
fileObjs["combined"]["Polygons"] = combined_polys

print(fileObjs["combined"]["Verticies"])
print(fileObjs["combined"]["Polygons"])

objMaker.append(Object3D(fileObjs, "combined", (0, 0, 0), rendType))
objMaker.append(Object3D(fileObjs, "tris", (0, 3, 0), rendType))

for obj_name in combinedObjs:
fileObjs[obj_name]["Verticies"].clear()
fileObjs[obj_name]["Polygons"].clear()

objPos.clear()
combinedObjs.clear()

return objMaker

def distance(obj, cam):
dx = obj.pos[0] - cam.pos[0]
dy = obj.pos[1] - cam.pos[1]
dz = obj.pos[2] - cam.pos[2]
return dx * dx + dy * dy + dz * dz

while True:
display.update()
display.fill(0)

if gameStart == 1:
objects.sort(key=lambda obj: distance(obj, cam), reverse=True)
for obj in objects:
obj.render(fov, (w, h), (cx, cy), cam, -1, 20)

cam.update(dt, buttons, objects)

display.drawText("X: " + str(int(cam.pos[0])), 2, 2, 2)
display.drawText("Y: " + str(int(cam.pos[1])), 2, 8, 2)
display.drawText("Z: " + str(int(cam.pos[2])), 35, 8, 2)
display.drawText("Style: " + str(cam.style), 35, 2, 2)
elif gameStart == 0:
display.drawText("Press A for...", 10, 3, 1)
display.drawText("Filled Polys!", 10, 10, 2)

display.drawText("Press B for...", 10, 26, 1)
display.drawText("Lined Polys!", 10, 33, 2)

if buttons.buttonA.justPressed():
rendType = 1
gameStart = 1
objects = makeObjs(fileObjs, rendType)
if buttons.buttonB.justPressed():
rendType = 0
gameStart = 1
objects = makeObjs(fileObjs, rendType)
127 changes: 127 additions & 0 deletions Foxgine/Obj3D.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import ujson
from thumbyGrayscale import display
from math import *

class Object3D:
def __init__(self, fileObjs, model_name, pos, rendType):
self.models = fileObjs
self.model_name = model_name
self.pos = pos
self.vert_list = []
self.screen_coords = []
self.rendType = rendType
self.skip = 0

def render(self, fov, w_h, center, cam, min_depth, max_depth):
verts = self.models[self.model_name]["Verticies"]
faces = self.models[self.model_name]["Polygons"]

self.vert_list.clear()
self.screen_coords.clear()

for x, y, z in verts:
x += self.pos[0]
y += self.pos[1]
z += self.pos[2]

x, z = rotate2D((x - cam.pos[0], z - cam.pos[2]), cam.rot[1])
y, z = rotate2D((y - cam.pos[1], z), cam.rot[0])

if z == 0:
z += 0.01

f = fov / z
x, y = x * f, y * f
self.screen_coords.append((center[0] + int(x), center[1] - int(y), z))
self.vert_list.append((x, y, z))

for face in faces:
if len(face) < 4:
continue

color = face[-2]
cull_flag = face[-1]

face1 = face[:3]
face2 = [face[0], face[2], face[3]]

def process_face(face_part):
vertices = [self.screen_coords[i] for i in face_part]

if cull_flag == 1:
v0 = self.vert_list[face_part[0]]
v1 = self.vert_list[face_part[1]]
v2 = self.vert_list[face_part[2]]
normal = compute_normal(v0, v1, v2)
if normal[2] >= 0:
return

on_screen = all(min_depth < self.vert_list[i][2] < max_depth and
-150 <= vertices[i][0] < (w_h[0] + 100) and
-150 <= vertices[i][1] < (w_h[1] + 100) for i in range(3))

if on_screen:
if self.rendType == 0:
self.draw_edges(vertices, color)
if self.rendType == 1:
self.fill_polygon(vertices, color)

process_face(face1)
if len(face) > 5:
process_face(face2)

def draw_edges(self, vertices, color):
for i in range(len(vertices)):
x0, y0, _ = vertices[i]
x1, y1, _ = vertices[(i + 1) % len(vertices)]
self.draw_line(x0, y0, x1, y1, color)

def fill_polygon(self, vertices, color):
vertices = sorted(vertices, key=lambda v: v[1])

if len(vertices) < 3:
return

min_y = max(int(vertices[0][1]), 0)
max_y = min(int(vertices[-1][1]), display.height - 1)

for y in range(min_y, max_y, 2):
intersections = []

for i in range(len(vertices)):
x1, y1, _ = vertices[i]
x2, y2, _ = vertices[(i + 1) % len(vertices)]

if y1 <= y < y2 or y2 <= y < y1:
if y2 != y1:
x_inter = x1 + (y - y1) * (x2 - x1) / (y2 - y1)
intersections.append(x_inter)

if len(intersections) < 2:
continue

intersections.sort()
for j in range(0, len(intersections), 2):
x_start = max(int(intersections[j]), 0)
x_end = min(int(intersections[j + 1]), display.width - 1)
for x in range(x_start, x_end, 1):
display.setPixel(x, y, color)

def draw_line(self, x0, y0, x1, y1, color):
display.drawLine(int(x0), int(y0), int(x1), int(y1), color)

def distance_from_player(self, player_pos):
dx = self.pos[0] - player_pos[0]
dz = self.pos[2] - player_pos[2]
return sqrt(dx * dx + dz * dz)

def rotate2D(pos, rad):
x, y = pos
s, c = sin(rad), cos(rad)
return x * c - y * s, y * c + x * s

def compute_normal(v0, v1, v2):
u = (v1[0] - v0[0], v1[1] - v0[1], v1[2] - v0[2])
v = (v2[0] - v0[0], v2[1] - v0[1], v2[2] - v0[2])
normal = (u[1] * v[2] - u[2] * v[1], u[2] * v[0] - u[0] * v[2], u[0] * v[1] - u[1] * v[0])
return normal
7 changes: 7 additions & 0 deletions Foxgine/arcade_description.txt.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
A simple 3D engine that was made to be able to render out files similar to an obj

Author: PresentFox
Version: 1.0
License: Open Source ( please tag me if you use this engine! )

Thank you: Kada, Openmindedness, Demod ( for giving me advice and tips on 3D stuff! )
Binary file added Foxgine/arcade_title_video.webm.webm
Binary file not shown.
51 changes: 51 additions & 0 deletions Foxgine/models.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"quad": {
"Verticies": [
[0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0],
[0, 0, 1], [1, 0, 1], [1, 1, 1], [0, 1, 1]
],
"Polygons": [
[3, 2, 1, 0, 1, 1], [4, 5, 6, 7, 3, 1], [0, 1, 5, 4, 1, 1],
[1, 2, 6, 5, 1, 1], [2, 3, 7, 6, 2, 1], [3, 0, 4, 7, 3, 1]
]
}

"tri": {
"Verticies": [
[0, 0, 0], [1, 0, 0], [1, 1, 0],
[0, 1, 0], [0, 0, 1], [1, 0, 1]
],
"Polygons": [
[0, 1, 2, 1, 0],
[3, 4, 5, 2, 0]
]
}

"tris": {
"Verticies": [
[0, 0, 0], [1, 0, 0], [1, 1, 0],
[0, 1, 0], [0, 0, 1], [1, 0, 1]
],
"Polygons": [
[0, 1, 2, 1, 0],
[3, 4, 5, 2, 0]
]
}

"test": {
"Verticies": [
[0, 0, 0], [1, 0, 0], [1, 1, 0],
[0, 1, 0], [0, 0, 1], [1, 0, 1]
],
"Polygons": [
[0, 1, 2, 3, 1, 0],
[3, 4, 5, 1, 3, 0],
[3, 4, 0, 2, 0]
]
}

"combined": {
"Verticies": [],
"Polygons": []
}
}

0 comments on commit 9532883

Please sign in to comment.