Imagine Engine - a fast, high performance Swift 2D game engine for Apple's platforms

Last update: Jun 23, 2022

Imagine Engine

CocoaPods Carthage Twitter: @johnsundell

Welcome to Imagine Engine, an ongoing project that aims to create a fast, high performance Swift 2D game engine for Apple's platforms that is also a joy to use. You are hereby invited to participate in this new community to build a tool with an ambitious but clear goal - to enable you to easily build any game that you can imagine.

Fast Core Animation-based rendering

Imagine Engine uses Core Animation as its rendering backend - just like Apple's UI frameworks like UIKit and AppKit do. By leveraging the power of Core Animation's hardware accelerated 2D rendering capabilities, Imagine Engine is able to push lots of pixels onto the screen at the same time. That means more objects, more effects and less restrictions when designing your games.

An easy to use API

Besides its goal of being blazingly fast at rendering & updating your games, Imagine Engine aims to provide an easy to use API that anyone can learn - regardless of game development experience.

Start with just a few lines of code...

let scene = Scene(size: UIScreen.main.bounds.size)

let label = Label(text: "Hello world")
label.position = scene.center
scene.add(label)

let window = GameWindow(scene: scene)
window.makeKeyAndVisible()

...and smoothly scale up as your game grows in complexity on either iOS, macOS or tvOS.

๐ŸŒƒ Scenes present your game content

A scene can be a level, a menu or a "Game over" screen. You can easily switch the active scene of a game. Here's how you can create a scene with a blue background color:

let scene = Scene(size: Size(width: 500, height: 300))
scene.backgroundColor = .blue
game.scene = scene

๐ŸŽญ Actors bring your game to life

Actors are what will make up most of the active objects in any game. They are movable, animatable, can handle collisions and much more. Here's an example of how you can create a player that renders a "Running" animation, and constantly moves to the right:

let player = Actor()
player.animation = Animation(name: "Running", frameCount: 5, frameDuration: 0.15)
player.velocity.dx = 50
scene.add(player)

๐Ÿ“ฆ Easily create platforms and tiled textures with Blocks

Using blocks you can easily tile textures together to form objects that can scale nicely to any size, without having to scale any texture. This is done by stitching together up to 9 different textures to form a block of textures rendered side by side. Here's how you can easily create a block from a folder named "Platform" that contains the textures that should be stitched together:

let block = Block(size: Size(width: 300, height: 300), textureCollectionName: "Platform")
scene.add(block)

๐Ÿ…ฐ๏ธ Render text using Labels

