创建灵活的临时游戏数据存储系统

时间:2022-04-09 04:06:27

I'm making a 2D physics game with Java and have recently decided to completely start over so that the program's foundations have flexibility and threading in mind since. My problem is finding a way to store my game data for the duration of the program with threading in mind.

我正在用Java制作2D物理游戏,并且最近决定完全重新开始,以便该程序的基础具有灵活性和线程性。我的问题是找到一种方法来存储我的游戏数据在程序的持续时间与线程。

My previous library for storing data looked like this

我以前用于存储数据的库看起来像这样

public float[] sphereX = new float[sphereNum];
public float[] sphereY = new float[sphereNum];
public float[] sphereXMem = new float[sphereNum];
public float[] sphereYMem = new float[sphereNum];
public float[] sphereVX = new float[sphereNum]; // X Velocity
public float[] sphereVY = new float[sphereNum]; // Y Velocity

// Misc Variables
public float[] sphereMass = new float[sphereNum];
public float[] sphereRadius = new float[sphereNum];

While this was good for a program without threading and fewer features, my current program will have several new requirements that this previous version did not address. These include:

虽然这对于没有线程和更少功能的程序来说是好的,但我当前的程序将有几个新的要求,而这个以前的版本没有解决。这些包括:

  • The amount of spheres is constantly changing
  • 球体的数量不断变化

  • Spheres have even more data types. (boolean, int, and float)
  • Spheres拥有更多数据类型。 (boolean,int和float)

  • This game data is being continually accessed and modified by multiple threads
  • 多个线程不断访问和修改此游戏数据

I worry that locking threads out of data until the lock key becomes available will slow the program down significantly since about 1-4 threads will be chugging away at calculating all the physics.

我担心在锁定密钥可用之前将数据锁定在数据之外会使程序显着减慢,因为在计算所有物理时,大约有1-4个线程将会消失。

My current idea of a solution is to have an Arraylist of objects that containing an array of that object's parameters, but I do not have a clue as to how to make that work with threading.

我目前对解决方案的想法是让对象的Arraylist包含该对象的参数数组,但我不知道如何使用线程进行工作。

As you might guess, I'm somewhat new with threading but know basic concepts of volatility and basic synchronization. Also, if you wanted to know, I'm using threading to hopefully allow my program to take advantage of multiple cores.

正如你可能猜到的那样,我对线程有点新,但我知道波动性和基本同步的基本概念。另外,如果你想知道,我正在使用线程来希望我的程序能够利用多个核心。

Edit: After consideration from the comments I've come up with this. Is this right? I didn't intend to create a separate class at the start, but it is probably for the best. I feel stupid asking this, but will it retain its information if I place all of it in a separate file? From this, I'd just add multiple Items (Item is the new Sphere) to my ArrayList in the main class?

编辑:从评论中考虑后,我想出了这个。这是正确的吗?我不打算在一开始就创建一个单独的类,但它可能是最好的。我觉得这个问题很愚蠢,但如果我将所有信息放在一个单独的文件中,它会保留信息吗?从这里,我只是在主类的ArrayList中添加多个Items(Item是新的Sphere)?

