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

2015/5/20

Help: trouble Using get One Object At Offset to move a character along a set of tiles

Kami_Uizado Kami_Uizado

2015/5/20

#
I've only been using greenfoot for about a week now, and I'm working on this isometric puzzle game that involves using keys to move a box(character) along a set of tiles based on the tiles' location relative to the actor. However, when I use the method getOneObjectAtOffset to get the tile in the specific direction, I don't think it's getting the location of the correct tile. It is important that the box moves along the tiles, because I want to change this a bit so that the box will be able to move up walls. Also, binding the box's movement to the tiles would probably allow me to design levels a bit faster.
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
import greenfoot.*;
 
/**
 * Write a description of class character here.
 *
 * @author (your name)
 * @version (a version number or a date)
 */
public class character extends Actor
{
    public int frame=1;
    public void act()
    {
          
         if(Greenfoot.isKeyDown("d"))
        {         
            floor movetilePOSZ= (floor)getOneObjectAtOffset(((voxy)getWorld()).flrwidth/-2,((voxy)getWorld()).flrheight/2,floor.class);
            if(movetilePOSZ.getX()<getX()&&movetilePOSZ.getY()>getY())
            {
                setLocation(movetilePOSZ.getX(),movetilePOSZ.getY());
            }
            else
            {
                setLocation(getX(),getY());
            }
            for(frame=1;frame<=7;frame++)
             {
                 Greenfoot.delay(2);
                 setImage("zboxy"+frame+".png");
                 //setLocation(getX()-((voxy)getWorld()).flrwidth/14,getY()+((voxy)getWorld()).flrheight/14);
             }
             setImage("boxystat.png");
             Greenfoot.delay(5);
        }
        if(Greenfoot.isKeyDown("e"))
        {           
            floor movetileNEGZ= (floor)getOneObjectAtOffset(((voxy)getWorld()).flrwidth/2,((voxy)getWorld()).flrheight/-2,floor.class);
            if(movetileNEGZ.getX()<getX()&&movetileNEGZ.getY()>getY())
            {
                setLocation(movetileNEGZ.getX(),movetileNEGZ.getY());
            }
            else
            {
                setLocation(getX(),getY());
            }
             for(frame=7;frame>=1;frame--)
             {
                 Greenfoot.delay(2);
                 setImage("zboxy"+frame+".png");
                 //setLocation(getX()+((voxy)getWorld()).flrwidth/14,getY()-((voxy)getWorld()).flrheight/14);
             }
             setImage("boxystat.png");
             Greenfoot.delay(5);
        }
        if(Greenfoot.isKeyDown("w"))
        {           
            floor movetileNEGX= (floor)getOneObjectAtOffset(((voxy)getWorld()).flrwidth/-2,((voxy)getWorld()).flrheight/-2,floor.class);
            if(movetileNEGX.getX()<getX()&&movetileNEGX.getY()>getY())
            {
                setLocation(movetileNEGX.getX(),movetileNEGX.getY());
            }
            else
            {
                setLocation(getX(),getY());
            }
             for(frame=1;frame<=7;frame++)
             {
                 Greenfoot.delay(2);
                 setImage("xboxy"+frame+".png");
                 //setLocation(getX()-((voxy)getWorld()).flrwidth/14,getY()-((voxy)getWorld()).flrheight/14);
             }
             setImage("boxystat.png");
             Greenfoot.delay(5);
        }
        if(Greenfoot.isKeyDown("f"))
        {           
            floor movetilePOSX= (floor)getOneObjectAtOffset(((voxy)getWorld()).flrwidth/2,((voxy)getWorld()).flrheight/2,floor.class);
            if(movetilePOSX.getX()<getX()&&movetilePOSX.getY()>getY())
            {
                setLocation(movetilePOSX.getX(),movetilePOSX.getY());
            }
            else
            {
                setLocation(getX(),getY());
            }
             for(frame=7;frame>=1;frame--)
             {
                 Greenfoot.delay(2);
                 setImage("xboxy"+frame+".png");
                 //setLocation(getX()+((voxy)getWorld()).flrwidth/14,getY()+((voxy)getWorld()).flrheight/14);
             }
             setImage("boxystat.png");
             Greenfoot.delay(5);
        }
    
}
danpost danpost

2015/5/20

#
There are a couple of things that need clarification here. First thing, the cell size of your world is needed as well as the size of the tile images and the size of the image for your character. Second thing, it is unclear if your character is to be moving adjacent to or actually on the tiles. Next thing, a brief description of what your code is supposed to be doing (as least a run-down of what each line is intended to do for one of the keys -- be specific;). Then, a brief of which direction each key is intended for ("d", "e", "w" and "f" are not standard movement keys) -- like "'f' is used to move right", etc. As the code is right now, it appears your character, if moving at all, is moving on the tiles and only along the diagonals. This diagonal movement (1) is not standard and (2) was not mentioned; so, I feel it may not be the type of movement that you want for the character. All in all, posting the code that creates your world along with image sizes would help immensely along with a detailed description of how your character is supposed to be moving (what each key is intended to do and what each line of code for one of the keys is supposed to do).
Kami_Uizado Kami_Uizado

2015/5/20

#
Cell size is one pixel per cell, I can't find the pixel height and width of the image at the moment, but the tiles are diamond shapes. The tiles are all touching each other at their edges, and I think the detect method object isn't working because it's looking for things in rectangular image areas. The box is intended to move diagonally ON the tiles, with the center of the box being on the center of the tile by the end of the keypress. "w"moves the box up and left, "e" moves the box up and right, "d" moves the box down and left, and "f" moves the box down and right. (I can't get the image size right now because my schools system prevents me from obtaining certain properties of downloaded files) Sorry for being so vague.
danpost danpost

