Java 通过套接字发送时,定时被删除的问题
我设置了一个游戏,在这个游戏中,我通过服务器和客户端之间的套接字发送一组塔和部队对象,出于某种原因,攻击率和动画(这让我相信计时属性)被忽略/编辑。这是塔楼等级:Java 通过套接字发送时,定时被删除的问题,java,sockets,object,time,Java,Sockets,Object,Time,我设置了一个游戏,在这个游戏中,我通过服务器和客户端之间的套接字发送一组塔和部队对象,出于某种原因,攻击率和动画(这让我相信计时属性)被忽略/编辑。这是塔楼等级: package jandek.towers; import java.awt.Color; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.IOExce
package jandek.towers;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import jandek.handler.Handler;
import jandek.main.Frame;
import jandek.main.Game;
import jandek.utils.Utils;
public abstract class Tower implements Serializable{
private int range;
private double attackDMG;
private double attackSPEED; //1 = 1/60 seconds
private byte[][][] image;
private int x;
private int y;
private long lastAttackTime;
private int multiplier;
private int level; //0 = 1;
private boolean moving;
private boolean rangeNeedsToBeDrawn;
private int width = 32;
private int height = 32;
//private BufferedImage[][][] bufferedImages = new BufferedImage[16][4][2];
private ArrayList<Integer> troopsInTroopsArrayThatAreInRange;
private int animationFrame = 0;
private int animationFrameSpeed = 60; //nano seconds between changes
private double animationFrameLastChange; //last change
boolean attacked;
boolean animation = false;
/**
*
* @param x
* @param y
* @param level
* @param multiplier
* @param range
* @param attackDMG
* @param attackSPEED
* @param image
*/
public Tower(int x, int y, int level, int multiplier, int range, double attackDMG, double attackSPEED, byte[][][] image){
troopsInTroopsArrayThatAreInRange = new ArrayList<Integer>();
this.x = x;
this.y = y;
this.range = range;
this.attackDMG = attackDMG + (level * multiplier);
this.attackSPEED = attackSPEED;
this.image = image;
this.level = level;
this.multiplier = multiplier;
lastAttackTime = Handler.getGame().getTime();
moving = false;
rangeNeedsToBeDrawn = true;
}
public void update(){
attacked = false;
if(moving == true){
setX(Frame.getMouseX());
setY(Frame.getMouseY());
}
AttackTarget();
if(attacked){
animation = true;
animationFrameLastChange = Handler.getGame().getTime();
animationFrame = 1;
//Handler.getGame().getLogWriter().write("Animation is at the second image");
}
if(animation && Handler.getGame().getTime() - animationFrameLastChange >= animationFrameSpeed){
animationFrame = 0;
animation = false;
}
}
private void AttackTarget(){
if((Handler.getGame().getTime() - lastAttackTime) > attackSPEED && !moving){
for(int i = 0; i < Handler.getTroops().size() ; i++){
int x1 = this.x + this.width / 2;
int y1 = this.y + this.height / 2;
int x2 = Handler.getTroops().get(i).getX() + Handler.getTroops().get(i).getSize() / 2;
int y2 = Handler.getTroops().get(i).getY() + Handler.getTroops().get(i).getSize() / 2;
if(Utils.getDistance(x1, y1, x2, y2) <= range){
troopsInTroopsArrayThatAreInRange.add(i);
attacked = true;
}
}
}
if(attacked){
Handler.getGame().getLogWriter().write("");
Handler.getGame().getLogWriter().write(Handler.getGame().getTime() - lastAttackTime + " : " + attackSPEED);
lastAttackTime = Handler.getGame().getTime();
Handler.getGame().getLogWriter().write(Handler.getGame().getTime() - lastAttackTime + " : " + attackSPEED);
Handler.getGame().getLogWriter().write("");
double min = range;
int nearestTroop = -1;
for(int j = 0; j < troopsInTroopsArrayThatAreInRange.size(); j++){
int x1 = this.x + this.width / 2;
int y1 = this.y + this.height / 2;
int x2 = Handler.getTroops().get(troopsInTroopsArrayThatAreInRange.get(j)).getX() + Handler.getTroops().get(troopsInTroopsArrayThatAreInRange.get(j)).getSize() / 2;
int y2 = Handler.getTroops().get(troopsInTroopsArrayThatAreInRange.get(j)).getY() + Handler.getTroops().get(troopsInTroopsArrayThatAreInRange.get(j)).getSize() / 2;
if(Utils.getDistance(x1, y1, x2, y2) < min){
min = Utils.getDistance(x1, y1, x2, y2);
// Handler.getGame().getLogWriter().write("troop distance checked");
nearestTroop = troopsInTroopsArrayThatAreInRange.get(j);
}
}
Handler.getTroops().get(nearestTroop).changeHealth(-(int)attackDMG);
troopsInTroopsArrayThatAreInRange.clear();
}
}
}
上面的每个“1”都会在run方法的末尾打印出来,从而表明
Handler.getGame().getTime()-lastAttackTime
不知怎的被插座干扰了。有什么想法吗?我希望我没有遗漏一些过于明显或简单的东西
编辑套接字代码:
private void updateConnection(){
if(isClientActive()){
if(player.getType() == 0){
client.sendObjects(towers);
}else{
client.sendObjects(troops);
}
ArrayList<Object> obj = (ArrayList<Object>)client.receiveObjects();
if(obj != null && obj.size() > 0){
if (obj.get(0) instanceof Troop) {
mendTroops(obj);
}else if(obj.get(0) instanceof Troop){
mendTowers(obj);
}
}else{
if(player.getType() == 0){
troops.clear();
}else{
towers.clear();
}
}
}else if(isServerActive()){
if(player.getType() == 0){
server.sendObjects(towers);
}else{
server.sendObjects(troops);
}
ArrayList<Object> obj = (ArrayList<Object>)server.receiveObjects();
if(obj != null && obj.size() > 0){
if (obj.get(0) instanceof Troop) {
mendTroops(obj);
}else if(obj.get(0) instanceof Tower){
mendTowers(obj);
}
}else{
if(player.getType() == 0){
troops.clear();
}else{
towers.clear();
}
}
}
}
private void updateConnection(){
if(isClient()){
if(player.getType()==0){
客户。发送对象(塔);
}否则{
客户端。发送对象(部队);
}
ArrayList obj=(ArrayList)client.receiveObjects();
如果(obj!=null&&obj.size()>0){
if(对象获取(0)部队实例){
军事部队(obj);
}else if(对象获取(0)部队实例){
门德塔(obj);
}
}否则{
if(player.getType()==0){
部队。清除();
}否则{
塔。清除();
}
}
}else if(isServerActive()){
if(player.getType()==0){
服务器。发送对象(塔);
}否则{
sendObjects(部队);
}
ArrayList obj=(ArrayList)server.receiveObjects();
如果(obj!=null&&obj.size()>0){
if(对象获取(0)部队实例){
军事部队(obj);
}else if(对象获取塔的(0)实例){
门德塔(obj);
}
}否则{
if(player.getType()==0){
部队。清除();
}否则{
塔。清除();
}
}
}
}
我在你的帖子中没有看到任何套接字代码,但TCP和UDP都不提供任何时间保证。TCP广泛使用缓冲,以便将传出写入合并到较小数量的导线段中。您可以通过禁用Nagle算法来减轻这一点,但您永远无法从任何网络中获得实时性能。什么套接字?这里没有sockets代码。我不打算费力地通过代码墙来找出如何计算时间,但如果这取决于正在同步的系统时钟,并且您没有使用NTP设置时钟的系统,那么所有的赌注都是无效的。为了获得更好的帮助,请将代码简化为再现问题的最简单示例。你还不知道问题是什么,你只是从一个症状(发病率不是你期望的)跳到了一个原因(时间被丢弃),这可能是不合理的。减少代码的过程可能会揭示真正的问题。我知道它是在towers中的update()方法(更准确地说是attack()方法)中维持的。我使用一个以60 fps的速度运行的run方法,它存储在一个由tower对象静态访问的变量中。客户端和服务器不必同步,因为它们都使用相同的运行方法并同时启动。在我将套接字系统添加到游戏中之前,我的攻击率一直运行良好,因此我知道它与此有一定的相关性;因此,您必须打印出发送的数据(在发送端)和接收的数据(从接收器)-并进行比较-然后找到问题-我已经看到您正在使用一些奇特的方法,如writeUnshared()-对于初学者,听起来您是混合的,您在哪里看到writeUnshared?是的,问题是接收到的塔阵列并没有改变它的上次攻击时间,它是以任何时候初始化的。我不确定它是否是它的全部属性,但它很奇怪。我将尝试在服务器和clientOk之间如何更新阵列,那么,在两台计算机上运行一个程序,在它们之间发送需要使用攻击速度之类的对象,最好的方法是什么呢?另外,静态检查时间是否重要?您必须将速度作为数据的一部分发送,或者发送时间起点和增量,而不是依赖于零或固定的网络延迟,或者计算机之间的时差为零或固定数量。您能澄清一下速度是什么意思吗?你的意思是我应该在塔的对象中保留一个当前的游戏时间参考吗?这应该是一个评论,而不是一个答案。@JimGarrison你肯定是在开玩笑吧?“从不”在什么方面不是答案?
private void updateConnection(){
if(isClientActive()){
if(player.getType() == 0){
client.sendObjects(towers);
}else{
client.sendObjects(troops);
}
ArrayList<Object> obj = (ArrayList<Object>)client.receiveObjects();
if(obj != null && obj.size() > 0){
if (obj.get(0) instanceof Troop) {
mendTroops(obj);
}else if(obj.get(0) instanceof Troop){
mendTowers(obj);
}
}else{
if(player.getType() == 0){
troops.clear();
}else{
towers.clear();
}
}
}else if(isServerActive()){
if(player.getType() == 0){
server.sendObjects(towers);
}else{
server.sendObjects(troops);
}
ArrayList<Object> obj = (ArrayList<Object>)server.receiveObjects();
if(obj != null && obj.size() > 0){
if (obj.get(0) instanceof Troop) {
mendTroops(obj);
}else if(obj.get(0) instanceof Tower){
mendTowers(obj);
}
}else{
if(player.getType() == 0){
troops.clear();
}else{
towers.clear();
}
}
}
}