Parcourir la source

karlib -> karl2d

Karl Zylinski il y a 7 mois
Parent
commit
2dc388c5ba
7 fichiers modifiés avec 94 ajouts et 77 suppressions
  1. 2 0
      .gitignore
  2. 20 3
      README.md
  3. 36 36
      examples/raylib_ports/2d_camera/2d_camera.odin
  4. 29 29
      examples/snake/snake.odin
  5. 1 1
      karl2d.odin
  6. 6 1
      karl2d_raylib.odin
  7. 0 7
      util.odin

+ 2 - 0
.gitignore

@@ -1 +1,3 @@
+*.sublime-project
+*.sublime-workspace
 raylib/

+ 20 - 3
README.md

@@ -1,8 +1,10 @@
 ___This library is NOT ready for use!___
 
-This is a WIP library for creating 2D games using the Odin Programming Language. The API is heavily inspired by Raylib, and in its current state it wraps Raylib. In the long term the library will have its own implementation that only uses `core` libraries and rendering APIs from `vendor`.
+Karl2D is a WIP library for creating 2D games using the Odin Programming Language.
 
-The name _karlib_ will most likely change.
+The API is based on Raylib, but adapted to my tastes.
+
+In its current state, Karl2D wraps Raylib. But in the long term the library will have its own implementation that only uses `core` libraries and rendering APIs from `vendor`.
 
 Big upcoming tasks:
 * Port raylib examples to figure out API surface
@@ -10,4 +12,19 @@ Big upcoming tasks:
 
 ## Why does it wrap Raylib?
 
-I know Raylib very well and it made sense for me to create a wrapper for it, tweak the API and at some point rewrite the implementation without Raylib. That way we get a native, easy-to-use Odin library for making 2D games.
+I know Raylib very well. I like it, but I would like to have something written in native Odin. Having a native library is great for debugging, among other reasons. There are a few things I'd like to change about Raylib as well. So this library is meant to solve all those things.
+
+However, since I like Raylib, using something similar to its API is a good starting point. The steps towards a native Odin library independent of Raylib are:
+- Wrap Raylib
+- Modify the API to my tastes, within what is possible while still wrapping Raylib
+- Write a new implementation that uses native OS windowing APIs and rendering APIs
+- At this point I have more control and can further refine the API
+
+## What features of Raylib will not be included?
+
+* 3D
+* Some maths things that can be found in Odin's core libs
+
+Audio support isn't planned at first, but may be added later. Until then you can use `vendor:miniaudio` or similar.
+
+I might skip the GetFrameTime / GetTime from Raylib and let the user use `core:time` instead.

+ 36 - 36
examples/raylib_ports/2d_camera/2d_camera.odin

@@ -2,7 +2,7 @@
 
 package raylib_example_2d_camera
 
-import kl "../../.."
+import k2 "../../.."
 import "core:math/rand"
 import "core:math"
 
@@ -11,11 +11,11 @@ SCREEN_WIDTH :: 800
 SCREEN_HEIGHT :: 450
 
 main :: proc() {
-	kl.init(SCREEN_WIDTH, SCREEN_HEIGHT, "karlib: 2d camera (raylib [core] example - 2d camera)")
+	k2.init(SCREEN_WIDTH, SCREEN_HEIGHT, "Karl2D: 2d camera (raylib [core] example - 2d camera)")
 
-	player := kl.Rect { 400, 280, 40, 40 }
-    buildings: [MAX_BUILDINGS]kl.Rect
-    building_colors: [MAX_BUILDINGS]kl.Color
+	player := k2.Rect { 400, 280, 40, 40 }
+    buildings: [MAX_BUILDINGS]k2.Rect
+    building_colors: [MAX_BUILDINGS]k2.Color
 
     spacing: f32
 
@@ -40,67 +40,67 @@ main :: proc() {
     	}
     }
 
