|
Scrolling Camera - Using Transforms |
ryancoboy
Member #14,468
July 2012
|
I'm having an issue with using transformations to achieve a scrolling camera effect. I've just started learning about transformations today and I'm having trouble understanding some of the documentation on them. I'll start by saying what it is I'm drawing: NOTE: (I'm doing all of my "transform" related stuff in my "update" area. after looking around it appears as if people like to put their transform related stuff in their render section. Which is more correct?) The problem is when i move my character to the lower left hand corner of the screen, rather than my map being there, (which is 3200 x 3200 pixels and my display is only 800 x 600) all i see is a black abyss past that 800 x 600 point. Example: Pixels after 800 and after 600 are longer my map but rather a black non-drawn section. (Note: my character still gets drawn in this section just my map doesn't) Any ideas? I'm still new to transforms so I'm sure I've missed something. Ill post some of my code if needed. Thanks, -Ryan |
SiegeLord
Member #7,827
October 2006
|
ryancoboy said: Ill post some of my code if needed. Please. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
ryancoboy
Member #14,468
July 2012
|
Sorry for the late reply, had to run to the store. Edit: before I actually post my code can anyone one tell me how to put my code in a "code block" here on the forums. I've never done it before. Sorry. Thanks, -Ryan |
SiegeLord
Member #7,827
October 2006
|
"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
ryancoboy
Member #14,468
July 2012
|
Here is the code i believe to be in question. Update and Render method: 1//==============================================
2//GAME UPDATE
3//==============================================
4else if(ev.type == ALLEGRO_EVENT_TIMER)
5{
6 render = true;
7
8 //==============================================
9 //UPDATE characters position
10 //==============================================
11 UpdateCharaPos(Character);
12
13 //==============================================
14 //character animation delay
15 //==============================================
16 Character.Set_FrameCount(Character.Get_FrameCount() + 1);
17 if(Character.Get_FrameCount() >= Character.Get_FrameUpdateDelay())
18 {
19 //==============================================
20 //UPDATE characters animation
21 //==============================================
22 UpdateCharaAnim(Character);
23 Character.Set_FrameCount(0);
24 }
25
26 //==============================================
27 //Look for any collisions
28 //==============================================
29 MapChangeLayer(2);
30 BlockData = MapGetBlockInPixels(Character.Get_PosX() + (Character.Get_FrameHeight() / 2), Character.Get_PosY() + Character.Get_FrameWidth());
31
32 if(BlockData->user1 == 1 || Character.Get_PosX() <= 0 || Character.Get_PosY() + (Character.Get_FrameHeight() / 2) <= 0 || Character.Get_PosX() >= (mapwidth * 32) || Character.Get_PosY() >= (mapheight * 32))
33 {
34 ResolveCollision(Character);
35 }
36
37 MapChangeLayer(0);
38 //==============================================
39
40 //==============================================
41 //Transforms code
42 //==============================================
43 UpdateCamera(CamX, CamY, Character.Get_PosX(), Character.Get_PosY(), Character.Get_FrameWidth(), Character.Get_FrameHeight());
44
45 al_identity_transform(&camera);
46 al_translate_transform(&camera, -CamX, -CamY);
47 al_use_transform(&camera);
48 //==============================================
49
50
51 //UPDATE FPS===========
52 frames++;
53 if(al_current_time() - gameTime >= 1)
54 {
55 gameTime = al_current_time();
56 gameFPS = frames;
57 frames = 0;
58 }
59 //=====================
60
61 }
62
63 //==============================================
64 //RENDER
65 //==============================================
66 if(render && al_is_event_queue_empty(event_queue))
67 {
68 render = false;
69
70 //==============================================
71 //Draw the Map - and each of it's layers
72 //==============================================
73 MapDrawBG(0, 0, 0, 0, WIDTH, HEIGHT);
74 MapChangeLayer(1);
75 MapDrawBG(0, 0, 0, 0, WIDTH, HEIGHT);
76 MapChangeLayer(2);
77 MapDrawBG(0, 0, 0, 0, WIDTH, HEIGHT);
78 MapChangeLayer(0);
79 //==============================================
80
81 //==============================================
82 //Draw the character
83 //==============================================
84 DrawChara(Character);
85
86 al_draw_textf(font18, al_map_rgb(255, 0, 255), 5, 5, 0, "FPS: %i", gameFPS); //display FPS on screen
87
88 //FLIP BUFFERS========================
89 al_flip_display();
90 al_clear_to_color(al_map_rgb(255,255,255));
91 }
And here is the Update Camera function: void UpdateCamera(float &CamPosX, float &CamPosY, float x, float y, int PlayerWidth, int PlayerHeight) { CamPosX = -(WIDTH / 2) + (x + PlayerWidth / 2); CamPosY = -(HEIGHT / 2) + (y + PlayerHeight / 2); if(CamPosX < 0) { CamPosX = 0; } if(CamPosY < 0) { CamPosY = 0; } } EDIT: I should also mention that I'm using the tile engine "Mappy" in my project. @SiegeLord: Thank you for showing that. Thanks, -Ryan |
SiegeLord
Member #7,827
October 2006
|
You'll probably need to turn off the transformation while using the MapDrawBG calls. Mappy doesn't seem to be designed to be used with transformations. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
ryancoboy
Member #14,468
July 2012
|
I considered that. But that is where my understanding of the Allegro documentation fails. By "turn off transformation" I'm going to assume you mean set the transformation back to default. The only problem is I don't understand what it means when the documentation says "Use al_use_transform on an identity transformation to return to the default." So, if you could clarify that. I would be very grateful. perhaps give a real quick example? Thanks, -Ryan |
SiegeLord
Member #7,827
October 2006
|
ALLEGRO_TRANSFORM trans; al_identity_transform(&trans); al_use_transform(&trans); You'll also want to do this when before you draw your GUI. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
ryancoboy
Member #14,468
July 2012
|
Thanks it will be good to know how to do that in the future. but i do believe i found the problem. I believe (i may be reading the code wrong) what Mappy does is it "cuts" out a piece of my map that fits inside of my screen width and height. This makes sense because why draw what the user will "never" see. Well i want it to draw the whole thing. Ill show you the code for the MapDrawBG function and hopefully you can see what I would need to change in order to achieve my goal faster and easier than I will. 1/* draw the background graphics on the current layer to the target bitmap, usually backbuffer */
2void MapDrawBG (int mapxo, int mapyo, int mapx, int mapy,int mapw, int maph)
3{
4 int i, j, mycl, mycr, myct, mycb, mapvclip, maphclip;
5 int mbgx, mbgy;
6 short int *mymappt;
7 short int *mymap2pt;
8 BLKSTR *blkdatapt;
9 ANISTR *myanpt;
10 ALLEGRO_BITMAP* mapdestpt;
11
12 mapdestpt=PushTargetDisplayAndBitmap(NULL);
13 al_get_clipping_rectangle(&mycl,&mycr,&myct,&mycb);
14 al_set_clipping_rectangle(mapx,mapy,mapw,maph);// set_clip (mapdestpt, mapx, mapy, mapx+mapw-1, mapy+maph-1);
15
16 mapxo -= mapblockstaggerx;
17 mapyo -= mapblockstaggery;
18 mymappt = (short int *) mappt;
19 if (mapblockstaggerx || mapblockstaggery)
20 {
21 mymappt += (mapxo/mapblockgapx)+((mapyo/mapblockgapy)*mapwidth*2);
22 mbgx = mapblockgapx;
23 mbgy = mapblockgapy;
24 }
25 else
26 {
27 mymappt += (mapxo/mapblockgapx)+((mapyo/mapblockgapy)*mapwidth);
28 mbgx = 0;
29 mbgy = 0;
30 }
31 mapvclip = mapyo%mapblockgapy;
32 maphclip = mapxo%mapblockgapx;
33
34 mymap2pt = mymappt;
35 for (j=((mapy-mapvclip)-mbgy);j<((mapy+maph));j+=mapblockgapy)
36 {
37 for (i=((mapx-maphclip)-mbgx);i<((mapx+mapw));i+=mapblockgapx)
38 {
39 if (*mymappt>=0)
40 blkdatapt = ((BLKSTR*) mapblockstrpt) + *mymappt;
41 else
42 {
43 myanpt = mapanimstrendpt + *mymappt;
44 blkdatapt = ((BLKSTR *) mapblockstrpt) + mapanimseqpt[myanpt->ancuroff];
45 }
46 if (mapblockstaggerx || mapblockstaggery)
47 {
48 if (abmTiles[0] != (ALLEGRO_BITMAP *) blkdatapt->bgoff)
49 //masked_blit ((ALLEGRO_BITMAP *) blkdatapt->bgoff, mapdestpt, 0, 0, i, j, mapblockwidth, mapblockheight);
50 al_draw_bitmap((ALLEGRO_BITMAP *) blkdatapt->bgoff,i,j,0); //size should be the same
51 }
52 else
53 {
54 al_draw_bitmap_region((ALLEGRO_BITMAP *) blkdatapt->bgoff,0,0,mapblockwidth,mapblockheight,i,j,0); //blit ((BITMAP *) blkdatapt->bgoff, mapdestpt, 0, 0, i, j, mapblockwidth, mapblockheight);
55 }
56 mymappt++;
57 }
58 if (mapblockstaggerx || mapblockstaggery)
59 {
60 mymap2pt += mapwidth;
61 mymappt = mymap2pt;
62 for (i=(((mapx-maphclip)-mbgx)+mapblockstaggerx);i<((mapx+mapw));i+=mapblockgapx)
63 {
64 if (*mymappt>=0)
65 blkdatapt = ((BLKSTR*) mapblockstrpt) + *mymappt;
66 else
67 {
68 myanpt = mapanimstrendpt + *mymappt;
69 blkdatapt = ((BLKSTR *) mapblockstrpt) + mapanimseqpt[myanpt->ancuroff];
70 }
71 if (abmTiles[0] != (ALLEGRO_BITMAP *) blkdatapt->bgoff)
72 //masked_blit ((ALLEGRO_BITMAP *) blkdatapt->bgoff, mapdestpt, 0, 0, i, j+mapblockstaggery, mapblockwidth, mapblockheight);
73 al_draw_bitmap((ALLEGRO_BITMAP *) blkdatapt->bgoff,i,j+mapblockstaggery,0); //size should be the same
74
75 mymappt++;
76 }
77 }
78 mymap2pt += mapwidth;
79 mymappt = mymap2pt;
80 }
81 al_set_clipping_rectangle(mycl,mycr,myct,mycb);
82 PopTargetDisplayAndBitmap();
83}
EDIT: hmmm... this bit of code doesn't seem to be where the "cut" is made rather what portion of the cut is shown. Also the setting transforms back to default brings up another problem that I'm to avoid. And I'm trying to use transforms to avoid that problem. EDIT: Ok, I've decided(and think it's safe to say), to make a new topic due to the fact that my problem is no longer with transformations but rather Mappy. Thanks, -Ryan |
SiegeLord
Member #7,827
October 2006
|
Well, it is a good idea not to display more of the map than you need to... it's just that you need to clip the map AND draw it untranslated. Try this, I suppose: 1/* draw the background graphics on the current layer to the target bitmap, usually backbuffer */
2void MapDrawBG (int mapxo, int mapyo, int mapx, int mapy,int mapw, int maph)
3{
4 int i, j, mycl, mycr, myct, mycb, mapvclip, maphclip;
5 int mbgx, mbgy;
6 short int *mymappt;
7 short int *mymap2pt;
8 BLKSTR *blkdatapt;
9 ANISTR *myanpt;
10 ALLEGRO_BITMAP* mapdestpt;
11
12 mapdestpt=PushTargetDisplayAndBitmap(NULL);
13 al_get_clipping_rectangle(&mycl,&mycr,&myct,&mycb);
14 al_set_clipping_rectangle(mapx,mapy,mapw,maph);// set_clip (mapdestpt, mapx, mapy, mapx+mapw-1, mapy+maph-1);
15
16 mapxo -= mapblockstaggerx;
17 mapyo -= mapblockstaggery;
18 mymappt = (short int *) mappt;
19 if (mapblockstaggerx || mapblockstaggery)
20 {
21 mymappt += (mapxo/mapblockgapx)+((mapyo/mapblockgapy)*mapwidth*2);
22 mbgx = mapblockgapx;
23 mbgy = mapblockgapy;
24 }
25 else
26 {
27 mymappt += (mapxo/mapblockgapx)+((mapyo/mapblockgapy)*mapwidth);
28 mbgx = 0;
29 mbgy = 0;
30 }
31 mapvclip = mapyo%mapblockgapy;
32 maphclip = mapxo%mapblockgapx;
33
34 mymap2pt = mymappt;
35 for (j=((mapy-mapvclip)-mbgy);j<((mapy+maph));j+=mapblockgapy)
36 {
37 for (i=((mapx-maphclip)-mbgx);i<((mapx+mapw));i+=mapblockgapx)
38 {
39 if (*mymappt>=0)
40 blkdatapt = ((BLKSTR*) mapblockstrpt) + *mymappt;
41 else
42 {
43 myanpt = mapanimstrendpt + *mymappt;
44 blkdatapt = ((BLKSTR *) mapblockstrpt) + mapanimseqpt[myanpt->ancuroff];
45 }
46 if (mapblockstaggerx || mapblockstaggery)
47 {
48 if (abmTiles[0] != (ALLEGRO_BITMAP *) blkdatapt->bgoff)
49 //masked_blit ((ALLEGRO_BITMAP *) blkdatapt->bgoff, mapdestpt, 0, 0, i, j, mapblockwidth, mapblockheight);
50 al_draw_bitmap((ALLEGRO_BITMAP *) blkdatapt->bgoff,i - mapxo,j - mapyo,0); //size should be the same
51 }
52 else
53 {
54 al_draw_bitmap_region((ALLEGRO_BITMAP *) blkdatapt->bgoff,0,0,mapblockwidth,mapblockheight,i,j,0); //blit ((BITMAP *) blkdatapt->bgoff, mapdestpt, 0, 0, i, j, mapblockwidth, mapblockheight);
55 }
56 mymappt++;
57 }
58 if (mapblockstaggerx || mapblockstaggery)
59 {
60 mymap2pt += mapwidth;
61 mymappt = mymap2pt;
62 for (i=(((mapx-maphclip)-mbgx)+mapblockstaggerx);i<((mapx+mapw));i+=mapblockgapx)
63 {
64 if (*mymappt>=0)
65 blkdatapt = ((BLKSTR*) mapblockstrpt) + *mymappt;
66 else
67 {
68 myanpt = mapanimstrendpt + *mymappt;
69 blkdatapt = ((BLKSTR *) mapblockstrpt) + mapanimseqpt[myanpt->ancuroff];
70 }
71 if (abmTiles[0] != (ALLEGRO_BITMAP *) blkdatapt->bgoff)
72 //masked_blit ((ALLEGRO_BITMAP *) blkdatapt->bgoff, mapdestpt, 0, 0, i, j+mapblockstaggery, mapblockwidth, mapblockheight);
73 al_draw_bitmap((ALLEGRO_BITMAP *) blkdatapt->bgoff,i - mapxo,j+mapblockstaggery - mapyo,0); //size should be the same
74
75 mymappt++;
76 }
77 }
78 mymap2pt += mapwidth;
79 mymappt = mymap2pt;
80 }
81 al_set_clipping_rectangle(mycl,mycr,myct,mycb);
82 PopTargetDisplayAndBitmap();
83}
(I changed the draw bitmap calls) and in your code change these lines: MapDrawBG(CamX, CamY, 0, 0, WIDTH, HEIGHT);
"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
ryancoboy
Member #14,468
July 2012
|
That is definitely a step in the right direction. when i walk around now i do see more of the map becoming visible. However, if i make my character go straight down or right he eventually passes up the map and is now walking in blackness. Essentially the map it being "updated" or "redrawn" to slowly, i think. Thank you very much for all your help so far. Thanks, -Ryan |
SiegeLord
Member #7,827
October 2006
|
Looks like I missed one of the calls, change the al_draw_bitmap_region call in MapDrawBG to this: al_draw_bitmap_region((ALLEGRO_BITMAP *) blkdatapt->bgoff,0,0,mapblockwidth,mapblockheight,i - mapxo,j - mapyo,0) If that doesn't work, then I think the best course of action is for you to post your entire code so someone (me) can try it out themselves... I really would rather not have to learn Mappy and make my own tiled game with a camera to fix this . "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
ryancoboy
Member #14,468
July 2012
|
Still doesn't work. Here, I've attached all of my code. If worst does come to worst, I will just make my own tile engine. I just don't want to give up on mappy quite yet. EDIT: Can't believe i didn't notice this before but when i changed my MapDrawBG code to MapDrawBG(CamX,CamY,0,0,WIDTH,HEIGHT); My character now moves at, what seems like, double his normal intended speed. Thought might be good to know. I'll look further into that. Thanks, -Ryan |
SiegeLord
Member #7,827
October 2006
|
MappyA5's code is really horrid and doesn't even compile on GCC. Whoever wrote that should be slapped. Anyway, here are two solutions... first one doesn't involve mucking around with the Mappy code, and the second one does. I still don't get why you just don't temporarily turn off transformations for just the map drawing (that's what the first way does): First way: 1//==============================================
2//RENDER
3//==============================================
4if(render && al_is_event_queue_empty(event_queue))
5{
6 render = false;
7
8 al_identity_transform(&camera);
9 al_use_transform(&camera);
10
11 MapDrawBG(CamX, CamY,0, 0, WIDTH, HEIGHT);
12 MapChangeLayer(1);
13 MapDrawBG(CamX, CamY, 0, 0, WIDTH, HEIGHT);
14 MapChangeLayer(2);
15 MapDrawBG(CamX, CamY, 0, 0, WIDTH, HEIGHT);
16 MapChangeLayer(0);
17
18 al_identity_transform(&camera);
19 al_translate_transform(&camera, -CamX, -CamY);
20 al_use_transform(&camera);
21
22 DrawChara(Character);
23
24 al_identity_transform(&camera);
25 al_use_transform(&camera);
26
27 al_draw_textf(font18, al_map_rgb(255, 0, 255), 5, 5, 0, "FPS: %i", gameFPS); //display FPS on screen
28
29 //FLIP BUFFERS========================
30 al_flip_display();
31 al_clear_to_color(al_map_rgb(0,0,0));
32}
Second way, replace the MapDrawBG with this code: 1/* draw the background graphics on the current layer to the target bitmap, usually backbuffer */
2void MapDrawBG (int mapxo, int mapyo, int mapx, int mapy,int mapw, int maph)
3{
4 int i, j, mycl, mycr, myct, mycb, mapvclip, maphclip;
5 int mbgx, mbgy;
6 short int *mymappt;
7 short int *mymap2pt;
8 BLKSTR *blkdatapt;
9 ANISTR *myanpt;
10 ALLEGRO_BITMAP* mapdestpt;
11 int real_mapxo = mapxo;
12 int real_mapyo = mapyo;
13
14 mapdestpt=PushTargetDisplayAndBitmap(NULL);
15 al_get_clipping_rectangle(&mycl,&mycr,&myct,&mycb);
16 al_set_clipping_rectangle(mapx,mapy,mapw,maph);// set_clip (mapdestpt, mapx, mapy, mapx+mapw-1, mapy+maph-1);
17
18 mapxo -= mapblockstaggerx;
19 mapyo -= mapblockstaggery;
20 mymappt = (short int *) mappt;
21 if (mapblockstaggerx || mapblockstaggery)
22 {
23 mymappt += (mapxo/mapblockgapx)+((mapyo/mapblockgapy)*mapwidth*2);
24 mbgx = mapblockgapx;
25 mbgy = mapblockgapy;
26 }
27 else
28 {
29 mymappt += (mapxo/mapblockgapx)+((mapyo/mapblockgapy)*mapwidth);
30 mbgx = 0;
31 mbgy = 0;
32 }
33 mapvclip = mapyo%mapblockgapy;
34 maphclip = mapxo%mapblockgapx;
35
36 mymap2pt = mymappt;
37 for (j=((mapy-mapvclip)-mbgy) + real_mapyo;j<((mapy+maph)) + real_mapyo;j+=mapblockgapy)
38 {
39 for (i=((mapx-maphclip)-mbgx) + real_mapxo;i<((mapx+mapw)) + real_mapxo;i+=mapblockgapx)
40 {
41 if (*mymappt>=0)
42 blkdatapt = ((BLKSTR*) mapblockstrpt) + *mymappt;
43 else
44 {
45 myanpt = mapanimstrendpt + *mymappt;
46 blkdatapt = ((BLKSTR *) mapblockstrpt) + mapanimseqpt[myanpt->ancuroff];
47 }
48 if (mapblockstaggerx || mapblockstaggery)
49 {
50 if (abmTiles[0] != (ALLEGRO_BITMAP *) blkdatapt->bgoff)
51 //masked_blit ((ALLEGRO_BITMAP *) blkdatapt->bgoff, mapdestpt, 0, 0, i, j, mapblockwidth, mapblockheight);
52 al_draw_bitmap((ALLEGRO_BITMAP *) blkdatapt->bgoff,i,j,0); //size should be the same
53 }
54 else
55 {
56 al_draw_bitmap_region((ALLEGRO_BITMAP *) blkdatapt->bgoff,0,0,mapblockwidth,mapblockheight,i,j,0); //al_draw_bitmap_region((ALLEGRO_BITMAP *) blkdatapt->bgoff,0,0,mapblockwidth,mapblockheight,i,j,0); //blit ((BITMAP *) blkdatapt->bgoff, mapdestpt, 0, 0, i, j, mapblockwidth, mapblockheight);
57 }
58 mymappt++;
59 }
60 if (mapblockstaggerx || mapblockstaggery)
61 {
62 mymap2pt += mapwidth;
63 mymappt = mymap2pt;
64 for (i=(((mapx-maphclip)-mbgx)+mapblockstaggerx);i<((mapx+mapw));i+=mapblockgapx)
65 {
66 if (*mymappt>=0)
67 blkdatapt = ((BLKSTR*) mapblockstrpt) + *mymappt;
68 else
69 {
70 myanpt = mapanimstrendpt + *mymappt;
71 blkdatapt = ((BLKSTR *) mapblockstrpt) + mapanimseqpt[myanpt->ancuroff];
72 }
73 if (abmTiles[0] != (ALLEGRO_BITMAP *) blkdatapt->bgoff)
74 //masked_blit ((ALLEGRO_BITMAP *) blkdatapt->bgoff, mapdestpt, 0, 0, i, j+mapblockstaggery, mapblockwidth, mapblockheight);
75 al_draw_bitmap((ALLEGRO_BITMAP *) blkdatapt->bgoff,i,j+mapblockstaggery,0); //size should be the same
76
77 mymappt++;
78 }
79 }
80 mymap2pt += mapwidth;
81 mymappt = mymap2pt;
82 }
83 al_set_clipping_rectangle(mycl,mycr,myct,mycb);
84 PopTargetDisplayAndBitmap();
85}
"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
ryancoboy
Member #14,468
July 2012
|
For whatever reason, your fist method was not working for me when i tried it. But now it works perfectly. i must have not reset something of made some logic error somewhere but your first method works like a charm now. Thank you very much for showing me this method again. Also your second method works. And it works better in terms of performance. in the first method my FPS occasionally would drop to 50-59 FPS. the second method made my FPS drop down to 59 a couple of times. So, I'll probably stick to this method. Again, Thank you very much. Your time and efforts are most appreciated. Time to go look over what you changed and study it. Thanks, -Ryan |
|