enter code here`public class Item 
{
    private Object lockActive = new Object();
    private Object lockType = new Object();
    private Object lockMass = new Object();
    private Object lockLocation = new Object();
    private Object lockLocationMemory = new Object();
    private Object lockVelocity = new Object();

    private boolean active;
    private int type;
    private float mass;
    private float[] location;
    private float[] locationMemory;
    private float[] velocity;

    public Item(boolean active, int type, float mass, float[] location, float[] locationMemory, float[] velocity) 
    {
        this.active = active;
        this.type = type;
        this.mass = mass;
        this.location = location;
        this.locationMemory = locationMemory;
        this.velocity = velocity;
    }

    public boolean GetActive() 
    {
        synchronized (lockActive)
        {
            try
            {
                Thread.sleep(1);
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
            return active;
        }
    }

    public synchronized int GetType() 
    {
        synchronized (lockType)
        {
            try
            {
                Thread.sleep(1);
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
            return type;
        }
    }

    public synchronized float GetMass() 
    {
        synchronized (lockMass)
        {
            try
            {
                Thread.sleep(1);
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
            return mass;
        }
    }

    public synchronized float[] GetLocation() 
    {
        synchronized (lockLocation)
        {
            try
            {
                Thread.sleep(1);
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
            return location;
        }
    }

    public synchronized float[] GetLocationMemory() 
    {
        synchronized (lockLocationMemory)
        {
            try
            {
                Thread.sleep(1);
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
            return locationMemory;
        }
    }

    public synchronized float[] GetVelocity() 
    {
        synchronized (lockVelocity)
        {
            try
            {
                Thread.sleep(1);
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
            return velocity;
        }
    }

    public void SetActive() 
    {
        synchronized (lockActive)
        {
            try
            {
                Thread.sleep(1);
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
            this.active = active;
        }
    }

    public void SetType(int type) 
    {
        synchronized (lockType)
        {
            try
            {
                Thread.sleep(1);
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
            this.type = type;
        }
    }

    public void SetMass(float mass) 
    {
        synchronized (lockMass)
        {
            try
            {
                Thread.sleep(1);
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
            this.mass = mass;
        }
    }

    public void SetLocation(float[] location) 
    {
        synchronized (lockLocation)
        {
            try
            {
                Thread.sleep(1);
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
            this.location = location;
        }
    }

    public void SetLocationMemory(float[] locationMemory) 
    {
        synchronized (lockLocationMemory)
        {
            try
            {
                Thread.sleep(1);
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
            this.locationMemory = locationMemory;
        }
    }

    public void SetVelocity(float[] velocity) 
    {
        synchronized (lockVelocity)
        {
            try
            {
                Thread.sleep(1);
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
            this.velocity = velocity;
        }
    }

}

1 个解决方案

#1


4  

Don't do that to yourself. Rather than making one data-structure per attribute, define a sphere object to hold all of a sphere's attributes. Write synchronized methods so that multiple threads don't alter a single sphere at once.

不要那样对自己。不是为每个属性创建一个数据结构,而是定义一个球体对象来保存球体的所有属性。编写同步方法,以便多个线程不会同时改变单个球体。

Here's a quick and dirty start:

这是一个快速而又肮脏的开始:

//Sphere.java
public class Sphere {
    private float[] position;
    private float[] mem; 
    private float[] velocity;

    public Sphere(float[] position, float[] mem,  float[] velocity) {
        this.position = position;
        this.mem = mem;
        this.velocity = velocity;
    }

    public synchronized float[] getPosition() {
        return position;
    }
    public synchronized float[] getVelocity() {
        return velocity;
    }

    public synchronized void move() {
        position[0]+=velocity[0];
        position[1]+=velocity[1];
    }
}

Then you might initialize your data somewhere else:

然后你可以在其他地方初始化你的数据:

    int sphereCount = 30;
    List<Sphere> spheres = new ArrayList<Sphere>();
    Random rand = new Random();
    for( int i = 0; i < sphereCount; i++) {
        spheres.add(
            new Sphere(
                new float[]{20*rand.nextFloat(), 20*rand.nextFloat()}, //position
                new float[]{20*rand.nextFloat(), 20*rand.nextFloat()}, //mem
                new float[]{2*rand.nextFloat(), 2*rand.nextFloat()} //velocity
            )
        );
    }

Again, this is just rough, vague code, and I haven't given it much thought. The big idea here is to use objects to describe 'things' so that you can put all the nitty-gritty code to manipulate them in those objects and out of the rest of your code.

同样,这只是粗糙,模糊的代码,我没有多想。这里的主要思想是使用对象来描述“事物”,这样你就可以将所有细节代码放在那些对象中以及其他代码中。

As for the synchronized keyword, it means that everything within that method happens either completely before or completely after any other synchronized method call on that same object.

对于synchronized关键字,这意味着该方法中的所有内容都在完全在该同一对象上的任何其他同步方法调用之前或完全之后发生。

#1


4  

Don't do that to yourself. Rather than making one data-structure per attribute, define a sphere object to hold all of a sphere's attributes. Write synchronized methods so that multiple threads don't alter a single sphere at once.

不要那样对自己。不是为每个属性创建一个数据结构,而是定义一个球体对象来保存球体的所有属性。编写同步方法,以便多个线程不会同时改变单个球体。

Here's a quick and dirty start:

这是一个快速而又肮脏的开始:

//Sphere.java
public class Sphere {
    private float[] position;
    private float[] mem; 
    private float[] velocity;

    public Sphere(float[] position, float[] mem,  float[] velocity) {
        this.position = position;
        this.mem = mem;
        this.velocity = velocity;
    }

    public synchronized float[] getPosition() {
        return position;
    }
    public synchronized float[] getVelocity() {
        return velocity;
    }

    public synchronized void move() {
        position[0]+=velocity[0];
        position[1]+=velocity[1];
    }
}

Then you might initialize your data somewhere else:

然后你可以在其他地方初始化你的数据:

    int sphereCount = 30;
    List<Sphere> spheres = new ArrayList<Sphere>();
    Random rand = new Random();
    for( int i = 0; i < sphereCount; i++) {
        spheres.add(
            new Sphere(
                new float[]{20*rand.nextFloat(), 20*rand.nextFloat()}, //position
                new float[]{20*rand.nextFloat(), 20*rand.nextFloat()}, //mem
                new float[]{2*rand.nextFloat(), 2*rand.nextFloat()} //velocity
            )
        );
    }

Again, this is just rough, vague code, and I haven't given it much thought. The big idea here is to use objects to describe 'things' so that you can put all the nitty-gritty code to manipulate them in those objects and out of the rest of your code.

同样,这只是粗糙,模糊的代码,我没有多想。这里的主要思想是使用对象来描述“事物”,这样你就可以将所有细节代码放在那些对象中以及其他代码中。

As for the synchronized keyword, it means that everything within that method happens either completely before or completely after any other synchronized method call on that same object.

对于synchronized关键字,这意味着该方法中的所有内容都在完全在该同一对象上的任何其他同步方法调用之前或完全之后发生。