![]() |
|
scrolling camera along with player? |
allegronewb
Member #13,942
January 2012
|
hey everyone, not really sure how to make the screen move along with my player in a side-scroller. I searched it in this forum and found some references to a camera, but I am not sure how to implement this. By the way I am using Mappy for my tiled background Currently I am using this: 1const int WIDTH = 800;
2const int HEIGHT = 600;
3
4else if(ev.type == ALLEGRO_EVENT_TIMER)
5{
6 //player.x is the center position of my rectangular player, and bx is the bounding box
7 player.x += keys[RIGHT] * 5;
8 player.x -= keys[LEFT] * 5;
9
10 if (player.x + player.bx > WIDTH - 250)
11 xOff += player.x + player.bx - 550;
12 if(xOff > (mapwidth*mapblockwidth - WIDTH))
13 xOff = mapwidth*mapblockwidth - WIDTH;
14
15 render = true;
16
17}
18if (render && al_is_event_queue_empty(event_queue))
19{
20 render = false;
21
22 MapDrawBG(xOff, yOff, 0, 0, WIDTH, HEIGHT);
23 DrawPlayer(player);
24
25 al_flip_display();
26 al_clear_to_color(al_map_rgb(0,0,0));
27}
the problem here is that when my player passes that certain pixel on the right, the entire screen continuously shifts until it hits the end of the map. I wanted something similar to most platformers, where after a certain point on the screen the camera jumps that much distance and no more Thanks everyone |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
Basic camera algorithm : int camerax = playerx - SCREEN_WIDTH/2; int cameray = playery - SCREEN_HEIGHT/2; if (camerax < 0) {camerax = 0;} if (camerax >= MAP_WIDTH - SCREEN_WIDTH) {camerax = MAP_WIDTH - SCREEN_WIDTH;} if (cameray < 0) {cameray = 0;} if (cameray >= MAP_HEIGHT - SCREEN_HEIGHT) {cameray = MAP_HEIGHT - SCREEN_HEIGHT;} Then you render everything at (x - camerax , y - cameray). My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
allegronewb
Member #13,942
January 2012
|
Thanks for the help. Just a question though, you said to render at (x - camerax, y- cameray). What is x and y? I tried using player.x - camerax, and that crashed immediately 1else if(ev.type == ALLEGRO_EVENT_TIMER)
2 {
3 /*
4 xOff += keys[RIGHT] * 4;
5 xOff -= keys[LEFT] * 10;
6 yOff += keys[DOWN] * 10;
7 yOff -= keys[UP] * 10;
8 */
9
10 player.x += keys[RIGHT] * 5;
11 player.x -= keys[LEFT] * 5;
12
13 camerax = player.x - WIDTH/2;
14 cameray = player.y - HEIGHT/2;
15
16 if (camerax < 0) {camerax = 0;}
17 if (camerax >= mapwidth*mapblockwidth - WIDTH) {camerax = mapwidth*mapblockwidth - WIDTH;}
18 if (cameray < 0) {cameray = 0;}
19 if (cameray >= mapheight*mapblockheight - HEIGHT) {cameray = mapheight*mapblockheight - HEIGHT;}
20
21 /*
22 if(xOff < 0)
23 xOff = 0;
24 if(yOff < 0)
25 yOff = 0;
26 if(xOff > (mapwidth*mapblockwidth - WIDTH))
27 xOff = mapwidth*mapblockwidth - WIDTH;
28 if(yOff > mapheight*mapblockheight - HEIGHT)
29 yOff = mapheight*mapblockheight - HEIGHT;
30 */
31
32 CollideBottomTiles(player);
33
34 render = true;
35 }
36
37 if(render && al_is_event_queue_empty(event_queue))
38 {
39 render = false;
40
41 MapDrawBG(camerax,cameray, 0, 0, WIDTH, HEIGHT);
42 DrawPlayer(player);
43
44 al_flip_display();
45 al_clear_to_color(al_map_rgb(0,0,0));
46 }
|
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
Forgot to say you draw the world at (-camerax , -cameray). As to why it crashes, I don't know. Use a debugger. Or show more code. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
allegronewb
Member #13,942
January 2012
|
Thanks for the help. Unfortunately I still can't get it to work I tried the (-camerax, -cameray), but my Player and the screen were moving incorrectly in the opposite directions. Your algorithm helped a ton, but my issue is speed I think. Whats happening is that my player moves to the right of the screen (and eventually off of it) much quicker than the screen gets to adjust to his place. 1const int WIDTH = 800;
2const int HEIGHT = 600;
3
4bool keys[] = {false, false, false, false};
5enum KEYS{UP, DOWN, LEFT, RIGHT};
6
7struct Player
8{
9 int x;
10 int y;
11
12 int bx;
13 int by;
14};
15
16void InitPlayer(Player &player, int x, int y, int bx, int by);
17void DrawPlayer(Player &player);
18int main(void)
19{
20 //variables
21 bool done = false;
22 bool render = false;
23
24 int xOff = 0;
25 int yOff = 0;
26
27 int camerax;
28 int cameray;
29
30 Player player;
31
32 InitPlayer(player, 400, 300, 16, 16);
33
34
35 //allegro variable
36 ALLEGRO_DISPLAY *display = NULL;
37 ALLEGRO_EVENT_QUEUE *event_queue = NULL;
38 ALLEGRO_TIMER *timer;
39
40 //program init
41 if(!al_init()) //initialize Allegro
42 return -1;
43
44 display = al_create_display(WIDTH, HEIGHT); //create our display object
45
46 if(!display) //test display object
47 return -1;
48
49 //addon init
50 al_install_keyboard();
51 al_init_image_addon();
52 al_init_font_addon();
53 al_init_ttf_addon();
54 al_init_primitives_addon();
55
56 if(MapLoad("map2.FMP", 1))
57 return -5;
58
59 event_queue = al_create_event_queue();
60 timer = al_create_timer(1.0 / 60);
61
62 al_register_event_source(event_queue, al_get_timer_event_source(timer));
63 al_register_event_source(event_queue, al_get_keyboard_event_source());
64
65 al_start_timer(timer);
66 while(!done)
67 {
68 ALLEGRO_EVENT ev;
69 al_wait_for_event(event_queue, &ev);
70
71 if(ev.type == ALLEGRO_EVENT_KEY_DOWN)
72 {
73 switch(ev.keyboard.keycode)
74 {
75 case ALLEGRO_KEY_ESCAPE:
76 done = true;
77 break;
78 case ALLEGRO_KEY_LEFT:
79 keys[LEFT] = true;
80 break;
81 case ALLEGRO_KEY_RIGHT:
82 keys[RIGHT] = true;
83 break;
84 case ALLEGRO_KEY_UP:
85 keys[UP] = true;
86 break;
87 case ALLEGRO_KEY_DOWN:
88 keys[DOWN] = true;
89 break;
90 }
91 }
92 else if(ev.type == ALLEGRO_EVENT_KEY_UP)
93 {
94 switch(ev.keyboard.keycode)
95 {
96 case ALLEGRO_KEY_ESCAPE:
97 done = true;
98 break;
99 case ALLEGRO_KEY_LEFT:
100 keys[LEFT] = false;
101 break;
102 case ALLEGRO_KEY_RIGHT:
103 keys[RIGHT] = false;
104 break;
105 case ALLEGRO_KEY_UP:
106 keys[UP] = false;
107 break;
108 case ALLEGRO_KEY_DOWN:
109 keys[DOWN] = false;
110 break;
111 }
112 }
113 else if(ev.type == ALLEGRO_EVENT_TIMER)
114 {
115 player.x += keys[RIGHT] * 5;
116 player.x -= keys[LEFT] * 5;
117
118 camerax = player.x - WIDTH/2;
119 cameray = player.y - HEIGHT/2;
120
121 if (camerax < 0) {camerax = 0;}
122 if (camerax >= mapwidth*mapblockwidth - WIDTH) {camerax = mapwidth*mapblockwidth - WIDTH;}
123 if (cameray < 0) {cameray = 0;}
124 if (cameray >= mapheight*mapblockheight - HEIGHT) {cameray = mapheight*mapblockheight - HEIGHT;}
125
126 render = true;
127 }
128
129 if(render && al_is_event_queue_empty(event_queue))
130 {
131 render = false;
132
133 MapDrawBG(-camerax,-cameray, 0, 0, WIDTH, HEIGHT);
134 DrawPlayer(player);
135
136 al_flip_display();
137 al_clear_to_color(al_map_rgb(0,0,0));
138 }
139 }
140
141 MapFreeMem();
142 al_destroy_event_queue(event_queue);
143 al_destroy_display(display); //destroy our display object
144
145 return 0;
146}
147
148void InitPlayer(Player &player, int x, int y, int bx, int by)
149{
150 player.x = x;
151 player.y = y;
152 player.bx = bx;
153 player.by = by;
154}
155void DrawPlayer(Player &player)
156{
157 al_draw_filled_rectangle(player.x - player.bx, player.y - player.by, player.x + player.bx, player.y + player.by,
158 al_map_rgb(0,0,255));
159}
|
gnolam
Member #2,030
March 2002
![]() |
Edgar: don't teach him to abuse C's whitespace rules like that. Bad: Good: if ((foo || bar) && frotz) { // Much more readable! fnord = baz; }
-- |
Mark Oates
Member #1,146
March 2001
![]() |
allegronewb, You should look into using the ALLEGRO_TRANSFORMs as a camera. Something as simple as this will work nicely: ALLEGRO_TRANSFORM camera_transform; ALLEGRO_STATE previous_state; al_store_state(&previous_state, ALLEGRO_STATE_TRANSFORM); al_build_transform(&camera_transform, -camera_x+SCREEN_W/2, -camera_y+SCREEN_H/2, 1, 1, 0); al_use_transform(&camera_transform); // draw all your world's stuff here, in regular world coordinates // ... al_restore_state(&previous_state); If you then set the camera_x and camera_y to your player's coordinates, it will follow him. (I didn't test the above code, but it should work). -- |
Arthur Kalliokoski
Second in Command
February 2005
![]() |
gnolam said: if ((foo || bar) && frotz) fnord = baz; // Where does the if statement end? I don't have trouble reading it, but if you're stepping through the code with a debugger you can't see intermediate results. They all watch too much MSNBC... they get ideas. |
allegronewb
Member #13,942
January 2012
|
I feel like an idiot here but I'm still not getting it working. I feel like everything is working at its barebones, but my Player still moves too fast for the Screen. Player ends up going off the screen by the time the screen catches up. |
Mark Oates
Member #1,146
March 2001
![]() |
Could you attach the all of your code (and the files)? -- |
allegronewb
Member #13,942
January 2012
|
Of course! Thanks. Also, I want to thank everyone else for contributing, seriously. I used to be a math tutor and would often get frustrated if someone didn't understand a topic quick enough (Didn't say I was a good tutor haha) but thanks for bearing with me. Everything is inside the main.cpp, but to compile you would also need the the .c and the .h files I have attached. Also the image file I have attached from Mappy. Thanks again |
Mark Oates
Member #1,146
March 2001
![]() |
The easiest solution is to render your player (DrawPlayer()) relative to the camera: void DrawPlayer(Player &player, float camerax, float cameray) { al_draw_filled_rectangle(player.x - player.bx - camerax, player.y - player.by - cameray, player.x + player.bx - camerax, player.y + player.by - cameray, al_map_rgb(0,0,255)); } A more complex solution would involve an ALLEGRO_TRANSFORM as a camera but things could get a little strange since you're using the MapDrawBG for offsets and clipping, so I would just do the above. -- |
allegronewb
Member #13,942
January 2012
|
Wow...that's perfect. Just put it into the code and it works like a charm. Definitely going to study it a little bit more to see what I was doing it wrong. Thanks a lot, everyone |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
gnolam said:
Edgar: don't teach him to abuse C's whitespace rules like that. Meh. I was being lazy and using forum type. And yeah, it makes it a bitch to debug. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
|