2015/5/20

#
As the tiles are diamond shaped, the overlapping of the images would be presumably in a state that the corners of one would coincide with the location of its adjacent tiles (the center point of the adjacent tiles). Therefore, you do not have to go all the way to the edge to detect an adjacent tile. I am referring to the offsets provide in lines 17, 37, 57 and 77. One or two pixels offset would probably be sufficient; however, half the distance offset of what you are currently using would work fine (change '/-2' and '/2' to '/-4' and '/4'). This should limit the number of possible tiles detected at any point to one. To code you have given is a bit bulky; plus, the behavior of the character might be a bit off if more than one key was held down at one time. Adding 'else' for subsequent key checks (lines 18, 38, 58 an 78) would only cause some keys to be favored over others, which is not preferable. We can deal with both these issues by making sure only one key is down before moving:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public void act()
{
    // get user direction
    int dx = 0, dy = 0, n = 0;
    if (Greenfoot.isKeyDown("w")) { dx--; dy--; n++; }
    if (Greenfoot.isKeyDown("e")) { dx++; dy--; n++; }
    if (Greenfoot.isKeyDown("d")) { dx--; dy++; n++; }
    if (Greenfoot.isKeyDown("f")) { dx++; dy++; n++; }
    if (n != 1) return; // ensures only one key is down
    floor tile = (floor)getOneObjectAtOffset(((voxy)getWorld()).flrwidth*dx/4, ((voxy)getWorld()).flrheight*dy/4, floor.class);
    if (tile != null) // this will keep actor on tiles
    {
        setLocation(tile.getX(), tile.getY());
        for (frame=1; frame<=7; frame++)
        {
            setImage("xboxy"+frame+".png");
            Greenfoot.delay(2);
        }
        setImage("boxystat.png");
        Greenfoot.delay(5);
    }
}
danpost danpost

2015/5/21

#
Sorry. I was mistaken in the above. The check on line 10 limits the number of tiles that could be detected to two -- which will not work. The other tile detected will be the tile that the character is current at. If you import java.util.List into the class you can replace my lines 10 through 12 above with the following:
1
2
3
4
5
6
7
int fw = ((voxy)getWorld()).flrwidth;
int fh = ((voxy)getWorld()).flrheight;
List<?> tiles = getObjectsAtOffset(fw*dx/4, fh*dy/4, floor.class);
tiles.removeAll(getObjectsAtOffset(-fw*dx/4, -fh*dy/4, floor.class));
if (!tiles.isEmpty())
{
    floor tile = (floor)tiles.get(0);
Here, line 4 will remove the tile the character is currently on from the list created on line 3.
You need to login to post a reply.