Jump to content

Java camera following


Recommended Posts

Trying to make a kind of 2D game in java to learn the basics. Anyways, I need to make like, the window follow the character, while moving the map and everything else.

 

Can anyone help with this? Remember, I'm just beginning in java. :\

untitled6kv7.gif

sterlite.png

Sterlite.png

Link to comment
Share on other sites

You don't code the character to move.

 

You code it so when you click to move it runs a movement animation on the character but its actually the map etc tht moves.

Plv6Dz6.jpg

Operation Gold Sparkles :: Chompy Kills ::  Full Profound :: Champions :: Barbarian Notes :: Champions Tackle Box :: MA Rewards

Dragonkin Journals :: Ports Stories :: Elder Chronicles :: Boss Slayer :: Penance King :: Kal'gerion Titles :: Gold Statue

Link to comment
Share on other sites

You don't code the character to move.

 

You code it so when you click to move it runs a movement animation on the character but its actually the map etc tht moves.

 

I was thinking that at first, but then moved to the character moving idea because of all the things that would need to move on the map...NPCs, etc... Oh well, I guess. :P

 

So, any ideas on how to start on this then?

untitled6kv7.gif

sterlite.png

Sterlite.png

Link to comment
Share on other sites

Um....By beginning do you mean your first month or have you been at this for awhile. Also, is this your first programming language?

Quote - Revenge is such a nasty thing that only breeds more vengeful souls, but in some situations revenge does not even need to be sought out, but only bided.

Link to comment
Share on other sites

Um....By beginning do you mean your first month or have you been at this for awhile. Also, is this your first programming language?

This.

 

This is a good resource book: http://www.amazon.com/Killer-Game-Programming-Andrew-Davison/dp/0596007302/ref=sr_1_1?ie=UTF8&s=books&qid=1280710993&sr=8-1

polvCwJ.gif
"It's not a rest for me, it's a rest for the weights." - Dom Mazzetti

Link to comment
Share on other sites

Here is what I would do:

 

 

//PseudoCode by ballerplaya

//This will make the character appear to move
//This assumes this is using KeyListener and is in the keypressed method
//This also assumes that the map is placed using static X,Y positioning

public void KeyPressed(KeyEvent evt)
{

int key = evt.getKeyCode();


switch(key)
{

case KeyEvent.VK_UP:
//We want to move the map down as well as make it look like the character is moving up

MapPosY --; //Reduce Y-coord by one
Character.WalkNorth(); //Trigger an animation to make it look like it is walking North
break;

case KeyEvent.VK_DOWN:
MapPosY ++; //Increase Y-coord by one
Character.WalkSouth(); //Trigger an animation to make it look like it is walking South
break;

case KeyEvent.VK_LEFT:
MapPosX --; //Reduce X-coord by one
Character.WalkWest(); //Trigger an animation to make it look like it is walking West
break;

case KeyEvent.VK_RIGHT:
MapPosX ++; //Reduce X-coord by one
Character.WalkEast(); //Trigger an animation to make it look like it is walking East
break;


Default:
}

//Update the graphics so it shows your changes and animation
UpdateGraphics();



}


 

If you need an example, PM me and I can whip you up something.

 

 

 

You don't code the character to move.

 

You code it so when you click to move it runs a movement animation on the character but its actually the map etc tht moves.

 

I was thinking that at first, but then moved to the character moving idea because of all the things that would need to move on the map...NPCs, etc... Oh well, I guess. :P

 

So, any ideas on how to start on this then?

 

 

If you have some coordinate system setup, as long as your "camera" is showing the area in which NPC's, buildings, etc are, it shouldn't matter.

 

 

Lets say your "camera" covers a 10 by 10 grid. Lets say you have an npc which automatically walks between 12,13 to 14,15. If your map gets relocated in the area in which the npc is located, it will show that npc doing it's thing.

sigcp.png

 

65,280 to 99 fletching on 3-14-09

40,405 to 99 woodcutting on 10-17-2009

Link to comment
Share on other sites

Bear in mind if you want to actually make a serious, playable game, you need to use timers to control frames per second and other stuff like that.

 

I'd really recommend buying that book I linked, it's a really great resource that thoroughly describes how to do that.

polvCwJ.gif
"It's not a rest for me, it's a rest for the weights." - Dom Mazzetti

Link to comment
Share on other sites

First month or so....Using this mainly to learn more. :)

 

