This site requires JavaScript, please enable it in your browser!
Greenfoot back
Tim1Blau
Tim1Blau wrote ...

2019/5/5

Game lags with bigger world sizes

Tim1Blau Tim1Blau

2019/5/5

#
I am making a multiplayer racing game for a school project, that draws a 4 player splitscreen on the Camera Actors Class image. The world size is set by the world class and everything works fine with world sizes smaller than 1200x800px. If i want to use a bigger world though it starts running really slow.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import org.jbox2d.common.*;
import java.awt.image.*;
import java.awt.*;
import java.awt.geom.AffineTransform;
 
 
public class Camera extends Actor
{
    //Verzögerung mit der Kamera Auto folgt: je kleiner, desto größer die Verzögerung
    private float lag = 0.07f;
 
    private Vec2[] camPos;
    private Vec2[] carPos;
    private Vec2[] carPosRaw;
    private float[] carRot;
 
    private MyWorld world;
    private boolean setup = false;
    private GreenfootImage track = new GreenfootImage("images/Download.png");
    private GreenfootImage carImg = new GreenfootImage("images/car02.png");
    private BufferedImage srcAwt;
    private Rectangle rect;
    private GreenfootImage gCrop;
    private BufferedImage bCrop;
    private int width = world.width;
    private int height = world.height;
 
    public Camera()
    {
        gCrop = new GreenfootImage(width, height);
        setImage(gCrop);
        camPos = new Vec2[4];
        carPos = new Vec2[4];
        carPosRaw = new Vec2[4];
        carRot = new float[4];
        for(int i = 0; i<4; i++)
        {
            camPos[i] = new Vec2(0,0);
            carPos[i] = new Vec2(0,0);
            carPosRaw[i] = new Vec2(0,0);
            carRot[i] = 0;
        }
         
    }
 
    public void setup()
    {
        world = (MyWorld)getWorld();
    }
 
    public void act()
    {
        if(!setup)
        {
            setup();
            setup = true;
        }
    }
 
    public void setCarTransform(Vec2 pos, float rot, int n)
    {
        carPos[n] = pos;
        carRot[n] = rot;
    }
 
    public void followLocation(int n)
    {   Vec2 offset = new Vec2(0,0);      
        if(setup)
        {
            camPos[n].x += (-carPos[n].x - camPos[n].x) * lag;
            camPos[n].y += (-carPos[n].y - camPos[n].y) * lag;
            carPos[n].x += camPos[n].x;
            carPos[n].y += camPos[n].y;
            splitScreen();           
        }
        carPosRaw[n] = new Vec2(carPos[n].x-camPos[n].x, carPos[n].y-camPos[n].y);    
    }
 
    public void splitScreen()
    {
         
        splitCar(track, 0,0);
        splitCar(track, 1,1);
        splitCar(track, 2,2);
        splitCar(track, 3,3);
        Vec2 offsetCam = new Vec2(0,0);
         
        // i: Screen, u: Auto
        for(int i= 0; i<4; i++)
        {
            switch(i)
            {
                case 0:
                offsetCam = new Vec2(width/4, height/4);
                break;
 
                case 1:
                offsetCam = new Vec2(3*width/4, height/4);
                break;
 
                case 2:
                offsetCam = new Vec2(width/4, 3*height/4);
                break;
 
                case 3:
                offsetCam = new Vec2(3*width/4, 3*height/4);
                break;
            }
            for(int u = 0; u<4; u++)
            {
                splitCopy(carImg, i, new Vec2(carPosRaw[u].x+camPos[i].x+offsetCam.x,carPosRaw[u].y+camPos[i].y+offsetCam.y), carRot[u]);
            }
        }
         
    }
 
    public void splitCopy(GreenfootImage src, int n, Vec2 pos, float rot)
    {
        Vec2 posInCam = new Vec2(pos.x-38.5f, pos.y-18f);
        float x = posInCam.x;
        float y = posInCam.y;       
        splitscreen(src,n,x,y,-rot);
    }
 
    public void splitCar(GreenfootImage src, int n, int s)
    {
        float x = camPos[s].x;
        float y = camPos[s].y;
        AffineTransform at = new AffineTransform();
        switch(n)
        {
            case 0:
            at.translate(x,y);
            break;
 
            case 1:
            x += width/2;
            break;
 
            case 2:
            y+= height/2;
            break;
 
            case 3:
            x+= width/2;
            y+= height/4;
            break;
        }
        splitscreen(src, n, x,y, 0);
    }
 
