Java-Gaming.org Hi !
Featured games (81)
games approved by the League of Dukes
Games in Showcase (513)
Games in Android Showcase (119)
games submitted by our members
Games in WIP (576)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Java Slick2D: When camera is scrolling, character moves too fast  (Read 421 times)
0 Members and 1 Guest are viewing this topic.
Offline Desbrina

Senior Newbie


Exp: 3 years



« Posted 2014-04-23 15:22:40 »

I've been playing around with Slick2D for Java and I managed to get it to display maps and have my character sprite move around.

I've tried to implement a camera that follows the player so that the map scrolls. While the map is scrolling, that characters move speed is faster than it should be (possibly due to the camera srolling it as well as it moving with the keys)

I'm stumped on how to solve it though

This is an example of what i mean - https://www.youtube.com/watch?v=IPmw4t1YnUo

The camera code is something i found on the slick forums, and modified slightly to draw each layer seperatly, modifying both drawmap methods to add the layer in. I would ask on the forums but they seem dead.

This is the camera code

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  
187  
188  
189  
190  
191  
192  
193  
194  
195  
196  
197  
198  
199  
200  
201  
202  
203  
204  
205  
206  
207  
    /*
     * To change this license header, choose License Headers in Project Properties.
     * To change this template file, choose Tools | Templates
     * and open the template in the editor.
     */

    package engine;
   
    /**
     *
     * @author Ceri
     */

    import java.awt.geom.Point2D;
    import org.newdawn.slick.GameContainer;
    import org.newdawn.slick.geom.Shape;
    import org.newdawn.slick.tiled.TiledMap;
   
    public class Camera {
   
        /**
         * the map used for our scene
         */

        protected TiledMap map;
   
        /**
         * the number of tiles in x-direction (width)
         */

        protected int numTilesX;
   
        /**
         * the number of tiles in y-direction (height)
         */

        protected int numTilesY;
   
        /**
         * the height of the map in pixel
         */

        protected int mapHeight;
   
        /**
         * the width of the map in pixel
         */

        protected int mapWidth;
   
        /**
         * the width of one tile of the map in pixel
         */

        protected int tileWidth;
   
        /**
         * the height of one tile of the map in pixel
         */

        protected int tileHeight;
   
        /**
         * the GameContainer, used for getting the size of the GameCanvas
         */

        protected GameContainer gc;
   
        /**
         * the x-position of our "camera" in pixel
         */

        protected float cameraX;
   
        /**
         * the y-position of our "camera" in pixel
         */

        protected float cameraY;
   
        protected Point2D.Float currentCenterPoint = new Point2D.Float(0, 0);
   
        /**
         * Create a new camera
         *
         * @param gc the GameContainer, used for getting the size of the GameCanvas
         * @param map the TiledMap used for the current scene
         */

        public Camera(GameContainer gc, TiledMap map) {
            this.map = map;
   
            this.numTilesX = map.getWidth();
            this.numTilesY = map.getHeight();
   
            this.tileWidth = map.getTileWidth();
            this.tileHeight = map.getTileHeight();
   
            this.mapWidth = this.numTilesX * this.tileWidth;
            this.mapHeight = this.numTilesY * this.tileHeight;
   
            this.gc = gc;
        }
   
        /**
         * "locks" the camera on the given coordinates. The camera tries to keep the
         * location in it's center.
         *
         * @param x the real x-coordinate (in pixel) which should be centered on the
         * screen
         * @param y the real y-coordinate (in pixel) which should be centered on the
         * screen
         * @return
         */

        public Point2D.Float centerOn(float x, float y) {
            //try to set the given position as center of the camera by default
            cameraX = x - gc.getWidth() / 2;
            cameraY = y - gc.getHeight() / 2;
   
            //if the camera is at the right or left edge lock it to prevent a black bar
            if (cameraX < 0) {
                cameraX = 0;
            }
            if (cameraX + gc.getWidth() > mapWidth) {
                cameraX = mapWidth - gc.getWidth();
            }
   
            //if the camera is at the top or bottom edge lock it to prevent a black bar
            if (cameraY < 0) {
                cameraY = 0;
            }
            if (cameraY + gc.getHeight() > mapHeight) {
                cameraY = mapHeight - gc.getHeight();
            }
   
            currentCenterPoint.setLocation(cameraX, cameraY);
            return currentCenterPoint;
        }
   
        /**
         * "locks" the camera on the center of the given Rectangle. The camera tries
         * to keep the location in it's center.
         *
         * @param x the x-coordinate (in pixel) of the top-left corner of the
         * rectangle
         * @param y the y-coordinate (in pixel) of the top-left corner of the
         * rectangle
         * @param height the height (in pixel) of the rectangle
         * @param width the width (in pixel) of the rectangle
         */

        public void centerOn(float x, float y, float height, float width) {
            this.centerOn(x + width / 2, y + height / 2);
        }
   
        /**
         * "locks the camera on the center of the given Shape. The camera tries to
         * keep the location in it's center.
         *
         * @param shape the Shape which should be centered on the screen
         */

        public void centerOn(Shape shape) {
            this.centerOn(shape.getCenterX(), shape.getCenterY());
        }
   
        /**
         * draws the part of the map which is currently focussed by the camera on
         * the screen
         */

        public void drawMap(int layer) {
            this.drawMap(0, 0, layer);
        }
   
        /**
         * draws the part of the map which is currently focussed by the camera on
         * the screen.<br>
         * You need to draw something over the offset, to prevent the edge of the
         * map to be displayed below it<br>
         * Has to be called before Camera.translateGraphics() !
         *
         * @param offsetX the x-coordinate (in pixel) where the camera should start
         * drawing the map at
         * @param offsetY the y-coordinate (in pixel) where the camera should start
         * drawing the map at
         */

        public void drawMap(int offsetX, int offsetY, int layer) {
            //calculate the offset to the next tile (needed by TiledMap.render())
            int tileOffsetX = (int) -(cameraX % tileWidth);
            int tileOffsetY = (int) -(cameraY % tileHeight);
   
            //calculate the index of the leftmost tile that is being displayed
            int tileIndexX = (int) (cameraX / tileWidth);
            int tileIndexY = (int) (cameraY / tileHeight);
   
            //finally draw the section of the map on the screen
            map.render(
                    tileOffsetX + offsetX,
                    tileOffsetY + offsetY,
                    tileIndexX,
                    tileIndexY,
                    (gc.getWidth() - tileOffsetX) / tileWidth + 1,
                    (gc.getHeight() - tileOffsetY) / tileHeight + 1, layer, false);
        }
   
        /**
         * Translates the Graphics-context to the coordinates of the map - now
         * everything can be drawn with it's NATURAL coordinates.
         */

        public void translateGraphics() {
            gc.getGraphics().translate(-cameraX, -cameraY);
        }
   
        /**
         * Reverses the Graphics-translation of Camera.translatesGraphics(). Call
         * this before drawing HUD-elements or the like
         */

        public void untranslateGraphics() {
            gc.getGraphics().translate(cameraX, cameraY);
        }
   
    }