As for the keypressed thing, yeah I know about KeyPressed events >.< I just wanted an example of a basic "Character.WalkNorth();" Or some help on it. :)

 

I'm also going to draw the map in sections, 700x700 pixels and am not sure on how to make them connect, etc..

untitled6kv7.gif

sterlite.png

Sterlite.png

Link to comment
Share on other sites

First month or so....Using this mainly to learn more. :)

 

As for the keypressed thing, yeah I know about KeyPressed events >.< I just wanted an example of a basic "Character.WalkNorth();" Or some help on it. :)

 

I'm also going to draw the map in sections, 700x700 pixels and am not sure on how to make them connect, etc..

 

 

Lets say you wanted a 32 by 32 grid across that 700x700 area. ALl you would have to do is create a function which returns the value of a pixel multiplied by 32.

 

public int GetGridSpace(int value) 
{
    return value*32;
}

 

Now for an example:

 

//This would be in your paint method!!!!!

This will draw your toon along a 32x32 grid in the desired position as long as it is within the screen bounds, not the image bounds.
if(GetGridSpace(ToonX) < getWidth() && GetGridSpace(ToonY < getHeight()){

g.drawImage(ToonImage, GetGridSpace(ToonX) ,GetGridSpace(ToonY) ,null);

}

 

 

Now for a WalkNorth method you would do something like:

 


//This assumes you have an image named CharacterImage as well as a Boolean for each direction you are facing and all of the necessary images. This is psuedocode also.
public void WalkNorth()
{
//Change the image to one which face north (no animation is used)
CharacterImage =Toolkit.getDefaultToolkit().getImage(class.getClass().getResource("/charNorth/png"));


//If you have animation
CharacterImage =Toolkit.getDefaultToolkit().getImage(class.getClass().getResource(CharacterAnimationClass.getNextImageMethod()).toString());




}

 

In your character animation class, you want to store the images for that animation in an array and loop through the array as you move.

 

Its like midnight my time and I need to get some sleep so I will check this thread when I wake up.

 

-bp

sigcp.png

 

65,280 to 99 fletching on 3-14-09

40,405 to 99 woodcutting on 10-17-2009

Link to comment
Share on other sites

Within previous games I've made, I always used a similar approach to what has been stated above. Moving everything other than the player to incorporate player movement. However, with that implementation; you do need to be wary. If you are going to be doing anything where it could be necessary for the camera to be located at a different point - this isn't going to follow that logical an approach.

 

Essentially, what I did in a previous game was to define the 'world' in which the player existed and a camera to view this world between specific regions. As the player moved, the camera moved to provide exactly the same as above, yet if the camera had to be moved to a different position it was extremely easy and logical.

 

Although the above method works fine largely for most games, if you are developing in complexity in may be worth considering more than the standard approach. :)

Link to comment
Share on other sites

Within previous games I've made, I always used a similar approach to what has been stated above. Moving everything other than the player to incorporate player movement. However, with that implementation; you do need to be wary. If you are going to be doing anything where it could be necessary for the camera to be located at a different point - this isn't going to follow that logical an approach.

 

Essentially, what I did in a previous game was to define the 'world' in which the player existed and a camera to view this world between specific regions. As the player moved, the camera moved to provide exactly the same as above, yet if the camera had to be moved to a different position it was extremely easy and logical.

 

Although the above method works fine largely for most games, if you are developing in complexity in may be worth considering more than the standard approach. :)

 

Thanks, I'll defiantly look into that. :o

 

Anyone got any ideas on stiching the map segments together?...

untitled6kv7.gif

sterlite.png

Sterlite.png

Link to comment
Share on other sites

Well, rationally speaking - you're going to need some form of structure to keep track of which segment aligns with others on the map. The map segments; the 700x700 pieces are presumably images (or can be considered as such when generated), therefore in order to 'stitch' these together, you need to store them or a reference to them (i.e File name) in a structure which will represent the map. When it comes to drawing the map, you can find which piece(s) need(s) to be drawn and draw them relative to the location of each other.

 

One method is to view the entire 'map' as being made up of tiled segments, which are the 700x700 areas. If you're looking for simplicity - you could easily store the references in an array (assuming you have a fixed size for the map). The array could be one or two-dimensional; two-dimensional may be more representative of a simple, square, 2D-map yet one-dimensional could easily work the same way, you would simply have to resolve the index to x,y components.

 

Although this method works, it's very static and generic. If you suddenly want to swap map-pieces around, insert some in a different place or even create an entirely different shaped map - you may well run into complications.

 

