如何从中心旋转由多个形状组成的物体?

问题描述 投票:0回答:2

我希望能够使用按键上的 rotate() 函数从中心点旋转由许多形状组成的火鸡。在实践中,您可以使用箭头键将火鸡缓慢地向左或向右转圈。火鸡的位置不会改变,因为它是从中心旋转的,但它只是真正意义上的旋转。

我现在的问题是我不知道如何从它的确切中心旋转整个形状,而不是围绕一个随机点。那么我将如何为每个形状设置一个旋转点?

这是我当前的代码:

let bubbles=[];  //arrayList

function setup() {
  createCanvas(windowWidth, windowHeight);
  angleMode(DEGREES);
  speedX=random(1,3);
  speedY=random(1,2);
}

function mouseDragged() {
  let a=bubbles.length;
  bubbles.pop(a);
}



function mousePressed() {
  let d=random(10,50);
  let w=random(50, 180);
  let b=new Bubble(mouseX,mouseY,d, w);
  bubbles.push(b);
}

function draw() {
  background(255);
  for (let bubble of bubbles) {
    bubble.move(); 
    bubble.show();
  }
}

class Bubble {
  
  constructor(x,y,d,w) {
    this.x=x;
    this.y=y;
    this.d=d;
    this.speedX=random(15, 15);
    this.speedY=random(15, 15);
    this.d=random(0.5, 1.5);
    this.w=w;
  }
  move() {

    if (this.x > width-this.w/1.08/2 || this.x < 0+this.w/1.08/2) {
      this.speedX=-this.speedX;
      this.speedX*=1.1
    } // right and left bounce
    
    if (this.y > height-this.w/1.05 || this.y < 0+this.w/2/2) {
      this.speedY=-this.speedY;
      this.speedY*1.1
    } // bottom and top bounce 
  

    this.x+=this.speedX;     //x=x+speedX;
    this.y+=this.speedY;
  }
  show() {  
  //200 200
           push();
    translate(this.x+this.w/5, this.y+this.w/8);
    rotate(25);
    fill(255,153,51);
    ellipseMode(CENTER);
    ellipse(0, 0, this.w/1.67, this.w/0.67); //left orange feather
    pop(); 
    
       push();
    translate(this.x-this.w/5, this.y+this.w/8);
    rotate(-25);
    fill(255,153,51);
    ellipseMode(CENTER);
    ellipse(0, 0, this.w/1.67, this.w/0.67); //left orange feather
    pop(); 
    
        push();
    translate(this.x+this.w/2, this.y+this.w/5);
    rotate(60);
    fill(255,0,0);
    ellipseMode(CENTER);
  ellipse(0, 0, this.w/1.67, this.w/0.67) //right red feather
    pop();
    
    push();
  translate(this.x-this.w/2, this.y+this.w/5);
    rotate(-60);
    fill(255,0,0);
    ellipseMode(CENTER);
  ellipse(0, 0, this.w/1.67, this.w/0.67) //left red feather
    pop();
    
 
   fill(255,204,0);   
  ellipse(this.x, this.y+this.w/20, this.w/1.67, this.w/0.67) //yellow feather
    
    push();
    translate(this.x-this.w/2, this.y+this.w/1.67);
    rotate(10);
    fill(78,39,0);
    ellipse(0, 0, this.w/0.8, this.w/1.67);
    pop();
    
    push();
    translate(this.x+this.w/2, this.y+this.w/1.67);
    rotate(-10);
    fill(78,39,0);
    ellipse(0, 0, this.w/0.8, this.w/1.67);
    pop();
     
    
  fill(153, 102, 51, 255);
  ellipse(this.x, this.y+this.w/2.11, this.w/1.08, this.w/1.08); //body
  ellipse(this.x, this.y, this.w/2, this.w/2) //head
  
  fill(255);
  ellipse(this.x-this.w/10, this.y-this.w/20, this.w/6.67*this.d, this.w/6.67*this.d); //eye
  ellipse(this.x+this.w/10, this.y-this.w/20, this.w/6.67*this.d, this.w/6.67*this.d); //eye
  
  fill(0);
  ellipse(this.x-this.w/11.77, this.y-this.w/28.57, this.w/13.33*this.d, this.w/13.33*this.d) //pupil
  ellipse(this.x+this.w/8.7, this.y-this.w/28.57, this.w/13.33*this.d, this.w/13.33*this.d) //pupil
  
    
  fill(255, 0, 0);
  ellipse(this.x-this.w/20, this.y+this.w/5, this.w/10, this.w/5); //gobble
  fill(255,153,51);
 triangle(this.x, this.y+this.w/3.33,  this.x-this.w/10, this.y+this.w/10,  this.x+this.w/10, this.y+this.w/10) //beak
    
  triangle(this.x-this.w/13.33, this.y+this.w/1.05, this.x-this.w/3.08, this.y+this.w/1.05, this.x-this.w/13.33, this.y+this.w/1.29) //left foot
  triangle(this.x+this.w/13.33, this.y+this.w/1.05, this.x+this.w/3.08, this.y+this.w/1.05, this.x+this.w/13.33, this.y+this.w/1.29); //right foot
    
    
    push();
    translate(this.x-this.w/2.22, this.y+this.w/2.22);
    rotate(30);
  fill(218,180,142);
    ellipse(0, 0, this.w/3.64, this.w/1.67); //left wing
    pop(); 
    
  push();
    translate(this.x+this.w/2.22, this.y+this.w/2.22);
    rotate(-30);
    fill(218,180,142)
    ellipse(0,0, this.w/3.64, this.w/1.67); //right wing
    pop();
    
  } 
}
javascript rotation p5.js
2个回答
0
投票

