类实现故障求助:旋转追踪鼠标的三角形敌人无法绘制
问题排查与修复方案
看起来你在重构Enemy类后遇到了几个关键问题,导致敌人无法渲染,甚至影响了后续图形的显示。我们一步步拆解问题并给出修复方案:
1. Setup方法中的循环错误(最致命的初始化问题)
你的setup代码里有一个多余的分号,导致循环完全没有执行添加敌人的逻辑,最终只添加了一个敌人:
for (i = 0; i<difficulty; i++); // 这里的分号让循环体为空! enemies.add(new Enemy(i*5));
修正后要去掉分号,把add操作放进循环体,同时显式声明变量类型避免隐式错误:
for (int i = 0; i < difficulty; i++) { enemies.add(new Enemy(i*5)); }
2. RotateEnemy方法中的参数与逻辑错误
你的旋转方法存在多处致命问题:
theta2变量在Enemy类中完全没有声明,会直接导致编译失败;- 调用旋转方法时错误地传入了
x2作为y坐标参数(比如rotateX(x2, x2, theta2, 0)),应该传入对应点的x和y值(x2和y2); - 旋转后的赋值逻辑混乱,比如
x2 = rotateY(...)后又立刻用x2Rotated覆盖,完全丢失了旋转结果。
我们可以直接用三角函数实现顶点旋转,同时添加角度变量:
// 在Enemy类成员变量中添加 float theta; void rotateEnemy() { // 计算敌人朝向鼠标的角度 theta = atan2(mouseY - y, mouseX - x); // 旋转三角形的三个顶点(基于自身中心) float x1Rotated = cos(theta) * x1 - sin(theta) * y1; float y1Rotated = sin(theta) * x1 + cos(theta) * y1; float x2Rotated = cos(theta) * x2 - sin(theta) * y2; float y2Rotated = sin(theta) * x2 + cos(theta) * y2; float x3Rotated = cos(theta) * x3 - sin(theta) * y3; float y3Rotated = sin(theta) * x3 + cos(theta) * y3; // 更新顶点坐标 x1 = x1Rotated; y1 = y1Rotated; x2 = x2Rotated; y2 = y2Rotated; x3 = x3Rotated; y3 = y3Rotated; }
3. DrawEnemy方法的两个关键错误
- 三角形参数错误:你写的
triangle(x1, y1, x2, x2, x3, x3)会把第二个点设为(x2, x2),第三个点设为(x3, x3),这根本不是你定义的三角形顶点,应该用(x2, y2)和(x3, y3); - 坐标系未重置:
translate(x,y)会修改全局坐标系,如果不用pushMatrix()和popMatrix()包裹,后续的图形绘制都会受到影响(比如你提到的椭圆不显示)。
修正后的drawEnemy方法:
void drawEnemy() { pushMatrix(); // 保存当前坐标系状态 translate(x, y); triangle(x1, y1, x2, y2, x3, y3); popMatrix(); // 恢复坐标系,不影响后续绘制 }
4. 未定义的变量问题
你的Enemy类中使用了speedChange、isDeadly、energy、points等变量,但这些变量既没有在Enemy类中声明,也没有作为参数传入。你需要:
- 如果是全局变量,确保在主程序中定义为全局;
- 如果是Enemy的属性,在Enemy类中添加成员变量并初始化。
比如在Enemy类中补充:
float speedChange = 0; // 根据需求调整默认值 boolean isDeadly = true;
主程序中补充全局变量:
float energy; int points; int difficulty = 5; // 示例值,根据你的需求设置
5. Respawn方法的范围错误
你的respawn逻辑中存在无效的随机范围,比如x = random(0, -width/2),random函数要求第一个参数小于第二个,应该修正为:
if (ranQuadrant1 == 0) { if (ranSide1 == 0) { x = random(-width/2, 0); // 左边界外 } else { x = random(width, width + width/2); // 右边界外 y = random(-height/2, height + height/2); } } // 其他分支同理修正random的参数顺序
修正后的核心Enemy类片段
class Enemy { float x = random(-width, 0); float y = random(0, height); // 三角形顶点(基于自身中心的相对坐标) float x1 = 0; float y1 = (sqrt(3)/3)*40; float x2 = -20; float y2 = -(sqrt(3)/3)*40; float x3 = 20; float y3 = -(sqrt(3)/3)*40; float speed; float theta; // 旋转角度 float speedChange = 0; boolean isDeadly = true; Enemy(float tempSpeed) { speed = tempSpeed; } void rotateEnemy() { theta = atan2(mouseY - y, mouseX - x); float x1Rotated = cos(theta) * x1 - sin(theta) * y1; float y1Rotated = sin(theta) * x1 + cos(theta) * y1; float x2Rotated = cos(theta) * x2 - sin(theta) * y2; float y2Rotated = sin(theta) * x2 + cos(theta) * y2; float x3Rotated = cos(theta) * x3 - sin(theta) * y3; float y3Rotated = sin(theta) * x3 + cos(theta) * y3; x1 = x1Rotated; y1 = y1Rotated; x2 = x2Rotated; y2 = y2Rotated; x3 = x3Rotated; y3 = y3Rotated; } void move() { theta = atan2(mouseY - y, mouseX - x); x += cos(theta) * (speed + speedChange); y += sin(theta) * (speed + speedChange); } void drawEnemy() { pushMatrix(); translate(x, y); triangle(x1, y1, x2, y2, x3, y3); popMatrix(); } void collisionDetect() { if (abs(mouseX-x) + abs(mouseY-y) < 80) { if (isDeadly) { respawn(); energy -= height/16; points += 500; } else { energy = 0; } } } void respawn() { int ranQuadrant1 = (int)random(0, 2); int ranSide1 = (int)random(0, 2); if (ranQuadrant1 == 0) { if (ranSide1 == 0) { x = random(-width/2, 0); } else { x = random(width, width + width/2); y = random(-height/2, height + height/2); } } else if (ranSide1 == 0) { y = random(-height/2, 0); } else { y = random(height, height + height/2); x = random(-width/2, width + width/2); } } }
这些修正应该能解决敌人不显示的问题,同时恢复后续图形的正常渲染。记得确保主程序中的全局变量都正确定义并初始化。
内容的提问来源于stack exchange,提问作者Ethan Graney
相关产品推荐
相关产品推荐

