Giter Site home page Giter Site logo

stregasgate / raylib Goto Github PK

View Code? Open in Web Editor NEW
103.0 2.0 13.0 2.34 MB

A Swift package for Raylib. Builds Raylib from source so no need to fiddle with libraries. Just add as a dependency in you game package and go!

License: MIT License

Swift 9.43% C 88.62% CMake 0.13% Makefile 1.10% Zig 0.14% HTML 0.59%
gamedev raylib raylib-swift swift

raylib's Introduction

Raylib for Swift

Windows macOS Linux

Twitter YouTube Reddit Discord

This package brings Raylib to Swift.

Raylib for Swift uses Swift's C interoperability and compiler to build Raylib from source code. Just add the package as a dependency (to your swift executable package) and start making games!

Requirements & Setup

On Windows and macOS you only need Swift. For Linux, see install required libraries.

Creating a new project

1. Create a Swift package for your project.

$ cd my/projects/folder/path
$ mkdir MyGame
$ cd MyGame
$ swift package init --type executable

2. Edit the newly created Package.swift to add Raylib to the dependencies array:

.package(url: "https://github.com/STREGAsGate/Raylib.git", branch: "master")

On Windows and macOS you only need Swift. For linux, see install required libraries.

Note: .branch("master") is required, you cannot use tags, commits, or versions. Swift doesn't allow unsafe build flags for specific versions and build flags are required to build Raylib, so you must use master at this time or you will get an error from SwiftPM.

3. Add the following to the static func main() in MyGame.swift.

    let screenWidth: Int32 = 800
    let screenHeight: Int32 = 450

    Raylib.initWindow(screenWidth, screenHeight, "MyGame")
    Raylib.setTargetFPS(30)
    let randomColors: [Color] = [.blue, .red, .green, .yellow, .darkBlue, .maroon, .magenta]
    var ballColor: Color = .maroon
    var ballPosition = Vector2(x: -100, y: -100)
    var previousBallPosition: Vector2
    while Raylib.windowShouldClose == false {
        // update
        previousBallPosition = ballPosition
        ballPosition = Raylib.getMousePosition()
        if Raylib.isMouseButtonDown(.left) {
            ballColor = randomColors.randomElement() ?? .black
        }
        let size = max(abs(ballPosition.x - previousBallPosition.x) + abs(ballPosition.y - previousBallPosition.y), 10)

        // draw
        Raylib.beginDrawing()
        Raylib.clearBackground(.rayWhite)
        Raylib.drawText("Hello, world!", 425, 25, 25, .darkGray)
        Raylib.drawCircleV(ballPosition, size, ballColor)
        Raylib.drawFPS(10, 10)
        Raylib.endDrawing()
    }
    Raylib.closeWindow()

About

Original Raylib global functions are now static members of the Raylib type.

Raylib.initWindow(screenWidth, screenheight, "My First Raylib Window!")

It's a goal of this project to have all the global functions available on their respective types as members.

As an example Image, now has new initializers.

let image = Image(color: .green, width: 256, height: 256)

Doing this for the entire API will increase discoverability and make Raylib for Swift a more Swifty experience.

raylib's People

Contributors

alexito4 avatar mgrider avatar xirov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

raylib's Issues

Can't make sense of the README.

I tried to follow the README, but it didn't make sense. Steps 1 and 2 were fine (and I could build the project with the dependency, without any code of my own), but Step 3 was completely confusing:

  1. Add the following to the static func main() in MyGame.swift.

The swift package init --type executable command does not create a file named MyGame.swift. There's only main.swift (inside ~/Projects/MyGame/Sources). And, I cannot add the provided code "to the static func main()", as that construct doesn't exist in Swift. A static func must be a method.

Note: The main.swift file only contains print("hello world") by default. There's no class or struct or anything to add to.

It looks like a really fun project. I just couldn't follow the tutorial. :(

Shader example?

The shader stuff appears to be wrapped but it silently halts the program for me when I try to load one:

let rscFS = "/home/arckex/Raylib/Sources/Example/resources/shaders/glsl330/bloom.fs"
let rscFSTXT = try String(contentsOfFile: rscFS)
let rscVS = "/home/arckex/Raylib/Sources/Example/resources/shaders/glsl330/base.vs"
let rscVSTXT = try String(contentsOfFile: rscVS)
let shader = Raylib.loadShaderFromMemory(rscVSTXT, rscFSTXT)

Can you make a min example of loading a shader? Thanks so much

Pseudo-RNG does not seem to work

[Raylib] - [Pseudo-RNG does not seem to work]

Description
Since the .getRandomValue(min: , max:) method seems to be deprecated, I tried using Int32.random(in:)/Int.random(in:) as stated in the deprecation message. However, these methods do not seem to be affected by the .setRandomSeed() method. I even attempted to set the seed via srand() and srandom(), but this did not work either.

Steps to Reproduce

  1. Set the seed via .setRandomSeed() once (I did it in the beginning immediately after window initialization).
  2. Generate a random value using the method Int32.random(in:).
  3. Print the generated value to the console.
  4. Restart the application and repeat steps 1-3 using the exact same code/seed.

Current Behavior
The generated values are not identical, nor are their sequences anywhere near identical. When using .getRandomValue(min: , max:), everything works fine.

Relevant Screenshots/Logs
-

Environment
Operating System: Ubuntu 20.04.6 LTS
Project Version: master
Swift Version: 5.6.2
Target: x86_64-unknown-linux-gnu

