package main
import ecs "deps/secs"
import rl "vendor:raylib"
import "core:fmt"
MAX_BUILDINGS :: 100
screenWidth :: 800
screenHeight :: 450
GameStateStartup :: struct {}
GameStateStartScreen :: struct {}
GameStateLoop :: struct {}
GameStateExitRequested :: struct {}
GameState :: union {
GameStateStartup,
GameStateStartScreen,
GameStateLoop,
GameStateExitRequested,
}
generate_buildings :: proc(
) -> (
buildings: [MAX_BUILDINGS]rl.Rectangle,
buildColors: [MAX_BUILDINGS]rl.Color,
) {
spacing: i32 = 0
for i in 0 ..< MAX_BUILDINGS {
buildings[i].width = f32(rl.GetRandomValue(50, 200))
buildings[i].height = f32(rl.GetRandomValue(100, 800))
buildings[i].y = screenHeight - 130.0 - buildings[i].height
buildings[i].x = f32(-6000.0 + spacing)
spacing += i32(buildings[i].width)
buildColors[i] = rl.Color(
{
u8(rl.GetRandomValue(200, 240)),
u8(rl.GetRandomValue(200, 240)),
u8(rl.GetRandomValue(200, 240)),
255,
},
)
}
return buildings, buildColors
}
Drawable :: union {
rl.Rectangle,
}
handle_input :: proc(world: ^ecs.World) {
ecs.Work(world, proc(e: ecs.Entity, p: ^Position, d: ^Player) {
if rl.IsKeyDown(rl.KeyboardKey.A) do p.x -= 2
if rl.IsKeyDown(rl.KeyboardKey.D) do p.x += 2
if rl.IsKeyDown(rl.KeyboardKey.W) do p.y -= 2
if rl.IsKeyDown(rl.KeyboardKey.S) do p.y += 2
})
}
Player :: struct {}
Position :: struct {
x: f32,
y: f32,
}
CameraTarget :: struct {}
camera: rl.Camera2D
main :: proc() {
rl.InitWindow(screenWidth, screenHeight, "raylib [core] example - 2d camera")
exitWindow := false // Flag to set window to exit
world := ecs.NewWorld()
e := ecs.CreateEntity(world)
ecs.AddComponents(
world,
e,
Player{},
Position{400, 280},
Drawable(rl.Rectangle{0, 0, 40, 40}),
CameraTarget{},
)
buildings, buildColors := generate_buildings()
game_state: GameState = GameStateStartup{}
last_state: GameState = nil
camera.offset = rl.Vector2({screenWidth / 2.0, screenHeight / 2.0})
camera.rotation = 0.0
camera.zoom = 1.0
rl.SetTargetFPS(60)
for !exitWindow {
switch s in game_state {
case GameStateStartup:
game_state = GameStateStartScreen{}
case GameStateStartScreen:
game_state = GameStateLoop{}
case GameStateLoop:
handle_input(world)
ecs.Work(world, proc(done: ^bool, e: ecs.Entity, p: ^Position, d: ^CameraTarget) {
camera.target = rl.Vector2({p.x + 20, p.y + 20})
done^ = true
})
camera.zoom += f32(rl.GetMouseWheelMove() * 0.05)
if camera.zoom > 3.0 do camera.zoom = 3.0
else if camera.zoom < 0.1 do camera.zoom = 0.1
if rl.IsKeyPressed(rl.KeyboardKey.R) {
camera.zoom = 1.0
camera.rotation = 0.0
}
if (rl.WindowShouldClose() || rl.IsKeyPressed(rl.KeyboardKey.ESCAPE)) do game_state = GameStateExitRequested{}
case GameStateExitRequested:
// A request for close window has been issued, we can save data before closing
// or just show a message asking for confirmation
if (rl.IsKeyPressed(rl.KeyboardKey.Y) || rl.IsKeyPressed(rl.KeyboardKey.Z)) do exitWindow = true
else if (rl.IsKeyPressed(rl.KeyboardKey.N)) do game_state = last_state
}
rl.BeginDrawing()
rl.ClearBackground(rl.RAYWHITE)
rl.BeginMode2D(camera)
rl.DrawRectangle(-6000, 320, 13000, 8000, rl.DARKGRAY)
for i in 0 ..< MAX_BUILDINGS do rl.DrawRectangleRec(buildings[i], buildColors[i])
ecs.Work(world, proc(e: ecs.Entity, p: ^Position, d: ^Drawable) {
switch d in d {
case rl.Rectangle:
rl.DrawRectangleRec(rl.Rectangle{d.x + p.x, d.y + p.y, d.width, d.height}, rl.RED)
}
})
rl.DrawLine(
i32(camera.target.x),
-screenHeight * 10,
i32(camera.target.x),
screenHeight * 10,
rl.GREEN,
)
rl.DrawLine(
-screenWidth * 10,
i32(camera.target.y),
screenWidth * 10,
i32(camera.target.y),
rl.GREEN,
)
rl.EndMode2D()
rl.DrawText("SCREEN AREA", 640, 10, 20, rl.RED)
rl.DrawRectangle(0, 0, screenWidth, 5, rl.RED)
rl.DrawRectangle(0, 5, 5, screenHeight - 10, rl.RED)
rl.DrawRectangle(screenWidth - 5, 5, 5, screenHeight - 10, rl.RED)
rl.DrawRectangle(0, screenHeight - 5, screenWidth, 5, rl.RED)
rl.DrawRectangle(10, 10, 250, 80, rl.Fade(rl.SKYBLUE, 0.5))
rl.DrawRectangleLines(10, 10, 250, 80, rl.BLUE)
rl.DrawText("Free 2d camera controls:", 20, 20, 10, rl.BLACK)
rl.DrawText("- WASD to move", 40, 40, 10, rl.DARKGRAY)
rl.DrawText("- Mouse Wheel to Zoom in-out", 40, 60, 10, rl.DARKGRAY)
#partial switch _ in game_state {
case GameStateExitRequested:
rl.DrawRectangle(0, 100, screenWidth, 200, rl.BLACK)
rl.DrawText("Are you sure you want to exit program? [Y/N]", 40, 180, 30, rl.WHITE)
}
rl.EndDrawing()
}
rl.CloseWindow()
}