commit
81eae2921a
6 changed files with 863 additions and 0 deletions
261
examples/core/2d_camera_platformer/main.go
Normal file
261
examples/core/2d_camera_platformer/main.go
Normal file
|
@ -0,0 +1,261 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import rl "github.com/gen2brain/raylib-go/raylib"
|
||||||
|
|
||||||
|
const (
|
||||||
|
screenWidth = 800
|
||||||
|
screenHeight = 450
|
||||||
|
gravity = 400
|
||||||
|
playerJumpSpeed = 350.0
|
||||||
|
playerHORSpeed = 200.0
|
||||||
|
)
|
||||||
|
|
||||||
|
type Player struct {
|
||||||
|
position rl.Vector2
|
||||||
|
speed float32
|
||||||
|
canJump bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type EnvironmentItem struct {
|
||||||
|
rect rl.Rectangle
|
||||||
|
blocking bool
|
||||||
|
color rl.Color
|
||||||
|
}
|
||||||
|
|
||||||
|
type cameraUpdater func(*rl.Camera2D, *Player, []EnvironmentItem, float32)
|
||||||
|
|
||||||
|
// These 3 variables are used only for camera 4,
|
||||||
|
// but they need to be declared on module level
|
||||||
|
// for camera 4 to work (static in C)
|
||||||
|
var eveningOut = false
|
||||||
|
var evenOutSpeed float32 = 700
|
||||||
|
var evenOutTarget float32 = 0
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
rl.InitWindow(screenWidth, screenHeight, "raylib [core] example - 2d camera platformer")
|
||||||
|
|
||||||
|
player := Player{
|
||||||
|
position: rl.NewVector2(400, 280),
|
||||||
|
speed: 0,
|
||||||
|
canJump: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
envItems := []EnvironmentItem{
|
||||||
|
{rect: rl.Rectangle{Width: 1000, Height: 400}, blocking: false, color: rl.LightGray},
|
||||||
|
{rect: rl.Rectangle{Y: 400, Width: 1000, Height: 200}, blocking: true, color: rl.Gray},
|
||||||
|
{rect: rl.Rectangle{X: 300, Y: 200, Width: 400, Height: 10}, blocking: true, color: rl.Gray},
|
||||||
|
{rect: rl.Rectangle{X: 250, Y: 300, Width: 100, Height: 10}, blocking: true, color: rl.Gray},
|
||||||
|
{rect: rl.Rectangle{X: 650, Y: 300, Width: 100, Height: 10}, blocking: true, color: rl.Gray},
|
||||||
|
}
|
||||||
|
|
||||||
|
camera := rl.Camera2D{
|
||||||
|
Offset: rl.Vector2{X: screenWidth / 2, Y: screenHeight / 2},
|
||||||
|
Target: player.position,
|
||||||
|
Rotation: 0,
|
||||||
|
Zoom: 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
cameraUpdaters := []cameraUpdater{
|
||||||
|
updateCameraCenter,
|
||||||
|
updateCameraCenterInsideMap,
|
||||||
|
updateCameraCenterSmoothFollow,
|
||||||
|
updateCameraEvenOutOnLanding,
|
||||||
|
updateCameraPlayerBoundsPush,
|
||||||
|
}
|
||||||
|
cameraDescriptions := []string{
|
||||||
|
"1. Follow player center",
|
||||||
|
"2. Follow player center, but clamp to map edges",
|
||||||
|
"3. Follow player center; smoothed",
|
||||||
|
"4. Follow player center horizontally; update player center vertically after landing",
|
||||||
|
"5. Player push camera on getting too close to screen edge",
|
||||||
|
}
|
||||||
|
|
||||||
|
cameraOption := 0
|
||||||
|
|
||||||
|
rl.SetTargetFPS(60)
|
||||||
|
|
||||||
|
for !rl.WindowShouldClose() {
|
||||||
|
deltaTime := rl.GetFrameTime()
|
||||||
|
|
||||||
|
updatePlayer(&player, envItems, deltaTime)
|
||||||
|
|
||||||
|
camera.Zoom += rl.GetMouseWheelMove() * 0.05
|
||||||
|
|
||||||
|
camera.Zoom = clamp(camera.Zoom, 0.25, 3)
|
||||||
|
|
||||||
|
if rl.IsKeyPressed(rl.KeyC) {
|
||||||
|
cameraOption = (cameraOption + 1) % len(cameraUpdaters)
|
||||||
|
}
|
||||||
|
// Call update camera function by its pointer
|
||||||
|
cameraUpdaters[cameraOption](&camera, &player, envItems, deltaTime)
|
||||||
|
|
||||||
|
// Draw
|
||||||
|
rl.BeginDrawing()
|
||||||
|
rl.ClearBackground(rl.RayWhite)
|
||||||
|
rl.BeginMode2D(camera)
|
||||||
|
|
||||||
|
for _, item := range envItems {
|
||||||
|
rl.DrawRectangleRec(item.rect, item.color)
|
||||||
|
}
|
||||||
|
|
||||||
|
playerRect := rl.Rectangle{
|
||||||
|
X: player.position.X - 20,
|
||||||
|
Y: player.position.Y - 40,
|
||||||
|
Width: 40,
|
||||||
|
Height: 40,
|
||||||
|
}
|
||||||
|
rl.DrawRectangleRec(playerRect, rl.Red)
|
||||||
|
rl.DrawCircleV(player.position, 5, rl.Gold)
|
||||||
|
|
||||||
|
rl.EndMode2D()
|
||||||
|
|
||||||
|
rl.DrawText("Controls:", 20, 20, 10, rl.Black)
|
||||||
|
rl.DrawText(" - Right/Left to move", 40, 40, 10, rl.DarkGray)
|
||||||
|
rl.DrawText(" - Space to jump", 40, 60, 10, rl.DarkGray)
|
||||||
|
rl.DrawText(" - Mouse Wheel to Zoom in-out, R to reset zoom", 40, 80, 10, rl.DarkGray)
|
||||||
|
rl.DrawText(" - C to change camera mode", 20, 100, 10, rl.Black)
|
||||||
|
rl.DrawText("Current Camera Mode:", 20, 120, 10, rl.DarkGray)
|
||||||
|
rl.DrawText(cameraDescriptions[cameraOption], 40, 140, 10, rl.DarkGray)
|
||||||
|
|
||||||
|
rl.EndDrawing()
|
||||||
|
}
|
||||||
|
rl.CloseWindow()
|
||||||
|
}
|
||||||
|
|
||||||
|
func updatePlayer(player *Player, envItems []EnvironmentItem, delta float32) {
|
||||||
|
if rl.IsKeyDown(rl.KeyLeft) {
|
||||||
|
player.position.X -= playerHORSpeed * delta
|
||||||
|
}
|
||||||
|
if rl.IsKeyDown(rl.KeyRight) {
|
||||||
|
player.position.X += playerHORSpeed * delta
|
||||||
|
}
|
||||||
|
if rl.IsKeyDown(rl.KeySpace) && player.canJump {
|
||||||
|
player.speed = -playerJumpSpeed
|
||||||
|
player.canJump = false
|
||||||
|
}
|
||||||
|
|
||||||
|
hitObstacle := false
|
||||||
|
for _, item := range envItems {
|
||||||
|
if item.blocking &&
|
||||||
|
item.rect.X <= player.position.X && item.rect.X+item.rect.Width >= player.position.X &&
|
||||||
|
item.rect.Y >= player.position.Y && item.rect.Y <= player.position.Y+player.speed*delta {
|
||||||
|
hitObstacle = true
|
||||||
|
player.speed = 0
|
||||||
|
player.position.Y = item.rect.Y
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !hitObstacle {
|
||||||
|
player.position.Y += player.speed * delta
|
||||||
|
player.speed += gravity * delta
|
||||||
|
player.canJump = false
|
||||||
|
} else {
|
||||||
|
player.canJump = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateCameraCenter(camera *rl.Camera2D, player *Player, _ []EnvironmentItem, _ float32) {
|
||||||
|
camera.Offset = rl.Vector2{X: screenWidth / 2, Y: screenHeight / 2}
|
||||||
|
camera.Target = player.position
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateCameraCenterInsideMap(camera *rl.Camera2D, player *Player, envItems []EnvironmentItem, _ float32) {
|
||||||
|
camera.Offset = rl.Vector2{X: screenWidth / 2, Y: screenHeight / 2}
|
||||||
|
camera.Target = player.position
|
||||||
|
|
||||||
|
var minX, minY, maxX, maxY float32 = 1000, 1000, -1000, -10000
|
||||||
|
|
||||||
|
for _, item := range envItems {
|
||||||
|
minX = min(item.rect.X, minX)
|
||||||
|
maxX = max(item.rect.X+item.rect.Width, maxX)
|
||||||
|
minY = min(item.rect.Y, minY)
|
||||||
|
maxY = max(item.rect.Y+item.rect.Height, maxY)
|
||||||
|
}
|
||||||
|
|
||||||
|
maxV := rl.GetWorldToScreen2D(rl.Vector2{X: maxX, Y: maxY}, *camera)
|
||||||
|
minV := rl.GetWorldToScreen2D(rl.Vector2{X: minX, Y: minY}, *camera)
|
||||||
|
|
||||||
|
if maxV.X < screenWidth {
|
||||||
|
camera.Offset.X = screenWidth - (maxV.X - screenWidth/2)
|
||||||
|
}
|
||||||
|
if maxV.Y < screenHeight {
|
||||||
|
camera.Offset.Y = screenHeight - (maxV.Y - screenHeight/2)
|
||||||
|
}
|
||||||
|
if minV.X > 0 {
|
||||||
|
camera.Offset.X = screenWidth/2 - minV.X
|
||||||
|
}
|
||||||
|
if minV.Y > 0 {
|
||||||
|
camera.Offset.Y = screenHeight/2 - minV.Y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateCameraCenterSmoothFollow(camera *rl.Camera2D, player *Player, _ []EnvironmentItem, delta float32) {
|
||||||
|
var minSpeed, minEffectLength, fractionSpeed float32 = 30.0, 10.0, 0.8
|
||||||
|
|
||||||
|
camera.Offset = rl.Vector2{X: screenWidth / 2, Y: screenHeight / 2}
|
||||||
|
diff := rl.Vector2Subtract(player.position, camera.Target)
|
||||||
|
length := rl.Vector2Length(diff)
|
||||||
|
|
||||||
|
if length > minEffectLength {
|
||||||
|
speed := max(fractionSpeed*length, minSpeed)
|
||||||
|
camera.Target = rl.Vector2Add(camera.Target, rl.Vector2Scale(diff, speed*delta/length))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateCameraEvenOutOnLanding(camera *rl.Camera2D, player *Player, _ []EnvironmentItem, delta float32) {
|
||||||
|
camera.Offset = rl.Vector2{X: screenWidth / 2, Y: screenHeight / 2}
|
||||||
|
camera.Target.X = player.position.X
|
||||||
|
|
||||||
|
if eveningOut {
|
||||||
|
if evenOutTarget > camera.Target.Y {
|
||||||
|
camera.Target.Y += evenOutSpeed * delta
|
||||||
|
if camera.Target.Y > evenOutTarget {
|
||||||
|
camera.Target.Y = evenOutTarget
|
||||||
|
eveningOut = false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
camera.Target.Y -= evenOutSpeed * delta
|
||||||
|
if camera.Target.Y < evenOutTarget {
|
||||||
|
camera.Target.Y = evenOutTarget
|
||||||
|
eveningOut = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if player.canJump && player.speed == 0 && player.position.Y != camera.Target.Y {
|
||||||
|
eveningOut = true
|
||||||
|
evenOutTarget = player.position.Y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateCameraPlayerBoundsPush(camera *rl.Camera2D, player *Player, _ []EnvironmentItem, _ float32) {
|
||||||
|
bbox := rl.Vector2{X: 0.2, Y: 0.2}
|
||||||
|
|
||||||
|
bboxWorldMin := rl.GetScreenToWorld2D(rl.Vector2{X: (1 - bbox.X) * 0.5 * screenWidth, Y: (1 - bbox.Y) * 0.5 * screenHeight}, *camera)
|
||||||
|
bboxWorldMax := rl.GetScreenToWorld2D(rl.Vector2{X: (1 + bbox.X) * 0.5 * screenWidth, Y: (1 + bbox.Y) * 0.5 * screenHeight}, *camera)
|
||||||
|
camera.Offset = rl.Vector2{X: (1 - bbox.X) * 0.5 * screenWidth, Y: (1 - bbox.Y) * 0.5 * screenHeight}
|
||||||
|
|
||||||
|
if player.position.X < bboxWorldMin.X {
|
||||||
|
camera.Target.X = player.position.X
|
||||||
|
}
|
||||||
|
if player.position.Y < bboxWorldMin.Y {
|
||||||
|
camera.Target.Y = player.position.Y
|
||||||
|
}
|
||||||
|
if player.position.X > bboxWorldMax.X {
|
||||||
|
camera.Target.X = bboxWorldMin.X + (player.position.X - bboxWorldMax.X)
|
||||||
|
}
|
||||||
|
if player.position.Y > bboxWorldMax.Y {
|
||||||
|
camera.Target.Y = bboxWorldMin.Y + (player.position.Y - bboxWorldMax.Y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func clamp(zoom float32, min float32, max float32) float32 {
|
||||||
|
if zoom < min {
|
||||||
|
return min
|
||||||
|
}
|
||||||
|
if zoom > max {
|
||||||
|
return max
|
||||||
|
}
|
||||||
|
return zoom
|
||||||
|
}
|
131
examples/core/custom_frame_control/main.go
Normal file
131
examples/core/custom_frame_control/main.go
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
/*******************************************************************************************
|
||||||
|
*
|
||||||
|
* raylib [core] example - custom frame control
|
||||||
|
*
|
||||||
|
* NOTE: WARNING: This is an example for advanced users willing to have full control over
|
||||||
|
* the frame processes. By default, EndDrawing() calls the following processes:
|
||||||
|
* 1. Draw remaining batch data: rlDrawRenderBatchActive()
|
||||||
|
* 2. SwapScreenBuffer()
|
||||||
|
* 3. Frame time control: WaitTime()
|
||||||
|
* 4. PollInputEvents()
|
||||||
|
*
|
||||||
|
* To avoid steps 2, 3 and 4, flag SUPPORT_CUSTOM_FRAME_CONTROL can be enabled in
|
||||||
|
* config.h (it requires recompiling raylib). This way those steps are up to the user.
|
||||||
|
*
|
||||||
|
* Note that enabling this flag invalidates some functions:
|
||||||
|
* - GetFrameTime()
|
||||||
|
* - SetTargetFPS()
|
||||||
|
* - GetFPS()
|
||||||
|
*
|
||||||
|
* Example originally created with raylib 4.0, last time updated with raylib 4.0
|
||||||
|
*
|
||||||
|
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||||
|
* BSD-like license that allows static linking with closed source software
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021-2024 Ramon Santamaria (@raysan5)
|
||||||
|
*
|
||||||
|
********************************************************************************************/
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
rl "github.com/gen2brain/raylib-go/raylib"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
screenWidth = 800
|
||||||
|
screenHeight = 450
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
rl.InitWindow(screenWidth, screenHeight, "raylib [core] example - Custom Frame Control")
|
||||||
|
|
||||||
|
previousTime := rl.GetTime()
|
||||||
|
currentTime := 0.0
|
||||||
|
updateDrawTime := 0.0
|
||||||
|
waitTime := 0.0
|
||||||
|
deltaTime := 0.0
|
||||||
|
|
||||||
|
timeCounter := 0.0
|
||||||
|
position := 0.0
|
||||||
|
pause := false
|
||||||
|
|
||||||
|
targetFPS := 60
|
||||||
|
|
||||||
|
for !rl.WindowShouldClose() {
|
||||||
|
rl.PollInputEvents() // Poll input events (SUPPORT_CUSTOM_FRAME_CONTROL)
|
||||||
|
|
||||||
|
if rl.IsKeyPressed(rl.KeySpace) {
|
||||||
|
pause = !pause
|
||||||
|
}
|
||||||
|
if rl.IsKeyPressed(rl.KeyUp) {
|
||||||
|
targetFPS += 20
|
||||||
|
} else if rl.IsKeyPressed(rl.KeyDown) {
|
||||||
|
targetFPS -= 20
|
||||||
|
}
|
||||||
|
|
||||||
|
if targetFPS < 0 {
|
||||||
|
targetFPS = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if !pause {
|
||||||
|
position += 200 * deltaTime // We move at 200 pixels per second
|
||||||
|
if position >= float64(rl.GetScreenWidth()) {
|
||||||
|
position = 0
|
||||||
|
}
|
||||||
|
timeCounter += deltaTime // We count time (seconds)
|
||||||
|
}
|
||||||
|
|
||||||
|
rl.BeginDrawing()
|
||||||
|
rl.ClearBackground(rl.RayWhite)
|
||||||
|
|
||||||
|
for i := 0; i < rl.GetScreenWidth()/200; i++ {
|
||||||
|
rl.DrawRectangle(200*int32(i), 0, 1, int32(rl.GetScreenHeight()), rl.SkyBlue)
|
||||||
|
}
|
||||||
|
|
||||||
|
rl.DrawCircle(int32(position), int32(rl.GetScreenHeight()/2-25), 50, rl.Red)
|
||||||
|
|
||||||
|
msg := fmt.Sprintf("%03.0f ms", timeCounter*1000)
|
||||||
|
rl.DrawText(msg, int32(position-40), int32(rl.GetScreenHeight()/2-100), 20, rl.Maroon)
|
||||||
|
msg = fmt.Sprintf("PosX: %03.0f", position)
|
||||||
|
rl.DrawText(msg, int32(position-50), int32(rl.GetScreenHeight()/2+40), 20, rl.Black)
|
||||||
|
|
||||||
|
msg = "Circle is moving at a constant 200 pixels/sec,\nindependently of the frame rate."
|
||||||
|
rl.DrawText(msg, 10, 10, 20, rl.DarkGray)
|
||||||
|
msg = "PRESS SPACE to PAUSE MOVEMENT"
|
||||||
|
rl.DrawText(msg, 10, int32(rl.GetScreenHeight()-60), 20, rl.Gray)
|
||||||
|
msg = "PRESS UP | DOWN to CHANGE TARGET FPS"
|
||||||
|
rl.DrawText(msg, 10, int32(rl.GetScreenHeight()-30), 20, rl.Gray)
|
||||||
|
msg = fmt.Sprintf("TARGET FPS: %d", targetFPS)
|
||||||
|
rl.DrawText(msg, int32(rl.GetScreenWidth()-220), 10, 20, rl.Lime)
|
||||||
|
msg = fmt.Sprintf("CURRENT FPS: %d", int(1/deltaTime))
|
||||||
|
rl.DrawText(msg, int32(rl.GetScreenWidth()-220), 40, 20, rl.Lime)
|
||||||
|
|
||||||
|
rl.EndDrawing()
|
||||||
|
|
||||||
|
// NOTE: In case raylib is configured to SUPPORT_CUSTOM_FRAME_CONTROL,
|
||||||
|
// Events polling, screen buffer swap and frame time control must be managed by the user
|
||||||
|
|
||||||
|
rl.SwapScreenBuffer() // We want a fixed frame rate
|
||||||
|
|
||||||
|
currentTime = rl.GetTime()
|
||||||
|
updateDrawTime = currentTime - previousTime
|
||||||
|
|
||||||
|
if targetFPS > 0 { // We want a fixed frame rate
|
||||||
|
waitTime = (1 / float64(targetFPS)) - updateDrawTime
|
||||||
|
if waitTime > 0 {
|
||||||
|
rl.WaitTime(waitTime)
|
||||||
|
currentTime = rl.GetTime()
|
||||||
|
deltaTime = currentTime - previousTime
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
deltaTime = updateDrawTime
|
||||||
|
}
|
||||||
|
|
||||||
|
previousTime = currentTime
|
||||||
|
}
|
||||||
|
|
||||||
|
rl.CloseWindow()
|
||||||
|
}
|
49
examples/core/custom_logging/main.go
Normal file
49
examples/core/custom_logging/main.go
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
rl "github.com/gen2brain/raylib-go/raylib"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
screenWidth = 800
|
||||||
|
screenHeight = 450
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Set custom logger
|
||||||
|
rl.SetTraceLogCallback(customLog)
|
||||||
|
|
||||||
|
rl.InitWindow(screenWidth, screenHeight, "raylib [core] example - Custom Logging")
|
||||||
|
|
||||||
|
rl.SetTargetFPS(60)
|
||||||
|
|
||||||
|
for !rl.WindowShouldClose() {
|
||||||
|
rl.BeginDrawing()
|
||||||
|
rl.ClearBackground(rl.RayWhite)
|
||||||
|
rl.DrawText("Check the console output to see the custom logger in action!", 60, 200, 20, rl.LightGray)
|
||||||
|
rl.EndDrawing()
|
||||||
|
}
|
||||||
|
|
||||||
|
rl.CloseWindow()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Custom logging function
|
||||||
|
func customLog(msgType int, text string) {
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
|
switch rl.TraceLogLevel(msgType) {
|
||||||
|
case rl.LogInfo:
|
||||||
|
fmt.Println("[INFO] : ", now, text)
|
||||||
|
case rl.LogError:
|
||||||
|
fmt.Println("[ERROR] : ", now, text)
|
||||||
|
case rl.LogWarning:
|
||||||
|
fmt.Println("[WARNING] : ", now, text)
|
||||||
|
case rl.LogDebug:
|
||||||
|
fmt.Println("[DEBUG] : ", now, text)
|
||||||
|
default:
|
||||||
|
fmt.Println("[UNKNOWN] : ", now, text)
|
||||||
|
}
|
||||||
|
}
|
260
examples/core/window_flags/main.go
Normal file
260
examples/core/window_flags/main.go
Normal file
|
@ -0,0 +1,260 @@
|
||||||
|
/*******************************************************************************************
|
||||||
|
*
|
||||||
|
* raylib [core] example - window flags
|
||||||
|
*
|
||||||
|
* Example originally created with raylib 3.5, last time updated with raylib 3.5
|
||||||
|
*
|
||||||
|
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||||
|
* BSD-like license that allows static linking with closed source software
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020-2024 Ramon Santamaria (@raysan5)
|
||||||
|
*
|
||||||
|
********************************************************************************************/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
rl "github.com/gen2brain/raylib-go/raylib"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
screenWidth = 800
|
||||||
|
screenHeight = 450
|
||||||
|
)
|
||||||
|
|
||||||
|
// Possible window flags
|
||||||
|
/*
|
||||||
|
FLAG_VSYNC_HINT
|
||||||
|
FLAG_FULLSCREEN_MODE -> not working properly -> wrong scaling!
|
||||||
|
FLAG_WINDOW_RESIZABLE
|
||||||
|
FLAG_WINDOW_UNDECORATED
|
||||||
|
FLAG_WINDOW_TRANSPARENT
|
||||||
|
FLAG_WINDOW_HIDDEN
|
||||||
|
FLAG_WINDOW_MINIMIZED -> Not supported on window creation
|
||||||
|
FLAG_WINDOW_MAXIMIZED -> Not supported on window creation
|
||||||
|
FLAG_WINDOW_UNFOCUSED
|
||||||
|
FLAG_WINDOW_TOPMOST
|
||||||
|
FLAG_WINDOW_HIGHDPI -> errors after minimize-resize, fb size is recalculated
|
||||||
|
FLAG_WINDOW_ALWAYS_RUN
|
||||||
|
FLAG_MSAA_4X_HINT
|
||||||
|
*/
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Set configuration flags for window creation
|
||||||
|
//SetConfigFlags(FLAG_VSYNC_HINT | FLAG_MSAA_4X_HINT | FLAG_WINDOW_HIGHDPI);
|
||||||
|
rl.InitWindow(screenWidth, screenHeight, "raylib [core] example - Window Flags")
|
||||||
|
|
||||||
|
ballPosition := rl.Vector2{X: float32(rl.GetScreenWidth()) / 2.0, Y: float32(rl.GetScreenHeight()) / 2.0}
|
||||||
|
ballSpeed := rl.Vector2{X: 5.0, Y: 4.0}
|
||||||
|
ballRadius := float32(20.0)
|
||||||
|
framesCounter := 0
|
||||||
|
|
||||||
|
rl.SetTargetFPS(60) // Set our game to run at 60 frames-per-second
|
||||||
|
|
||||||
|
for !rl.WindowShouldClose() { // Detect window close button or ESC key
|
||||||
|
if rl.IsKeyPressed(rl.KeyF) {
|
||||||
|
rl.ToggleFullscreen() // modifies window size when scaling!
|
||||||
|
}
|
||||||
|
|
||||||
|
if rl.IsKeyPressed(rl.KeyR) {
|
||||||
|
if rl.IsWindowState(rl.FlagWindowResizable) {
|
||||||
|
rl.ClearWindowState(rl.FlagWindowResizable)
|
||||||
|
} else {
|
||||||
|
rl.SetWindowState(rl.FlagWindowResizable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if rl.IsKeyPressed(rl.KeyD) {
|
||||||
|
if rl.IsWindowState(rl.FlagWindowUndecorated) {
|
||||||
|
rl.ClearWindowState(rl.FlagWindowUndecorated)
|
||||||
|
} else {
|
||||||
|
rl.SetWindowState(rl.FlagWindowUndecorated)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if rl.IsKeyPressed(rl.KeyH) {
|
||||||
|
if !rl.IsWindowState(rl.FlagWindowHidden) {
|
||||||
|
rl.SetWindowState(rl.FlagWindowHidden)
|
||||||
|
}
|
||||||
|
|
||||||
|
framesCounter = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if rl.IsWindowState(rl.FlagWindowHidden) {
|
||||||
|
framesCounter++
|
||||||
|
if framesCounter >= 240 {
|
||||||
|
rl.ClearWindowState(rl.FlagWindowHidden) // Show window after 3 seconds
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if rl.IsKeyPressed(rl.KeyN) {
|
||||||
|
if !rl.IsWindowState(rl.FlagWindowMinimized) {
|
||||||
|
rl.MinimizeWindow()
|
||||||
|
}
|
||||||
|
|
||||||
|
framesCounter = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if rl.IsWindowState(rl.FlagWindowMinimized) {
|
||||||
|
framesCounter++
|
||||||
|
if framesCounter >= 240 {
|
||||||
|
rl.RestoreWindow() // Restore window after 3 seconds
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if rl.IsKeyPressed(rl.KeyM) {
|
||||||
|
// NOTE: Requires FLAG_WINDOW_RESIZABLE enabled!
|
||||||
|
if rl.IsWindowState(rl.FlagWindowMaximized) {
|
||||||
|
rl.RestoreWindow()
|
||||||
|
} else {
|
||||||
|
rl.MaximizeWindow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if rl.IsKeyPressed(rl.KeyU) {
|
||||||
|
if rl.IsWindowState(rl.FlagWindowUnfocused) {
|
||||||
|
rl.ClearWindowState(rl.FlagWindowUnfocused)
|
||||||
|
} else {
|
||||||
|
rl.SetWindowState(rl.FlagWindowUnfocused)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if rl.IsKeyPressed(rl.KeyT) {
|
||||||
|
if rl.IsWindowState(rl.FlagWindowTopmost) {
|
||||||
|
rl.ClearWindowState(rl.FlagWindowTopmost)
|
||||||
|
} else {
|
||||||
|
rl.SetWindowState(rl.FlagWindowTopmost)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if rl.IsKeyPressed(rl.KeyA) {
|
||||||
|
if rl.IsWindowState(rl.FlagWindowAlwaysRun) {
|
||||||
|
rl.ClearWindowState(rl.FlagWindowAlwaysRun)
|
||||||
|
} else {
|
||||||
|
rl.SetWindowState(rl.FlagWindowAlwaysRun)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if rl.IsKeyPressed(rl.KeyV) {
|
||||||
|
if rl.IsWindowState(rl.FlagVsyncHint) {
|
||||||
|
rl.ClearWindowState(rl.FlagVsyncHint)
|
||||||
|
} else {
|
||||||
|
rl.SetWindowState(rl.FlagVsyncHint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bouncing ball logic
|
||||||
|
ballPosition.X += ballSpeed.X
|
||||||
|
ballPosition.Y += ballSpeed.Y
|
||||||
|
if (ballPosition.X >= (float32(rl.GetScreenWidth()) - ballRadius)) || (ballPosition.X <= ballRadius) {
|
||||||
|
ballSpeed.X *= -1.0
|
||||||
|
}
|
||||||
|
if (ballPosition.Y >= (float32(rl.GetScreenHeight()) - ballRadius)) || (ballPosition.Y <= ballRadius) {
|
||||||
|
ballSpeed.Y *= -1.0
|
||||||
|
}
|
||||||
|
|
||||||
|
rl.BeginDrawing()
|
||||||
|
if rl.IsWindowState(rl.FlagWindowTransparent) {
|
||||||
|
rl.ClearBackground(rl.Blank)
|
||||||
|
} else {
|
||||||
|
rl.ClearBackground(rl.White)
|
||||||
|
}
|
||||||
|
|
||||||
|
rl.DrawCircleV(ballPosition, ballRadius, rl.Maroon)
|
||||||
|
rl.DrawRectangleLinesEx(
|
||||||
|
rl.Rectangle{
|
||||||
|
Width: float32(rl.GetScreenWidth()),
|
||||||
|
Height: float32(rl.GetScreenHeight()),
|
||||||
|
},
|
||||||
|
4, rl.White,
|
||||||
|
)
|
||||||
|
|
||||||
|
rl.DrawCircleV(rl.GetMousePosition(), 10, rl.DarkBlue)
|
||||||
|
|
||||||
|
rl.DrawFPS(10, 10)
|
||||||
|
|
||||||
|
rl.DrawText(
|
||||||
|
fmt.Sprintf("Screen Size: [%d, %d]", rl.GetScreenWidth(), rl.GetScreenHeight()),
|
||||||
|
10,
|
||||||
|
40,
|
||||||
|
10,
|
||||||
|
rl.Green,
|
||||||
|
)
|
||||||
|
|
||||||
|
// Draw window state info
|
||||||
|
rl.DrawText("Following flags can be set after window creation:", 10, 60, 10, rl.Gray)
|
||||||
|
if rl.IsWindowState(rl.FlagFullscreenMode) {
|
||||||
|
rl.DrawText("[F] FLAG_FULLSCREEN_MODE: on", 10, 80, 10, rl.Lime)
|
||||||
|
} else {
|
||||||
|
rl.DrawText("[F] FLAG_FULLSCREEN_MODE: off", 10, 80, 10, rl.Maroon)
|
||||||
|
}
|
||||||
|
if rl.IsWindowState(rl.FlagWindowResizable) {
|
||||||
|
rl.DrawText("[R] FLAG_WINDOW_RESIZABLE: on", 10, 100, 10, rl.Lime)
|
||||||
|
} else {
|
||||||
|
rl.DrawText("[R] FLAG_WINDOW_RESIZABLE: off", 10, 100, 10, rl.Maroon)
|
||||||
|
}
|
||||||
|
if rl.IsWindowState(rl.FlagWindowUndecorated) {
|
||||||
|
rl.DrawText("[D] FLAG_WINDOW_UNDECORATED: on", 10, 120, 10, rl.Lime)
|
||||||
|
} else {
|
||||||
|
rl.DrawText("[D] FLAG_WINDOW_UNDECORATED: off", 10, 120, 10, rl.Maroon)
|
||||||
|
}
|
||||||
|
if rl.IsWindowState(rl.FlagWindowHidden) {
|
||||||
|
rl.DrawText("[H] FLAG_WINDOW_HIDDEN: on", 10, 140, 10, rl.Lime)
|
||||||
|
} else {
|
||||||
|
rl.DrawText("[H] FLAG_WINDOW_HIDDEN: off", 10, 140, 10, rl.Maroon)
|
||||||
|
}
|
||||||
|
if rl.IsWindowState(rl.FlagWindowMinimized) {
|
||||||
|
rl.DrawText("[N] FLAG_WINDOW_MINIMIZED: on", 10, 160, 10, rl.Lime)
|
||||||
|
} else {
|
||||||
|
rl.DrawText("[N] FLAG_WINDOW_MINIMIZED: off", 10, 160, 10, rl.Maroon)
|
||||||
|
}
|
||||||
|
if rl.IsWindowState(rl.FlagWindowMaximized) {
|
||||||
|
rl.DrawText("[M] FLAG_WINDOW_MAXIMIZED: on", 10, 180, 10, rl.Lime)
|
||||||
|
} else {
|
||||||
|
rl.DrawText("[M] FLAG_WINDOW_MAXIMIZED: off", 10, 180, 10, rl.Maroon)
|
||||||
|
}
|
||||||
|
if rl.IsWindowState(rl.FlagWindowUnfocused) {
|
||||||
|
rl.DrawText("[G] FLAG_WINDOW_UNFOCUSED: on", 10, 200, 10, rl.Lime)
|
||||||
|
} else {
|
||||||
|
rl.DrawText("[U] FLAG_WINDOW_UNFOCUSED: off", 10, 200, 10, rl.Maroon)
|
||||||
|
}
|
||||||
|
if rl.IsWindowState(rl.FlagWindowTopmost) {
|
||||||
|
rl.DrawText("[T] FLAG_WINDOW_TOPMOST: on", 10, 220, 10, rl.Lime)
|
||||||
|
} else {
|
||||||
|
rl.DrawText("[T] FLAG_WINDOW_TOPMOST: off", 10, 220, 10, rl.Maroon)
|
||||||
|
}
|
||||||
|
if rl.IsWindowState(rl.FlagWindowAlwaysRun) {
|
||||||
|
rl.DrawText("[A] FLAG_WINDOW_ALWAYS_RUN: on", 10, 240, 10, rl.Lime)
|
||||||
|
} else {
|
||||||
|
rl.DrawText("[A] FLAG_WINDOW_ALWAYS_RUN: off", 10, 240, 10, rl.Maroon)
|
||||||
|
}
|
||||||
|
if rl.IsWindowState(rl.FlagVsyncHint) {
|
||||||
|
rl.DrawText("[V] FLAG_VSYNC_HINT: on", 10, 260, 10,
|
||||||
|
rl.Lime)
|
||||||
|
} else {
|
||||||
|
rl.DrawText("[V] FLAG_VSYNC_HINT: off", 10, 260, 10, rl.Maroon)
|
||||||
|
}
|
||||||
|
|
||||||
|
rl.DrawText("Following flags can only be set before window creation:", 10, 300, 10, rl.Gray)
|
||||||
|
if rl.IsWindowState(rl.FlagWindowHighdpi) {
|
||||||
|
rl.DrawText("FLAG_WINDOW_HIGHDPI: on", 10, 320, 10, rl.Lime)
|
||||||
|
} else {
|
||||||
|
rl.DrawText("FLAG_WINDOW_HIGHDPI: off", 10, 320, 10, rl.Maroon)
|
||||||
|
}
|
||||||
|
if rl.IsWindowState(rl.FlagWindowTransparent) {
|
||||||
|
rl.DrawText("FLAG_WINDOW_TRANSPARENT: on", 10, 340, 10, rl.Lime)
|
||||||
|
} else {
|
||||||
|
rl.DrawText("FLAG_WINDOW_TRANSPARENT: off", 10, 340, 10, rl.Maroon)
|
||||||
|
}
|
||||||
|
if rl.IsWindowState(rl.FlagMsaa4xHint) {
|
||||||
|
rl.DrawText("FLAG_MSAA_4X_HINT: on", 10, 360, 10, rl.Lime)
|
||||||
|
} else {
|
||||||
|
rl.DrawText("FLAG_MSAA_4X_HINT: off", 10, 360, 10, rl.Maroon)
|
||||||
|
}
|
||||||
|
|
||||||
|
rl.EndDrawing()
|
||||||
|
}
|
||||||
|
rl.CloseWindow()
|
||||||
|
}
|
115
examples/core/window_letterbox/main.go
Normal file
115
examples/core/window_letterbox/main.go
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"image/color"
|
||||||
|
|
||||||
|
rl "github.com/gen2brain/raylib-go/raylib"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
screenWidth = 800
|
||||||
|
screenHeight = 450
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Enable config flags for resizable window and vertical synchro
|
||||||
|
rl.SetConfigFlags(rl.FlagWindowResizable | rl.FlagVsyncHint)
|
||||||
|
rl.InitWindow(screenWidth, screenHeight, "raylib [core] example - Window Scale Letterbox")
|
||||||
|
rl.SetWindowMinSize(320, 240)
|
||||||
|
|
||||||
|
gameScreenWidth, gameScreenHeight := int32(640), int32(480)
|
||||||
|
|
||||||
|
// Render texture initialization, used to hold the rendering result so we can easily resize it
|
||||||
|
target := rl.LoadRenderTexture(gameScreenWidth, gameScreenHeight)
|
||||||
|
rl.SetTextureFilter(target.Texture, rl.FilterBilinear) // Texture scale filter to use
|
||||||
|
|
||||||
|
colors := getRandomColors()
|
||||||
|
|
||||||
|
rl.SetTargetFPS(60) // Set our game to run at 60 frames-per-second
|
||||||
|
|
||||||
|
for !rl.WindowShouldClose() { // Detect window close button or ESC key
|
||||||
|
// Compute required frame buffer scaling
|
||||||
|
scale := min(float32(rl.GetScreenWidth())/float32(gameScreenWidth),
|
||||||
|
float32(rl.GetScreenHeight())/float32(gameScreenHeight))
|
||||||
|
|
||||||
|
if rl.IsKeyPressed(rl.KeySpace) {
|
||||||
|
// Recalculate random colors for the bars
|
||||||
|
colors = getRandomColors()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update virtual mouse (clamped mouse value behind game screen)
|
||||||
|
mouse := rl.GetMousePosition()
|
||||||
|
virtualMouse := rl.Vector2{
|
||||||
|
X: (mouse.X - (float32(rl.GetScreenWidth())-(float32(gameScreenWidth)*scale))*0.5) / scale,
|
||||||
|
Y: (mouse.Y - (float32(rl.GetScreenHeight())-(float32(gameScreenHeight)*scale))*0.5) / scale,
|
||||||
|
}
|
||||||
|
virtualMouse = rl.Vector2Clamp(
|
||||||
|
virtualMouse,
|
||||||
|
rl.Vector2{},
|
||||||
|
rl.Vector2{X: float32(gameScreenWidth), Y: float32(gameScreenHeight)},
|
||||||
|
)
|
||||||
|
|
||||||
|
// Apply the same transformation as the virtual mouse to the real mouse (i.e. to work with raygui)
|
||||||
|
//rl.SetMouseOffset(
|
||||||
|
// int(-(float32(rl.GetScreenWidth())-(float32(gameScreenWidth)*scale))*0.5),
|
||||||
|
// int(-(float32(rl.GetScreenHeight())-(float32(gameScreenHeight)*scale))*0.5),
|
||||||
|
//)
|
||||||
|
//rl.SetMouseScale(1/scale, 1/scale)
|
||||||
|
|
||||||
|
// Draw everything in the render texture, note this will not be rendered on screen, yet
|
||||||
|
rl.BeginTextureMode(target)
|
||||||
|
|
||||||
|
rl.ClearBackground(rl.White)
|
||||||
|
for i := int32(0); i < 10; i++ {
|
||||||
|
rl.DrawRectangle(0, (gameScreenHeight/10)*i, gameScreenWidth, gameScreenHeight/10, colors[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
text := "If executed inside a window,\nyou can resize the window,\nand see the screen scaling!"
|
||||||
|
rl.DrawText(text, 10, 25, 20, rl.White)
|
||||||
|
text = fmt.Sprintf("Default Mouse: [%.0f , %.0f]", mouse.X, mouse.Y)
|
||||||
|
rl.DrawText(text, 350, 25, 20, rl.Green)
|
||||||
|
text = fmt.Sprintf("Virtual Mouse: [%.0f , %.0f]", virtualMouse.X, virtualMouse.Y)
|
||||||
|
rl.DrawText(text, 350, 55, 20, rl.Yellow)
|
||||||
|
|
||||||
|
rl.EndTextureMode()
|
||||||
|
|
||||||
|
rl.BeginDrawing()
|
||||||
|
rl.ClearBackground(rl.Black)
|
||||||
|
// Draw render texture to screen, properly scaled
|
||||||
|
rl.DrawTexturePro(
|
||||||
|
target.Texture,
|
||||||
|
rl.Rectangle{Width: float32(target.Texture.Width), Height: float32(-target.Texture.Height)},
|
||||||
|
rl.Rectangle{
|
||||||
|
X: (float32(rl.GetScreenWidth()) - float32(gameScreenWidth)*scale) * 0.5,
|
||||||
|
Y: (float32(rl.GetScreenHeight()) - float32(gameScreenHeight)*scale) * 0.5,
|
||||||
|
Width: float32(gameScreenWidth) * scale,
|
||||||
|
Height: float32(gameScreenHeight) * scale,
|
||||||
|
},
|
||||||
|
rl.Vector2{X: 0, Y: 0}, 0, rl.White,
|
||||||
|
)
|
||||||
|
rl.EndDrawing()
|
||||||
|
}
|
||||||
|
rl.UnloadRenderTexture(target)
|
||||||
|
rl.CloseWindow() // Close window and OpenGL context
|
||||||
|
}
|
||||||
|
|
||||||
|
func getRandomColors() []color.RGBA {
|
||||||
|
var colors []color.RGBA
|
||||||
|
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
randomColor := color.RGBA{
|
||||||
|
R: rndUint8(100, 250),
|
||||||
|
G: rndUint8(50, 150),
|
||||||
|
B: rndUint8(10, 100),
|
||||||
|
A: 255,
|
||||||
|
}
|
||||||
|
colors = append(colors, randomColor)
|
||||||
|
}
|
||||||
|
|
||||||
|
return colors
|
||||||
|
}
|
||||||
|
|
||||||
|
func rndUint8(min, max int32) uint8 {
|
||||||
|
return uint8(rl.GetRandomValue(min, max))
|
||||||
|
}
|
47
examples/core/window_should_close/main.go
Normal file
47
examples/core/window_should_close/main.go
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import rl "github.com/gen2brain/raylib-go/raylib"
|
||||||
|
|
||||||
|
const (
|
||||||
|
screenWidth = 850
|
||||||
|
screenHeight = 480
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
rl.InitWindow(screenWidth, screenHeight, "raylib [core] example - window should close")
|
||||||
|
|
||||||
|
rl.SetExitKey(rl.KeyNull) // Disable KEY_ESCAPE to close window, X-button still works
|
||||||
|
|
||||||
|
exitWindowRequested := false // Flag to request window to exit
|
||||||
|
exitWindow := false // Flag to set window to exit
|
||||||
|
|
||||||
|
rl.SetTargetFPS(60) // Set our game to run at 60 frames-per-second
|
||||||
|
|
||||||
|
for !exitWindow {
|
||||||
|
if rl.WindowShouldClose() || rl.IsMouseButtonPressed(rl.KeyEscape) {
|
||||||
|
exitWindowRequested = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if exitWindowRequested {
|
||||||
|
if rl.IsKeyPressed(rl.KeyY) {
|
||||||
|
exitWindow = true
|
||||||
|
} else if rl.IsKeyPressed(rl.KeyN) {
|
||||||
|
exitWindowRequested = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rl.BeginDrawing()
|
||||||
|
rl.ClearBackground(rl.RayWhite)
|
||||||
|
|
||||||
|
if exitWindowRequested {
|
||||||
|
rl.DrawRectangle(0, 100, screenWidth, 200, rl.Black)
|
||||||
|
rl.DrawText("Are you sure you want to exit the program? [Y/N]", 40, 180, 30, rl.White)
|
||||||
|
} else {
|
||||||
|
rl.DrawText("Try to close the window to get confirmation message!", 120, 200, 20, rl.LightGray)
|
||||||
|
}
|
||||||
|
|
||||||
|
rl.EndDrawing()
|
||||||
|
}
|
||||||
|
|
||||||
|
rl.CloseWindow() // Close window and OpenGL context
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue