Some Python Raylib Notes

Coordinates vs pixels

Since I’m interested in using raylib to visualize some computations, I want to deal with world coordinates (in, say, meters), rather than screen coordinates (in pixels).

For example, if you want:

When my code generates x and y values in meters, I want to convert those “world coords” (m) into “screen coords” (pixels) so I can draw things. If we use “w” to mean world, and “s” to mean screen, and just put in \(C_{1}\) and \(C_{2}\) to stand-in for the conversion factors between screen (pixels) and world (meters):

\[x_{\text{s}} = C_{1}x_{\text{w}}\]

\[y_{\text{s}} = -y_{\text{w}} + h\]

where \(h\) is screen_height.

Here’s the code:

#!/usr/bin/env python3

import pyray as pr

# Conversion factor:
# 800 px == 10 meters  (or, 80 px == 1 m)

screen_width  = 800  # = 10 m
screen_height = 640  # =  8 m (converted 8 m to px)

# Location of our little box we'll draw, in real world
# coords (meters).
x_wo_loc = 1.0
y_wo_loc = 2.0

def main():
    init_game()
    while not pr.window_should_close():
        update_game()

        pr.begin_drawing()
        pr.clear_background(pr.BLACK)

        draw_game()

        pr.end_drawing()

    pr.close_window()

def init_game():
    pr.init_window(screen_width, screen_height,
                   "Now using real-world coords")
    pr.set_target_fps(60)

def update_game():
    global x_wo_loc, y_wo_loc
    # Pressing a key moves the object in 10 cm (0.10 m) increments.
    # Note difference betw `is_key_down` & `is_key_pressed`. :)
    if pr.is_key_pressed(pr.KEY_RIGHT):
        x_wo_loc += 0.10
    if pr.is_key_down(pr.KEY_LEFT):
        x_wo_loc -= 0.10
    if pr.is_key_down(pr.KEY_UP):
        y_wo_loc += 0.10
    if pr.is_key_down(pr.KEY_DOWN):
        y_wo_loc -= 0.10

def draw_game():
    pr.draw_text("x: " + str(round(x_wo_loc, 2)) + " m",
                 x_sc(0.2), y_sc(7.6), 18, pr.GREEN)
    pr.draw_text("y: " + str(round(y_wo_loc, 2)) + " m",
                 x_sc(0.2), y_sc(7.2), 18, pr.GREEN)

    pr.draw_rectangle(x_sc(x_wo_loc),
                      y_sc(y_wo_loc),
                      10, 10, pr.RED)

#----------------------------------------------------------
# Convert pixel coord val (n) to value in meters.
def to_m(n):
    # * 10 / 800
    return n / 80

# Convert meters to pixels
def to_px(x):
    # * 800 / 10
    return int(x * 80)

# x world to screen coord
def x_sc(x_wo):
    return to_px(x_wo)

# x screen to world coord
def x_wo(x_sc):
    return to_m(x_sc)

# y world to screen coord
def y_sc(y_wo):
    return -1 * to_px(y_wo) + screen_height

# y screen to world coord
def y_wo(y_sc):
    return to_m(screen_height - y_sc)

#---------------
main()

Run it and see how the screen is 10 m wide and 8 m tall.