turns-00080.parquet:903
49b7f7595297b52b6b5845a0
turn 1/16gpt-4.1-mini-2025-04-14SpanishMexico1402 words
degenerate_repetitionAbsentFinal dense release
USER
Necesito un código en ActionScript 3 que cree un cubo 3D sin utilizar clases. El cubo debe estar formado por seis caras con colores diferentes. Quiero que el cubo sea interactivo: al hacer clic y arrastrar el ratón sobre él, el cubo debe rotar sobre su propio eje en función del movimiento del mouse. Además, al soltarlo (o 'lanzarlo'), la rotación debe continuar con un efecto easing que simule inercia y desaceleración progresiva. El código no debe usar clases, es decir, debe estar escrito en un único archivo o en el timeline. Incluye comentarios en el código para explicar cada parte y utiliza técnicas de easing para suavizar la rotación.
ASSISTANT
```actionscript3
// Código para crear un cubo 3D interactivo en AS3 sin usar clases.
// El cubo se puede rotar con el ratón (clic y arrastrar) y al soltar continúa girando con inercia y easing.
// --- CONFIGURACIÓN INICIAL ---
stage.frameRate = 60;
// Importamos eventos necesarios
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.geom.Point;
// --- VARIABLES ---
// Tamaño del cubo
var size:Number = 150;
// Array para guardar las caras (Sprites)
var faces:Array = [];
// Variables para la rotación acumulada en X e Y (en grados)
var rotationX:Number = 0;
var rotationY:Number = 0;
// Variables para la velocidad angular (grados por frame)
var velocityX:Number = 0;
var velocityY:Number = 0;
// Variables para control de arrastre
var dragging:Boolean = false;
var lastMousePos:Point = new Point();
var currentMousePos:Point = new Point();
// --- CREAMOS LAS CARAS DEL CUBO ---
// Cada cara es un Sprite con un cuadrado coloreado
// Colores para cada cara
var colors:Array = [0xFF0000, 0x00FF00, 0x0000FF, 0xFFFF00, 0xFF00FF, 0x00FFFF];
// Definimos las caras
// Cada cara tiene un centro en 3D y orientación
// Vamos a definirlas con puntos centrados en el origen para poder rotar fácilmente
// Función para crear una cara
function createFace(color:uint):Sprite {
var s:Sprite = new Sprite();
s.graphics.beginFill(color);
s.graphics.drawRect(-size/2, -size/2, size, size);
s.graphics.endFill();
addChild(s);
return s;
}
// Creamos las 6 caras
// Las posiciones iniciales las definiremos en el update del render
for(var i:int=0; i<6; i++) {
faces[i] = createFace(colors[i]);
}
// --- PUNTOS 3D PARA LAS CARAS ---
// Definimos la posición y normal de cada cara en 3D local antes de la rotación
// Cada cara definida por su centro 3D y normal vector
// We'll store centers in 3D coordinates (x,y,z)
// order: front, back, left, right, top, bottom
var facePositions:Array = [
{x:0, y:0, z:size/2}, // Front
{x:0, y:0, z:-size/2}, // Back
{x:-size/2, y:0, z:0}, // Left
{x:size/2, y:0, z:0}, // Right
{x:0, y:-size/2, z:0}, // Top (y is negative up)
{x:0, y:size/2, z:0} // Bottom
];
// Normales para el painter's algorithm (usamos para ordenar caras delante/atrás)
// Inicialmente iguales a caras (front face normals)
var faceNormals:Array = [
{x:0, y:0, z:1},
{x:0, y:0, z:-1},
{x:-1, y:0, z:0},
{x:1, y:0, z:0},
{x:0, y:-1, z:0},
{x:0, y:1, z:0}
];
// Distancia focal para perspectiva simple
var focalLength:Number = 600;
// --- FUNCIONES DE ROTACIÓN EN 3D ---
// Convertimos grados a radianes para trigonometría
function deg2rad(deg:Number):Number {
return deg * Math.PI / 180;
}
// Función para rotar un punto en 3D alrededor del eje X
function rotateX(point:Object, angle:Number):Object {
var rad:Number = deg2rad(angle);
var cosA:Number = Math.cos(rad);
var sinA:Number = Math.sin(rad);
return {
x:point.x,
y:point.y*cosA - point.z*sinA,
z:point.y*sinA + point.z*cosA
};
}
// Función para rotar un punto en 3D alrededor del eje Y
function rotateY(point:Object, angle:Number):Object {
var rad:Number = deg2rad(angle);
var cosA:Number = Math.cos(rad);
var sinA:Number = Math.sin(rad);
return {
x:point.x*cosA + point.z*sinA,
y:point.y,
z:-point.x*sinA + point.z*cosA
};
}
// --- PROYECTAR PUNTO 3D A 2D ---
function project(point:Object):Point {
// Proyección perspectiva simple
var scale:Number = focalLength / (focalLength + point.z);
return new Point(point.x * scale, point.y * scale);
}
// --- RENDERIZAR CUBO ---
// Esta función actualiza la posición de las caras según las rotaciones
function render():void {
var transformedCenters:Array = [];
var transformedNormals:Array = [];
// Aplicamos la rotación a las posiciones y normales de cada cara
for(var i:int=0; i<6; i++) {
var pos:Object = facePositions[i];
var norm:Object = faceNormals[i];
// Rotación sobre X e Y
var rotatedPos:Object = rotateX(rotateY(pos, rotationY), rotationX);
var rotatedNorm:Object = rotateX(rotateY(norm, rotationY), rotationX);
transformedCenters[i] = rotatedPos;
transformedNormals[i] = rotatedNorm;
}
// Usamos un simple painter's algorithm: ordenamos las caras por la Z del centro (de más lejos a más cerca)
// Luego colocamos el display list en ese orden para simulación 3D simple
// Las caras con más Z (más cerca del viewer) están encima
// Creamos array de indices con Z para ordenar
var faceDepth:Array = [];
for(i=0; i<6; i++) {
faceDepth[i] = {index:i, z:transformedCenters[i].z};
}
// Ordenamos ascendente por z -> Las caras con mayor z al final (las últimas se dibujan encima)
faceDepth.sortOn("z", Array.NUMERIC);
// Reordenamos en display list
for(i=0; i<6; i++) {
setChildIndex(faces[faceDepth[i].index], i);
}
// Posicionamos las caras con proyección y escala según Z para simular perspectiva
for(i=0; i<6; i++) {
var c:Object = transformedCenters[i];
var p:Point = project(c);
var s:Number = focalLength / (focalLength + c.z);
var face:Sprite = faces[i];
face.x = stage.stageWidth/2 + p.x;
face.y = stage.stageHeight/2 + p.y;
face.scaleX = face.scaleY = s;
// Opcional: ajustar alpha según profundidad para dar sensación de profundidad
// Las caras que están "de frente" (normal con Z hacia adelante) más opacas
// Normal Z es componente Z del normal después de la rotación
var normalZ:Number = transformedNormals[i].z;
// Ajustamos el brillo de la cara basada en normalZ para simular luz
var brightness:Number = (normalZ + 1) / 2; // NormalZ va de -1 a 1, a 0 a 1
// Como no podemos manipular brillo directamente sin filtros, ajustamos alpha mínimo a 0.6
face.alpha = 0.6 + 0.4 * brightness;
}
}
// --- INTERACCIÓN DEL RATÓN ---
// Eventos para arrastrar y rotar el cubo
stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
stage.addEventListener(MouseEvent.MOUSE_OUT, onMouseUp); // si el ratón sale del stage también suelta
function onMouseDown(e:MouseEvent):void {
dragging = true;
lastMousePos.x = stage.mouseX;
lastMousePos.y = stage.mouseY;
// Al empezar arrastre, detenemos la inercia
velocityX = 0;
velocityY = 0;
}
function onMouseUp(e:MouseEvent):void {
dragging = false;
// El movimiento que genero el usuario queda en velocity para la inercia
}
stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
function onEnterFrame(e:Event):void {
if(dragging){
currentMousePos.x = stage.mouseX;
currentMousePos.y = stage.mouseY;
// Calculamos diferencia de movimiento
var dx:Number = currentMousePos.x - lastMousePos.x;
var dy:Number = currentMousePos.y - lastMousePos.y;
// Ajustamos la rotación en función del movimiento delta del ratón
// Aquí invertimos Y para que arrastrar hacia abajo rote positivo en X y viceversa
rotationY += dx * 0.5;
rotationX += dy * 0.5;
// Guardamos velocidad para inercia (se suaviza fuera del drag)
velocityY = dx * 0.5;
velocityX = dy * 0.5;
lastMousePos.x = currentMousePos.x;
lastMousePos.y = currentMousePos.y;
} else {
// Cuando no arrastramos, aplicamos easing para que siga rotando y decelerando (inercia)
// Usamos un factor de fricción para que la velocidad disminuya hasta 0
var friction:Number = 0.90; // 0 = para y 1 no se frena
velocityX *= friction;
velocityY *= friction;
// Si la velocidad es muy pequeña, la hacemos 0 para evitar giros infinitos muy lentos
if(Math.abs(velocityX) < 0.01) velocityX = 0;
if(Math.abs(velocityY) < 0.01) velocityY = 0;
rotationX += velocityX;
rotationY += velocityY;
}
// Limitamos la rotacionX a -90 a 90 para no perder la referencia visual (opcional)
// Comentamos para que pueda girar libremente:
/*
if(rotationX > 90) rotationX = 90;
if(rotationX < -90) rotationX = -90;
*/
// LLAMAMOS A RENDERIZAR EL CUBO CON NUEVAS ROTACIONES
render();
}
// --- INICIALIZAMOS ---
render();
```
---
### Explicación resumida:
- Se crean 6 caras con colores distintos, cada una representando un lado del cubo.
- Cada cara tiene una posición y una normal en 3D, desde el origen.
- Las rotaciones se aplican manualmente con funciones que rotan puntos 3D alrededor de los ejes X e Y.
- Cada frame las posiciones de las caras son calculadas, proyectadas en 2D y se reordenan para simular profundidad.
- Se escucha el mouse para detectar arrastre; durante el arrastre la rotación sigue el movimiento del mouse.
- Cuando se suelta, la velocidad se mantiene y se reduce gradual con un coeficiente `friction` para simular inercia con easing.
- La escala y el alpha de cada cara se ajustan según la profundidad y la orientación para mejorar la percepción 3D.
- Todo está en un solo archivo/timeline y no se usan clases.