An alternative method would be to create a 'Linked' map, as such. Within this, each map-piece could have a reference to any adjacent pieces. If the reference doesn't exist - you know you can't move to that area. It would also be flexible in the case that if you wanted to change the shape of the map - you could quite easily do so with the usage of ENUMs to represent the position of tile references and a change to your drawing code. However, if you're wanting to keep things simple - this method may produce more overload than an array-based map.

 

Anyway, once you've got a structure that you've determined is appropriate - you need to create the drawing code that will draw the current location. From the choice of area-size; I'd presume that you've got the screen displaying at 700x700? If so - when drawing you'll need to consider the current area to draw, as well as the adjacent areas - otherwise it will be very obvious that the game will be 'jumping' between areas rather than transitioning. The simple thing to do here is to draw all adjacent tiles as well as the current, relative to the position of the current one being drawn. Alternatively, you could attempt to only draw the part of the other areas needed. (As a large part will obviously be outside of the players viewport).

 

If you're wanting some mock-code to explain more anything that I've said here feel free to ask. Others might have some better suggestions too! :)

 

Apologies about the wall-of-text too...It seems to be my speciality at times!

Link to comment
Share on other sites

I suppose a basic 2D map that loads the segmet you're currently on and, as you said, all the ones around it. (The screen is actually 500x400 to be honest.)

 

Some kind of "mock-code" to work off of would be very much appreciated, as well. :)

untitled6kv7.gif

sterlite.png

Sterlite.png

Link to comment
Share on other sites

I suppose a basic 2D map that loads the segmet you're currently on and, as you said, all the ones around it. (The screen is actually 500x400 to be honest.)

 

Some kind of "mock-code" to work off of would be very much appreciated, as well. :)

Ok then, I've drawn up a simple(ish) MapHandler class. I've (briefly) tested it too, so it should manage for an example and even basic-tests. But if you're actually going to use it be sure to check everything works fine.

 

It's commented in all places that it needs to be, if there's anything that you don't quite get about it feel free to ask. I took into account the different screen-size (sorry for that assumption ;) ) and also made it flexible for tile-sizes if you decide to change to larger / smaller areas. This means it will actually print more than just a single adjacent tile if the player's viewport can see that.

 

In terms of efficiency, I'm not quite sure how well this would do. It would very likely need to be optimised. I did draw up a simple cache-loading for the tile-images but that would probably need to be managed better in a full-game.

 

Anyway, hopefully it helps! :)

 

[hide=MapHandler.java]

package mapmock;

import java.awt.Graphics;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import javax.imageio.ImageIO;

/**
* A mock-up of a MapHandler class for a game. This loads tiles when needed and displays at a specific location, drawing
* all the tiles that the player can view. Certain variables should be configred / assigned at runtime - in particular the WIDTH / HEIGHT
* constants.
*
* Remember - I've omitted many of the convenience methods that would be practical to have as well! 
* 
* @author Ronan
*/
public class MapHandler {
   /* The screen width & height */
   private final int SCREEN_WIDTH = 500;
   private final int SCREEN_HEIGHT = 400;

   /* Dimensions of the tiles. */
   private final int TILE_WIDTH = 700;
   private final int TILE_HEIGHT = 700;

   /*
    * Map contains file-references to each tile-image. Ideally, you'd probably
    * want to cache-load these in an actual game. This would involve loading
    * the map-piece if it hasn't been loaded and storing the loaded-piece.
    *
    * Prior to attempting to load the piece, the Handler could check if it has
    * been loaded and use that instead.
    *
    * Obviously with large maps clean-up would need to be involved to unload
    * previous stored areas that aren't used commonly.
    */
   private File[][] map;

   /*
    * A possible implementation of the cache-loading process.
    */
   private HashMap<File, BufferedImage> loadedTiles;

   /*
    * Stores the pointer to the map-array, determining where our current location
    * is.
    */
   private Point current = new Point(0,0);

   /* Simple test constructor. */
   public MapHandler(File[][] map, Point current) {
       loadedTiles = new HashMap<File, BufferedImage>();

       this.map = map;

       moveCurrent(current);
   }

