Coder Social home page Coder Social logo

robreuss / virtualgamecontroller Goto Github PK

View Code? Open in Web Editor NEW
461.0 27.0 44.0 105.15 MB

Software-based game controllers for iOS, tvOS, OS X and watchOS in Swift 4.2.

License: MIT License

Objective-C 10.45% Swift 68.52% Makefile 20.93% C 0.10%

virtualgamecontroller's Introduction

Language Platforms OS X | iOS | watchOS | tvOS License MIT Carthage CocoaPods Travis

Logo

Virtual Game Controller

Overview

Virtual Game Controller (VGC) makes it simple to create software-based controllers for games and other purposes, enabling you to easily control one iOS device with another (or multiple other devices, such as in the case of a tvOS game). The framework wraps Apple's GCController Framework API, making it easy to simulatenously support both your own software-based controllers and hardware-based controllers that conform to the MFi standard, with a single code base. The GCController API supports both reading the values of game controller elements directly (polling) as well as registering to be called when a value changes using a block-based handler. VGC operates the same way and supports all of the features of the GCController API for both software- and hardware-based controllers.

While VGC is typically used to have an iOS device act as a controller for another iOS or tvOS device, it can also be used where two iOS devices act as peers, with a shared game environment presented on each device. In that type of implementation, user inputs through on-screen controls flow through the framework and are processed by the handlers on both devices. VGC supports easy creation of custom element types, including images and Data types, so that game logic such as state can be coordinated between the two devices. This capability is perfect for table-top games with two players, including ARKit games where you want both players to see and act on a common game space.

Important: The framework comes with a rich set of sample apps for iOS, tvOS, and MacOS, including both SceneKit and SprikeKit examples. A considerable amount of documentation appears as comments in the iOS Peripheral and iOS Central sample projects, and using those two projects on seperate devices is the best place to start. Next, consider trying the SceneKitShipDemo, which really gives a feel for how the framework can enhance a game. If you have trouble getting the sample projects to work or any other questions, contact me at [email protected].

Features

  • Wraps Apple's GameController framework API (GCController)
  • Create software-based controllers
  • High performance
  • <5ms latency (including processing) when sending Doubles (64-bit words) at 60/sec
  • Both closures and polling supported for processing input
  • Support for peer mode
  • Controller forwarding
  • Simple bidirectional communication on a shared channel
  • Device motion support
  • Custom elements
  • Custom element mapping
  • WiFi-based
  • Ability to enhance inexpensive slide-on/form-fitting controllers
  • iCade controller support
  • Support for snapshots compatible with GCController snapshots
  • Framework-based, no dependencies

Requirements

  • iOS 9.0+ / MacOS 10.9+
  • Xcode 9 / Swift 4.2 / Objective C

Platform Support

  • iOS
  • tvOS
  • MacOS
  • watchOS

Some Use Cases

VirtualGameController is a drop-in replacement for Apple's Game Controller framework, so it can be easily integrated into existing controller-based games.

VirtualGameController may be useful in the following cases:

  • Developing and supporting software-based controllers. Enable your users to use their iPhone, iPad or Apple Watch to control your game, leveraging 3d touch and motion input. Especially useful with Apple TV. Inputs are flowed through the GCController API (that is, through the MFi profiles) and so your software-based controller will appear as a hardware-based controller. Easily send information from your game to your software controller (bidirectional communication). The API for creating a software-based controller is simple and easy-to-use.
  • Providing a pair of users with a shared gaming experience (ARKit). VGC makes it easy to implement a shared controller environment, so that a pair of users playing the same game on their respective devices will receive controller input data from both devices (users). A single set of block-based handlers can be implemented to handle input from both on-screen controls and controller data received from the opposite device. VGC also makes it easy to manage state across the devices by using custom elements.
  • Creating a hybrid hardware/software controller using controller forwarding.
  • Supporting large numbers of controllers for social games. There are no imposed limits on the number of hardware or software controllers that can be used with a game. The two third-party controller limit on the Apple TV can be exceeded using controller forwarding (bridging), hybrid controllers and software-based controllers.
  • Creating text-driven games. Support for string-based custom inputs makes it easy to create text-oriented games. Use of voice dictation is demonstrated in the sample projects.

Terminology

  • Peripheral: A software-based game controller.
  • Central: Typically a game that supports hardware and software controllers. The Central utilizes VirtualGameController as a replacement for the Apple Game Controller framework.
  • Bridge: Acts as a relay between a Peripheral and a Central, and represents a hybrid of the two. Key use case is "controller forwarding".

Framework Integration

