creating butterfly animate with python

Introduction to Creating Butterfly with Python

Butterflies, with their vibrant colors and graceful movements, have long captured the imagination of nature enthusiasts and artists alike. Replicating the beauty of these delicate creatures through programming can be an exciting and creative endeavor. In this tutorial, we will delve into the world of Python programming to create a stunning butterfly pattern.

Python, a versatile and beginner-friendly programming language, provides a perfect canvas for generating intricate patterns and designs. By leveraging libraries such as Turtle Graphics, matplotlib, or even GUI frameworks like Tkinter, we can bring our artistic vision to life on the digital canvas.

Throughout this tutorial, we will explore step-by-step how to construct a butterfly illustration. We will begin by setting up our programming environment, introducing the chosen libraries, and discussing the basic concepts of drawing and positioning shapes. As we progress, we will delve into more advanced techniques, such as incorporating color gradients, adding symmetry, and achieving intricate details.

The tutorial assumes no prior experience in programming or digital art, making it accessible to both beginners and those with some coding background. Each code snippet will be accompanied by clear explanations, allowing you to understand not only how to create a butterfly with Python but also the underlying principles that govern the process.

Whether you’re a programmer looking to explore your creative side or an artist interested in incorporating technology into your work, this tutorial will provide you with a foundation to experiment, customize, and create your own butterfly designs. So, let’s spread our coding wings and embark on this captivating journey of transforming lines of code into a mesmerizing digital butterfly masterpiece.

  1. Setting Up the Environment: We’ll guide you through installing any necessary libraries and tools, ensuring that your Python environment is ready for artistic exploration.
  2. Drawing Basics: Before we dive into creating complex shapes, we’ll cover fundamental drawing concepts. This includes understanding coordinates, shapes, and how to control the pen (or brush) to create lines and curves.
  3. Constructing the Butterfly Body: We’ll start by creating the butterfly’s body using basic shapes and lines. This will introduce you to the process of positioning elements on the canvas.
  4. Designing the Wings: The wings are the most captivating part of a butterfly. We’ll show you how to use symmetry to create beautifully intricate wing patterns. This will involve combining various shapes and colors.
  5. Adding Color and Detail: No butterfly is complete without vibrant colors and fine details. We’ll explore techniques for adding gradients, textures, and patterns to the wings, enhancing the visual appeal of our creation.
  6. Animating the Butterfly: To add a touch of realism, we’ll learn how to animate the butterfly’s wings using simple animations. This will showcase how Python can bring our static design to life.
  7. Advanced Customization: Once you’re comfortable with the basics, we’ll introduce more advanced concepts such as user interaction, customizing the butterfly’s appearance, and experimenting with different styles.
  8. Saving and Sharing: Finally, we’ll cover how to save your masterpiece as an image file and discuss options for sharing your butterfly creation with friends, on social media, or even incorporating it into your own projects.

By the end of this tutorial, you’ll have a newfound appreciation for the intersection of art and technology. You’ll also possess the skills to create not just butterflies, but a wide range of digital art using Python. Remember, creativity knows no bounds, and the techniques you’ll learn can be applied to various other imaginative projects.

So, if you’re ready to embark on this coding journey and bring the enchanting beauty of butterflies to life through lines of Python code, let’s get started with setting up our environment and diving into the wonderful world of digital artistry!

html code :

.p-summary
  h1 Butterfly
  p
    a(href="https://ykob.github.io/sketch-threejs/sketch/butterfly.html", target="_blank")
      |this source.

canvas(id="canvas-webgl", class="p-canvas-webgl")

css code :

@import url('https://fonts.googleapis.com/css?family=Homenaje');

.p-canvas-webgl {
  position: fixed;
  z-index: 1;
  top: 0; left: 0;
}

.p-summary {
  position: absolute;
  top: 20px; left: 20px;
  z-index: 2;
  color: #111;
  font-family: 'Homenaje', sans-serif;
  h1 {
    margin: 0 0 0.2em;
    font-size: 42px;
    font-weight: 400;
    letter-spacing: 0.05em;
  }
  p {
    margin: 0;
    font-size: 1.1rem;
    letter-spacing: 0.1em;
  }
  a {
    color: #111;
  }
}

java script :

class ConsoleSignature {
  constructor() {
    this.message = `created by yoichi kobayashi`;
    this.url = `http://www.tplh.net`;
    this.show();
  }
  show() {
    if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1) {
      const args = [
        `\n%c ${this.message} %c%c ${this.url} \n\n`,
        'color: #fff; background: #222; padding:3px 0;',
        'padding:3px 1px;',
        'color: #fff; background: #47c; padding:3px 0;',
      ];
      console.log.apply(console, args);
    } else if (window.console) {
      console.log(`${this.message} ${this.url}`);
    }
  }
}

const debounce = (callback, duration) => {
  var timer;
  return function(event) {
    clearTimeout(timer);
    timer = setTimeout(function(){
      callback(event);
    }, duration);
  };
};

const SIZE = 280;