您所做的很多事情都与宽度和高度有关。与其这样做,不如创建表演,就好像它的中心是 (0,0),根据需要旋转它们,然后调用 transform(this.x, this.y) 将它们映射到您需要它们去的地方。

为了帮助说明我的意思,这里有一个简短的演示:

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(220);
  
  push()
  angleMode(DEGREES) // Set the anglemode to degrees instead of radians.
  translate(200,200) // Move the figure to (200,200), the center of the canvas
  rotate(45) // Rotate 45 degrees
  // Draw the shapes, working as if the center of them was (0,0)
  rect(-10,-10,20,20)
  ellipse(-40,0,20,20)
  ellipse(40,0,20,20)
  pop()
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.6.0/p5.js"></script>

希望这有帮助!


0
投票

要从中心旋转由多个形状组成的对象,请按照下列步骤操作:

确定物体的中心点。这可以通过找到对象边界框的中点或使用对象顶点的平均值来完成。

平移物体,使中心点在原点。

将旋转矩阵应用于对象。旋转矩阵是表示旋转变换的 2x2 矩阵。您可以使用三角函数根据所需的旋转角度计算矩阵的值。

通过应用步骤 2 中的反向翻译,将对象翻译回其原始位置。

这里是 Python 中的示例代码片段,演示了如何使用 Pygame 库从中心旋转由多个形状组成的对象:

import pygame
import math

# Define the object as a list of shapes
object_shapes = [
    [(100, 100), (150, 100), (150, 150), (100, 150)],  # square
    [(125, 50), (175, 50), (150, 100)],  # triangle
    [(110, 110), (140, 110), (140, 140), (110, 140)]  # rectangle
]

# Determine the center point of the object
center_x = sum(x for shape in object_shapes for x, y in shape) / len(object_shapes) / len(object_shapes[0])
center_y = sum(y for shape in object_shapes for x, y in shape) / len(object_shapes) / len(object_shapes[0])
center = (center_x, center_y)

# Define the rotation angle in degrees
angle_degrees = 45

# Translate the object to the origin
translated_shapes = []
for shape in object_shapes:
    translated_shape = []
    for x, y in shape:
        translated_x = x - center_x
        translated_y = y - center_y
        translated_shape.append((translated_x, translated_y))
    translated_shapes.append(translated_shape)