   /**
    * Loads the specific tile from the map-array. Deals with the cache-loading process.
    *
    * @param x The x-index of the tile to load.
    * @param y The y-index of the tile to load.
    *
    * @return Returns the loaded image from the map-array. Will throw an IOException
    *         if the image cannot be loaded.
    */
   public BufferedImage loadTile(int x, int y) {
       File currentFile = map[x][y];

       if(!loadedTiles.containsKey(currentFile)) {
           try {
               /* Place the loaded image and file into the loaded-tiles cache. */
               BufferedImage image = loadedTiles.put(currentFile, ImageIO.read(currentFile));

               return image;
           } catch (IOException e) {
               /*
                * Throw exception if the file can't be read correctly,
                * alternatively could deal with the error.
                */
               throw new RuntimeException("I/O Exception occured during reading " +
                       "of file: " + currentFile.getName());
           }
       } else {
           /* We've loaded the tile already - return it from the cache. */
           return loadedTiles.get(currentFile);
       }
   }

   /**
    * Used to move the player's active-area from one location to another.
    *
    * @param newLocation The point reference to the new-location. Corresponds
    *                    to the index to the map array.
    */
   public void moveCurrent(Point newLocation) {
       int newX = newLocation.x;
       int newY = newLocation.y;

       /* Error-check the location we're changing to. */
       if(newX < 0 || newY < 0 || newX >= map.length || newY > map[newX].length) {
           throw new RuntimeException("New Location out of Bounds: (" + newX + "," + newY + ")");
       }

       current.x = newX;
       current.y = newY;

       /*
        * Cache-loading details. Loads the current tile's file and adjacent
        * tiles when moved. Could also invole unloading of previous tiles.
        */
       for(int x = current.x - 1; x <= current.x + 1; x++) {
           /* Make sure we don't load tiles out of bounds. */
           if(x < 0 || x >= map.length) continue;

           for(int y = current.y - 1; y <= current.y + 1; y++) {
               /* Make sure we don't load tiles out of bounds. */
               if(y < 0 || y >= map[x].length) continue;

               loadTile(x, y);
           }
       }
   }

   /**
    * Draws the current tile and adjacent tiles.
    *
    * @param g The Graphics to draw the map to.
    * @param position The position to draw the map at. This position represents
    *                 the upper-left co-ordinate of the current tile and should
    *                 be determined at runtime based on your implementation of drawing.
    *
    * NOTE :- This doesn't implement cutting of the image-area that isn't going
    *         to be visible to the user. That may be something else to consider.
    *
    *         As you stated the screen is 500x400, I've edited it a bit to only
    *         draw the other tiles that are needed. Not all 8 adjacent.
    */
   public void paint(Graphics g, Point position) {
       /*
        * Calculate extra tiles to be drawn.
        */

       /*
        * Determines the number of tiles that we need to draw above and to the left
        * of the current tile.
        *
        * This is based on taking the gap between the upper-left of the 'viewport'
        * and the position that we're drawing the current tile at. We then
        * calculate the number of tiles that will fit into the gap, taking the
        * ceiling of the calculation to make sure no small-gaps are left.
        */
       Point upperLeft = new Point(position.x < 0 ? 0 : (int)Math.ceil((double)position.x / TILE_WIDTH),
               position.y < 0 ? 0 : (int)Math.ceil((double)position.y / TILE_WIDTH));

       int lowerWidth = SCREEN_WIDTH - position.x + TILE_WIDTH;
       int lowerHeight = SCREEN_HEIGHT - position.y + TILE_HEIGHT;

       /*
        * A similar method to above is used to calculate the lower-right boundaries.
        */
       Point lowerRight = new Point(lowerWidth < 0 ? 0 : (int)Math.ceil((double)lowerWidth / TILE_WIDTH),
               lowerHeight < 0 ? 0 : (int)Math.ceil((double)lowerHeight / TILE_HEIGHT));

       /*
        * We now loop over the entire 'area' that we've generated, skipping if
        * any points are out of bounds. (This should mean we're at the edge of
        * the map rather than a problem). 
        */
       for(int x = current.x - upperLeft.x; x <= current.x + lowerRight.x; x++) {
           if(x <= 0 || x >= map.length) continue;

           for(int y = current.y - upperLeft.y; y <= current.y + lowerRight.y; y++) {
               if(y <= 0 || y >= map[x].length) continue;

               /*
                * We draw the tile we're currently at, relative to the position specified
                * for the 'current' tile that the player is on.
                */
               g.drawImage(loadTile(x, y), position.x - ((current.x - x) * TILE_WIDTH),
                       position.y - ((current.y - y) * TILE_HEIGHT), null);
           }
       }
   }
}

[/hide]

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.