and this is how its being called
In the engine class

1  
2  
3  
4  
5  
6  
7  
8  
9  
    public void render(GameContainer gc, Graphics g) throws SlickException {
           
            camera = new Camera(gc, world.map);
            camera.centerOn(player.getX(), player.getY());
            camera.drawMap(0);
            camera.drawMap(1);
            player.draw();
            camera.drawMap(2);
        }
Offline Endos
« Reply #1 - Posted 2014-04-23 17:50:34 »

The problem is that you are moving both, the player and the camera, at the same time.
If the camera moves, the player must stop, and vice versa. Instead of using the player coordinates, use other variables and update the player or the camera depending on what must move.

Bored Birds - End with your boredom for Android
Retroships - Space Shooter for Android
Ultimate - 2D Side-Scrolling Platformer project
Offline Desbrina

Senior Newbie


Exp: 3 years



« Reply #2 - Posted 2014-04-23 17:59:48 »

So i need to stop one or the other from moving. Stopping the player is probably the easiest, i could probably check the players update and make it so that the change in x and y doesn't happen by having it check that the camera isn't scrolling , though i've yet to work out where the scrolling takes place in the camera class to set a variable that can be checked.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Rayvolution

JGO Kernel


Medals: 216
Projects: 2
Exp: 1 year


Resident Crazyman


« Reply #3 - Posted 2014-04-24 21:40:35 »

What Endos said; Basically you're moving the character on the *screen* not on the *map*, then moving the map as well. The player isnt actually speeding up, he's staying at the same speed.. But you're also moving the map at the same speed in the opposite direction, thus he ends up traveling twice as fast. (Think of it like this: He's walking the same speed, but now on an escalator, so he's covering 2x the ground)

A possible solution is to seperate the camera and player completely, what I do is render the player on the screen in relation to where the map is, and then make the map move in relation to where the player is. They don't have any connection to each other.

(NOTE: Stripped all the way down to be super simple)
Example of renders/moving my character, where entityX and Y are in relation to where the map is being rendered, NOT in relation to where the character is on the screen. :
1  
2  
3  
4  
5  
6  
7  
   public void render(Graphics g, boolean debug) throws SlickException{      
      entity.render(entityX+mapX,entityY+mapY);
   }

   public void moveEntityNorth() throws SlickException{
      entityY -= entitySpeed;
   }


and moving the map/camera around to follow the player, but it's coordinates aren't "attached" to the player. NOTE: You will have to change the values after >=/<= to match your screen size to where you want the movement to start. My game is rendered in 720p and scaled x3, thats why my values are so low. Yours will probably be much higher than mine:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
   public void update(GameContainer gc, StateBasedGame sbg, int delta) throws SlickException{
      if((mapX*-1)-entityX >= -161){
         mapX += entitySpeed;
      }

      if((mapX*-1)-entityX <= -233){
         mapX -= entitySpeed;
      }
     
      if((mapY*-1)-entityY() >= -86){
         mapY += entitySpeed;
      }
     
      if((mapY*-1)-entityY() <= -106){
         mapY -= entitySpeed;
      }
   }


The results are a camera that follows around the player, not a camera that moves based on your inputs. If that makes sense.

(Note: This may also help solve your TileID problem in your other thread)

- Raymond "Rayvolution" Doerr.
Retro-Pixel Castles - Survival Sim/Builder/Roguelike!
LIVE-STREAMING DEVELOPMENT: http://www.twitch.tv/SG_Rayvolution
Pages: [1]
  ignore  |  Print  
 
 

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

Longarmx (38 views)
2014-10-17 03:59:02

Norakomi (28 views)
2014-10-16 15:22:06

Norakomi (24 views)
2014-10-16 15:20:20

lcass (28 views)
2014-10-15 16:18:58

TehJavaDev (53 views)
2014-10-14 00:39:48

TehJavaDev (54 views)
2014-10-14 00:35:47

TehJavaDev (43 views)
2014-10-14 00:32:37

BurntPizza (64 views)
2014-10-11 23:24:42

BurntPizza (36 views)
2014-10-11 23:10:45

BurntPizza (78 views)
2014-10-11 22:30:10
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!