Recién llegados

Guía de iniciación a la pintura digital con Procreate

Guía de iniciación a la pintura digital con Procreate

Max Ulichney

Diario ilustrado de la naturaleza. Guía de observación y dibujo

Diario ilustrado de la naturaleza. Guía de observación y dibujo

John Muir Laws

Búsqueda

Buscador avanzado

Rayman Shimeji Instant

canvas:active cursor: grabbing;

.badge position: fixed; bottom: 20px; left: 20px; background: rgba(0,0,0,0.5); border-radius: 20px; padding: 4px 12px; font-size: 12px; color: #ccc; font-family: monospace; pointer-events: none; z-index: 10000; backdrop-filter: blur(4px); Rayman Shimeji

body margin: 0; min-height: 100vh; background: linear-gradient(145deg, #2b3b4e 0%, #1d2c3a 100%); font-family: 'Segoe UI', 'Quicksand', system-ui, -apple-system, 'Poppins', sans-serif; display: flex; justify-content: center; align-items: center; overflow: hidden; cursor: default; position: relative; canvas:active cursor: grabbing;

<script> (function() // --- Rayman Shimeji - Desktop Companion --- // features: follows mouse smoothly, idle animation, walking "run" cycle, // click reaction (jump + spin), dynamic direction flip, custom rayman style. const canvas = document.getElementById('raymanCanvas'); const ctx = canvas.getContext('2d'); // dimensions let width = window.innerWidth; let height = window.innerHeight; // Rayman character position (center of sprite) let raymanX = width/2; let raymanY = height/2; // target position (mouse coordinates) let targetX = width/2; let targetY = height/2; // animation state let frameCount = 0; let walkCycle = 0; // 0..1 for limb swing let isWalking = false; let facingRight = true; // true = right, false = left // special click reaction: "jumpSpin" let jumpSpinActive = false; let jumpSpinTimer = 0; let jumpSpinOffsetY = 0; // y offset for jump arc let jumpSpinRotation = 0; // extra rotation (in radians) // idle bounce factor let idleBounce = 0; let idleBounceSpeed = 0.08; // movement smoothing const FOLLOW_SPEED = 0.12; // distance threshold to start walking animation const WALK_DIST_THRESH = 8; // resize handler function resizeCanvas() width = window.innerWidth; height = window.innerHeight; canvas.width = width; canvas.height = height; // keep within bounds raymanX = Math.min(Math.max(raymanX, 40), width - 40); raymanY = Math.min(Math.max(raymanY, 40), height - 50); targetX = Math.min(Math.max(targetX, 40), width - 40); targetY = Math.min(Math.max(targetY, 40), height - 50); window.addEventListener('resize', () => resizeCanvas(); ); // --- Mouse tracking (desktop follows cursor) --- function handleMouseMove(e) const rect = canvas.getBoundingClientRect(); const scaleX = canvas.width / rect.width; const scaleY = canvas.height / rect.height; let mouseCanvasX = (e.clientX - rect.left) * scaleX; let mouseCanvasY = (e.clientY - rect.top) * scaleY; // clamp to canvas edges with padding mouseCanvasX = Math.min(Math.max(mouseCanvasX, 30), width - 30); mouseCanvasY = Math.min(Math.max(mouseCanvasY, 30), height - 40); targetX = mouseCanvasX; targetY = mouseCanvasY; // click triggers joyful reaction function handleClick(e) if(!jumpSpinActive) jumpSpinActive = true; jumpSpinTimer = 18; // duration frames ~0.3 sec (60fps) jumpSpinOffsetY = 0; jumpSpinRotation = 0; canvas.addEventListener('mousemove', handleMouseMove); canvas.addEventListener('click', handleClick); // optional touch for mobile-like but mainly desktop canvas.addEventListener('touchmove', (e) => e.preventDefault(); const rect = canvas.getBoundingClientRect(); const touch = e.touches[0]; let tx = (touch.clientX - rect.left) * (canvas.width/rect.width); let ty = (touch.clientY - rect.top) * (canvas.height/rect.height); tx = Math.min(Math.max(tx, 30), width - 30); ty = Math.min(Math.max(ty, 30), height - 40); targetX = tx; targetY = ty; ); canvas.addEventListener('touchstart', (e) => e.preventDefault(); handleClick(e); ); // --- update movement & animations --- function updateMovement() // smooth follow let dx = targetX - raymanX; let dy = targetY - raymanY; let distance = Math.hypot(dx, dy); if (distance > 0.5) // move towards target let moveX = dx * FOLLOW_SPEED; let moveY = dy * FOLLOW_SPEED; raymanX += moveX; raymanY += moveY; // set walking animation if moving enough isWalking = distance > WALK_DIST_THRESH; // update facing direction based on horizontal movement if (Math.abs(dx) > 0.5) facingRight = dx > 0; else isWalking = false; // boundary clamp (prevent going off-screen) raymanX = Math.min(Math.max(raymanX, 38), width - 38); raymanY = Math.min(Math.max(raymanY, 45), height - 48); // sync target to avoid stuck edges but keep smooth targetX = Math.min(Math.max(targetX, 38), width - 38); targetY = Math.min(Math.max(targetY, 45), height - 48); // update walk cycle (limb swing) if (isWalking && !jumpSpinActive) walkCycle = (walkCycle + 0.22) % (Math.PI * 2); else if(!jumpSpinActive) // gentle idle sway walkCycle = Math.sin(frameCount * 0.08) * 0.5; // idle bounce (gentle floating) if(!jumpSpinActive && !isWalking) idleBounce = Math.sin(frameCount * 0.12) * 3; else if(!jumpSpinActive) idleBounce = Math.sin(frameCount * 0.2) * 1.5; else idleBounce = 0; // --- Jump spin reaction (happy jump) --- if (jumpSpinActive) // arc: parabolic jump (up then down) let t = (18 - jumpSpinTimer) / 18; // 0 -> start, 1 -> end let arc = Math.sin(Math.PI * t); // 0 -> 1 -> 0 // peak height: -28px relative to base jumpSpinOffsetY = -arc * 28; // spin rotation: full 360deg during jump jumpSpinRotation = t * Math.PI * 1.8; jumpSpinTimer--; if (jumpSpinTimer <= 0) jumpSpinActive = false; jumpSpinOffsetY = 0; jumpSpinRotation = 0; else jumpSpinOffsetY = 0; jumpSpinRotation = 0; // --- Drawing Rayman (stylized iconic character) --- // dimensions: body ~ 48x48, hair tuft, big fists, floating limbs function drawRayman(ctx, x, y, faceRight, walkAngle, jumpRot, extraYOffset) // extraYOffset from idleBounce + jump offset let baseY = y + extraYOffset + (jumpSpinActive ? jumpSpinOffsetY : idleBounce); let rot = jumpSpinActive ? jumpSpinRotation : 0; ctx.save(); ctx.translate(x, baseY); if(rot !== 0) ctx.rotate(rot); // scale for facing direction let dirScale = faceRight ? 1 : -1; ctx.scale(dirScale, 1); // ---- BODY: round torso ---- ctx.beginPath(); ctx.ellipse(0, 0, 18, 22, 0, 0, Math.PI*2); ctx.fillStyle = "#FADB67"; // bright yellow/golden rayman skin ctx.fill(); ctx.strokeStyle = "#CFA23B"; ctx.lineWidth = 1.5; ctx.stroke(); // hoodie / neck shadow ctx.beginPath(); ctx.ellipse(0, -6, 12, 8, 0, 0, Math.PI*2); ctx.fillStyle = "#E5B83C"; ctx.fill(); // ---- FACE ---- // eyes (big, white with black pupils) ctx.beginPath(); ctx.arc(-7, -8, 5, 0, Math.PI*2); ctx.fillStyle = "#FFFFFF"; ctx.fill(); ctx.strokeStyle = "#AA8E42"; ctx.lineWidth = 1; ctx.stroke(); ctx.beginPath(); ctx.arc(7, -8, 5, 0, Math.PI*2); ctx.fill(); ctx.stroke(); // pupils (follow direction? but always expressive) let pupilShift = faceRight ? 1.2 : -1.2; ctx.fillStyle = "#1F2E2E"; ctx.beginPath(); ctx.arc(-7 + pupilShift*0.8, -8.5, 2.2, 0, Math.PI*2); ctx.fill(); ctx.beginPath(); ctx.arc(7 + pupilShift*0.8, -8.5, 2.2, 0, Math.PI*2); ctx.fill(); // eye spark ctx.fillStyle = "white"; ctx.beginPath(); ctx.arc(-8 + pupilShift*0.4, -9.8, 0.9, 0, Math.PI*2); ctx.fill(); ctx.beginPath(); ctx.arc(6 + pupilShift*0.4, -9.8, 0.9, 0, Math.PI*2); ctx.fill(); // nose: little orange dot ctx.fillStyle = "#FF8C5A"; ctx.beginPath(); ctx.arc(0, -5, 2.2, 0, Math.PI*2); ctx.fill(); // big smile! (rayman's trademark) ctx.beginPath(); ctx.arc(0, -1.5, 10, 0.05, Math.PI - 0.05); ctx.strokeStyle = "#633C1C"; ctx.lineWidth = 2.5; ctx.stroke(); // little teeth ctx.fillStyle = "#FFF7E8"; ctx.beginPath(); ctx.rect(-3, -2.2, 2.5, 3); ctx.fill(); ctx.beginPath(); ctx.rect(0.8, -2.2, 2.5, 3); ctx.fill(); // ---- Hair / Rayman tuft (famous red hair tuft) ---- ctx.fillStyle = "#E34132"; ctx.beginPath(); ctx.moveTo(-4, -17); ctx.quadraticCurveTo(0, -28, 4, -17); ctx.fill(); ctx.beginPath(); ctx.moveTo(-2, -19); ctx.quadraticCurveTo(0, -31, 2, -19); ctx.fill(); ctx.fillStyle = "#C02F22"; ctx.beginPath(); ctx.ellipse(0, -21, 3, 5, 0, 0, Math.PI*2); ctx.fill(); // ---- LIMBS: detached hands/fists (Rayman signature floating limbs) ---- // walking angle influences arms & legs swing (radians) let swing = (typeof walkAngle === 'number') ? Math.sin(walkAngle) * 0.9 : 0; let legSwing = Math.sin(walkAngle + 1.2) * 0.9; // left arm (detached floating) let leftArmX = -24; let leftArmY = -4 + swing * 5; // right arm let rightArmX = 24; let rightArmY = -4 - swing * 5; // fists (big round gloves) ctx.fillStyle = "#FCE5B4"; ctx.shadowBlur = 0; // draw connecting "energy" lines? Actually floating style: just draw fists with small floating trails ctx.beginPath(); ctx.arc(leftArmX, leftArmY, 9, 0, Math.PI*2); ctx.fillStyle = "#FCD28F"; ctx.fill(); ctx.fillStyle = "#E1B070"; ctx.beginPath(); ctx.arc(leftArmX-1, leftArmY-1, 3, 0, Math.PI*2); ctx.fill(); ctx.beginPath(); ctx.arc(rightArmX, rightArmY, 9, 0, Math.PI*2); ctx.fillStyle = "#FCD28F"; ctx.fill(); ctx.fillStyle = "#E1B070"; ctx.beginPath(); ctx.arc(rightArmX+1, rightArmY-1, 3, 0, Math.PI*2); ctx.fill(); // add "cuff" like little wrist band ctx.fillStyle = "#BB7744"; ctx.beginPath(); ctx.ellipse(leftArmX-3, leftArmY+1, 3, 4, -0.3, 0, Math.PI*2); ctx.fill(); ctx.beginPath(); ctx.ellipse(rightArmX+3, rightArmY+1, 3, 4, 0.3, 0, Math.PI*2); ctx.fill(); // ---- LEGS (detached shoes) ---- let leftLegX = -14; let leftLegY = 18 + legSwing * 6; let rightLegX = 14; let rightLegY = 18 - legSwing * 6; ctx.fillStyle = "#E5AE5A"; ctx.beginPath(); ctx.ellipse(leftLegX, leftLegY, 8, 10, 0.2, 0, Math.PI*2); ctx.fill(); ctx.fillStyle = "#C4813B"; ctx.beginPath(); ctx.ellipse(leftLegX-1, leftLegY+2, 3, 4, 0, 0, Math.PI*2); ctx.fill(); ctx.fillStyle = "#E5AE5A"; ctx.beginPath(); ctx.ellipse(rightLegX, rightLegY, 8, 10, -0.2, 0, Math.PI*2); ctx.fill(); ctx.fillStyle = "#C4813B"; ctx.beginPath(); ctx.ellipse(rightLegX+1, rightLegY+2, 3, 4, 0, 0, Math.PI*2); ctx.fill(); // add little "glow" effect: floating particles ctx.fillStyle = "rgba(255,200,100,0.5)"; for(let i=0;i<2;i++) ctx.beginPath(); ctx.arc(leftArmX-4 + Math.sin(frameCount*0.5)*2, leftArmY+2, 2, 0, Math.PI*2); ctx.fill(); ctx.beginPath(); ctx.arc(rightArmX+4 + Math.cos(frameCount*0.7)*2, rightArmY+2, 2, 0, Math.PI*2); ctx.fill(); // ---- Extra rayman details: necklace / small medallion? ---- ctx.fillStyle = "#D4AF37"; ctx.beginPath(); ctx.ellipse(0, 9, 6, 4, 0, 0, Math.PI*2); ctx.fill(); ctx.fillStyle = "#F7D44A"; ctx.beginPath(); ctx.arc(0, 9, 2.8, 0, Math.PI*2); ctx.fill(); ctx.restore(); // restore rotation & scale // draw background floating effects (whimsical particles) function drawBackgroundEffects(ctx, width, height) // subtle radial gradient ambiance let grad = ctx.createLinearGradient(0, 0, width, height); grad.addColorStop(0, "#233142"); grad.addColorStop(1, "#16212b"); ctx.fillStyle = grad; ctx.fillRect(0, 0, width, height); // dreamy little sparkles for(let i=0;i<60;i++) let sx = (i * 131) % width; let sy = (i * 253) % height; let flicker = Math.sin(frameCount*0.02 + i)*0.4+0.6; ctx.fillStyle = `rgba(255, 235, 150, $flicker*0.25)`; ctx.beginPath(); ctx.arc(sx, sy, 1.5, 0, Math.PI*2); ctx.fill(); // draw floating name tag or cute little "ray" effects function drawCompanionExtras(ctx, x, y, facingRight) ctx.save(); ctx.font = "bold 16px 'Quicksand', 'Segoe UI'"; ctx.shadowBlur = 0; ctx.fillStyle = "#FFEDC0"; ctx.shadowColor = "rgba(0,0,0,0.4)"; let tagX = facingRight ? x + 20 : x - 70; ctx.fillText("⚡ Rayman", tagX, y-28); ctx.fillStyle = "#FABD6F"; ctx.font = "12px monospace"; ctx.fillText("✧ shimeji ✧", tagX+5, y-14); ctx.restore(); // --- main animation loop --- let animationId = null; function animate() updateMovement(); // update frame counter for sparkles & idle frameCount++; if(frameCount > 10000) frameCount = 0; // drawing ctx.clearRect(0, 0, width, height); drawBackgroundEffects(ctx, width, height); // get current walking angle for limb animation (if walking or idle) let animAngle = isWalking ? walkCycle : (Math.sin(frameCount * 0.12) * 0.8); if(jumpSpinActive) animAngle = walkCycle * 0.5; // less swing during jump // draw rayman at current position drawRayman(ctx, raymanX, raymanY, facingRight, animAngle, jumpSpinRotation, 0); // extra cute floating text drawCompanionExtras(ctx, raymanX, raymanY, facingRight); // draw subtle trail when walking (fun effect) if(isWalking && !jumpSpinActive) ctx.beginPath(); ctx.arc(raymanX - (facingRight? 12 : -12), raymanY+8, 5, 0, Math.PI*2); ctx.fillStyle = "rgba(255,215,100,0.3)"; ctx.fill(); // if click reaction active, draw little "pop" stars if(jumpSpinActive) let t = (18 - jumpSpinTimer)/18; let starCount = 5; for(let i=0;i<starCount;i++) let angle = (frameCount*0.4 + i) * Math.PI*2/starCount; let rad = 15 * (1-t) + 6; let sx = raymanX + Math.cos(angle)*rad; let sy = raymanY + Math.sin(angle)*rad - 12; ctx.fillStyle = `rgba(255, 210, 90, $1-t*0.6)`; ctx.beginPath(); ctx.moveTo(sx, sy-3); ctx.lineTo(sx+2, sy); ctx.lineTo(sx, sy+3); ctx.lineTo(sx-2, sy); ctx.fill(); animationId = requestAnimationFrame(animate); function init() resizeCanvas(); // center initial position raymanX = width/2; raymanY = height/2; targetX = width/2; targetY = height/2; animate(); init(); )(); </script> </body> </html> jumpSpinRotation : 0; ctx

Comparte este libro

Sinopsis

Aplicando unas reglas universales de la arquitectura de software, podrá mejorar tremendamente la productividad en la implementación de cualquier programa. Ahora, continuando el éxito sus libros más vendidos, "Código Limpio" y "The Clean Coder", el legendario experto en software Robert C. Martin revela estas reglas y le ayuda a implementarlas. Martin no se limita a presentar opciones. Apoyándose en más de medio siglo de experiencia en entornos de software de todos los tipos imaginables, le indica las decisiones que tomar y por qué resultan fundamentales para su éxito. Tal como se espera de "Uncle Bob", le ofrece un gran número de soluciones directas y lógicas para las dificultades reales a las que se enfrentará, aquellas que harán que sus proyectos tengan o no éxito. Este libro es una lectura fundamental para todo arquitecto de software o quien aspire a serlo, analistas y diseñadores de sistemas y gestores de software, y para cualquier programador que deba ejecutar los diseños de otro.

  • Colección

    TÍTULOS ESPECIALES

  • Código

    2315142

  • I.S.B.N.

    978-84-415-3990-7

  • Publicación
    01/03/2018

  • Clasificación IBIC

    UMA

  • Formato

    Papel

  • Páginas

    320

Libros de Robert C. Martin

TÍTULOS ESPECIALES

Nosotros, los programadores

Nosotros, los programadores

TÍTULOS ESPECIALES

Diseño funcional. Principios, patrones y prácticas

Diseño funcional. Principios, patrones y prácticas

TÍTULOS ESPECIALES

La artesanía del código limpio

La artesanía del código limpio

Sobre la colección TÍTULOS ESPECIALES

Nuestros libros

Recibe todas las noticias sobre novedades y eventos

books