-    camera := kl.Camera {
+    camera := k2.Camera {
     	origin = { SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2},
     	zoom = 1,
     }
 
-    for !kl.window_should_close() {
-    	kl.process_events()
+    for !k2.window_should_close() {
+    	k2.process_events()
 
-    	if kl.key_is_held(.Right) { player.x += 2 }
-    	else if kl.key_is_held(.Left) { player.x -= 2 }
+    	if k2.key_is_held(.Right) { player.x += 2 }
+    	else if k2.key_is_held(.Left) { player.x -= 2 }
 
         camera.target = { player.x + 20, player.y + 20 }
 
-        if kl.key_is_held(.A) { camera.rotation -= 1 }
-        else if kl.key_is_held(.S)  { camera.rotation += 1 }
+        if k2.key_is_held(.A) { camera.rotation -= 1 }
+        else if k2.key_is_held(.S)  { camera.rotation += 1 }
 
         if camera.rotation > 40 { camera.rotation = 40 }
         else if camera.rotation < -40 { camera.rotation = -40 }
 
-        camera.zoom = math.exp(math.log(camera.zoom, math.E) + f32(kl.get_mouse_wheel_delta() * 0.1))
+        camera.zoom = math.exp(math.log(camera.zoom, math.E) + f32(k2.get_mouse_wheel_delta() * 0.1))
       
         if camera.zoom > 3 { camera.zoom = 3 }
         else if camera.zoom < 0.1 { camera.zoom = 0.1 }
 
-        if kl.key_went_down(.R) {
+        if k2.key_went_down(.R) {
         	camera.zoom = 1
         	camera.rotation = 0
         }
 
-        kl.clear({ 245, 245, 245, 255 })
-        kl.set_camera(camera)
-        kl.draw_rect({-6000, 320, 13000, 8000}, kl.DARKGRAY)
+        k2.clear({ 245, 245, 245, 255 })
+        k2.set_camera(camera)
+        k2.draw_rect({-6000, 320, 13000, 8000}, k2.DARKGRAY)
 
         for i in 0..<MAX_BUILDINGS {
-            kl.draw_rect(buildings[i], building_colors[i])
+            k2.draw_rect(buildings[i], building_colors[i])
         }
 
-        kl.draw_rect(player, kl.RED)
-        kl.draw_line({camera.target.x, -SCREEN_HEIGHT * 10}, {camera.target.x, SCREEN_HEIGHT * 10 }, 1, kl.GREEN)
-        kl.draw_line({-SCREEN_WIDTH*10, camera.target.y}, {SCREEN_WIDTH*10, camera.target.y}, 1, kl.GREEN)
+        k2.draw_rect(player, k2.RED)
+        k2.draw_line({camera.target.x, -SCREEN_HEIGHT * 10}, {camera.target.x, SCREEN_HEIGHT * 10 }, 1, k2.GREEN)
+        k2.draw_line({-SCREEN_WIDTH*10, camera.target.y}, {SCREEN_WIDTH*10, camera.target.y}, 1, k2.GREEN)
 
-        kl.set_camera(nil)
-        kl.draw_text("SCREEN AREA", {640, 10}, 20, kl.RED)
+        k2.set_camera(nil)
+        k2.draw_text("SCREEN AREA", {640, 10}, 20, k2.RED)
 
-        kl.draw_rect({0, 0, SCREEN_WIDTH, 5}, kl.RED)
-        kl.draw_rect({0, 5, 5, SCREEN_HEIGHT - 10}, kl.RED)
-        kl.draw_rect({SCREEN_WIDTH - 5, 5, 5, SCREEN_HEIGHT - 10}, kl.RED)
-        kl.draw_rect({0, SCREEN_HEIGHT - 5, SCREEN_WIDTH, 5}, kl.RED)
+        k2.draw_rect({0, 0, SCREEN_WIDTH, 5}, k2.RED)
+        k2.draw_rect({0, 5, 5, SCREEN_HEIGHT - 10}, k2.RED)
+        k2.draw_rect({SCREEN_WIDTH - 5, 5, 5, SCREEN_HEIGHT - 10}, k2.RED)
+        k2.draw_rect({0, SCREEN_HEIGHT - 5, SCREEN_WIDTH, 5}, k2.RED)
 
-        kl.draw_rect({10, 10, 250, 113}, {102, 191, 255, 128})
-        kl.draw_rect_outline({10, 10, 250, 113}, 1, kl.BLUE)
+        k2.draw_rect({10, 10, 250, 113}, {102, 191, 255, 128})
+        k2.draw_rect_outline({10, 10, 250, 113}, 1, k2.BLUE)
 
-        kl.draw_text("Free 2d camera controls:", {20, 20}, 10, kl.BLACK)
-        kl.draw_text("- Right/Left to move Offset", {40, 40}, 10, kl.DARKGRAY)
-        kl.draw_text("- Mouse Wheel to Zoom in-out", {40, 60}, 10, kl.DARKGRAY)
-        kl.draw_text("- A / S to Rotate", {40, 80}, 10, kl.DARKGRAY)
-        kl.draw_text("- R to reset Zoom and Rotation", {40, 100}, 10, kl.DARKGRAY)
+        k2.draw_text("Free 2d camera controls:", {20, 20}, 10, k2.BLACK)
+        k2.draw_text("- Right/Left to move Offset", {40, 40}, 10, k2.DARKGRAY)
+        k2.draw_text("- Mouse Wheel to Zoom in-out", {40, 60}, 10, k2.DARKGRAY)
+        k2.draw_text("- A / S to Rotate", {40, 80}, 10, k2.DARKGRAY)
+        k2.draw_text("- R to reset Zoom and Rotation", {40, 100}, 10, k2.DARKGRAY)
 
-    	kl.present()
+    	k2.present()
     }
 
-    kl.shutdown()
+    k2.shutdown()
 }
 

+ 29 - 29
examples/snake/snake.odin

@@ -1,6 +1,6 @@
 package snake
 
-import kl "../.."
+import k2 "../.."
 import "core:math"
 import "core:fmt"
 import "core:time"
@@ -56,40 +56,40 @@ restart :: proc() {
 }
 
 main :: proc() {
-	kl.init(WINDOW_SIZE, WINDOW_SIZE, "Snake")
+	k2.init(WINDOW_SIZE, WINDOW_SIZE, "Snake")
 	prev_time := time.now()
 
 	restart()
 
-	food_sprite := kl.load_texture_from_file("food.png")
-	head_sprite := kl.load_texture_from_file("head.png")
-	body_sprite := kl.load_texture_from_file("body.png")
-	tail_sprite := kl.load_texture_from_file("tail.png")
+	food_sprite := k2.load_texture_from_file("food.png")
+	head_sprite := k2.load_texture_from_file("head.png")
+	body_sprite := k2.load_texture_from_file("body.png")
+	tail_sprite := k2.load_texture_from_file("tail.png")
 
-	for !kl.window_should_close() {
+	for !k2.window_should_close() {
 		time_now := time.now()
 		dt := f32(time.duration_seconds(time.diff(prev_time, time_now)))
 		prev_time = time_now
-		kl.process_events()
+		k2.process_events()
 
-		if kl.key_is_held(.Up) {
+		if k2.key_is_held(.Up) {
 			move_direction = {0, -1}
 		}
 
-		if kl.key_is_held(.Down) {
+		if k2.key_is_held(.Down) {
 			move_direction = {0, 1}
 		}
 
-		if kl.key_is_held(.Left) {
+		if k2.key_is_held(.Left) {
 			move_direction = {-1, 0}
 		}
 
-		if kl.key_is_held(.Right) {
+		if k2.key_is_held(.Right) {
 			move_direction = {1, 0}
 		}
 
 		if game_over {
-			if kl.key_went_down(.Enter) {
+			if k2.key_went_down(.Enter) {
 				restart()
 			}
 		} else {
@@ -125,14 +125,14 @@ main :: proc() {
 			tick_timer = TICK_RATE + tick_timer
 		}
 
-		kl.clear({76, 53, 83, 255})
+		k2.clear({76, 53, 83, 255})
 
-		camera := kl.Camera {
+		camera := k2.Camera {
 			zoom = f32(WINDOW_SIZE) / CANVAS_SIZE,
 		}
 
-		kl.set_camera(camera)
-		kl.draw_texture(food_sprite, {f32(food_pos.x), f32(food_pos.y)}*CELL_SIZE)
+		k2.set_camera(camera)
+		k2.draw_texture(food_sprite, {f32(food_pos.x), f32(food_pos.y)}*CELL_SIZE)
 
 		for i in 0..<snake_length {
 			part_sprite := body_sprite
@@ -150,38 +150,38 @@ main :: proc() {
 
 			rot := math.atan2(f32(dir.y), f32(dir.x)) * math.DEG_PER_RAD
 
-			source := kl.Rect {
+			source := k2.Rect {
 				0, 0,
 				f32(part_sprite.width), f32(part_sprite.height),
 			}
 
-			dest := kl.Rect {
+			dest := k2.Rect {
 				f32(snake[i].x)*CELL_SIZE + 0.5*CELL_SIZE,
 				f32(snake[i].y)*CELL_SIZE + 0.5*CELL_SIZE,
 				CELL_SIZE,
 				CELL_SIZE,
 			}
 
-			kl.draw_texture_ex(part_sprite, source, dest, {CELL_SIZE, CELL_SIZE}*0.5, rot)
+			k2.draw_texture_ex(part_sprite, source, dest, {CELL_SIZE, CELL_SIZE}*0.5, rot)
 		}
 
 		if game_over {
-			kl.draw_text("Game Over!", {4, 4}, 25, kl.RED)
-			kl.draw_text("Press Enter to play again", {4, 30}, 15, kl.BLACK)
+			k2.draw_text("Game Over!", {4, 4}, 25, k2.RED)
+			k2.draw_text("Press Enter to play again", {4, 30}, 15, k2.BLACK)
 		}
 
 		score := snake_length - 3
 		score_str := fmt.tprintf("Score: %v", score)
-		kl.draw_text(score_str, {4, CANVAS_SIZE - 14}, 10, kl.GRAY)
-		kl.present()
+		k2.draw_text(score_str, {4, CANVAS_SIZE - 14}, 10, k2.GRAY)
+		k2.present()
 
 		free_all(context.temp_allocator)
 	}
 
-	kl.destroy_texture(head_sprite)
-	kl.destroy_texture(food_sprite)
-	kl.destroy_texture(body_sprite)
-	kl.destroy_texture(tail_sprite)
+	k2.destroy_texture(head_sprite)
+	k2.destroy_texture(food_sprite)
+	k2.destroy_texture(body_sprite)
+	k2.destroy_texture(tail_sprite)
 
-	kl.shutdown()
+	k2.shutdown()
 }

+ 1 - 1
karlib.odin → karl2d.odin

@@ -1,4 +1,4 @@
-package karlib
+package karl2d
 
 // Opens a window and initializes some internal state. The internal state will use `allocator` for
 // all dynamically allocated memory. The return value can be ignored unless you need to later call

+ 6 - 1
karlib_raylib.odin → karl2d_raylib.odin

@@ -1,8 +1,9 @@
-package karlib
+package karl2d
 
 import rl "raylib"
 import "raylib/rlgl"
 import "core:log"
+import "core:strings"
 import "base:runtime"
 
 _init :: proc(width: int, height: int, title: string,
@@ -257,3 +258,7 @@ _present :: proc(do_flush := true) {
 	}
 	rl.SwapScreenBuffer()
 }
+
+temp_cstring :: proc(str: string) -> cstring {
+	return strings.clone_to_cstring(str, context.temp_allocator)
+}

+ 0 - 7
util.odin

@@ -1,7 +0,0 @@
-package karlib
-
-import "core:strings"
-
-temp_cstring :: proc(str: string) -> cstring {
-	return strings.clone_to_cstring(str, context.temp_allocator)
-}