Platform-specific framework projects are included in the workspace. A single framework file supports both Peripherals (software-based controllers) and Centrals (that is, your game).

import VirtualGameController

Note that you currently need to import GameController as well.

See the instructions on the Wiki for utilizing Objective C. ``

CocoaPods

Preliminary support is in place for CocoaPods.

Carthage

In order to integrate using Carthage, add VGC to your Cartfile:

github "robreuss/VirtualGameController"

Then use platform-specific commands to create the build products that you need to add to your project:

carthage update --platform iOS
carthage update --platform OSX
carthage update --platform tvOS
carthage update --platform watchOS

Reference Apps

The project includes a pair apps that implement most of the available framework features and settings, as well as providing a generally helpful test environment.

NOTE: You cannot run more than one app using simulators at one time because of IP address sharing. Run a Central or Peripheral in a simulator, and use hardware devices to interact.

Peripheral_iOS

The Peripheral_iOS sample project provides a reference implementation of a software-based game controller. Once you have implemented VGC in your game (Central) you can use the Peripheral_iOS app to test it:

Peripheral Test

Central_iOS

The Central_iOS sample project provides a reference implementation of a Central (your game, to which Peripherals connect). It provides a straightforward way of testing your implementation of Peripherals:

Central Test

Core Documentation

Further Documentation

Sample Projects

Contact and Support

Feel free to contact me with any questions either using LinkedIn or [email protected].

Working with MFi Hardware-based Controllers

VirtualGameController is a wrapper around Apple's Game Controller framework, and so working with hardware controllers with VGC is the same as it is with Apple's Game Controller framework. See the Game Integration section below and the sample projects for additional details.

License

The MIT License (MIT)

Copyright (c) [2018] [Rob Reuss]

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Logo from here

virtualgamecontroller's People

Contributors

cellininicholas avatar dzamir avatar ifeegoo avatar jakubknejzlik avatar megatron1000 avatar robreuss 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  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

virtualgamecontroller's Issues

Bluetooth Fallback

We are testing the sample projects with an Apple TV and an iPhone 6. Everything works fine when both Wifi and Bluetooth are on, but once I turn off Wifi the devices no longer see each other. After reading the documentation I thought it should be possible, am I wrong? Thanks

Invalid Checksum

Hi,

I get an invalid checksum error when I send a state of a custom element from the central to a peripheral.
This is only the case when the CustomElementType = .String.
Can you check if it's a general problem?
So to be clear: I try to send some information (a string) from the central to a peripheral, so I'm trying to implement bidirectional communication.

Thanks

CocoaPods Integration

Where is CocoaPods support in your roadmap? I saw it is forthcoming from the Read Me file.

I'm struggling to implement this framework in my project in a clean way that allows for easy updating. Do you have any tips for integration? Thank you for all of your work on this project!

Potential slowness on older hardware

Not sure if this is specific to VirtualGameController or a wider issue with connectivity to older devices. I have a iPhone 5s connecting to the central as a Peripheral but receiving elements is delayed by a few seconds in some cases.

Might totally be something in my implementation, happy to discuss further @robreuss.

Crash with app > 2 dots (.) in appIdentifier

To recreate (tested on Apple TV):
VgcManager.startAs(.Central, appIdentifier: "1.2.3.4", includesPeerToPeer: true)

Debug Log reports:
Setting up as a CENTRAL
IncludesPeerToPeer is set to: true
Initializing Central Publisher
Publishing NetService service to listen for Peripherals on Apple TV
Central net service did not publish, error: ["NSNetServicesErrorDomain": 10, "NSNetServicesErrorCode": -72004], registered name: nil, server name: Apple TV
Republishing net service

Results in an infinite loop, leading to an memory range crash.

Support for Android Peripherals

A request has been made for an implementation of the Peripheral part of the framework on Android, which would enable the creation of VGC-compatible software-based controllers.

There are a few challenges with this, but none are insurmountable:

  • Service discovery to interact with the NSNetService (Bonjour) implementation on the iOS side should be straightforward to implement using Network Service Discovery on the Android side .
  • For passing data values, VGC simply opens a socket and sends structured messages (i.e. a start of message indicator, type of element identifier, and the element value itself).
  • Some element values are in NSData form, so the Android side will need to be able to handle that format (which I think is just a byte array).
  • The DeviceInfo object passed from the Peripheral to the Central currently uses NSKeyedArchiver in binary format (NSData). It would be easy enough to transition to using plist, for which there are parsers on the Android side.
  • Some implementation of a solution for handling incoming data from the Central, presumably using the Java equivalent of blocks (closures?) as well as property inspection for use with a polling-based approach, etc.