class Butterfly {
  constructor(i, texture) {
    this.uniforms = {
      index: {
        type: 'f',
        value: i
      },
      time: {
        type: 'f',
        value: 0
      },
      size: {
        type: 'f',
        value: SIZE
      },
      texture: {
        type: 't',
        value: texture
      },
    }
    this.physicsRenderer = null;
    this.obj = this.createObj();
  }
  createObj() {
    const geometry = new THREE.PlaneBufferGeometry(SIZE, SIZE / 2, 24, 12);
    const mesh = new THREE.Mesh(
      geometry,
      new THREE.RawShaderMaterial({
        uniforms: this.uniforms,
        vertexShader: `attribute vec3 position;
attribute vec2 uv;

uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform float index;
uniform float time;
uniform float size;

varying vec3 vPosition;
varying vec2 vUv;

void main() {
  float flapTime = radians(sin(time * 6.0 - length(position.xy) / size * 2.6 + index * 2.0) * 45.0 + 30.0);
  float hovering = cos(time * 2.0 + index * 3.0) * size / 16.0;
  vec3 updatePosition = vec3(
    cos(flapTime) * position.x,
    position.y + hovering,
    sin(flapTime) * abs(position.x) + hovering
  );

  vec4 mvPosition = modelViewMatrix * vec4(updatePosition, 1.0);

  vPosition = position;
  vUv = uv;

  gl_Position = projectionMatrix * mvPosition;
}
`,
        fragmentShader: `precision highp float;

uniform float index;
uniform float time;
uniform float size;
uniform sampler2D texture;

varying vec3 vPosition;
varying vec2 vUv;

//
// Description : Array and textureless GLSL 2D/3D/4D simplex
//               noise functions.
//      Author : Ian McEwan, Ashima Arts.
//  Maintainer : ijm
//     Lastmod : 20110822 (ijm)
//     License : Copyright (C) 2011 Ashima Arts. All rights reserved.
//               Distributed under the MIT License. See LICENSE file.
//               https://github.com/ashima/webgl-noise
//

vec3 mod289(vec3 x) {
  return x - floor(x * (1.0 / 289.0)) * 289.0;
}

vec4 mod289(vec4 x) {
  return x - floor(x * (1.0 / 289.0)) * 289.0;
}

vec4 permute(vec4 x) {
     return mod289(((x*34.0)+1.0)*x);
}

vec4 taylorInvSqrt(vec4 r)
{
  return 1.79284291400159 - 0.85373472095314 * r;
}

float snoise3(vec3 v)
  {
  const vec2  C = vec2(1.0/6.0, 1.0/3.0) ;
  const vec4  D = vec4(0.0, 0.5, 1.0, 2.0);

// First corner
  vec3 i  = floor(v + dot(v, C.yyy) );
  vec3 x0 =   v - i + dot(i, C.xxx) ;

// Other corners
  vec3 g = step(x0.yzx, x0.xyz);
  vec3 l = 1.0 - g;
  vec3 i1 = min( g.xyz, l.zxy );
  vec3 i2 = max( g.xyz, l.zxy );

  //   x0 = x0 - 0.0 + 0.0 * C.xxx;
  //   x1 = x0 - i1  + 1.0 * C.xxx;
  //   x2 = x0 - i2  + 2.0 * C.xxx;
  //   x3 = x0 - 1.0 + 3.0 * C.xxx;
  vec3 x1 = x0 - i1 + C.xxx;
  vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y
  vec3 x3 = x0 - D.yyy;      // -1.0+3.0*C.x = -0.5 = -D.y

// Permutations
  i = mod289(i);
  vec4 p = permute( permute( permute(
             i.z + vec4(0.0, i1.z, i2.z, 1.0 ))
           + i.y + vec4(0.0, i1.y, i2.y, 1.0 ))
           + i.x + vec4(0.0, i1.x, i2.x, 1.0 ));

// Gradients: 7x7 points over a square, mapped onto an octahedron.
// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
  float n_ = 0.142857142857; // 1.0/7.0
  vec3  ns = n_ * D.wyz - D.xzx;

  vec4 j = p - 49.0 * floor(p * ns.z * ns.z);  //  mod(p,7*7)

  vec4 x_ = floor(j * ns.z);
  vec4 y_ = floor(j - 7.0 * x_ );    // mod(j,N)

  vec4 x = x_ *ns.x + ns.yyyy;
  vec4 y = y_ *ns.x + ns.yyyy;
  vec4 h = 1.0 - abs(x) - abs(y);

  vec4 b0 = vec4( x.xy, y.xy );
  vec4 b1 = vec4( x.zw, y.zw );

  //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;
  //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;
  vec4 s0 = floor(b0)*2.0 + 1.0;
  vec4 s1 = floor(b1)*2.0 + 1.0;
  vec4 sh = -step(h, vec4(0.0));

  vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;
  vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;

  vec3 p0 = vec3(a0.xy,h.x);
  vec3 p1 = vec3(a0.zw,h.y);
  vec3 p2 = vec3(a1.xy,h.z);
  vec3 p3 = vec3(a1.zw,h.w);

//Normalise gradients
  vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));
  p0 *= norm.x;
  p1 *= norm.y;
  p2 *= norm.z;
  p3 *= norm.w;

// Mix final noise value
  vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);
  m = m * m;
  return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1),
                                dot(p2,x2), dot(p3,x3) ) );
  }

vec3 convertHsvToRgb(vec3 c) {
  vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
  vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
  return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}

void main() {
  vec4 texColor = texture2D(texture, vUv);

  float noise = snoise3(vPosition / vec3(size * 0.25) + vec3(0.0, 0.0, time));
  vec3 hsv = vec3(1.0 + noise * 0.2 + index * 0.7, 0.4, 1.0);
  vec3 rgb = convertHsvToRgb(hsv);

  gl_FragColor = vec4(rgb, 1.0) * texColor;
}`,
        depthWrite: false,
        side: THREE.DoubleSide,
        transparent: true
      })
    );
    mesh.rotation.set(-45 * Math.PI / 180, 0, 0);
    return mesh;
  }
  render(renderer, time) {
    this.uniforms.time.value += time;
    this.obj.position.z = (this.obj.position.z > -900) ? this.obj.position.z - 4 : 900;
  }
}