Labels let you add text content to your game. They automatically resize to fit your text content (unless you don't want them to) and can be used to implement things like UI, score counters, etc. Here's an example of adding a label to a scene:

let label = Label(text: "Welcome to my game!")
label.position = scene.center
scene.add(label)

โšก๏ธ Use Events to drive your game logic

Events enable you to quickly script your games to drive your own logic. Imagine Engine's various objects contain built in events that can be used to observe whenever an object was moved, collided with something, etc. You can also define your own events that can be used to communicate between various parts of your code. Here's how you can observe whenever two actors collided with each other:

let player = Actor()
let enemy = Actor()

player.events.collided(with: enemy).observe {
    // Game over
}

๐Ÿƒ Create animations and effects using Actions

Actions let you make objects do something over a period of time, for example moving, resizing, fading in and out etc. Imagine Engine contains a suite of built-in actions and also makes it easy for you to define your own. Here's how an actor can be moved over 3 seconds:

let actor = Actor()
scene.add(actor)
actor.move(byX: 200, y: 100, duration: 3)

๐Ÿ”Œ Easily extend Imagine Engine with Plugins

Instead of relying on subclassing and overriding methods, Imagine Engine is designed to be easily extended through plugins. This enables you to share code between different games, and create new open source projects that add new functionality to the engine. You can attach plugins to most of Imagine Engine's objects, here's an example of creating a plugin that creates a new actor every time the scene is clicked or tapped:

class MyPlugin: Plugin {
    func activate(for scene: Scene, in game: Game) {
        scene.events.clicked.observe { scene in
            let actor = Actor()
            actor.position = scene.center
            scene.add(actor)
        }
    }
}

๐Ÿ• Precise timing using Timelines

Managing time and delayed events can sometimes be tricky in game development. Imagine Engine aims to make this a lot easier through its timeline API, that enables you to schedule single or repeated events in the future without having to worry about screen updates or if the game is paused. Here's how you can add an event to spawn a new enemy every 5 seconds:

scene.timeline.repeat(withInterval: 5) {
    let enemy = Actor()
    enemy.animation = Animation(name: "Enemy", frameCount: 5, frameDuration: 0.15)
    scene.add(enemy)
}

Platform support

  • ๐Ÿ“ฑ iOS 9 or later
  • ๐Ÿ–ฅ macOS 10.12 or later
  • ๐Ÿ“บ tvOS 10 or later

Imagine Engine supports all of Apple's platforms except watchOS. The API is also completely cross platform, so that you don't have to scatter #ifs all over your game code.

Xcode templates

Imagine Engine ships with Xcode project templates that makes it super easy to get started with a new project. You can find more information & installation instructions here.

Let's get started!

To get started, check out the tutorials section, which contains tutorials that will walk you through building your first Imagine Engine-powered games with very few lines of code. No previous game developer experience required!

If you need help getting started or have a question about Imagine Engine, feel free to open an issue! We're a friendly community who would love to get more people involved.

Imagine Engine is in active development, with new features being constantly added. Need something new, or want to help out making the engine even more capable? Browse and create new issues or open a PR.

Lets build some awesome games together! ๐Ÿš€

GitHub

https://github.com/JohnSundell/ImagineEngine
Comments
  • 1. Adds errorMode to TextureManager for Debug Mode.

    Issue number: #61

    @JohnSundell Could you throw some light on how this could be tested? Considering that the scenarios to be tested would be

    • Ensure there is no action when IgnoreError is selected
    • Ensure there is logging when LogError is selected
    • Ensure there is assert when TriggerAssertOnError is selected

    I am not entirely confident of the changes without the tests.

    Reviewed by vijaytholpadi at 2017-11-12 10:55
  • 2. Dialogue Plugin

    Hey there! I'm trying to create a plugin that handles dialogues. I could use some help :D The final goal is a plugin that can be added on any kinda games. Something simple like a sign in a village or even a complex dialogue with characters.

    Iโ€™ve two games (dialogue system or something like that) in mind:

    Fire Emblem Heroes uspiuus

    • Traditional RPG style (character is showed while talking)
    • Character animation (the character usually changes his pose/posture/sprite)

    Undertale screen shot 2018-01-11 at 18 24 13

    • Simple
    • Animated words (single and all the text) (Label supports animation now o/)

    I tried to play with those in mind on a Playground. What I got so far:

    • Reading a local JSON (Text, Character (name), Animation (Character sprite))
    • Update method that call the next item in array (JSON). Everything is working so far.
    screen shot 2018-01-11 at 16 58 23 screen shot 2018-01-11 at 18 49 38(Raven of Fire Emblem. Testing)

    Next:

    • Multiline (I was using \n on JSON haha) (HIGH PRIORITY!)
    • Simple animations (Label and Actor already got a lot what I need like fade out/in and so on)
    • Typing effect (as an option)
    • Adapt the plugin to be either simple (only a box n text), normal (name + dialogue) and dialogue (character sprite) and for any screen size

    This is it! Iโ€™m a beginner and I donโ€™t know if I can create something like that using clean and elegant code or best practices at all (But Iโ€™m learning. Reading Imagine Engine is helping me a lot). I could use some direction or tips. Thanks and sorry for all English mistake :D

    Reviewed by Alex88WH at 2018-01-11 21:12
  • 3. Add fastlane to ImagineEngine for automated tests

    So much prettier now โค๏ธ

    I'm not 100% sure if we need to specify the macOS destination value, or if it just works on Travis, let's see if the build is ๐Ÿ’š

    Reviewed by KrauseFx at 2018-01-08 19:08
  • 4. add isInContact API methods for an Actor.

    This PR adds the API methods requested in https://github.com/JohnSundell/ImagineEngine/issues/109 for knowing if one Actor is in contact with another actor or a Block.

    Reviewed by pablocarmu at 2018-01-17 07:16
  • 5. Strange behaviour when repeating RotateAction with a delta

    If you try to repeat a RotateAction with a delta the rotation is reset to the original value each time the rotation action repeats. I expected the rotation to continue at a constant rate until cancelled.

    Example code:

    actor.repeat(RotateAction(delta: 3.14, duration: 1))

    I think all that is needed is to add this function to MetricAction:

    public override func start(for object: Object) {
        startMetric = nil
    }
    

    This is consistent with how MoveAction is implemented.

    Reviewed by mattiashagstrand at 2017-11-15 19:17
  • 6. CI: Add Danger

    This change adds Danger to the CI process, to show linting warnings inline and whether a PR is too big or lacks a description.

    For now this uses the standard Ruby version of Danger, but we should totally use Danger-Swift & Marathon in the future.

    Reviewed by JohnSundell at 2017-11-12 10:50
  • 7. Add convenience API to add multiple objects to a scene at once

    It would be nice to have a convenience API that lets the user add multiple actors, blocks or labels to a scene at once. So that you can write code like this:

    let actorA = Actor()
    let actorB = Actor()
    let actorC = Actor()
    scene.add(actorA, actorB, actorC)
    
    let blockA = Block(size: .zero, textureCollectionName: "")
    let blockB = Block(size: .zero, textureCollectionName: "")
    let blockC = Block(size: .zero, textureCollectionName: "")
    scene.add(blockA, blockB, blockC)
    
    let labelA = Label()
    let labelB = Label()
    let labelC = Label()
    scene.add(labelA, labelB, labelC)
    

    The convenience API can be added as an extension on Scene ๐Ÿ‘

    Reviewed by JohnSundell at 2017-11-11 11:37
  • 8. [Help] How to use ImagineEngine in native development

    Hi John, I'm opening this issue after our small twitter ping-pong chat. I'm here to ask for your help on how to incorporate the ImagineEngine in the context of a native app. I started messing around the playground you created, and then I tried to port it to a full fledged app starting a blank application. I went through the code and came up that the GameViewController is a (closed) subclass of UIViewController, and that we have to feed it the Scene class where we describe the state of the components, actors and stuff. However (I didn't spend a lot of time into it yet), I couldn't get it to load the playground code in the app as I wasn't able to figure out how to transition between viewcontrollers (is that even possible?). A full fledged app would have more than one gameviewcontroller? Is the game flow represented only by scenes in one gameviewcontroller?

    Thanks in advance

    Reviewed by pmlbrito at 2017-11-06 14:35
  • 9. Issue153 - make Label conform to scalable

    I made Label conform to Scalable protocol and supported it with a test function.

    Since it's my first Open Source contribution (apart from some localization PRs), I'm ready for your criticism :)

    Reviewed by ghost at 2018-01-17 20:24
  • 10. Removing colliding actor sometimes causes extra collision event

    Here is a test that triggers this bug:

    func testObservingCollisionWhenCollidingActorIsRemoved() {
        actor.size = Size(width: 100, height: 100)
        actor.position = Point(x: 300, y: 300)
    
        let otherActor = Actor(size: Size(width: 100, height: 100))
        game.scene.add(otherActor)
    
        var numberOfCollisions = 0
    
        actor.events.collided(with: otherActor).observe {
            otherActor.remove()
            numberOfCollisions += 1
        }
    
        XCTAssertEqual(numberOfCollisions, 0)
    
        // Move the actor to trigger collision detection but not so far that it
        // collides with the other actor.
        actor.position = Point(x: 200, y: 0)
        // Move the other actor so that it collides with the actor
        otherActor.position = actor.position
    
        XCTAssertEqual(numberOfCollisions, 1)
    }
    

    Note that for this bug to happen the actor that is removed must be the one that triggers the collision.

    Doing the following in Grid fixes the bug:

    private func detectCollisions(between actor: Actor, and otherActors: Set<Actor>) {
        for otherActor in otherActors {
            guard otherActor !== actor else {
                continue
            }
    
            guard otherActor.scene != nil else {
                continue
            }
    
            guard actor.scene != nil else {
                continue
            }
    
            ...
        }
    }
    

    I haven't created a PR yet because even though all tests pass I'm unsure if this can cause other bugs. What do you thing @JohnSundell ?

    Reviewed by mattiashagstrand at 2017-11-28 17:36
  • 11. Best approach for implementing gravity in a platformer?

    I'm trying to make a Mario style platformer with Imagine. Nearly everything has been incredibly easy and intuitive so far, kudos! I would love to get some advice on the best approach to implementing gravity. The two approaches you mentioned on Twitter are:

    1. Use vertical velocity to continuously move the player downwards - pretty straightforward
    2. Create a custom action - curious on the best approach here

    Any code examples or tips would be greatly appreciated, thanks!

    Reviewed by illyabusigin at 2017-11-27 22:39
  • 12. Does this engine still work?

    I'm very interested in using this engine, but it doesn't look like it's been supported for years. Does anyone know if it still functions well? I'm willing to try once I finish another project I've been working on. I want to use this engine to replace spritekit in one of my games.

    Reviewed by JamesCastrejon at 2022-03-04 18:51
  • 13. Tutorials fail with `No such module 'ImagineEngine'`

    image I've never used xcode or swift before so I assume I must be doing something wrong.. Perhaps I need to import the module alternatively before declaring it? But it is included as part of the source files.

    Reviewed by jnc-nj at 2021-05-23 02:30
  • 14. Moving to Swift Package Manager

    Made a single Package to englobe all of ImagineEngine, changed Bundle.main to Bundle.module in tests and removed old project and podspec.

    Builds on Mac, iOS and tvOS. Tests passed on Mac, iOS and tvOS.

    Reviewed by Lancelotbronner at 2020-09-03 19:51
  • 15. What's the usage of the rootNode in Timeline?

    Firstly, I'd say sorry to ask question here. I read the Timeline.swift file, there is a private Node class in it. But I didn't see anywhere outside invoking it. So, could you help me to understand the usage of the Node? Many thanks.

    Reviewed by evanxlh at 2019-11-20 14:56
  • 16. Add Xcode template for tvOS projects

    Issue #161

    This change adds an Xcode template for generating Imagine Engine game project for tvOS.

    Just a heads-up; I've never actually created a project template for Xcode before so thought it would be nice to try it out and also contributing a little bit ;)

    Reviewed by markuspersson at 2018-05-04 19:14
A little arcade game that uses SwiftUI as a game engine.
A little arcade game that uses SwiftUI as a game engine.

SwiftUI Game A little arcade game that uses SwiftUI as a game engine :) Just copy the code into the Blank playgroundbook in Swift Playgrounds app on i

