如何使用PVectors实现Processing中子弹的恒定速度?
解决Processing中子弹恒定速度的问题
嘿,这个问题我之前做小游戏的时候也踩过坑!你现在的问题根源很清晰:你直接把鼠标与玩家的坐标差除以12作为子弹每次移动的增量,这就导致鼠标离玩家越近,这个差值越小,子弹的移动步长就跟着变小,速度自然变慢。要实现恒定速度,关键是把方向向量做归一化处理——简单来说,就是不管鼠标离玩家多远,都把方向向量的长度固定为1,再乘以你想要的速度值,这样每次移动的距离就一致了。
我给你两种解决方案,一种是不用PVector(贴合你目前的知识范围),另一种是用PVector(更简洁,适合以后拓展):
方案1:手动实现向量归一化(不用PVector)
核心思路是先计算鼠标到玩家的方向向量,再把这个向量的长度缩为1,最后乘以固定速度:
- 计算鼠标与玩家的坐标差:
dx = mX - pX,dy = mY - pY - 用勾股定理计算这个向量的长度:
float vectorLength = sqrt(dx*dx + dy*dy) - 为了避免鼠标刚好在玩家位置时除以0报错,加个判断:如果长度大于0,再计算单位向量
- 把单位向量乘以你想要的恒定速度(比如5,你可以自己调整),得到每次移动的增量
修改你的Bullet构造函数如下:
Bullet(float pX, float pY,float mX,float mY){ float dx = mX - pX; float dy = mY - pY; float vectorLength = sqrt(dx*dx + dy*dy); // 避免除以0的情况(鼠标刚好在玩家位置) if(vectorLength > 0){ // 归一化后乘以恒定速度(这里设为5,你可以调整) run = (dx / vectorLength) * 5; rise = (dy / vectorLength) * 5; } else { // 如果鼠标在玩家位置,默认朝某个方向(比如右) run = 5; rise = 0; } bulletX = pX; bulletY = pY; }
方案2:用PVector实现(更简洁)
虽然你课堂没学过PVector,但它其实就是Processing用来处理向量的工具类,用起来非常方便:
- 创建玩家位置和鼠标位置的PVector
- 用
sub()方法得到方向向量(鼠标减玩家) - 用
normalize()把向量归一化(长度变为1) - 用
mult()乘以你想要的速度 - 最后提取向量的x和y作为run和rise
修改后的Bullet构造函数:
Bullet(float pX, float pY,float mX,float mY){ PVector playerPos = new PVector(pX, pY); PVector mousePos = new PVector(mX, mY); // 计算方向向量并归一化、乘以速度 PVector direction = mousePos.sub(playerPos); direction.normalize(); direction.mult(5); // 这里的5是恒定速度,可调整 run = direction.x; rise = direction.y; bulletX = pX; bulletY = pY; }
完整修改后的代码示例
把上面的构造函数替换到你的代码里,shoot()方法不用改,这样不管鼠标离玩家多远,子弹都会以恒定速度朝瞄准方向飞行:
ArrayList<Bullet> bullets = new ArrayList<Bullet>(); float playerX = 200; // 假设玩家初始位置,你可以替换成自己的变量 float playerY = 200; void draw(){ background(255); // 绘制玩家(示例) fill(0); rect(playerX, playerY, 20, 20); if(keyPressed && key == ' '){ float currentPlayerX = playerX; float currentPlayerY = playerY; float currentMouseX = mouseX; float currentMouseY = mouseY; bullets.add(new Bullet(currentPlayerX, currentPlayerY, currentMouseX, currentMouseY)); } for(Bullet b: bullets){ b.shoot(); } } class Bullet{ float bulletX; float bulletY; float rise; float run; Bullet(float pX, float pY,float mX,float mY){ // 这里用方案1的代码,或者替换成方案2的代码 float dx = mX - pX; float dy = mY - pY; float vectorLength = sqrt(dx*dx + dy*dy); if(vectorLength > 0){ run = (dx / vectorLength) * 5; rise = (dy / vectorLength) * 5; } else { run = 5; rise = 0; } bulletX = pX; bulletY = pY; } void shoot(){ fill(255,0,0); rect(bulletX,bulletY,7,7); bulletX += run; bulletY += rise; } }
这样修改后,不管你鼠标离玩家近还是远,子弹的速度都会保持一致,完美解决你的问题!
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