# Apply the rotation transformation to the object
rotated_shapes = []
angle_radians = math.radians(angle_degrees)
rotation_matrix = [
    [math.cos(angle_radians), -math.sin(angle_radians)],
    [math.sin(angle_radians), math.cos(angle_radians)]
]
for shape in translated_shapes:
    rotated_shape = []
    for x, y in shape:
        rotated_x = x * rotation_matrix[0][0] + y * rotation_matrix[0][1]
        rotated_y = x * rotation_matrix[1][0] + y * rotation_matrix[1][1]
        rotated_shape.append((rotated_x, rotated_y))
    rotated_shapes.append(rotated_shape)

# Translate the object back to its original position
final_shapes = []
for shape in rotated_shapes:
    final_shape = []
    for x, y in shape:
        final_x = x + center_x
        final_y = y + center_y
        final_shape.append((final_x, final_y))
    final_shapes.append(final_shape)

# Draw the object on the screen using Pygame
pygame.init()
screen = pygame.display.set_mode((400, 400))
clock = pygame.time.Clock()
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            quit()
    screen.fill((255, 255, 255))
    for shape in final_shapes:
        pygame.draw.polygon(screen, (255, 0, 0), shape)
    pygame.display.update()
    clock.tick(60)

如何使用 HTML5 画布从中心旋转由多个形状组成的对象:

// Define the object as a list of shapes
const objectShapes = [
  [{ x: 100, y: 100 }, { x: 150, y: 100 }, { x: 150, y: 150 }, { x: 100, y: 150 }], // square
  [{ x: 125, y: 50 }, { x: 175, y: 50 }, { x: 150, y: 100 }], // triangle
  [{ x: 110, y: 110 }, { x: 140, y: 110 }, { x: 140, y: 140 }, { x: 110, y: 140 }] // rectangle
];

// Define the rotation angle in degrees
const angleDegrees = 45;

// Determine the center point of the object
const center = {
  x: objectShapes.reduce((total, shape) => total + shape.reduce((sum, { x }) => sum + x, 0), 0) / (objectShapes.length * objectShapes[0].length),
  y: objectShapes.reduce((total, shape) => total + shape.reduce((sum, { y }) => sum + y, 0), 0) / (objectShapes.length * objectShapes[0].length)
};

// Translate the object to the origin
const translatedShapes = objectShapes.map(shape =>
  shape.map(({ x, y }) => ({ x: x - center.x, y: y - center.y }))
);

// Apply the rotation transformation to the object
const angleRadians = angleDegrees * Math.PI / 180;
const rotationMatrix = [
  [Math.cos(angleRadians), -Math.sin(angleRadians)],
  [Math.sin(angleRadians), Math.cos(angleRadians)]
];
const rotatedShapes = translatedShapes.map(shape =>
  shape.map(({ x, y }) => ({ x: x * rotationMatrix[0][0] + y * rotationMatrix[0][1], y: x * rotationMatrix[1][0] + y * rotationMatrix[1][1] }))
);

// Translate the object back to its original position
const finalShapes = rotatedShapes.map(shape =>
  shape.map(({ x, y }) => ({ x: x + center.x, y: y + center.y }))
);

// Draw the object on the canvas
const canvas = document.createElement('canvas');
canvas.width = 400;
canvas.height = 400;
document.body.appendChild(canvas);
const ctx = canvas.getContext('2d');

function drawShapes(shapes) {
  shapes.forEach(shape => {
    ctx.beginPath();
    shape.forEach(({ x, y }, i) => {
      if (i === 0) {
        ctx.moveTo(x, y);
      } else {
        ctx.lineTo(x, y);
      }
    });
    ctx.closePath();
    ctx.fillStyle = 'red';
    ctx.fill();
  });
}

function animate() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  drawShapes(finalShapes);
  requestAnimationFrame(animate);
}

animate();
© www.soinside.com 2019 - 2024. All rights reserved.