Apr 8, 2022
๐Ÿฆ ๐Ÿƒ ๐Ÿ“ฑ An animal matching puzzle card gameโ€“ย built with turn-based game engine boardgame.io and React-Native + React-Native-Web
๐Ÿฆ ๐Ÿƒ ๐Ÿ“ฑ An animal matching puzzle card gameโ€“ย built with turn-based game engine boardgame.io and React-Native + React-Native-Web

Matchimals.fun an animal matching puzzle card game ?? ?? ?? Download for iOS from the App Store ?? Download for Android from the Google Play Store ??

Jun 15, 2022
A game engine built with SDL and Swift.

Lark A game engine made with Swift and SDL. This is a pre-alpha work-in-progress. Don't try to use this unless you really know what you're doing. I ba

Mar 11, 2022
2D ECS game engine in 100% Swift + SwiftUI for iOS, macOS, tvOS
2D ECS game engine in 100% Swift + SwiftUI for iOS, macOS, tvOS

OctopusKit A 2D game engine based on ECS and written in 100% Swift for iOS, macOS and tvOS. If you've tried making a game in Swift while sticking to t

Jun 28, 2022
The one and only open source 4X MMO mid-core strategy game for iOS. Similar to Game of War and Mobile Strike

4X MMO Strategy Game for iOS I have spent 4 years of my life and a significant amount of money into completing this game and I hope you enjoy it. For