I do not have the Android skills to do this myself, but we're hoping a developer/s will be willing to take the task on!

Any plans to update this project?

Hi there!

First off, love the project, and thank you for your contributions to the dev community!

Just wondering if there were any plans to update this project or if it is officially closed?

hardware controller reconnect question

Hi Rob, glad to see this project is still going, I'm just getting back into game dev & have been looking into local multi-player on iOS & tvOS recently, VGC is working great so far, thanks for all the great work!

Although this is a hardware controller question, I was hoping you, or someone here may be able to shed some light on an issue I'm seeing (this is running via VGC). Or maybe I'm going a little mad...

I have a SteelSeries Stratus (the smaller one) hardware controller (with latest fw) for testing, alongside VGC peripherals, they all connect & work as expected. Mainly working against tvOS 11 for this at the moment. I'm now trying to handle possible controller re-connections, e.g. if the controller goes to sleep after being inactive for a few minutes, & am seeing the following on the stratus controller:

  • on initial connect the playerIndex is set accordingly & I log the deviceHash from 'deviceHashFromController' to console
  • if the controller is switched off & back on (to simulate it going into sleep/timeout mode) it re-connects ok & shows up
  • but the playerIndex is back to 'unused'
  • & the deviceHash is different

Is this expected behaviour, & if so, is there a way to re-map the re-connected controller back to the player/playerIndex some other way? Maybe I'm missing something obvious?

Or is my stratus controller possibly playing up with the different hash values? (I know regular BLE devices on iOS/tvOS have the BLE id masked with a random value, so it can change between connections, if the deviceHash is based off that it might explain it, although it seems the controller sends it through manually which should avoid that).

I only have the one hardware controller to test with currently, will look to get a 2nd different controller to compare against soon, I'm mainly asking for sanity sake, if this is what others are seeing & have to work around, or if this is unexpected.

Support for multiple appIDs / local search

It would be great to be able to use one controller for multiple apps. I'm able to help with this feature, if it's possible to accomplish this. Is it even possible something like that? If so, could you point me where to start before diving deeply to your code? :)

tvOS 9.1 beta 2 build errors

Hi, I am having issues getting the sample application to build for tvOS 9.1 beta 2 - it builds for iOS/OSX but I get the following errors with tvOS, any ideas? The unknown OS is in reference to the "os(WatchOS)" lines.
screen shot 2015-11-14 at 1 32 04 pm

Motion Updates Sluggish - tvOS 9.1 beta 2

I'm experiencing sluggish motion updates, I have a feeling it's something in beta 2 as before using your library I was using UDP and my motion updates were ok but after going to beta 2, my own updates were sluggish. I found this library when looking to solve my problem but after getting this to work in my project I am now experiencing the issues with this as well. I am receiving alot invalid message responses from my central when trying to use the motion updates, do you experience the same on beta 2? Even when it tries to lower the number of updates I am seeing the red flash in the view controller.

Use iPhone as MFI controller

I need to make an iPhone act as an MFI controller. I want to control a 3rd party game that is running on the same or a different iPhone. Is that possible with this framework given that I cannot modify the game itself?

tvOS Remote not recognized

Am I correct, that on tvOS Apple TV Remote is not recognized with VgcController (not returned by VgcController.controllers())? I guess it's because it uses bluetooth, but is there some way to get this controller through VgcController?

Dosen't compile under Xcode 11 - VgcController.swift

VgcController.swift fails to compile with Xcode 11. I get the following two errors:

Swift Compiler Error Group
VirtualGameController-master/Source/Framework/VgcController.swift:2052:13: Setter for 'value' with Objective-C selector 'setValue:' conflicts with method 'setValue' from superclass 'GCControllerButtonInput' with the same Objective-C selector
/GameController.GCControllerButtonInput:11:15: Method 'setValue' declared here

VirtualGameController-master/Source/Framework/VgcController.swift:2125:13: Setter for 'value' with Objective-C selector 'setValue:' conflicts with method 'setValue' from superclass 'GCControllerAxisInput' with the same Objective-C selector
/GameController.GCControllerAxisInput:5:15: Method 'setValue' declared here

Race condition causing elements to return incorrect values after connecting

Currently testing things out a little more with more devices connecting to a tvOS app. If I have the peripherals searching for the Central and then publish the central all of the controllers connect correctly.

Within my controllerDidConnect I setup logic to receive an avatar and a string. These get sent from the peripheral straight after connecting but it seems they can get mixed up with some strings/avatars duplicating & populating incorrectly against other controllers.

