Reputation: 21
I have to write a clone of space invaders game for university in C language using SDL library for graphics.I am very new to C and programming in general so i struggle with it a lot. For now I have one row of enemies and I'm trying to make it move correctly. This are functions for movement of aliens, which check for the collision with right/left wall(which are SDL_Rects near window edges) and if it happens, enemies move one line lower in the opposite direction. The problem is it works okay for all ten enemies except the first one. Each time when collision with left wall occurs the first alien sort of moves away a bit from others instead of moving in one block as I want it to. I noticed that if I change the first for loop in move_aliens function to start from i=11 and i--, the same thing will happen to the enemy in last column. But I still dont know how to fix it. I would appreciate if someone could tell me what I'm doing wrong, give me an idea or sollution :). I uploaded a video of whats happening http://sendvid.com/dt1reizc
void move_down (GameState *game)
{
int i=0;
for(; i < HMALIENS; i++)
game->alien1[i].y += 25;
}
int collided(int a1, int b1, int a2, int b2, int width1,
int height1, int width2, int height2)
{
return (!((a1 > (a2+width2)) || (a2 > (a1+width1)) ||
(b1 > (b2+height2)) || (b2 > (b1+height1))));
}
void move_aliens(GameState *game)
{
int i=0;
for(; i < HMALIENS; i++)
{
if (game->alien1[i].dir==LEFT)
game->alien1[i].x -= 10;
if (game->alien1[i].dir==RIGHT)
game->alien1[i].x += 10;
if (collided(game->alien1[i].x, game->alien1[i].y,
game->leftwall.x, game->leftwall.y, 50, 50, 1, 600))
{
int i = 0;
for(; i < HMALIENS; i++)
game->alien1[i].dir=RIGHT;
move_down(game);
}
}
if(collided(game->alien1[i].x, game->alien1[i].y, game->rightwall.x,
game->rightwall.y, 50, 50, 1, 600))
{
int i = 0;
for(; i < HMALIENS; i++)
game->alien1[i].dir=LEFT;
move_down(game);
}
}
}
//edit HMALIENS is just a constant (11), the number of living enemies at the start GameState is a structure. LEFT/RIGHT stand for direction of movement (quite obvious) [enum Direction {LEFT, RIGHT};]. I have in my alien1 structure enum Direction dir and in the function which load_game function i set it to RIGHT.
typedef struct
{
Player player;
Rightwall rightwall;
Leftwall leftwall;
Alien1 alien1[HMALIENS];
SDL_Texture *bulet;
SDL_Texture *ship;
SDL_Texture *Alien1;
SDL_Renderer *renderer;
} GameState;
Upvotes: 1
Views: 2327
Reputation: 2184
typedef enum{
LEFT,
RIGHT
}GAME_DIRECTION;
int dir=LEFT;
#define SPRITE_WIDTH 50
#define SPRITE_HEIGHT 50
#define BOTTOM_LINE 600
void move_down (GameState *game)
{
int i;
for(i=0; i < HMALIENS; i++)
game->alien1[i].y += 25;
}
void do_slide(GameState *game)
{
int i;
for(i=0; i < HMALIENS; i++)
game->alien1[i].x += dir?10:-10;
}
int collided(GameState *game)
{
int i;
for(i=0; i < HMALIENS; i++){
if(
game->alien1[i].x <= game->leftwall.x ||
game->alien1[i].x >= game->rightwall.x +SPRITE_WIDTH ||
game->alien1[i].y >= BOTTOM_LINE - SPRITE_HEIGHT
)
return true;
}
return false;
}
void move_aliens(GameState *game)
{
if(collided(game)){
move_down (game);
dir=!dir; // update direction;
}else{
do_slide (game);
}
}
Upvotes: 1
Reputation: 5046
Maybe something like:
void move_aliens(GameState *game)
{
int i=0;
for(; i < HMALIENS; i++)
{
if (game->alien1[i].dir==LEFT)
game->alien1[i].x -= 10;
if (game->alien1[i].dir==RIGHT)
game->alien1[i].x += 10;
}
if (collided(
game->alien1[0].x, game->alien1[0].y,
game->leftwall.x, game->leftwall.y,
50, 50, 1, 600))
{
int i = 0;
for(; i < HMALIENS; i++)
game->alien1[i].dir=RIGHT;
move_down(game);
}
if(collided(
game->alien1[HMALIENS-1].x, game->alien1[HMALIENS-1].y,
game->rightwall.x, game->rightwall.y,
50, 50, 1, 600))
{
int i = 0;
for(; i < HMALIENS; i++)
game->alien1[i].dir=LEFT;
move_down(game);
}
}
I have tried to make the minimum changes. But @milevyo's more extensive rewrite looks good as well.
The problem, I think (just from looking), is you has the left collision test inside the loop so when that hits, the movement gets out of sync.
Also it was pretty subtle that the right collision test used i
from the previous loop which happens to index the last element (the rightmost alien). I changed that to explicitly use HMALIENS - 1
. When you start destroying aliens,
you'll have to track the first (leftmost) and last (rightmost) living aliens and use them for you collision tests.
Your indentation and formatting were a little off which makes the code much harder to read. Formatting is important, and will be even more so when your code gets more complicated.
Upvotes: 0
Reputation: 1680
Without rewriting your code, the problem is that you have already moved the first alien ([0]) left,
if (game->alien1[i].dir==LEFT)
game->alien1[i].x -= 10;
and then you are doing the collision test and flagging all of them to move right, but the loop continues with [1..10], while [0] has already moved.
Upvotes: 1