aboutsummaryrefslogtreecommitdiff
path: root/examples/game
diff options
context:
space:
mode:
Diffstat (limited to 'examples/game')
-rw-r--r--examples/game/box.tm8
-rw-r--r--examples/game/color.tm23
-rw-r--r--examples/game/game.tm31
-rw-r--r--examples/game/player.tm29
-rw-r--r--examples/game/raylib.tm62
-rw-r--r--examples/game/world.tm47
6 files changed, 109 insertions, 91 deletions
diff --git a/examples/game/box.tm b/examples/game/box.tm
index acff269e..03294a0a 100644
--- a/examples/game/box.tm
+++ b/examples/game/box.tm
@@ -1,9 +1,7 @@
# Defines a struct representing boxes on the terrain
-use vectors
-
use ./world.tm
-use ./color.tm
+use ./raylib.tm
-struct Box(pos:Vec2, size=Vec2(50, 50), color=Color.GRAY, blocking=yes):
+struct Box(pos:Vector2, size=Vector2(50, 50), color=Color(0x80,0x80,0x80), blocking=yes):
func draw(b:Box):
- b.color:draw_rectangle(b.pos, b.size)
+ DrawRectangleRec(Rectangle(b.pos.x, b.pos.y, b.size.x, b.size.y), b.color)
diff --git a/examples/game/color.tm b/examples/game/color.tm
deleted file mode 100644
index fef12e60..00000000
--- a/examples/game/color.tm
+++ /dev/null
@@ -1,23 +0,0 @@
-# Defines a struct used to represent colors using 64-bit floats (0.0 - 1.0),
-# which can be used to draw colored rectangles in raylib
-use <raylib.h>
-use vectors
-
-struct Color(r,g,b:Num,a=1.0):
- PLAYER := Color(.1,.1,.6,1.)
- GRAY := Color(.4,.4,.4)
- LIGHT_GRAY := Color(.7,.7,.7)
- GOAL := Color(.1,.5,.0)
-
- func draw_rectangle(c:Color, pos:Vec2, size:Vec2):
- inline C {
- DrawRectangle(
- (int)(_$pos.x), (int)(_$pos.y), (int)(_$size.x), (int)(_$size.y),
- ((Color){
- (int8_t)(uint8_t)(255.*_$c.r),
- (int8_t)(uint8_t)(255.*_$c.g),
- (int8_t)(uint8_t)(255.*_$c.b),
- (int8_t)(uint8_t)(255.*_$c.a),
- })
- );
- }
diff --git a/examples/game/game.tm b/examples/game/game.tm
index 86e4e01c..e0bf7b32 100644
--- a/examples/game/game.tm
+++ b/examples/game/game.tm
@@ -1,40 +1,29 @@
# This game demo uses Raylib to present a simple
-use libraylib.so
-use <raylib.h>
-use <raymath.h>
-
+use ./raylib.tm
use ./world.tm
func main(map=(./map.txt)):
- extern InitWindow:func(w:Int32, h:Int32, title:CString)
InitWindow(1600, 900, CString("raylib [core] example - 2d camera"))
map_contents := map:read() or exit("Could not find the game map: $map")
- World.CURRENT:load_map(map_contents)
+ world := @World(
+ player=@Player(Vector2(0,0), Vector2(0,0)),
+ goal=@Box(Vector2(0,0), Vector2(50,50), color=Color(0x10,0xa0,0x10)),
+ boxes=@[:@Box],
+ )
+ world:load_map(map_contents)
- extern SetTargetFPS:func(fps:Int32)
SetTargetFPS(60)
- extern WindowShouldClose:func(->Bool)
-
while not WindowShouldClose():
- extern GetFrameTime:func(->Num32)
dt := GetFrameTime()
- World.CURRENT:update(Num(dt))
+ world:update(dt)
- extern BeginDrawing:func()
BeginDrawing()
-
- inline C {
- ClearBackground((Color){0xCC, 0xCC, 0xCC, 0xFF});
- }
-
- World.CURRENT:draw()
-
- extern EndDrawing:func()
+ ClearBackground(Color(0xCC, 0xCC, 0xCC, 0xFF))
+ world:draw()
EndDrawing()
- extern CloseWindow:func()
CloseWindow()
diff --git a/examples/game/player.tm b/examples/game/player.tm
index a5c39a8d..dac2508a 100644
--- a/examples/game/player.tm
+++ b/examples/game/player.tm
@@ -1,25 +1,22 @@
# Defines a struct representing the player, which is controlled by WASD keys
-use libraylib.so
-use <raylib.h>
-use <raymath.h>
-
-use vectors
use ./world.tm
+use ./raylib.tm
-struct Player(pos,prev_pos:Vec2):
- WALK_SPEED := 500.
- ACCEL := 0.3
- FRICTION := 0.99
- SIZE := Vec2(30, 30)
+struct Player(pos,prev_pos:Vector2):
+ WALK_SPEED := Num32(500.)
+ ACCEL := Num32(0.3)
+ FRICTION := Num32(0.99)
+ SIZE := Vector2(30, 30)
+ COLOR := Color(0x60, 0x60, 0xbF)
func update(p:@Player):
- target_x := inline C:Num {
- (Num_t)((IsKeyDown(KEY_A) ? -1 : 0) + (IsKeyDown(KEY_D) ? 1 : 0))
+ target_x := inline C:Num32 {
+ (Num32_t)((IsKeyDown(KEY_A) ? -1 : 0) + (IsKeyDown(KEY_D) ? 1 : 0))
}
- target_y := inline C:Num {
- (Num_t)((IsKeyDown(KEY_W) ? -1 : 0) + (IsKeyDown(KEY_S) ? 1 : 0))
+ target_y := inline C:Num32 {
+ (Num32_t)((IsKeyDown(KEY_W) ? -1 : 0) + (IsKeyDown(KEY_S) ? 1 : 0))
}
- target_vel := Vec2(target_x, target_y):norm() * Player.WALK_SPEED
+ target_vel := Vector2(target_x, target_y):norm() * Player.WALK_SPEED
vel := (p.pos - p.prev_pos)/World.DT
vel *= Player.FRICTION
@@ -28,4 +25,4 @@ struct Player(pos,prev_pos:Vec2):
p.prev_pos, p.pos = p.pos, p.pos + World.DT*vel
func draw(p:Player):
- Color.PLAYER:draw_rectangle(p.pos, Player.SIZE)
+ DrawRectangleRec(Rectangle(p.pos.x, p.pos.y, Player.SIZE.x, Player.SIZE.y), Player.COLOR)
diff --git a/examples/game/raylib.tm b/examples/game/raylib.tm
new file mode 100644
index 00000000..2721d0e1
--- /dev/null
+++ b/examples/game/raylib.tm
@@ -0,0 +1,62 @@
+# Raylib wrapper for some functions and structs
+use libraylib.so
+use <raylib.h>
+use <raymath.h>
+
+struct Color(r,g,b:Byte,a=Byte(255); extern)
+struct Rectangle(x,y,width,height:Num32; extern):
+ func draw(r:Rectangle, color:Color):
+ DrawRectangleRec(r, color)
+
+struct Vector2(x,y:Num32; extern):
+ ZERO := Vector2(0, 0)
+ func plus(a,b:Vector2->Vector2; inline):
+ return Vector2(a.x+b.x, a.y+b.y)
+ func minus(a,b:Vector2->Vector2; inline):
+ return Vector2(a.x-b.x, a.y-b.y)
+ func times(a,b:Vector2->Vector2; inline):
+ return Vector2(a.x*b.x, a.y*b.y)
+ func negative(v:Vector2->Vector2; inline):
+ return Vector2(-v.x, -v.y)
+ func dot(a,b:Vector2->Num32; inline):
+ return ((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y))!
+ func cross(a,b:Vector2->Num32; inline):
+ return a.x*b.y - a.y*b.x
+ func scaled_by(v:Vector2, k:Num32->Vector2; inline):
+ return Vector2(v.x*k, v.y*k)
+ func divided_by(v:Vector2, divisor:Num32->Vector2; inline):
+ return Vector2(v.x/divisor, v.y/divisor)
+ func length(v:Vector2->Num32; inline):
+ return (v.x*v.x + v.y*v.y)!:sqrt()
+ func dist(a,b:Vector2->Num32; inline):
+ return a:minus(b):length()
+ func angle(v:Vector2->Num32; inline):
+ return Num32.atan2(v.y, v.x)
+ func norm(v:Vector2->Vector2; inline):
+ if v.x == 0 and v.y == 0:
+ return v
+ len := v:length()
+ return Vector2(v.x/len, v.y/len)
+ func rotated(v:Vector2, radians:Num32 -> Vector2):
+ cos := radians:cos() or return v
+ sin := radians:sin() or return v
+ return Vector2(cos*v.x - sin*v.y, sin*v.x + cos*v.y)
+ func mix(a,b:Vector2, amount:Num32 -> Vector2):
+ return Vector2(
+ amount:mix(a.x, b.x),
+ amount:mix(a.y, b.y),
+ )
+
+extern InitWindow:func(width:Int32, height:Int32, title:CString)
+extern SetTargetFPS:func(fps:Int32)
+extern WindowShouldClose:func(->Bool)
+extern GetFrameTime:func(->Num32)
+extern BeginDrawing:func()
+extern EndDrawing:func()
+extern CloseWindow:func()
+extern ClearBackground:func(color:Color)
+extern DrawRectangle:func(x,y,width,height:Int32, color:Color)
+extern DrawRectangleRec:func(rec:Rectangle, color:Color)
+extern DrawText:func(text:CString, x,y:Int32, text_height:Int32, color:Color)
+extern GetScreenWidth:func(->Int32)
+extern GetScreenHeight:func(->Int32)
diff --git a/examples/game/world.tm b/examples/game/world.tm
index f1b65a87..864bd8d2 100644
--- a/examples/game/world.tm
+++ b/examples/game/world.tm
@@ -1,12 +1,10 @@
-use vectors
-
use ./player.tm
-use ./color.tm
+use ./raylib.tm
use ./box.tm
# Return a displacement relative to `a` that will push it out of `b`
-func solve_overlap(a_pos:Vec2, a_size:Vec2, b_pos:Vec2, b_size:Vec2 -> Vec2):
+func solve_overlap(a_pos:Vector2, a_size:Vector2, b_pos:Vector2, b_size:Vector2 -> Vector2):
a_left := a_pos.x
a_right := a_pos.x + a_size.x
a_top := a_pos.y
@@ -23,27 +21,26 @@ func solve_overlap(a_pos:Vec2, a_size:Vec2, b_pos:Vec2, b_size:Vec2 -> Vec2):
# If either axis is not overlapping, then there is no collision:
if overlap_x <= 0 or overlap_y <= 0:
- return Vec2(0, 0)
+ return Vector2(0, 0)
if overlap_x < overlap_y:
if a_right > b_left and a_right < b_right:
- return Vec2(-(overlap_x), 0)
+ return Vector2(-(overlap_x), 0)
else if a_left < b_right and a_left > b_left:
- return Vec2(overlap_x, 0)
+ return Vector2(overlap_x, 0)
else:
if a_top < b_bottom and a_top > b_top:
- return Vec2(0, overlap_y)
+ return Vector2(0, overlap_y)
else if a_bottom > b_top and a_bottom < b_bottom:
- return Vec2(0, -overlap_y)
+ return Vector2(0, -overlap_y)
- return Vec2(0, 0)
+ return Vector2(0, 0)
-struct World(player:@Player, goal:@Box, boxes:@[@Box], dt_accum=0.0, won=no):
- DT := 1./60.
- CURRENT := @World(@Player(Vec2(0,0), Vec2(0,0)), @Box(Vec2(0,0), Vec2(0,0), Color.GOAL), @[:@Box])
- STIFFNESS := 0.3
+struct World(player:@Player, goal:@Box, boxes:@[@Box], dt_accum=Num32(0.0), won=no):
+ DT := (Num32(1.)/Num32(60.))!
+ STIFFNESS := Num32(0.3)
- func update(w:@World, dt:Num):
+ func update(w:@World, dt:Num32):
w.dt_accum += dt
while w.dt_accum > 0:
w:update_once()
@@ -52,7 +49,7 @@ struct World(player:@Player, goal:@Box, boxes:@[@Box], dt_accum=0.0, won=no):
func update_once(w:@World):
w.player:update()
- if solve_overlap(w.player.pos, Player.SIZE, w.goal.pos, w.goal.size) != Vec2(0,0):
+ if solve_overlap(w.player.pos, Player.SIZE, w.goal.pos, w.goal.size) != Vector2(0,0):
w.won = yes
# Resolve player overlapping with any boxes:
@@ -67,26 +64,24 @@ struct World(player:@Player, goal:@Box, boxes:@[@Box], dt_accum=0.0, won=no):
w.player:draw()
if w.won:
- inline C {
- DrawText("WINNER", GetScreenWidth()/2-48*3, GetScreenHeight()/2-24, 48, (Color){0,0,0,0xFF});
- }
+ DrawText(CString("WINNER"), GetScreenWidth()/Int32(2)-Int32(48*3), GetScreenHeight()/Int32(2)-Int32(24), 48, Color(0,0,0))
func load_map(w:@World, map:Text):
if map:has($/[]/):
map = map:replace_all({$/[]/="#", $/@{1..}/="@", $/ /=" "})
w.boxes = @[:@Box]
- box_size := Vec2(50., 50.)
+ box_size := Vector2(50., 50.)
for y,line in map:lines():
for x,cell in line:split():
if cell == "#":
- pos := Vec2((Num(x)-1) * box_size.x, (Num(y)-1) * box_size.y)
- box := @Box(pos, size=box_size, color=Color.GRAY)
+ pos := Vector2((Num32(x)-1) * box_size.x, (Num32(y)-1) * box_size.y)
+ box := @Box(pos, size=box_size, color=Color(0x80,0x80,0x80))
w.boxes:insert(box)
else if cell == "@":
- pos := Vec2((Num(x)-1) * box_size.x, (Num(y)-1) * box_size.y)
- pos += box_size/2. - Player.SIZE/2.
+ pos := Vector2((Num32(x)-1) * box_size.x, (Num32(y)-1) * box_size.y)
+ pos += box_size/Num32(2) - Player.SIZE/Num32(2)
w.player = @Player(pos,pos)
else if cell == "?":
- pos := Vec2((Num(x)-1) * box_size.x, (Num(y)-1) * box_size.y)
- w.goal = @Box(pos, size=box_size, color=Color.GOAL)
+ pos := Vector2((Num32(x)-1) * box_size.x, (Num32(y)-1) * box_size.y)
+ w.goal.pos = pos