Troubleshooting Steps Taken
I tried only setting the seed once at the very beginning. I used a hardcoded seed of '123'. I tried setting the seed via .setRandomSeed() as well as srand() and srandom(). For getting a pseudo-random value, I tried Int.random(in:), Int(random()), Int32.random(in:), as well as UInt32.random(in:). After getting a value from the PRNG, I restarted the application and did the exact same thing as before, expecting to get the exact same value. But the value I received was always different. I also tried replicating this in a playground environment, getting different values/sequences there as well.

Possible Solutions
Maybe the problem is with my usage, but I'm uncertain.

Additional Information
You can use .getRandomValue(min: , max:) as a workaround, regardless of its deprecation.

Physics support?

This library is great, thanks!

Am I correct that the physics library isn't included in this wrap?

Please indicate that `.branch("master")` is necessary to avoid a build error regarding unsafe build flags for Raylib and GLFW

Hello! Thank you very much for creating this Swift package to streamline working with Raylib.

While testing out your library, I tried using from: "4.0.0" for the package and encountered this error:

error: the target '_RaylibC' in product 'Raylib' contains unsafe build flags

Then I discovered this thread regarding the use of .unsafeFlags() and .branch() / from - https://forums.swift.org/t/question-about-contains-unsafe-build-flags-in-spm/47677

I understand that since your library needs to use .unsafeFlags() to compile Raylib and GLFW together via clang -x objective-c -fno-obj-arc, could you please document that users of this library must use .branch("master")?

package definition xcode

I was able to get this running in xcode 13.1, but I had to modify the package file slightly.

I had to modify the package and target thusly:

`
.package(name: "Raylib", url: "https://github.com/STREGAsGate/Raylib.git", .branch("master"))

...
.target(
name: "",
dependencies: ["Raylib"]),
`

without this, I would receive the error "No such module 'Raylib'" when I tried to import "Raylib" in my swift files. Not sure if it's an update with newer versions of Swift or not.

This is a fantastic project. Thanks for putting this work together.

rlLoadTexture EXC_BAD_ACCESS

Hello!
It's most likely I'm doing something wrong...

Let's say I'm trying to load image:
public var fish1 = Raylib.loadImage(Bundle.module.path(forResource: "fish1", ofType: "png", inDirectory: "Resources") ?? "")
And it's loaded successfully (output from terminal):
File loaded successfully
INFO: IMAGE: Data loaded successfully (256x256 | R8G8B8A8 | 1 mipmaps)

But then I'm trying to load texture:
public var fishTexture1 = Raylib.loadTextureFromImage(fish1)
And it bring back to _Sources/RaylibC/UnmodifiedRaylibCSrc/rlgl and rlLoadTexture (line number 2688) with EXC_BAD_ACCESS
Thanks in advance for your help!

Codepoints from .utf8 presentation not mapped correctly

Title: Bug in Font Loading Method - Incorrect Character Conversion

Description:

I'm using the 'STREGAsGate/Raylib' library, which provides a method called loadFontEx(...) to load font files into the VRAM. However, it seems that the current implementation of this method is using .utf8 to convert characters to code points, which results in incorrect behavior. Instead, the method should be using .unicodeScalars for accurate code point conversion.

Here is the original implementation of loadFontEx(...):

/// Load font from file with extended parameters
@inlinable
static func loadFontEx(_ fileName: String, _ fontSize: Int32, _ fontChars: [Character]? = nil) -> Font {
    return fileName.withCString { cString in
        if fontChars == nil {
            return RaylibC.LoadFontEx(cString, fontSize, nil, 0)
        } else {
            var chars: [Int32] = fontChars!.compactMap({$0.utf8.first}).map({Int32($0)})
            return chars.withUnsafeMutableBufferPointer { bufferPointer in
                return RaylibC.LoadFontEx(cString, fontSize, bufferPointer.baseAddress, Int32(bufferPointer.count))
            }
        }
    }
}

To fix this bug, I suggest modifying the implementation to use .unicodeScalars for character to code point conversion. Here is the updated implementation:

/// Load font from file with extended parameters (fixed bug in character conversion)
@inlinable
static func loadFontEx(_ fileName: String, _ fontSize: Int32, _ fontChars: [Character]? = nil) -> Font {
    return fileName.withCString { cString in
        if fontChars == nil {
            return RaylibC.LoadFontEx(cString, fontSize, nil, 0)
        } else {
            var chars: [Int32] = fontChars!.map({ Int32($0.unicodeScalars.first?.value ?? 0 )})
            return chars.withUnsafeMutableBufferPointer { bufferPointer in
                return RaylibC.LoadFontEx(cString, fontSize, bufferPointer.baseAddress, Int32(bufferPointer.count))
            }
        }
    }
}

By making this change, the font loading method should now handle character to code point conversion correctly, resolving the issue with incorrect font loading.

For further information/reproducing take a look into this discord conversation on the Raylib server. If you have any questions or need further assistance, feel free to reach out to me. I'd be happy to help!

program quits when using async/await

When using async/await, The program quits. I have tried only using Raylib commands on the Main Actor and main thread. Still crashes if there is an await.

I got it working with the following work around; however, this ties up the main thread with a semaphore.

    @MainActor static func main() {
        Raylib.initWindow(800, 450, "test")
        Raylib.setTargetFPS(60)
        
        while Raylib.windowShouldClose == false {
            let semaphore = DispatchSemaphore(value: 0)
            DispatchQueue.global().async {
                Task {
                    await update()
                    semaphore.signal()
                }
            }
            semaphore.wait()
            draw()
        }
        
        Raylib.closeWindow()
    }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.