I also tried delaying the sending to a second, it seems to improve things but you can still get an incorrect string/avatar being returned in the valueChangedHandler.

@robreuss I have pushed this to my repo if that helps debug things at all. I have 5 devices connecting pretty much instantly when I publish the service.

Is this approach allowed by Apple?

Hi, Great work! but it seems the Game Controller framework needs to work with a hardware controller? are you sure this is allowed by Apple and won't be rejected?

Thanks

MFi Controllers Not Found When VgcManager Initialised post launch

Because the app relies up listening for the GCControllerDidConnectNotification to add GCControllers to the array of VgcControllers if it's initialised post launch the notifications are missed and the controllers aren't found until they're disconnected and reconnected.

Connection question

I am developing an Apple TV game that uses the iPhone/iPad as a game controller. I can discover the service, connect the two devices, but the VgcGameController.controllers() call on the iPhone always returns an empty array. How do I get ahold of the controller that is connected to the Apple TV (simulator)? BTW, the controllerDidConnect(notification) notification callback never gets called on the TV simulator, but it does get called on the iPhone.

Also, the only data that I want to send from the controller to the Apple TV is a CGPoint (or, if a CGPoint is not possible, an X/Y pair of Float or Int). Any ideas on the best strategy for this?

Objective-C Usage

Hi,
This library seems really promising, & the samples seem to work great (tested between tvOS & iOS devices & it all ran very nicely).

I'm trying to use this in an existing objective-c based project, & have it compiling ok, but it seems a load of methods are missing from the 'VirtualGameController-Swift.h' file on the current version. I'm guessing this is just as no ones tried to use it outside of swift yet perhaps.

I've not really used swift much (so excuse if I'm missing something obvious), but on closer inspection, any methods that use certain swift specific features don't seem to be exposed in the header file, & so can't be accessed from objective-c code.

Adding a custom startAs alternative method to VgcManager as a test, which just changed the AppRole arg to a string & then it mapped the string arg to the 'CustomStringConvertible' based AppRole enum before calling the normal swift methods, which seemed to work. It exported the method in the header ok, & I could call & start the VGC setup up ok from objective-c.

I'm now trying to get the VgcService from the VgcPeripheralFoundService notification which is firing ok, but the whole of VgcService doesn't seem to be in the header file, & because of that, VgcPeripheral's connectToService etc. methods don't seem to be exposed. The object seems to only log out as 'VirtualGameController.VgcService' in the objective-c side.

Is there any plan to support objective-c usage? Or should it work already & maybe I've missed something obvious? Any tips on getting it going?

Thanks
Phil

Peripheral disconnect causes EXC_BREAKPOINT

Hi Rob,

as the title suggests, I'm trying to disconnect my peripheral from the central service but once I do it Xcode throws this error inside VgcBrowser.disconnectFromCentral() at vgcLogDebug()

I'm attaching an image with the error.

Thanks
untitled

Button release not firing for Peripheral_iOS

I have a SceneKit based app on Mac OS X that is using Virtual Game Controller as a Central and am using the Peripheral iOS app distributed with Virtual Game Controller to control it.

In my app I have registered for buttonA button press change's, similar to the DemoBot's example.

DemoBots/GameControllerInputSource.swift

The only differences is I am using it as an extendedGamePad, so I have something like this:

        // GCExtendedGamepad trigger handlers.
        if let extendedGamepad = gameController.extendedGamepad {
            extendedGamepad.buttonA.pressedChangedHandler = attackHandler
        }

And for now just a simple 'pressed' detection.

let attackHandler: GCControllerButtonValueChangedHandler = { [unowned self] button, _, pressed in
            print("Button pressed: \(pressed)")
            if pressed {
                self.shooting = true
            }
            else {
                self.shooting = false
            }
        }

Once everything is running and I press the 'A' button on my iPhone running Peripheral iOS , I observe my attackHandler ( a GCControllerButtonValueChangedHandler) getting called with 'pressed' set to 'true'.

However, when I release the 'A' button, I don't get a similar call to my handler with 'pressed' set to 'false'.

So assuming I have things coded correctly, I traced the issue to VgcController.swift line 2219

I change the '&&' to '||' and observed the expected behavior for both press and release.

If you need a better replication I could probably try it with the DemoBots app.

dpad.valueChangedHandler not called after reconnect

I'm getting nothing back on my dpad.valueChangedHandler after my controller gets reconnected.

