我希望能够使用按键上的 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();
}
}
您所做的很多事情都与宽度和高度有关。与其这样做,不如创建表演,就好像它的中心是 (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>
希望这有帮助!
要从中心旋转由多个形状组成的对象,请按照下列步骤操作:
确定物体的中心点。这可以通过找到对象边界框的中点或使用对象顶点的平均值来完成。
平移物体,使中心点在原点。
将旋转矩阵应用于对象。旋转矩阵是表示旋转变换的 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();