Jun 8, 2022
Switshot is a game media manager helps you transfer your game media from Nintendo Switch to your phone, and manage your media just few taps.
Switshot is a game media manager helps you transfer your game media from Nintendo Switch to your phone, and manage your media just few taps.

Switshot is a game media manager helps you transfer your game media from Nintendo Switch to your phone, and manage your media just few taps.

Mar 29, 2022
Gravity Switch - A dynamic game that integrates swiping and tapping to create a fun interactive game

GravitySwitch Gravity Switch is a dynamic game that integrates swiping and tappi

Jan 23, 2022
IOS Spin Game - A simple spin game using SwiftUI
IOS Spin Game - A simple spin game using SwiftUI

IOS_Spin_Game A simple spin game using Swift UI.

Mar 23, 2022
FlagGuess-Game - A game to collect points by guessing flags
FlagGuess-Game - A game to collect points by guessing flags

Flag Guess Game A game to collect points by guessing flags! Wrong Choice

Apr 18, 2022
Glide is a SpriteKit and GameplayKit based engine for building 2d games easily
Glide is a SpriteKit and GameplayKit based engine for building 2d games easily

Glide is a SpriteKit and GameplayKit based engine for building 2d games easily, with a focus on side scrollers. Glide is developed with Swift and works on iOS, macOS and tvOS.