I'm using the library with an Apple TV app and I'm testing it with the built in iOS 11 iPhone's Apple TV Remote App. Everytime the Apple TV Remote app is closed it loses its connection, as expected, but every subsequent connect fails to work. It successfully connects but nothing comes through on the dpad.valueChangedHandler. Restarting the app is the only thing that solves the issue.

I'm using the 0.0.19 release.

The logs look like this.

[VGC] Setting up as a CENTRAL
[VGC] IncludesPeerToPeer is set to: true
[VGC] Initializing Central Publisher
[VGC] Publishing NetService service to listen for Peripherals on Apple TV
[VGC] Service bonjour domain is local, type is _geekquiz_central._tcp., name is Apple TV
[VGC] NetService will be published
[VGC] Central is now published on: local._geekquiz_central._tcp.Apple TV
[VGC] Initializing new Controller
[VGC] Adding hardware controller Remote
[VGC] Profile type set to: MicroGamepad
[VGC] <<< ERROR[VGC] Device info set on controller
[VGC] Confirming controller doesn't already exist among 0 controllers
[VGC] Appending controller Remote to vControllers (1 controllers with new controller)
[VGC] nil stream SmallData error caught
[VGC] nil stream SmallData error caught
[VGC] nil stream SmallData error caught
[VGC] Got hardware didDisconnect notification: name = GCControllerDidDisconnectNotification, object = Optional(<GCController 0x1c02b2120 vendorName='Remote' deviceHash=0x137e5b6c0>), userInfo = nil
[VGC] Comparing UUID 0x137e5b6c0 to 0x137e5b6c0
[VGC] Removing controller from controllers array: <GCController 0x1c02b2120 vendorName='Remote' deviceHash=0x137e5b6c0>
[VGC] Initializing new Controller
[VGC] Adding hardware controller Remote
[VGC] Profile type set to: MicroGamepad
[VGC] <<< ERROR[VGC] Device info set on controller
[VGC] Confirming controller doesn't already exist among 0 controllers
[VGC] Appending controller Remote to vControllers (1 controllers with new controller)
[VGC] nil stream SmallData error caught
[VGC] nil stream SmallData error caught
[VGC] nil stream SmallData error caught
[VGC] nil stream SmallData error caught
[VGC] nil stream SmallData error caught
[VGC] nil stream SmallData error caught
[VGC] nil stream SmallData error caught
[VGC] nil stream SmallData error caught
[VGC] nil stream SmallData error caught
[VGC] nil stream SmallData error caught
[VGC] nil stream SmallData error caught
[VGC] nil stream SmallData error caught
[VGC] Got hardware didDisconnect notification: name = GCControllerDidDisconnectNotification, object = Optional(<GCController 0x1c42befc0 vendorName='Remote' deviceHash=0x137d6b6a0>), userInfo = nil
[VGC] Comparing UUID 0x137d6b6a0 to 0x137d6b6a0
[VGC] Removing controller from controllers array: <GCController 0x1c42befc0 vendorName='Remote' deviceHash=0x137d6b6a0>
[VGC] Initializing new Controller
[VGC] Adding hardware controller Remote
[VGC] Profile type set to: MicroGamepad
[VGC] <<< ERROR[VGC] Device info set on controller
[VGC] Confirming controller doesn't already exist among 0 controllers
[VGC] Appending controller Remote to vControllers (1 controllers with new controller)
[VGC] nil stream SmallData error caught
[VGC] nil stream SmallData error caught
[VGC] nil stream SmallData error caught
[VGC] nil stream SmallData error caught
[VGC] Got hardware didDisconnect notification: name = GCControllerDidDisconnectNotification, object = Optional(<GCController 0x1c42b7520 vendorName='Remote' deviceHash=0x137d6c190>), userInfo = nil
[VGC] Comparing UUID 0x137d6c190 to 0x137d6c190
[VGC] Re[VGC] Initializing new Controller
[VGC] Adding hardware controller Remote
[VGC] Profile type set to: MicroGamepad
[VGC] <<< ERROR[VGC] Device info set on controller
[VGC] Confirming controller doesn't already exist among 0 controllers
[VGC] Appending controller Remote to vControllers (1 controllers with new controller)
[VGC] nil stream SmallData error caught
[VGC] nil stream SmallData error caught
[VGC] nil stream SmallData error caught
[VGC] Got hardware didDisconnect notification: name = GCControllerDidDisconnectNotification, object = Optional(<GCController 0x1c02ae5e0 vendorName='Remote' deviceHash=0x137e733e0>), userInfo = nil
[VGC] Comparing UUID 0x137e733e0 to 0x137e733e0
[VGC] Re

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.