Compare commits
2 Commits
eb1d7fd0b9
...
d8f5dee46d
| Author | SHA1 | Date | |
|---|---|---|---|
| d8f5dee46d | |||
| e75be484cd |
@ -1,7 +1,7 @@
|
||||
|
||||
# 🟢 Yelbegen - Zig Oyun Motoru
|
||||
|
||||
**Yelbegen**, öğrenme ve deney amaçlı olarak geliştirilen **modüler bir oyun motoru**dur.
|
||||
**Yelbegen**, öğrenme ve deney amaçlı olarak geliştirilen **modüler bir simülatör motoru**dur.
|
||||
Motor, **Zig** programlama dili kullanılarak yazılmakta ve Raylib ile RayGUI kütüphanelerini kullanmaktadır.
|
||||
|
||||
---
|
||||
|
||||
44
build.zig
44
build.zig
@ -74,6 +74,24 @@ pub fn build(b: *std.Build) void {
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
const mod4 = b.addModule("InputOps", .{
|
||||
// The root source file is the "entry point" of this module. Users of
|
||||
// this module will only be able to access public declarations contained
|
||||
// in this file, which means that if you have declarations that you
|
||||
// intend to expose to consumers that were defined in other files part
|
||||
// of this module, you will have to make sure to re-export them from
|
||||
// the root file.
|
||||
.root_source_file = b.path("src/input/base_input.zig"),
|
||||
// Later on we'll use this module as the root module of a test executable
|
||||
// which requires us to specify a target.
|
||||
.target = target,
|
||||
.imports = &.{
|
||||
.{.name = "raylib", .module = raylib},
|
||||
.{.name = "Cam", .module = mod2},
|
||||
},
|
||||
});
|
||||
|
||||
const mod3 = b.addModule("GuiOps", .{
|
||||
// The root source file is the "entry point" of this module. Users of
|
||||
// this module will only be able to access public declarations contained
|
||||
@ -88,6 +106,26 @@ pub fn build(b: *std.Build) void {
|
||||
.imports = &.{
|
||||
.{.name = "raylib", .module = raylib},
|
||||
.{.name = "raygui", .module = raygui},
|
||||
.{ .name= "InputOps", .module = mod4 },
|
||||
},
|
||||
});
|
||||
|
||||
const mod5 = b.addModule("BaseDraw", .{
|
||||
// The root source file is the "entry point" of this module. Users of
|
||||
// this module will only be able to access public declarations contained
|
||||
// in this file, which means that if you have declarations that you
|
||||
// intend to expose to consumers that were defined in other files part
|
||||
// of this module, you will have to make sure to re-export them from
|
||||
// the root file.
|
||||
.root_source_file = b.path("src/graphics/base_drawers.zig"),
|
||||
// Later on we'll use this module as the root module of a test executable
|
||||
// which requires us to specify a target.
|
||||
.target = target,
|
||||
.imports = &.{
|
||||
.{.name = "raylib", .module = raylib},
|
||||
.{.name = "raygui", .module = raygui},
|
||||
.{ .name= "InputOps", .module = mod4 },
|
||||
.{ .name= "Cam", .module = mod2 },
|
||||
},
|
||||
});
|
||||
|
||||
@ -129,8 +167,10 @@ pub fn build(b: *std.Build) void {
|
||||
// can be extremely useful in case of collisions (which can happen
|
||||
// importing modules from different packages).
|
||||
.{ .name = "Drawers", .module = mod },
|
||||
.{ .name = "Cam", .module = mod2},
|
||||
.{ .name="Gui", .module = mod3},
|
||||
.{ .name = "Cam", .module = mod2 },
|
||||
.{ .name= "Gui", .module = mod3 },
|
||||
.{ .name= "InputOps", .module = mod4 },
|
||||
.{ .name= "BaseDraw", .module = mod5 },
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
@ -1,5 +1,34 @@
|
||||
const std = @import("std");
|
||||
const rl = @import("raylib");
|
||||
const cm = @import("Cam");
|
||||
const b_inp = @import("InputOps");
|
||||
|
||||
|
||||
pub fn add(a : f32, b : f32) f32 {
|
||||
return a + b;
|
||||
}
|
||||
// Raylib döngüsünde kullanmak için çizim fonksiyonu
|
||||
pub fn drawShapes(shapes : *std.ArrayList(b_inp.Shape)) void {
|
||||
for (shapes.items, 0..) |shape, index| {
|
||||
// Seçili nesneyi işaretle
|
||||
if (b_inp.selected_shape_index) |sel_index| {
|
||||
if (index == sel_index) {
|
||||
// Seçili nesnenin sınırlarını çiz
|
||||
switch (shape.data) {
|
||||
.cube => |d| {
|
||||
//const box = getBoundingBoxForCube(shape.position, d.width, d.height, d.length);
|
||||
//rl.drawCubeWiresV(box.min, box.max, .yellow);
|
||||
rl.drawCubeWires(shape.position, d.width + 0.5, d.height + 0.5, d.length + 0.5, .green);
|
||||
},
|
||||
.sphere => |d| rl.drawSphereWires(shape.position, d.radius + 0.5, 16, 16, .green),
|
||||
.cylinder => |d| rl.drawCylinderWires(shape.position, d.radius + 0.5, d.radius + 0.5, d.height, 10, .green),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Asıl nesneyi çiz
|
||||
switch (shape.data) {
|
||||
.cube => |d| rl.drawCubeV(shape.position, rl.Vector3.init(d.width, d.height, d.length), shape.color),
|
||||
.sphere => |d| rl.drawSphere(shape.position, d.radius, shape.color),
|
||||
.cylinder => |d| rl.drawCylinder(shape.position, d.radius, d.radius, d.height, 10, shape.color),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,30 +1,62 @@
|
||||
const gui = @import("raygui");
|
||||
const rl = @import("raylib");
|
||||
const std = @import("std");
|
||||
const io = @import("InputOps");
|
||||
|
||||
pub var is_cursor_hidden: bool = undefined;
|
||||
|
||||
pub const GUI = struct {
|
||||
pos : rl.Rectangle,
|
||||
gui_pos : rl.Rectangle,
|
||||
height: f32,
|
||||
width: f32,
|
||||
guiPos: rl.Rectangle,
|
||||
|
||||
pub fn init(pos : rl.Rectangle) GUI {
|
||||
var Gui__ = GUI {
|
||||
.pos = pos,
|
||||
.gui_pos = rl.Rectangle.init(0, 0, 0, 0),
|
||||
pub fn init(width_: f32, height_: f32) GUI {
|
||||
var Gui__ = GUI{
|
||||
.height = height_,
|
||||
.width = width_,
|
||||
.guiPos = rl.Rectangle.init(0, 0, 0, 0),
|
||||
};
|
||||
|
||||
Gui__.addRightSide();
|
||||
return Gui__;
|
||||
}
|
||||
|
||||
fn addRightSide(self : *GUI) void {
|
||||
self.gui_pos.height = self.pos.height;
|
||||
self.gui_pos.width = self.pos.width / 4;
|
||||
self.gui_pos.x = self.pos.x/4 * 3;
|
||||
self.gui_pos.y = 0;
|
||||
fn addRightSide(self: *GUI) void {
|
||||
// menü ekranın sağında olmalıdır ve absolute bir
|
||||
// pozisyondan kaçınır
|
||||
self.guiPos.height = self.height;
|
||||
self.guiPos.width = self.width / 4.0;
|
||||
self.guiPos.x = self.width / 4.0 * 3.0;
|
||||
self.guiPos.y = 0.0;
|
||||
|
||||
//gui pos sağ menunun güncel halidir
|
||||
}
|
||||
|
||||
pub fn draw(self : *GUI) void {
|
||||
pub fn draw(self: *GUI, shapes : std.ArrayList(io.Shape)) void {
|
||||
//panel
|
||||
rl.drawRectangleRec(self.gui_pos, .dark_gray);
|
||||
rl.drawRectangleRec(self.guiPos, .red);
|
||||
try self.objects(shapes);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
pub fn objects(self: *GUI, shapes: std.ArrayList(io.Shape)) !void {
|
||||
const button_height: f32 = 25; // Her düğmenin yüksekliği
|
||||
const button_spacing: f32 = 5; // Düğmeler arası boşluk
|
||||
|
||||
for (shapes.items, 0..) |shape, i| {
|
||||
// Her düğme için pozisyon hesapla
|
||||
const button_positions = rl.Rectangle.init(
|
||||
self.guiPos.x + 15,
|
||||
self.guiPos.y + 15 + (@as(f32, @floatFromInt(i)) * (button_height + button_spacing)),
|
||||
self.guiPos.width - 30, // Genişlik
|
||||
button_height,
|
||||
);
|
||||
|
||||
// GuiButton kullanarak şekil adını yazdır
|
||||
// GuiButton, tıklanırsa true, tıklanmazsa false döner
|
||||
if (gui.button(button_positions, shape.name)) {
|
||||
std.debug.print("Seçilen şekil: {s}, ID: {}\n", .{shape.name, shape.id});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@ -0,0 +1,180 @@
|
||||
const std = @import("std");
|
||||
const rl = @import("raylib");
|
||||
const cm = @import("Cam");
|
||||
|
||||
|
||||
pub var is_object_dragging : bool = undefined; // drag işlemi için gerekli
|
||||
pub var freeMode = false;
|
||||
pub var count_id : usize = 0; // bu değişken anlık id'yi tutar
|
||||
|
||||
// ışın ve ışına bağlı çarpışma ray ve raycollison değişkenleri ile yapılır.
|
||||
pub var selected_shape_index:?usize = 0;
|
||||
|
||||
pub const ShapeType = enum {
|
||||
cube,
|
||||
rectangle,
|
||||
sphere,
|
||||
cylinder,
|
||||
}; //tipler
|
||||
|
||||
pub const Shape = struct {
|
||||
id : usize = 0,
|
||||
name : [:0]const u8,
|
||||
position: rl.Vector3,
|
||||
color: rl.Color,
|
||||
|
||||
data: union(enum) {
|
||||
// 'box' terimi hem küpü hem de dikdörtgen prizmayı kapsar
|
||||
cube: struct {
|
||||
width: f32,
|
||||
height: f32,
|
||||
length: f32,
|
||||
},
|
||||
sphere: struct {
|
||||
radius: f32,
|
||||
},
|
||||
cylinder: struct {
|
||||
radius: f32,
|
||||
height: f32,
|
||||
},
|
||||
},
|
||||
|
||||
pub fn initCube(position: rl.Vector3, color: rl.Color, width: f32, height: f32, length: f32) Shape {
|
||||
count_id += 1;
|
||||
return Shape{
|
||||
.id = count_id,
|
||||
.name = "count_id",
|
||||
.position = position,
|
||||
.color = color,
|
||||
.data = .{ .cube = .{ .width = width, .height = height, .length = length } },
|
||||
};
|
||||
}
|
||||
|
||||
// Küre için özel init metodu
|
||||
pub fn initSphere(position: rl.Vector3, color: rl.Color, radius: f32) Shape {
|
||||
count_id += 1;
|
||||
return Shape{
|
||||
.id = count_id,
|
||||
.name= "count_id",
|
||||
.position = position,
|
||||
.color = color,
|
||||
.data = .{ .sphere = .{ .radius = radius } },
|
||||
};
|
||||
}
|
||||
|
||||
// Silindir için özel init metodu
|
||||
pub fn initCylinder(position: rl.Vector3, color: rl.Color, radius: f32, height: f32) Shape {
|
||||
count_id += 1;
|
||||
return Shape{
|
||||
.id = count_id,
|
||||
.name = "count_id",
|
||||
.position = position,
|
||||
.color = color,
|
||||
.data = .{ .cylinder = .{ .radius = radius, .height = height } },
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
pub fn findClosestHitObject(
|
||||
mouse_position: rl.Vector2,
|
||||
camera: rl.Camera3D,
|
||||
shapes: *std.ArrayList(Shape),
|
||||
) void {
|
||||
// Fare tuşuna basılıyorsa kontrol et
|
||||
if (!rl.isMouseButtonPressed(.left)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ray = rl.getScreenToWorldRay(mouse_position, camera);
|
||||
|
||||
var closest_hit_index: ?usize = null;
|
||||
var closest_distance = std.math.floatMax(f32);
|
||||
|
||||
for (shapes.items, 0..) |shape, index| {
|
||||
var hit_info = rl.RayCollision{.hit = false, .distance = 0.0,
|
||||
.normal = rl.Vector3.init(0, 0, 0),
|
||||
.point = rl.Vector3.init(0, 0, 0)};
|
||||
|
||||
switch (shape.data) {
|
||||
.cube => |cube_data| {
|
||||
const box = getBoundingBoxForCube(shape.position,
|
||||
cube_data.width, cube_data.height, cube_data.length);
|
||||
hit_info = rl.getRayCollisionBox(ray, box);
|
||||
},
|
||||
.sphere => |sphere_data| {
|
||||
hit_info = rl.getRayCollisionSphere(ray, shape.position, sphere_data.radius);
|
||||
},
|
||||
.cylinder => |cylinder_data| {
|
||||
// Performans için BoundingBox çarpışma testini kullan
|
||||
const box = getBoundingBoxForCylinder(shape.position, cylinder_data.radius, cylinder_data.height);
|
||||
hit_info = rl.getRayCollisionBox(ray, box);
|
||||
},
|
||||
}
|
||||
|
||||
if (hit_info.hit and hit_info.distance < closest_distance) {
|
||||
closest_hit_index = index;
|
||||
closest_distance = hit_info.distance;
|
||||
}
|
||||
}
|
||||
|
||||
selected_shape_index = closest_hit_index;
|
||||
}
|
||||
|
||||
|
||||
pub fn inputControls() void {
|
||||
|
||||
if (rl.isMouseButtonPressed(.right)) {
|
||||
freeMode = !freeMode;
|
||||
if (freeMode) {
|
||||
rl.disableCursor();
|
||||
} else {
|
||||
rl.enableCursor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn getBoundingBoxForCube(position: rl.Vector3, width: f32, height: f32, length: f32) rl.BoundingBox {
|
||||
// Nesnenin boyutlarının yarısını hesapla
|
||||
const half_width = width / 2.0;
|
||||
const half_height = height / 2.0;
|
||||
const half_length = length / 2.0;
|
||||
|
||||
// Minimum köşeyi (sol alt arka) hesapla
|
||||
const min_x = position.x - half_width;
|
||||
const min_y = position.y - half_height;
|
||||
const min_z = position.z - half_length;
|
||||
|
||||
// Maksimum köşeyi (sağ üst ön) hesapla
|
||||
const max_x = position.x + half_width;
|
||||
const max_y = position.y + half_height;
|
||||
const max_z = position.z + half_length;
|
||||
|
||||
return rl.BoundingBox{
|
||||
.min = rl.Vector3.init(min_x, min_y, min_z),
|
||||
.max = rl.Vector3.init(max_x, max_y, max_z),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
pub fn getBoundingBoxForCylinder(position: rl.Vector3, radius: f32, height: f32) rl.BoundingBox {
|
||||
// Yüksekliğin yarısını hesapla
|
||||
const half_height = height / 2.0;
|
||||
|
||||
// Minimum köşe noktasını (min x, min y, min z) hesapla
|
||||
const min_x = position.x - radius;
|
||||
const min_y = position.y - half_height;
|
||||
const min_z = position.z - radius;
|
||||
|
||||
// Maksimum köşe noktasını (max x, max y, max z) hesapla
|
||||
const max_x = position.x + radius;
|
||||
const max_y = position.y + half_height;
|
||||
const max_z = position.z + radius;
|
||||
|
||||
// BoundingBox yapısını döndür
|
||||
return rl.BoundingBox{
|
||||
.min = rl.Vector3.init(min_x, min_y, min_z),
|
||||
.max = rl.Vector3.init(max_x, max_y, max_z),
|
||||
};
|
||||
}
|
||||
68
src/main.zig
68
src/main.zig
@ -1,54 +1,78 @@
|
||||
const std = @import("std");
|
||||
const rl = @import("raylib");
|
||||
const gi = @import("raygui");
|
||||
const gr = @import("Drawers");
|
||||
const drw = @import("BaseDraw");
|
||||
const cm = @import("Cam");
|
||||
const panel = @import("Gui");
|
||||
const io = @import("InputOps");
|
||||
|
||||
var text: [:0]u8 = undefined;
|
||||
const screen_width = 1920;
|
||||
const screen_height = 1080;
|
||||
const allocator = std.heap.c_allocator; // C deki malloc a ulaşır
|
||||
|
||||
pub fn main() anyerror!void {
|
||||
|
||||
var shapes = try std.ArrayList(io.Shape).initCapacity(allocator, 1024);
|
||||
defer shapes.deinit(allocator);
|
||||
|
||||
const base_cube = rl.Vector3.init(-20, 20, 0);
|
||||
var my_gui = panel.GUI.init(@floatFromInt(screen_width), @floatFromInt(screen_height));
|
||||
|
||||
const my_cube = io.Shape.initCube(rl.Vector3.init(0, 0, 0),
|
||||
.red, 2.0, 2.0, 2.0);
|
||||
const my_sphere = io.Shape.initSphere(rl.Vector3.init(2.0, 0, 0), .gold, 1.0);
|
||||
const my_cylinder = io.Shape.initCylinder(rl.Vector3.init(-2.0, 0, 0), .pink, 1, 1);
|
||||
|
||||
const screen_height = 1200;
|
||||
const screen_width = 800;
|
||||
try shapes.append(allocator, my_cube);
|
||||
try shapes.append(allocator, my_sphere);
|
||||
try shapes.append(allocator, my_cylinder);
|
||||
|
||||
var my_gui = panel.GUI.init(rl.Rectangle.init(0, 0, screen_width, screen_height));
|
||||
|
||||
rl.initWindow(screen_height, screen_width, "YELBEGEN");
|
||||
panel.is_cursor_hidden = false;
|
||||
io.is_object_dragging = false;
|
||||
|
||||
rl.initWindow(screen_width, screen_height, "YELBEGEN");
|
||||
|
||||
defer rl.closeWindow();
|
||||
|
||||
var cam = rl.Camera3D{
|
||||
.position = rl.Vector3.init(290, 120, 250),
|
||||
.target = rl.Vector3.init(20,20,20),
|
||||
.up = rl.Vector3.init(0, 2.0, 0),
|
||||
.position = rl.Vector3.init(10, 10, 10),
|
||||
.target = rl.Vector3.init(0,0,0),
|
||||
.up = rl.Vector3.init(0, 1.0, 0),
|
||||
.fovy = 45.0,
|
||||
.projection = rl.CameraProjection.perspective,
|
||||
};
|
||||
|
||||
|
||||
rl.setTargetFPS(60);
|
||||
|
||||
|
||||
while (!rl.windowShouldClose()) {
|
||||
|
||||
//update
|
||||
if (rl.isKeyDown(.a)) {
|
||||
cam.position.x += 0.01;
|
||||
} else if (rl.isKeyDown(.b)) {
|
||||
cam.position.y += 0.01;
|
||||
} else if (rl.isKeyDown(.c)) {
|
||||
cam.position.z += 0.01;
|
||||
}
|
||||
io.inputControls();
|
||||
io.findClosestHitObject(rl.getMousePosition(), cam, &shapes);
|
||||
|
||||
if (io.freeMode) {
|
||||
rl.updateCamera(&cam, .free);
|
||||
}
|
||||
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
rl.beginMode3D(cam);
|
||||
rl.drawCube(base_cube, 40, 40, 40, .red);
|
||||
rl.drawCube(rl.Vector3.zero(), 300, 1, 300, .gray);
|
||||
drw.drawShapes(&shapes);
|
||||
rl.drawGrid(10, 1.0);
|
||||
rl.endMode3D();
|
||||
rl.drawText(rl.textFormat("x:%.2f y:%.2f z:%.2f", .{cam.position.x, cam.position.y, cam.position.z}),
|
||||
180, 200, 20, .light_gray);
|
||||
my_gui.draw();
|
||||
rl.drawText(rl.textFormat("x : %d y : %d", .{rl.getScreenWidth(), rl.getScreenHeight()}), 50, 50, 20, .red);
|
||||
my_gui.draw(shapes);
|
||||
rl.drawFPS(200, 200);
|
||||
if (io.is_object_dragging) {
|
||||
rl.drawText("Nesne drag...", 10, 10, 20, .dark_gray);
|
||||
} else {
|
||||
rl.drawText("Nesne hazır...", 10, 10, 20, .dark_gray);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user