How to add a game over? If you are not familiar with the Doodle Jump game, it is where a character will need to bounce off a platform to progress. But if the player doesnt land on the platform, the game is over.
But in my case, even if I dont land on a platform, the game still continues.
`
#include <SFML/Graphics.hpp>
#include <time.h>
using namespace sf;
struct point
{
int x, y;
};
int main()
{
srand(time(0));
RenderWindow app(VideoMode(400, 533), "Doodle Game!");
app.setFramerateLimit(60);
Texture t1, t2, t3;
t1.loadFromFile("C:/Users/Dani/Documents/GAMES SFML/16_Games/02 Doodle Jump/images/background.png");
t2.loadFromFile("C:/Users/Dani/Documents/GAMES SFML/16_Games/02 Doodle Jump/images/platform.png");
t3.loadFromFile("C:/Users/Dani/Documents/GAMES SFML/16_Games/02 Doodle Jump/images/mark.png");
Sprite sBackground(t1), sPlat(t2), sPers(t3);
point plat[20];
for (int i = 0; i < 10; i++)
{
plat[i].x = rand() % 400;
plat[i].y = rand() % 533;
}
int x = 100, y = 100, h = 200;
float dx = 0, dy = 0;
while (app.isOpen())
{
Event e;
while (app.pollEvent(e))
{
if (e.type == Event::Closed)
app.close();
}
if (Keyboard::isKeyPressed(Keyboard::Right)) x += 3;
if (Keyboard::isKeyPressed(Keyboard::Left)) x -= 3;
dy += 0.2;
y += dy;
if (y > 500) dy = -10;
if (y < h)
for (int i = 0; i < 10; i++)
{
y = h;
plat[i].y = plat[i].y - dy;
if (plat[i].y > 533) { plat[i].y = 0; plat[i].x = rand() % 400; }
}
for (int i = 0; i < 10; i++)
if ((x + 50 > plat[i].x) && (x + 20 < plat[i].x + 68)
&& (y + 70 > plat[i].y) && (y + 70 < plat[i].y + 14) && (dy > 0)) dy = -10;
sPers.setPosition(x, y);
app.draw(sBackground);
app.draw(sPers);
for (int i = 0; i < 10; i++)
{
sPlat.setPosition(plat[i].x, plat[i].y);
app.draw(sPlat);
}
app.display();
}
return 0;
}
`
Thank you, all of your answers will be appreciated.
I managed with some help to know how when two rectangles are intersecting each other, from there it should be easy to make what i just said in the title but ...
So, short story of what i just did below:
Created a for loop from 1 to Number_of_Obstacles
In that for an random obstacle (rectangle/square) is created and it will be checked if it is overlaped with all other obstacles created from 0 to the loop contor (or in other words every obstacle stored in the vector)
Again, the doOverLap function works. Tested it with a square which i made a controller and other random rectangle created on the screen. It outputs in chat when i'm overlaping it and trust me, i overlaped it from all angles.
Here is a picture with the overlaping issue: https://imgur.com/a/ZzorOcD
bool doOverlap(A a, B b)
{
if (a.x1 > b.x2 || b.x1 > a.x2)
return false;
if (a.y1 > b.y2 || b.y1 > a.y2)
return false;
return true;
}
struct Obstacles {
int X, Y;
void Create_Random_Obstacles(Obstacles Obj[], int Numar_Obstacole)
{
srand(time(NULL));
A Rectangle_1;
B Rectangle_2;
/* To avoid rendering outside of the screen */
int X_Axis = X_RESOLUTION - 40;
int Y_Axis = Y_RESOLUTION - 40;
int obstacolX = rand() % X_Axis + 1;
int obstacolY = rand() % Y_Axis + 1;
Obj[0].X = obstacolX;
Obj[0].Y = obstacolY;
for (int i = 1; i < Numar_Obstacole; i++)
{
obstacolX = rand() % X_Axis + 1;
obstacolY = rand() % Y_Axis + 1;
Rectangle_1.x1 = obstacolX;
Rectangle_1.x2 = obstacolX + 40;
Rectangle_1.y1 = obstacolY;
Rectangle_1.y2 = obstacolY + 40;
for (int j = 0; j < i; j++) {
Rectangle_2.x1 = Obj[j].X;
Rectangle_2.x2 = Obj[j].X + 40;
Rectangle_2.y1 = Obj[j].Y;
Rectangle_2.y2 = Obj[j].Y + 40;
if (doOverlap(Rectangle_1, Rectangle_2))
{
std::cout << "Overlap\n";
}
else
{
Obj[i].X = obstacolX;
Obj[i].Y = obstacolY;
}
}
}
}
void Render(SDL_Renderer* renderer, Obstacles Obj[], int Numar_Obstacole) {
for (int i = 0; i < Numar_Obstacole; i++)
{
SDL_Rect r{ Obj[i].X, Obj[i].Y, 40, 40 };
SDL_SetRenderDrawColor(renderer, 255, 160, 15, 255);
SDL_RenderFillRect(renderer, &r);
}
}
};
Restart selection when collision occurs, something like:
bool Has_Overlap(const Obstacles& obj, const Obstacles* Objs, int Size)
{
B Rectangle_2;
Rectangle_2.x1 = obs.X;
Rectangle_2.x2 = obs.X + 40;
Rectangle_2.y1 = obs.Y;
Rectangle_2.y2 = obs.Y + 40;
for (int i = 0; i != Size; ++i) {
A Rectangle_1;
Rectangle_1.x1 = Obs[i].X;
Rectangle_1.x2 = Obs[i].X + 40;
Rectangle_1.y1 = Obs[i].Y;
Rectangle_1.y2 = Obs[i].Y + 40;
if (doOverlap(Rectangle_1, Rectangle_2)) {
return true;
}
}
return false;
}
void Create_Random_Obstacles(Obstacles* Objs, int Size)
{
/* To avoid rendering outside of the screen */
const int X_Axis = X_RESOLUTION - 40;
const int Y_Axis = Y_RESOLUTION - 40;
for (int i = 0; i < Size; i++)
{
do {
Objs[i].X = rand() % X_Axis + 1;
Objs[i].Y = rand() % Y_Axis + 1;
} while (Has_Overlap(Objs[i], Objs, i));
}
}
I'm currently trying to write a menu function for one of my projects. I'm remaking pac-man and I'd like to be able to modularize the main menu, calling it when I want it to appear. I'm thinking an SDL_surface and a TTF font are all I need as parameters for this particular function.
I ran into trouble when I used SDL functions only available in SDL 1.2 as opposed to 2.0. I would like this code to be as reusable as possible. How would you guys approach this problem? I have some sample code below, though not all of it is my own. I'd like to get something like this working:
int showmenu(SDL_Surface* screen, TTF_Font* font)
{
Uint32 time;
int x, y;
const int NUMMENU = 2;
const char* labels[NUMMENU] = {"Continue","Exit"};
SDL_Surface* menus[NUMMENU];
bool selected[NUMMENU] = {0,0};
SDL_Color color[2] = {{255,255,255},{255,0,0}};
menus[0] = TTF_RenderText_Solid(font,labels[0],color[0]);
menus[1] = TTF_RenderText_Solid(font,labels[1],color[0]);
SDL_Rect pos[NUMMENU];
pos[0].x = screen->clip_rect.w/2 - menus[0]->clip_rect.w/2;
pos[0].y = screen->clip_rect.h/2 - menus[0]->clip_rect.h;
pos[1].x = screen->clip_rect.w/2 - menus[0]->clip_rect.w/2;
pos[1].y = screen->clip_rect.h/2 + menus[0]->clip_rect.h;
SDL_FillRect(screen,&screen>clip_rect,SDL_MapRGB(screen>format,0x00,0x00,0x00));
SDL_Event event;
while(1)
{
time = SDL_GetTicks();
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_QUIT:
SDL_FreeSurface(menus[0]);
SDL_FreeSurface(menus[1]);
return 1;
case SDL_MOUSEMOTION:
x = event.motion.x;
y = event.motion.y;
for(int i = 0; i < NUMMENU; i += 1)
{
if(x >= pos[i].x && x <= pos[i].x + pos[i].w &&
y >= pos[i].y && y <= pos[i].y + pos[i].h)
{
if(!selected[i])
{
selected[i] = 1;
SDL_FreeSurface(menus[i]);
menus[i] = TTF_RenderText_Solid(font,labels[i],color[1]);
}
}
else
{
if(selected[i])
{
selected[i] = 0;
SDL_FreeSurface(menus[i]);
menus[i] = TTF_RenderText_Solid(font,labels[i],color[0]);
}
}
}
break;
case SDL_MOUSEBUTTONDOWN:
x = event.button.x;
y = event.button.y;
for(int i = 0; i < NUMMENU; i += 1)
{
if(x >= pos[i].x && x <= pos[i].x + pos[i].w &&
y >= pos[i].y && y <= pos[i].y + pos[i].h)
{
SDL_FreeSurface(menus[0]);
SDL_FreeSurface(menus[1]);
return i;
}
}
break;
case SDL_KEYDOWN:
if(event.key.keysym.sym == SDLK_ESCAPE)
{
SDL_FreeSurface(menus[0]);
SDL_FreeSurface(menus[1]);
return 0;
}
}
}
for(int i = 0; i < NUMMENU; i += 1)
{
SDL_BlitSurface(menus[i],NULL,screen,&pos[i]);
}
}
}
I do school project on basis of Atari Breakout. I do it in c++ using ALLEGRO 5 library. I don't know how to avoid one problem. When I compile my program i have flickering image on my program and the ball is going too slow. I was trying to change FPS but it still doesn't work properly.
Main loop is collecting informations about position of mouse (paddle), position of ball and bricks left. Than it should print it smoothly on the screen. Do you have any ideas, what i did wrong?
Here is my code:
#include <allegro5/allegro.h>
#include <allegro5\allegro_native_dialog.h>
#include <allegro5/allegro_primitives.h>
#include <allegro5/allegro_font.h>
#include <allegro5/allegro_ttf.h>
#define BRICKS_HORIZONTALLY 10
#define BRICKS_VERTICALLY 5
#define BRICK_WIDTH 102
#define BRICK_HEIGHT 50
#define BRICK_GAP 2
#define PADDLE_WIDTH 100
#define PADDLE_HEIGHT 20
#define PADDLE_POSITION_Y (768-50)
ALLEGRO_DISPLAY *display = NULL;
ALLEGRO_EVENT_QUEUE *event_queue = NULL;
struct ball_typ {
int xv, yv;
int x, y;
};
int playerPaddleEdgeX;
ball_typ ball;
int bricks[BRICKS_VERTICALLY][BRICKS_HORIZONTALLY];
void makeScreenBlack() { //clead screen to black
al_clear_to_color(al_map_rgb(0, 0, 0));
al_flip_display();
}
void resetBricks() {
for (int i = 0; i<BRICKS_VERTICALLY; i++) {
for (int ii = 0; ii<BRICKS_HORIZONTALLY; ii++) {
bricks[i][ii] = 1;
}
}
}
int numberOfBricksRemaining() {
int numberOfBricksRemaining;
numberOfBricksRemaining = 0;
for (int i = 0; i<BRICKS_VERTICALLY; i++) {
for (int ii = 0; ii<BRICKS_HORIZONTALLY; ii++) {
if (bricks[i][ii] != 0) {
numberOfBricksRemaining++;
}
}
}
return numberOfBricksRemaining;
}
void drawingThings() {
makeScreenBlack();
// draw the bricks
for (int i = 0; i<BRICKS_VERTICALLY; i++) {
for (int ii = 0; ii<BRICKS_HORIZONTALLY; ii++) {
if (bricks[i][ii] != 0) {
al_draw_filled_rectangle(ii*BRICK_WIDTH, i*BRICK_HEIGHT,(ii + 1)*BRICK_WIDTH - BRICK_GAP, (i + 1)*BRICK_HEIGHT - BRICK_GAP, al_map_rgb(255, 0, 0));
}
}
}
// draw the ball
al_draw_filled_circle(ball.x, ball.y, 8, al_map_rgb(255, 255, 255));
// draw the player
al_draw_filled_rectangle(playerPaddleEdgeX, PADDLE_POSITION_Y,playerPaddleEdgeX + PADDLE_WIDTH, PADDLE_POSITION_Y + PADDLE_HEIGHT, al_map_rgb(255, 255, 255));
ALLEGRO_FONT *font = al_create_builtin_font();
al_draw_textf(font, al_map_rgb(0, 0, 0), 10, 10, 0, "Player Position (playerPaddleEdgeX is %i)", playerPaddleEdgeX);
al_draw_textf(font, al_map_rgb(0, 0, 0), 10, 20, 0, "ball (x,y) position is (%i, %i)", ball.x, ball.y);
}
void resetBall() {
ball.x = 1024 / 2;
ball.y = 768 / 2;
ball.xv = 4;
ball.yv = 2;
}
int doesOverlap(int objectX, int objectY,
int areaLeft, int areaTop,
int areaRight, int areaBottom) {
if (ball.x > areaLeft &&
ball.x < areaRight &&
ball.y > areaTop &&
ball.y < areaBottom) {
return 1; // 1 here means yes
}
return 0; // 0 here means no
}
void moveBall() {
// update the ball's position for the next frame
ball.x += ball.xv;
ball.y += ball.yv;
// if the ball is overlapping the rectangle
if (ball.yv > 0) { // only if the ball is moving down
if (doesOverlap(ball.x, ball.y,
playerPaddleEdgeX + (PADDLE_WIDTH*0.0),
PADDLE_POSITION_Y,
playerPaddleEdgeX + (PADDLE_WIDTH*0.25),
PADDLE_POSITION_Y + PADDLE_HEIGHT) == 1) {
ball.xv = -5;
ball.yv = -3;
}
if (doesOverlap(ball.x, ball.y,
playerPaddleEdgeX + (PADDLE_WIDTH*0.25),
PADDLE_POSITION_Y,
playerPaddleEdgeX + (PADDLE_WIDTH*0.5),
PADDLE_POSITION_Y + PADDLE_HEIGHT) == 1) {
ball.xv = -3;
ball.yv = -5;
}
if (doesOverlap(ball.x, ball.y,
playerPaddleEdgeX + (PADDLE_WIDTH*0.5),
PADDLE_POSITION_Y,
playerPaddleEdgeX + (PADDLE_WIDTH*0.75),
PADDLE_POSITION_Y + PADDLE_HEIGHT) == 1) {
ball.xv = 3;
ball.yv = -5;
}
if (doesOverlap(ball.x, ball.y,
playerPaddleEdgeX + (PADDLE_WIDTH*0.75),
PADDLE_POSITION_Y,
playerPaddleEdgeX + (PADDLE_WIDTH*1.0),
PADDLE_POSITION_Y + PADDLE_HEIGHT) == 1) {
ball.xv = 5;
ball.yv = -3;
}
}
for (int i = 0; i<BRICKS_VERTICALLY; i++) {
for (int ii = 0; ii<BRICKS_HORIZONTALLY; ii++) {
if (bricks[i][ii] != 0) { // is the brick still here?
if (doesOverlap(ball.x, ball.y,
ii*BRICK_WIDTH, i*BRICK_HEIGHT,
(ii + 1)*BRICK_WIDTH - BRICK_GAP,
(i + 1)*BRICK_HEIGHT - BRICK_GAP) == 1) {
// reverse ball's vertical direction
ball.yv = -ball.yv;
bricks[i][ii] = 0; // erase the brick
}
}
}
}
// bounce off edges of screen
if (ball.x > 1024) {
ball.xv = -ball.xv;
}
if (ball.x < 0) {
ball.xv = -ball.xv;
}
if (ball.y < 0) {
ball.yv = -ball.yv;
}
// but reset ball if it goes off bottom of screen
if (ball.y > 768) {
// lose!
ALLEGRO_MOUSE_STATE state;
al_get_mouse_state(&state);
if (state.buttons & 1) { //reappear ball
resetBall();
}
}
}
void updatePaddlePosition() {
// for now, put the player's paddle where the mouse is
int pos_x = 1024 / 2;
ALLEGRO_MOUSE_STATE state;
al_get_mouse_state(&state);
pos_x = state.x;
playerPaddleEdgeX = pos_x;
}
void gameSetup() {
resetBricks();
resetBall();
// start with the ball off the bottom of the screen
ball.y = 768 + 50;
}
int main() {
ALLEGRO_TIMER * timer = NULL;
int FPS = 60;
al_init(); // allegro initializing
al_init_font_addon();
al_init_primitives_addon();
if (!al_init()){ //check
al_show_native_message_box(NULL, NULL, NULL,
"failed to initialize allegro!", NULL, NULL);
return -1;
}
timer = al_create_timer(1.0 / FPS);
al_install_keyboard();
al_install_mouse();
event_queue = al_create_event_queue();
al_register_event_source(event_queue, al_get_mouse_event_source());
al_register_event_source(event_queue, al_get_timer_event_source(timer));
al_set_new_window_position(20, 30);
display = al_create_display(1024, 768);
if (!display){ //check
al_show_native_message_box(NULL, NULL, NULL,
"failed to initialize display!", NULL, NULL);
return -1;
}
makeScreenBlack();
updatePaddlePosition();
gameSetup();
ALLEGRO_KEYBOARD_STATE key;
al_start_timer(timer);
while (al_key_down(&key, ALLEGRO_KEY_ESCAPE)){
updatePaddlePosition();
moveBall();
if (numberOfBricksRemaining() == 0) {
resetBricks();
}
drawingThings();
al_flip_display();
al_rest(0.01);
}
al_destroy_display(display);
return 0;
}
You're calling al_flip_display twice. You should remove the call to al_flip_display in makeScreenBlack() and keep the other one.
I have multiple SDL_Rects creating a snake that is supposed to stay in a specific area. Sometimes when the "snake" reaches the boundaries a part disappears.
void Snake::update(SDL_Surface *screen, int level)
{
old_pos.first = snake_rect[0];
if(x_axis)
snake_rect[0].x += snake_speed * level * direction_multiplier;
else if(!x_axis)
snake_rect[0].y += snake_speed * level * direction_multiplier;
for(unsigned int i = 1; i < snake_rect.size(); ++i)
{
old_pos.second = snake_rect[i];
snake_rect[i] = old_pos.first;
old_pos.first = old_pos.second;
}
boundariesCheck(screen);
/// Making the enemy move randomly
if(rand() % 100 < 10)
{
if(x_axis)
{
x_axis = false;
direction.second = rand() % 2;
if(direction.second)
direction_multiplier = 1;
else if(!direction.second)
direction_multiplier = -1;
}
else if(!x_axis)
{
x_axis = true;
direction.first = rand() % 2;
if(direction.first)
direction_multiplier = 1;
else if(!direction.first)
direction_multiplier = -1;
}
}
}
void Snake::draw(SDL_Surface *screen)
{
for(unsigned int i = 1; i < snake_rect.size(); ++i)
{
SDL_FillRect(screen, &snake_rect[i], 0xFF0000);
}
SDL_FillRect(screen, &snake_rect[0], 0xFF5500);
}