    public void splitscreen(GreenfootImage src, int n, float x, float y, float rot)
    {
        srcAwt = src.getAwtImage();
 
        Graphics2D g2d =  gCrop.getAwtImage().createGraphics();
        switch(n)
        {
            case 0:
            rect = new Rectangle(0,0,width/2,height/2);
            break;
 
            case 1:
            rect = new Rectangle(width/2,0,width,height/2);
            break;
 
            case 2:
            rect = new Rectangle(0,height/2,width/2,height);
            break;
 
            case 3:
            rect = new Rectangle(width/2,height/2,width,height);
            break;
        }
        g2d.clip(rect);
 
        AffineTransform tx = AffineTransform.getRotateInstance(rot, x+srcAwt.getWidth()/2, y+srcAwt.getHeight()/2);
        tx.translate(x,y);
        // g2d.drawImage(srcAwt,x, y,null);
        g2d.drawImage(srcAwt,tx,null);
 
        g2d.setClip(null);
        g2d.dispose();
    }
}
nccb nccb

2019/5/7

#
I imagine the issue is that the copying of the rotated image is probably done on the CPU, which is a bit slow. Java doesn't allow easy direct access to GPU acceleration, especially for off-screen images, but you can try and use hints to get it to use acceleration. This question and answer may help: https://stackoverflow.com/questions/2374321/how-can-i-create-a-hardware-accelerated-image-with-java2d I think BufferedImage will be necessary rather than volatile image, but try the setAccelerationPriority(1) call mentioned in the accepted answer. Note that if you need to pass any arguments to the JVM (e.g. the OpenGL flag they mention) you can do this by editing greenfoot.defs in the lib directory of your installation. Add them to the end of the last line in the file, which should start "greenfoot.windows.vm.args="
Tim1Blau Tim1Blau

2019/5/8

#
I'm sorry but i don't understand what I have to change in my code. I know little about drawing BufferedImages and all that. In my original code I set a GreenfootImage as the Image od the class, which basically represents the screen. now I draw on the GreenfootImage by drawing on it's g2d. I think that's how it currently works. Now I don't know where and how to apply your answer. Do I have to change the GreenfootImage to a BufferedImage and apply the acceleration on it, or do I somehow apply this to the src Images.
Tim1Blau Tim1Blau

2019/5/8

#
I don't know if this makes any sense but this is my attempt to apply your answer to the screen Image... which should now be the same thing as the original gCrop GreenfootImage
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
public Camera()
    {
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsConfiguration gc = ge.getDefaultScreenDevice().getDefaultConfiguration();
        screen = gc.createCompatibleImage(width, height, Transparency.TRANSLUCENT);
        screen.setAccelerationPriority(1);
        camPos = new Vec2[4];
        carPos = new Vec2[4];
        carPosRaw = new Vec2[4];
        carRot = new float[4];
        for(int i = 0; i<4; i++)
        {
            camPos[i] = new Vec2(0,0);
            carPos[i] = new Vec2(0,0);
            carPosRaw[i] = new Vec2(0,0);
            carRot[i] = 0;
        }
 
    }
 
 
 
public void splitscreen(GreenfootImage src, int n, float x, float y, float rot)
    {
        srcAwt = src.getAwtImage();
 
         
        Graphics g = screen.createGraphics();
        g.drawImage(screen,0,0,null);
        Graphics2D g2d = (Graphics2D)g;
        switch(n)
        {
            case 0:
            rect = new Rectangle(0,0,width/2,height/2);
            break;
 
            case 1:
            rect = new Rectangle(width/2,0,width,height/2);
            break;
 
            case 2:
            rect = new Rectangle(0,height/2,width/2,height);
            break;
 
            case 3:
            rect = new Rectangle(width/2,height/2,width,height);
            break;
        }
        g2d.clip(rect);
 
        AffineTransform tx = AffineTransform.getRotateInstance(rot, x+srcAwt.getWidth()/2, y+srcAwt.getHeight()/2);
        tx.translate(x,y);
        g2d.drawImage(srcAwt,tx,null);
         
        g2d.setClip(null);
    }
It doesn't display anything but I don't know how it should work instead..
nccb nccb

2019/5/9

#
Sorry -- I was in a bit of a rush when I wrote the first reply. I've now had a play myself, but it's difficult to get the acceleration working. I have an idea but it may be easiest if I can modify your scenario. Would you be willing to send over the scenario (before the latest modification) to support@greenfoot.org? Can't promise anything, but it would be nice to make sure Greenfoot is performing as fast as it can.
Tim1Blau Tim1Blau

2019/5/10

#
Thanks for your answer, I have sent the project files to the given adress. I hope you can help me with my problem!
You need to login to post a reply.