Jun 16, 2022
A snake engine written in SpriteKit for all Apple devices.
A snake engine written in SpriteKit for all Apple devices.

A snake engine written in SpriteKit for all Apple devices. โญ Features Fully tested engine functionality. Framework based, super easy to integrate in d

Mar 13, 2022
A simple Chess game for iOS, written in Swift
A simple Chess game for iOS, written in Swift

Swift Chess This is a simple chess game for iPhone and iPad, designed for novice players. It features a very simple AI that plays much like a beginner

Jun 23, 2022
iOS Swift Game - Push SpriteKit to the limit
iOS Swift Game - Push SpriteKit to the limit

iOS Swift Project - Legend Wings - EverWing's Mini Clone EverWing is a popular action game. Survive as much you can, earn gold, and upgrade/purchase n

Jun 11, 2022
Simple memory game written in Swift 4 using VIPER Architecture.
Simple memory game written in Swift 4 using VIPER Architecture.

Viper Memory Game Simple memory game written in Swift 4.2 using VIPER Architecture. The Memory Game is a deck of cards where the user needs to find ma

Jun 6, 2022
Letter Quiz game with swift for ios
Letter Quiz game with swift for ios

LETTERQUIZ Title: LetterQuiz Category: Game Genre: Trivia, Puzzle, Quiz Platform: IOS Language: Swift 4.0 Available at: Developer: Martin Bruland Crea

Feb 3, 2022
it's simple swift find different colour game.
it's simple swift find different colour game.

SWift_FindColourGame it's simple swift find different colour game. This is a sample project students or kids can use to learn how to find difference c

Oct 20, 2021
A Peggle game implemented in swift using UIKit
A Peggle game implemented in swift using UIKit

Ocean Peggle Author: Tian Fang This is a Peggle game implemented in swift using UIKit. Credits octopus png from pngtree.com pumpkin png from pngtree.c

Mar 8, 2022
War card game built with swift

Overview Do you love card games? Well here goes a very old, fun card game you can play! This is based off of luck and requires no skill. You deal card

Nov 12, 2021
Game in development in Swift through XCode.

Space-Cruise-App Est. September 2021 Author: Tony Le Game in development in Swift through XCode. This game lets user dodge and shoot incoming enemies.

Nov 14, 2021