Book Image

Cinder Creative Coding Cookbook

Book Image

Cinder Creative Coding Cookbook

Overview of this book

Cinder is one of the most exciting frameworks available for creative coding. It is developed in C++ for increased performance and allows for the fast creation of visually complex, interactive applications."Cinder Creative Coding Cookbook" will show you how to develop interactive and visually dynamic applications using simple-to-follow recipes.You will learn how to use multimedia content, draw generative graphics in 2D and 3D, and animate them in compelling ways. Beginning with creating simple projects with Cinder, you will use multimedia, create animations, and interact with the user.From animation with particles to using video, audio, and images, the reader will gain a broad knowledge of creating applications using Cinder.With recipes that include drawing in 3D, image processing, and sensing and tracking in real-time from camera input, the book will teach you how to develop interesting applications."Cinder Creative Coding Cookbook" will give you the necessary knowledge to start creating projects with Cinder that use animations and advanced visuals.
Table of Contents (19 chapters)
Cinder Creative Coding Cookbook
Credits
About the Authors
About the Reviewers
www.PacktPub.com
Preface
Index

Responding to touch input


A Cinder application can receive several touch events.

The available touch event handlers that get called by touch interaction are listed in the following table:

Method

Usage

touchesBegan

This is called when new touches are detected

touchesMoved

This is called when existing touches move

touchesEnded

This is called when existing touches are removed

All of the preceding methods receive a ci::app::TouchEvent object as a parameter with a std::vector of ci::app::TouchEvent::Touch objects with information about each touch detected. Since many devices can detect and respond to several touches simultaneously, it is possible and common for a touch event to contain several touches.

It is not mandatory to implement all of the preceding event handlers; you can use the ones your application requires specifically.

Cinder applications can respond to touch events on any touch-enabled device running Windows 7, OS X, or iOS.

Getting ready

Implement the necessary touch event handlers according to the touch events you want to respond to. For example, to respond to all available touch events (touches added, touches moved, and touches removed), you would need to declare and implement the following methods:

void touchesBegan( TouchEvent event );
void touchesMoved( TouchEvent event );
void touchesEnded( TouchEvent event );

How to do it…

We will learn how to work with the ci::app::TouchEvent class to understand touch events. Perform the following steps to do so:

  1. To access the list of touches, you can type in the following line of code:

    const std::vector<TouchEvent::Touch>& touches = event.getTouches();

    Iterate through the container to access each individual element.

    for( std::vector<TouchEvent::Touch>::const_iterator it = touches.begin(); it != touches.end(); ++it ){
      const TouchEvent::Touch& touch = *it;
      //do something with the touch object
    }
  2. You can get the position of a touch by calling the getPos method that returns a Vec2f value with its position or using the getX and getY methods to receive the x and y coordinates separately, for example:

    for( std::vector<TouchEvent::Touch>::const_iterator it = touches.begin(); it != touches.end(); ++it ){
      const TouchEvent::Touch& touch = *it;
      vec2f pos = touch.getPos();
      float x = touch.getX();
      float y = touch.getY(); 
    }
  3. The getId method returns a uint32_t value with a unique ID for the touch object. This ID is persistent throughout the lifecycle of the touch, which means you can use it to keep track of a specific touch as you access it on the different touch events.

    For example, to make an application where we draw lines using our fingers, we can create std::map that associates each line, in the form of a ci::PolyLine<Vec2f> object, with a uint32_t key with the unique ID of a touch.

    We need to include the file with std::map and PolyLine to our project by adding the following code snippet to the beginning of the source file:

    #include "cinder/polyline.h"
    #include <map>
  4. We can now declare the container:

    std::map< uint32_t, PolyLine<Vec2f> > mLines;
  5. In the touchesBegan method we create a new line for each detected touch and map it to the unique ID of each touch:

    const std::vector<TouchEvent::Touch>& touches = event.getTouches();
    for( std::vector<TouchEvent::Touch>::const_iterator it = touches.begin(); it != touches.end(); ++it ){
      const TouchEvent::Touch& touch = *it;
      mLines[ touch.getId() ] = PolyLine<Vec2f>();
    }
  6. In the touchesMoved method, we add the position of each touch to its corresponding line:

    const std::vector<TouchEvent::Touch>& touches = event.getTouches();
    for( std::vector<TouchEvent::Touch>::const_iterator it = touches.begin(); it != touches.end(); ++it ){
      const TouchEvent::Touch& touch = *it;
      mLines[ touch.getId() ].push_back( touch.getPos() ); 
    }
  7. In the touchesEnded method, we remove the line that corresponds to a touch being removed:

    const std::vector<TouchEvent::Touch>& touches = event.getTouches();
    for( std::vector<TouchEvent::Touch>::const_iterator it = touches.begin(); it != touches.end(); ++it ){
      const TouchEvent::Touch& touch = *it;
      mLines.erase( touch.getId() );
    }
  8. Finally, the lines can be drawn. Here we clear the background with black and draw the lines with in white. The following is the implementation of the draw method:

    gl::clear( Color::black() );
    gl::color( Color::white() );
    for( std::map<uint32_t, PolyLine<Vec2f> >::iterator it = mLines.begin(); it != mLines.end(); ++it ){
      gl::draw( it->second );
    }

    The following is a screenshot of our app running after drawing some lines:

How it works…

A Cinder application responds internally to the system calls for any touch event. It will then create a ci::app::TouchEvent object with information about the event and call the corresponding event handler in our application's class. The way to respond to touch events becomes uniform across the Windows and Mac platforms.

The ci::app::TouchEvent class contains only one accessor method that returns a const reference to a std::vector<TouchEvent::Touch> container. This container has one ci::app::TouchEvent::Touch object for each detected touch and contains information about the touch.

The ci::app::TouchEvent::Touch object contains information about the touch including position and previous position, unique ID, the time stamp, and a pointer to the native event object which maps to UITouch on Cocoa Touch and TOUCHPOINT on Windows 7.

There's more...

At any time, it is also possible to get a container with all active touches by calling the getActiveTouches method. It returns a const reference to a std::vector<TouchEvent::Touch> container. It offers flexibility when working with touch applications as it can be accessed outside the touch event methods.

For example, if you want to draw a solid red circle around each active touch, you can add the following code snippet to your draw method:

const std::vector<TouchEvent::Touch>&activeTouches = getActiveTouches();
gl::color( Color( 1.0f, 0.0f, 0.0f ) );
for( std::vector<TouchEvent::Touch>::const_iterator it = activeTouches.begin(); it != activeTouches.end(); ++it ){
  const TouchEvent::Touch& touch = *it;
gl::drawSolidCircle( touch.getPos(), 10.0f );
}