const resolution = {
  x: 0,
  y: 0
};
const canvas = document.getElementById('canvas-webgl');
const renderer = new THREE.WebGLRenderer({
  antialias: false,
  canvas: canvas,
});
const scene = new THREE.Scene();
const camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 1, 10000);
const clock = new THREE.Clock();
const loader = new THREE.TextureLoader();

const vectorTouchStart = new THREE.Vector2();
const vectorTouchMove = new THREE.Vector2();
const vectorTouchEnd = new THREE.Vector2();

const CAMERA_SIZE_X = 640;
const CAMERA_SIZE_Y = 480;

const BUTTERFLY_NUM = 7;
const butterflies = [];

const resizeCamera = () => {
  const x = Math.min((resolution.x / resolution.y) / (CAMERA_SIZE_X / CAMERA_SIZE_Y), 1.0) * CAMERA_SIZE_X;
  const y = Math.min((resolution.y / resolution.x) / (CAMERA_SIZE_Y / CAMERA_SIZE_X), 1.0) * CAMERA_SIZE_Y;
  camera.left   = x * -0.5;
  camera.right  = x *  0.5;
  camera.top    = y *  0.5;
  camera.bottom = y * -0.5;
  camera.updateProjectionMatrix();
};
const resizeWindow = () => {
  resolution.x = window.innerWidth;
  resolution.y = window.innerHeight;
  canvas.width = resolution.x;
  canvas.height = resolution.y;
  resizeCamera();
  renderer.setSize(resolution.x, resolution.y);
}
const render = () => {
  const time = clock.getDelta();
  for (var i = 0; i < butterflies.length; i++) {
    butterflies[i].render(renderer, time);
  }
  renderer.render(scene, camera);
}
const renderLoop = () => {
  render();
  requestAnimationFrame(renderLoop);
}
const on = () => {
  window.addEventListener('resize', debounce(resizeWindow), 1000);
}

const init = () => {
  resizeWindow();
  on();

  renderer.setClearColor(0xeeeeee, 1.0);
  camera.position.set(250, 500, 1000);
  camera.lookAt(new THREE.Vector3());

  loader.crossOrigin = 'anonymous';  
  loader.load('http://ykob.github.io/sketch-threejs/img/sketch/butterfly/tex.png', (texture) => {
    texture.magFilter = THREE.NearestFilter;
    texture.minFilter = THREE.NearestFilter;

    for (var i = 0; i < BUTTERFLY_NUM; i++) {
      butterflies[i] = new Butterfly(i, texture);
      butterflies[i].obj.position.set(((i + 1) % 3 - 1) * i * 50, 0, 1800 / BUTTERFLY_NUM * i);
      scene.add(butterflies[i].obj);
    }
    renderLoop();
  });
}
init();

new ConsoleSignature();

Conclusion:

In this tutorial, we’ve explored the fascinating realm of creating butterfly art using the Python programming language. From setting up the environment to crafting intricate wing patterns, we’ve covered a range of concepts that bridge the gap between coding and artistry. As we conclude this journey, let’s reflect on what we’ve achieved and where you can go from here.

Through your efforts, you’ve learned the basics of drawing shapes, positioning elements, and utilizing color to create visually appealing butterfly designs. You’ve harnessed the power of libraries like Turtle Graphics or matplotlib to manipulate the canvas and bring your ideas to fruition. Additionally, you’ve gained insights into animation, customization, and saving your creations for future admiration.

While we’ve focused on butterflies, the skills you’ve acquired can be extended to any form of digital art. Python provides a flexible and creative platform that enables you to translate your imagination into tangible expressions. Whether you’re interested in nature, abstract designs, or even interactive art, the principles covered in this tutorial lay the groundwork for your artistic exploration.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top