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:
- y-direction to point up instead of down (origin at bottom left)
- the window to be 800 px wide
- x goes from 0 \(\rightarrow\) 10
- y goes from 0 \(\rightarrow\) 8
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)
= 800 # = 10 m
screen_width = 640 # = 8 m (converted 8 m to px)
screen_height
# Location of our little box we'll draw, in real world
# coords (meters).
= 1.0
x_wo_loc = 2.0
y_wo_loc
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")
60)
pr.set_target_fps(
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):
+= 0.10
x_wo_loc if pr.is_key_down(pr.KEY_LEFT):
-= 0.10
x_wo_loc if pr.is_key_down(pr.KEY_UP):
+= 0.10
y_wo_loc if pr.is_key_down(pr.KEY_DOWN):
-= 0.10
y_wo_loc
def draw_game():
"x: " + str(round(x_wo_loc, 2)) + " m",
pr.draw_text(0.2), y_sc(7.6), 18, pr.GREEN)
x_sc("y: " + str(round(y_wo_loc, 2)) + " m",
pr.draw_text(0.2), y_sc(7.2), 18, pr.GREEN)
x_sc(
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.