为什么我移动时游戏中的东西会发生变化? Java 加工环境
Why are things in my game shifting when I move? Java Processing environment
我正在制作一个 2D 游戏,正在处理中。
- 玩家总是在屏幕中央
- 玩家总是面向鼠标
- 移动是通过相对于玩家移动世界来实现的
每个游戏循环:
- 玩家速度被添加到位置
- 玩家加速度被添加到速度
- 加速度设置为鼠标方向,与鼠标到屏幕中心的距离成正比。
- velocity += (-velocity * resistance),这样当你改变方向时你会得到平滑的过渡。
所以基本上,您总是以与鼠标到玩家(屏幕中心)的距离成正比的速度移向鼠标。
到目前为止,我的所有机制都运行良好,除了我的世界中对象的绘制方式存在一个错误。当我移动时,项目会根据方向轻微移动,但它们移动得非常流畅,就像它与我的速度有关一样。看起来很像拖拽效果
我添加了一个世界边界,以及世界上一些随机的圆圈。边界似乎停留在正确的位置,但是如果我向与墙相反的方向移动,边缘附近的圆圈可以越过边缘。
知道是什么原因造成的吗?这是相关代码(抱歉,有一点..)
import java.util.ArrayList;
//constants
int ROCKET_WIDTH = 32;
int ROCKET_HEIGHT = 52;
float PLAYER_MAX_ACC = 0.4;
float PLAYER_MAX_VEL = 12;
float MOVEMENT_RESISTANCE = 0.05;
//global variables
Rocket player;
ArrayList<PVector> balls;
float offsetX;
float offsetY;
void setup()
{
size(800,600);
frameRate(30);
background(0);
player = new Rocket();
balls = new ArrayList<PVector>();
offsetX = width/2 - player.pos.x;
offsetY = height/2 - player.pos.y;
for (int i = 0;i < 100;i++)
{
PVector vec = new PVector(random(-width,width*2),random(-height,height*2));
balls.add(vec);
}
}
void draw()
{
background(0);
drawWorldEdges();
updateMechanics();
for (PVector b:balls)
{
ellipseMode(CENTER);
ellipse(b.x + offsetX,b.y + offsetY,10,10);
}
drawPlayer();
}
void drawWorldEdges()
{
//top,right,bottom,left
strokeWeight(1);
stroke(255);
line(-width + offsetX,-height + offsetY,(width * 2) + offsetX,-height +offsetY);
line((width*2) + offsetX,-height + offsetY,(width*2)+offsetX,(height*2)+offsetY);
line(-width+offsetX,(height*2)+offsetY,(width*2)+offsetX,(height*2)+offsetY);
line(-width+offsetX,-height+offsetY,-width+offsetX,(height*2)+offsetY);
}
void updateMechanics()
{
offsetX = width/2 -player.pos.x;
offsetY = height/2 - player.pos.y;
updateFacing();
getMoveInput();
updatePhysics();
}
void updatePhysics()
{
if (player.pos.x < width*2 && player.pos.x >= -width)
{
player.pos.x += player.vel.x;
}
if (player.pos.y < height*2 && player.pos.y >= -height)
{
player.pos.y += player.vel.y;
}
player.vel.x += -player.vel.x * MOVEMENT_RESISTANCE;
player.vel.y += -player.vel.y * MOVEMENT_RESISTANCE;
}
void getMoveInput()
{
PVector vel = new PVector(mouseX - width/2,mouseY - height/2);
float distMult = dist(mouseX,mouseY,width/2,height/2)/(Math.min(width,height) / 2);
vel = vel.normalize().setMag(PLAYER_MAX_ACC * distMult);
PVector newVel = new PVector(player.vel.x,player.vel.y);
newVel.add(vel);
if (newVel.mag() <= PLAYER_MAX_VEL)
{
player.vel.add(vel);
}
}
void updateFacing()
{
float x = mouseX;
if (x == 0)
{
x = 0.1;
}
player.facing = PI/2 + atan((mouseY-(height/2))/(x-(width/2)));
if (x < width/2)
{
player.facing += PI;
}
}
void drawPlayer()
{
pushMatrix();
translate(width/2,height/2);
rotate(player.facing);
stroke(255);
strokeWeight(2);
fill(127);
rect(-ROCKET_WIDTH/4,0-ROCKET_HEIGHT/2,ROCKET_WIDTH/2,ROCKET_HEIGHT*0.75);
rect(-ROCKET_WIDTH/2,0,ROCKET_WIDTH/4,ROCKET_HEIGHT*0.5);
rect(ROCKET_WIDTH/4,0,ROCKET_WIDTH/4,ROCKET_HEIGHT*0.5);
popMatrix();
}
火箭 class:
class Rocket
{
PVector pos;
PVector vel;
float facing; //radians
boolean pressingW,pressingA,pressingS,pressingD,mouseLClicked = false;
public Rocket()
{
pos = new PVector(0,0);
vel = new PVector(0,0);
facing = 0;
}
public Rocket(int x,int y)
{
pos = new PVector(x,y);
vel = new PVector(0,0);
facing = 0;
}
}
以后,请尝试 post 一个 MCVE 而不是整个项目。将它缩小到尽可能少的代码行。在你的情况下,你只需要显示两个圆圈,你可以删除任何其他代码,例如显示船。
也就是说,您的问题是由多种因素共同造成的:
- 您的 "stars" 的位置存储在
PVector
中,它将它们存储为 float
值。
- 您的
offsetX
和 offsetY
也是 float
值。
- 但是,像素始终是
int
值! (有半个像素真的没有意义。)
发生的情况是,您的开始移动的间隔略有不同,您的眼睛将其检测为零星移动。这是由 float
值在不同时间达到下一个 int
值引起的。
假设您有两个职位:一个在 [0, 10]
,另一个在 [.6, 20]
。最初,它们具有相同的像素 X 值 0
,因为像素始终是 int
值。现在假设您的 xOffset
是 .5
,您将其添加到您的位置以获得 [.5, 10]
和 [1.1, 20]
。现在它们有 0
和 1
的不同像素 X 值,这使得它看起来像第二个移动但第一个没有移动!这就是导致您出现问题的原因。
有很多方法可以解决这个问题,但最简单的方法可能是将您的星星位置初始化为 int
值:
PVector vec = new PVector(int(random(-width,width*2)), int(random(-height,height*2)));
这也是您的墙壁看起来不错的原因:这实际上只是您正在更新的一个位置。
我正在制作一个 2D 游戏,正在处理中。
- 玩家总是在屏幕中央
- 玩家总是面向鼠标
- 移动是通过相对于玩家移动世界来实现的
每个游戏循环:
- 玩家速度被添加到位置
- 玩家加速度被添加到速度
- 加速度设置为鼠标方向,与鼠标到屏幕中心的距离成正比。
- velocity += (-velocity * resistance),这样当你改变方向时你会得到平滑的过渡。
所以基本上,您总是以与鼠标到玩家(屏幕中心)的距离成正比的速度移向鼠标。
到目前为止,我的所有机制都运行良好,除了我的世界中对象的绘制方式存在一个错误。当我移动时,项目会根据方向轻微移动,但它们移动得非常流畅,就像它与我的速度有关一样。看起来很像拖拽效果
我添加了一个世界边界,以及世界上一些随机的圆圈。边界似乎停留在正确的位置,但是如果我向与墙相反的方向移动,边缘附近的圆圈可以越过边缘。
知道是什么原因造成的吗?这是相关代码(抱歉,有一点..)
import java.util.ArrayList;
//constants
int ROCKET_WIDTH = 32;
int ROCKET_HEIGHT = 52;
float PLAYER_MAX_ACC = 0.4;
float PLAYER_MAX_VEL = 12;
float MOVEMENT_RESISTANCE = 0.05;
//global variables
Rocket player;
ArrayList<PVector> balls;
float offsetX;
float offsetY;
void setup()
{
size(800,600);
frameRate(30);
background(0);
player = new Rocket();
balls = new ArrayList<PVector>();
offsetX = width/2 - player.pos.x;
offsetY = height/2 - player.pos.y;
for (int i = 0;i < 100;i++)
{
PVector vec = new PVector(random(-width,width*2),random(-height,height*2));
balls.add(vec);
}
}
void draw()
{
background(0);
drawWorldEdges();
updateMechanics();
for (PVector b:balls)
{
ellipseMode(CENTER);
ellipse(b.x + offsetX,b.y + offsetY,10,10);
}
drawPlayer();
}
void drawWorldEdges()
{
//top,right,bottom,left
strokeWeight(1);
stroke(255);
line(-width + offsetX,-height + offsetY,(width * 2) + offsetX,-height +offsetY);
line((width*2) + offsetX,-height + offsetY,(width*2)+offsetX,(height*2)+offsetY);
line(-width+offsetX,(height*2)+offsetY,(width*2)+offsetX,(height*2)+offsetY);
line(-width+offsetX,-height+offsetY,-width+offsetX,(height*2)+offsetY);
}
void updateMechanics()
{
offsetX = width/2 -player.pos.x;
offsetY = height/2 - player.pos.y;
updateFacing();
getMoveInput();
updatePhysics();
}
void updatePhysics()
{
if (player.pos.x < width*2 && player.pos.x >= -width)
{
player.pos.x += player.vel.x;
}
if (player.pos.y < height*2 && player.pos.y >= -height)
{
player.pos.y += player.vel.y;
}
player.vel.x += -player.vel.x * MOVEMENT_RESISTANCE;
player.vel.y += -player.vel.y * MOVEMENT_RESISTANCE;
}
void getMoveInput()
{
PVector vel = new PVector(mouseX - width/2,mouseY - height/2);
float distMult = dist(mouseX,mouseY,width/2,height/2)/(Math.min(width,height) / 2);
vel = vel.normalize().setMag(PLAYER_MAX_ACC * distMult);
PVector newVel = new PVector(player.vel.x,player.vel.y);
newVel.add(vel);
if (newVel.mag() <= PLAYER_MAX_VEL)
{
player.vel.add(vel);
}
}
void updateFacing()
{
float x = mouseX;
if (x == 0)
{
x = 0.1;
}
player.facing = PI/2 + atan((mouseY-(height/2))/(x-(width/2)));
if (x < width/2)
{
player.facing += PI;
}
}
void drawPlayer()
{
pushMatrix();
translate(width/2,height/2);
rotate(player.facing);
stroke(255);
strokeWeight(2);
fill(127);
rect(-ROCKET_WIDTH/4,0-ROCKET_HEIGHT/2,ROCKET_WIDTH/2,ROCKET_HEIGHT*0.75);
rect(-ROCKET_WIDTH/2,0,ROCKET_WIDTH/4,ROCKET_HEIGHT*0.5);
rect(ROCKET_WIDTH/4,0,ROCKET_WIDTH/4,ROCKET_HEIGHT*0.5);
popMatrix();
}
火箭 class:
class Rocket
{
PVector pos;
PVector vel;
float facing; //radians
boolean pressingW,pressingA,pressingS,pressingD,mouseLClicked = false;
public Rocket()
{
pos = new PVector(0,0);
vel = new PVector(0,0);
facing = 0;
}
public Rocket(int x,int y)
{
pos = new PVector(x,y);
vel = new PVector(0,0);
facing = 0;
}
}
以后,请尝试 post 一个 MCVE 而不是整个项目。将它缩小到尽可能少的代码行。在你的情况下,你只需要显示两个圆圈,你可以删除任何其他代码,例如显示船。
也就是说,您的问题是由多种因素共同造成的:
- 您的 "stars" 的位置存储在
PVector
中,它将它们存储为float
值。 - 您的
offsetX
和offsetY
也是float
值。 - 但是,像素始终是
int
值! (有半个像素真的没有意义。)
发生的情况是,您的开始移动的间隔略有不同,您的眼睛将其检测为零星移动。这是由 float
值在不同时间达到下一个 int
值引起的。
假设您有两个职位:一个在 [0, 10]
,另一个在 [.6, 20]
。最初,它们具有相同的像素 X 值 0
,因为像素始终是 int
值。现在假设您的 xOffset
是 .5
,您将其添加到您的位置以获得 [.5, 10]
和 [1.1, 20]
。现在它们有 0
和 1
的不同像素 X 值,这使得它看起来像第二个移动但第一个没有移动!这就是导致您出现问题的原因。
有很多方法可以解决这个问题,但最简单的方法可能是将您的星星位置初始化为 int
值:
PVector vec = new PVector(int(random(-width,width*2)), int(random(-height,height*2)));
这也是您的墙壁看起来不错的原因:这实际上只是您正在更新的一个位置。