I will never say no to someone who try to help me help myself... I know I keep making theses posts. Its just I have assignments due and I feels like my lectures are impossible to impress.
I will never say no to someone who try to help me help myself... I know I keep making theses posts. Its just I have assignments due and I feels like my lectures are impossible to impress.
Your program is beginning to look interesting. You should post the whole thing so I can run it.
I don't know what's causing your segfault but you're not drawing the message to the window before presenting it, so the message won't be displayed.
You need something like this after creating the message and before presenting the scene:
I would make your delay longer, too. 10ms delay means 100fps, which is pretty fast.Code:SDL_Rect offset = {300, 200, 0, 0}; // only x,y used SDL_BlitSurface(message, NULL, window, &offset);
Algorism... here is the full program. Its not finished. The idea of the game is to keep the ball from falling. There is no game over state right now so you cant lose.
The idea of the orange drop zones they will kill you if they hit the bat. The red zone drops a second ball and the green zones give you a extra life. most of that logic is not in the game yet as I was waiting until I have text working. Then I could update the score and numbers of lifes left.
I removed the TTF stuff so I could work on the automated testing. I can't get more than a 2.1 unless I include it. So make sure to run it without any arguments other wise it will go into test mode.
Code:#include <stdio.h> #include <SDL.h> #include <SDL_ttf.h> typedef struct { int score; int bbhold; int f1hold; } Game; typedef struct { int x; int y; } Bat; typedef struct { int x; int y; int conx; int cony; } Ball; int events(SDL_Window *window, Bat *bat){ int done = 0; SDL_Event event; while (SDL_PollEvent(&event)) { switch(event.type){ case SDL_WINDOWEVENT_CLOSE: { if (window){ SDL_DestroyWindow(window); window = NULL; done = 1; } } break; case SDL_KEYDOWN: { switch(event.key.keysym.sym) { case SDLK_ESCAPE: done = 1; break; } } break; case SDL_QUIT: done = 1; break; } } //left and right key detection const Uint8 *state = SDL_GetKeyboardState(NULL); if (state[SDL_SCANCODE_LEFT]) { bat->x = bat->x - 9; } if (state[SDL_SCANCODE_RIGHT]) { bat->x = bat->x + 9; } if (bat->x < 0) { bat->x = 0; } if (bat->x > 700) { bat->x = 700; } return done; } void bat_ren(SDL_Renderer *renderer, Bat *bat) { SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); SDL_Rect rect = {bat->x, 550, 100, 20}; SDL_RenderFillRect(renderer, &rect); } void mball (SDL_Renderer *renderer, Ball *balla, Bat *bat, Game *game, Ball *ballb, Ball *f1, Ball *f2){ SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); SDL_Rect rect = {balla->x, balla->y, 20, 20}; SDL_RenderFillRect(renderer, &rect); balla->x = balla->x + balla->conx; balla->y = balla->y + balla->cony; //wall colitions if (balla->x < 0) { balla->conx = balla->conx * -1; balla->x = 0; } if (balla->x > 800) { balla->conx = balla->conx * -1; balla->x = 800; } if (balla->y < 0) { balla->cony = balla->cony * -1; balla->y = 0; } if (balla->y > 600) { balla->cony = balla->cony * -1; balla->y = 600; } //bat collitons if ((balla->y > 550) && (balla->x >= bat->x) && (balla->x <= (bat->x + 100))) { balla->cony = balla->cony * -1; balla->y = 550; } //ball B logic if ((balla->y < 8) && (balla->x >= 350) && (balla->x <= 450) && game->bbhold > 1) { ballb->x = 100; ballb->y = 10; game->bbhold = 0; } //f1 logic if ((balla->x < 8) && (balla->y >= 100) && (balla->y <= 180)) { f1->x = 0; f1->y = 100; f2->x = 800; f2->y = 100; game->f1hold = 1; } if ((balla->x > 792) && (balla->y >= 100) && (balla->y <= 180)) { f1->x = 0; f1->y = 100; f2->x = 800; f2->y = 100; game->f1hold = 1; } } void bball (SDL_Renderer *renderer, Ball *ballb, Bat *bat, Game *game){ SDL_SetRenderDrawColor(renderer, 255, 0, 50, 255); SDL_Rect rect = {ballb->x, ballb->y, 20, 20}; SDL_RenderFillRect(renderer, &rect); ballb->x = ballb->x + ballb->conx; ballb->y = ballb->y + ballb->cony; //wall colitions if (ballb->x < 0) { ballb->conx = ballb->conx * -1; ballb->x = 0; } if (ballb->x > 800) { ballb->conx = ballb->conx * -1; ballb->x = 800; } if (ballb->y < 0) { ballb->cony = ballb->cony * -1; ballb->y = 0; } if (ballb->y > 600) { ballb->cony = ballb->cony * -1; ballb->y = 600; } //bat collitons if ((ballb->y > 550) && (ballb->x >= bat->x) && (ballb->x <= (bat->x + 100))) { ballb->cony = ballb->cony * -1; ballb->y = 550; game->bbhold++; } } void ballf1 (SDL_Renderer *renderer, Ball *f1, Bat *bat, Game *game){ SDL_SetRenderDrawColor(renderer, 255, 193, 0, 255); SDL_Rect rect = {f1->x, f1->y, 30, 30}; SDL_RenderFillRect(renderer, &rect); f1->x = f1->x + f1->conx; f1->y = f1->y + f1->cony; //wall colitions if (f1->x < 0) { f1->conx = f1->conx * -1; f1->x = 0; } if (f1->x > 800) { f1->conx = f1->conx * -1; f1->x = 800; } if (f1->y < 0) { f1->y = 0; } if (f1->y > 600) { f1->y = 600; } //end of ball if (f1->y == 600) { game->f1hold = 0; f1->x = 0; f1->y = 100; } //bat collitons if ((f1->y > 550) && (f1->x >= bat->x) && (f1->x <= (bat->x + 100))) { f1->y = 550; } } void ballf2 (SDL_Renderer *renderer, Ball *f2, Bat *bat, Game *game){ SDL_SetRenderDrawColor(renderer, 255, 193, 0, 255); SDL_Rect rect = {f2->x, f2->y, 30, 30}; SDL_RenderFillRect(renderer, &rect); f2->x = f2->x + f2->conx; f2->y = f2->y + f2->cony; //wall colitions if (f2->x < 0) { f2->conx = f2->conx * -1; f2->x = 0; } if (f2->x > 800) { f2->conx = f2->conx * -1; f2->x = 800; } if (f2->y < 0) { f2->y = 0; } if (f2->y > 600) { f2->y = 600; } //end of ball if (f2->y == 600) { game->f1hold = 0; f2->x = 800; f2->y = 100; } //bat collitons if ((f2->y > 550) && (f2->x >= bat->x) && (f2->x <= (bat->x + 100))) { f2->y = 550; } } void test(SDL_Window *window, SDL_Renderer *renderer, Ball *balla, Bat *bat, Game *game, Ball *ballb, Ball *f1, Ball *f2){ //printf("test working\n"); int test = 0; //bat wall collisions bat->x = -10; events(window, bat); if (bat->x == 0) { printf("bat left collisions test passed\n"); test++; } bat->x = 770; events(window, bat); if (bat->x == 700) { printf("bat right collisions test passed\n"); test++; } //mball wall collisions balla->conx = 7; balla->x = -10; mball(renderer, balla, bat, game, ballb, f1, f2); if (balla->conx == -7) { printf("Mball x left wall collisions test passed\n"); test++; } balla->conx = 7; balla->x = 870; mball(renderer, balla, bat, game, ballb, f1, f2); if (balla->conx == -7) { printf("Mball x right wall collisions test passed\n"); test++; } balla->cony = 7; balla->y = -10; mball(renderer, balla, bat, game, ballb, f1, f2); if (balla->cony == -7) { printf("Mball y up wall collisions test passed\n"); test++; } balla->cony = -7; balla->y = 601; mball(renderer, balla, bat, game, ballb, f1, f2); if (balla->cony == 7) { printf("Mball y down wall collisions test passed\n"); test++; } //mball bat collisions bat->x = 10; balla->y = 555; balla->x = 100; balla->cony = 7; mball(renderer, balla, bat, game, ballb, f1, f2); if (balla->cony == -7) { printf("Mball bat collisions test passed\n"); test++; } //Bball wall collisions ballb->conx = 7; ballb->x = -10; bball(renderer, ballb, bat, game); if (ballb->conx == -7) { printf("Bball x left wall collisions test passed\n"); test++; } ballb->conx = 7; ballb->x = 870; bball(renderer, ballb, bat, game); if (ballb->conx == -7) { printf("Bball x right wall collisions test passed\n"); test++; } ballb->cony = 7; ballb->y = -10; bball(renderer, ballb, bat, game); if (ballb->cony == -7) { printf("Bball y up wall collisions test passed\n"); test++; } ballb->cony = 7; ballb->y = 601; bball(renderer, ballb, bat, game); if (ballb->cony == -7) { printf("Bball y down wall collisions test passed\n"); test++; } //Bball bat collisions bat->x = 10; ballb->y = 555; ballb->x = 100; ballb->cony = 7; bball(renderer, ballb, bat, game); if (ballb->cony == -7) { printf("Bball bat collisions test passed\n"); test++; } printf("Tests passed = %d\n", test); exit(0); } int main(int argc, char *argv[]){ int done = 0; Game game; game.score = 0; game.bbhold = 2; game.f1hold = 0; Bat bat; bat.x = 16; bat.y = 16; Ball balla; balla.x = 100; balla.y = 300; balla.conx = 7; balla.cony = 7; Ball ballb; ballb.x = 100; ballb.y = 10; ballb.conx = 2; ballb.cony = 3; Ball f1; f1.x = 0; f1.y = 100; f1.conx = 4; f1.cony = 4; Ball f2; f2.x = 800; f2.y = 100; f2.conx = 4; f2.cony = 4; //setup SDL_Window *window; SDL_Renderer *renderer; SDL_Init(SDL_INIT_VIDEO); window = SDL_CreateWindow( "Keep It UP!", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 800, 600, 0 ); renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); //end of setup //test function calls if (argc > 1) { test(window, renderer, &balla, &bat, &game, &ballb, &f1, &f2); } //main game loop while (!done) { done = events(window, &bat); //screen setup SDL_SetRenderDrawColor(renderer, 0, 0,255, 255); SDL_RenderClear(renderer); // ball b drop zone SDL_SetRenderDrawColor(renderer, 255, 0, 50, 255); SDL_Rect rect = {350, 0, 100, 7}; SDL_RenderFillRect(renderer, &rect); // fire ball drop zones SDL_SetRenderDrawColor(renderer, 255, 217, 0, 255); SDL_Rect rectf1 = {0, 100, 7, 80}; SDL_RenderFillRect(renderer, &rectf1); SDL_Rect rectf2 = {793, 100, 7, 80}; SDL_RenderFillRect(renderer, &rectf2); //set new life zones SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255); SDL_Rect rectg1 = {0, 250, 7, 50}; SDL_RenderFillRect(renderer, &rectg1); SDL_Rect rectg2 = {793, 250, 7, 50}; SDL_RenderFillRect(renderer, &rectg2); //main function calls bat_ren(renderer, &bat); mball(renderer, &balla, &bat, &game, &ballb, &f1, &f2); // ball b logic if (game.bbhold < 2) { bball(renderer, &ballb, &bat, &game); } //f ball logic if (game.f1hold > 0) { ballf1(renderer, &f1, &bat, &game); ballf2(renderer, &f2, &bat, &game); } //render objects SDL_RenderPresent(renderer); SDL_Delay(10); } SDL_DestroyWindow(window); SDL_DestroyRenderer(renderer); SDL_Quit(); return 0; }
Seems to work pretty well. I'm not sure what it's supposed to do, though.
I assume the forum is adding the double-spacing!
You do a lot of this:
It is more idiomatic, easier to read and less error prone to write:Code:ballb->conx = ballb->conx * -1;
You should remove exit(0) from the end of test() and jump to the cleanup code at the end of main after test() returns.Code:ballb->conx *= -1;
A helper function or two cleans up main a little:
I tried to put the font stuff in there. You need to put in the correct font file name. It doesn't actually work for me. TTF_OpenFont fails with "Couldn't load font file", which means that it was able to find the file but it couldn't "load" it.Code:void renderFillRect(SDL_Renderer *rend, int x, int y, int w, int h) { SDL_Rect rect = {x, y, w, h}; SDL_RenderFillRect(rend, &rect); } void err(const char *msg) { fprintf(stderr, "Error: %s: %s\n", msg, SDL_GetError()); } void err_ttf(const char *msg) { fprintf(stderr, "Error: %s: %s\n", msg, TTF_GetError()); } int main(int argc, char *argv[]){ Game game = {0, 2, 0}; // score, bbhold, f1hold Bat bat = {16, 16}; // x, y Ball balla = {100, 300, 7, 7}; // x, y, conx, cony Ball ballb = {100, 10, 2, 3}; Ball f1 = { 0, 100, 4, 4}; Ball f2 = {800, 100, 4, 4}; SDL_Window *window = NULL; SDL_Renderer *renderer = NULL; TTF_Font *times = NULL; if (TTF_Init() == -1) { err_ttf("TTF_Init"); return 1; } if (SDL_Init(SDL_INIT_VIDEO) != 0) { err("SDL_Init"); TTF_Quit(); return 1; } window = SDL_CreateWindow("Keep It UP!", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 800, 600, 0); if (!window) { err("SDL_CreateWindow"); goto CleanUp; } renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); if (!renderer) { err("SDL_CreateRenderer"); goto CleanUp; } times = TTF_OpenFont("/home/me/Downloads/Tinsnips.ttf", 16); if (!times) { err_ttf("TTF_OpenFont"); goto CleanUp; } SDL_Color white = {255, 255, 255}; //test function calls if (argc > 1) { test(window, renderer, &balla, &bat, &game, &ballb, &f1, &f2); goto CleanUp; } //main game loop while (!events(window, &bat)) { SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255); SDL_RenderClear(renderer); // ball b drop zone SDL_SetRenderDrawColor(renderer, 255, 0, 50, 255); renderFillRect(renderer, 350, 0, 100, 7); // fire ball drop zones SDL_SetRenderDrawColor(renderer, 255, 217, 0, 255); renderFillRect(renderer, 0, 100, 7, 80); renderFillRect(renderer, 793, 100, 7, 80); //set new life zones SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255); renderFillRect(renderer, 0, 250, 7, 50); renderFillRect(renderer, 793, 250, 7, 50); //main function calls bat_ren(renderer, &bat); mball(renderer, &balla, &bat, &game, &ballb, &f1, &f2); // ball b logic if (game.bbhold < 2) bball(renderer, &ballb, &bat, &game); //f ball logic if (game.f1hold > 0) { ballf1(renderer, &f1, &bat, &game); ballf2(renderer, &f2, &bat, &game); } //ttf text SDL_Surface *message = TTF_RenderText_Solid(times, "Hello World", white); if (message == NULL) { err_ttf("TTF_RenderText_Solid"); goto CleanUp; } SDL_Rect offset = {300, 200, 0, 0}; // only x, y used SDL_BlitSurface(message, NULL, SDL_GetWindowSurface(window), &offset); //render objects SDL_RenderPresent(renderer); SDL_Delay(30); SDL_FreeSurface(message); } CleanUp: if (window) SDL_DestroyWindow(window); if (renderer) SDL_DestroyRenderer(renderer); if (times) TTF_CloseFont(times); TTF_Quit(); SDL_Quit(); return 0; }
Last edited by algorism; 11-26-2016 at 06:11 PM.
Thanks that looks so much cleaner.
Yeah I got the same error. I tried to load a font I had in the project folder but still no luck. I have no idea how to fix it.
I was able to get the text to display. It was linking with the wrong library. It should be: -lSDL2_ttf -lfreetype .
I'm using Ubuntu Linux. Are you using linux? Is it ubuntu?
-lSDL2_ttf wouldn't work at first.
I downloaded the SDL_ttf source, configured, built, and installed it (the usual process), but then I had to manually copy libSDL2_ttf.a to its installation directory (which for me was /usr/lib/x86_64-linux-gnu). Once that was done (and freetype was installed) it worked with the above libraries.
freetype was easy to install: sudo apt-get install libfreetype6-dev
I also wasn't displaying it correctly. Here's the updated main:
Code:int main(int argc, char *argv[]){ int ret = EXIT_FAILURE; Game game = {0, 2, 0}; // score, bbhold, f1hold Bat bat = {16, 16}; // x, y Ball balla = {100, 300, 7, 7}; // x, y, conx, cony Ball ballb = {100, 10, 2, 3}; Ball f1 = { 0, 100, 4, 4}; Ball f2 = {800, 100, 4, 4}; SDL_Window *window = NULL; SDL_Renderer *renderer = NULL; TTF_Font *times = NULL; if (SDL_Init(SDL_INIT_VIDEO) != 0) { err("SDL_Init"); goto CleanUp; } atexit(SDL_Quit); if (TTF_Init() == -1) { err_ttf("TTF_Init"); goto CleanUp; } atexit(TTF_Quit); window = SDL_CreateWindow("Keep It UP!", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 800, 600, 0); if (!window) { err("SDL_CreateWindow"); goto CleanUp; } renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); if (!renderer) { err("SDL_CreateRenderer"); goto CleanUp; } times = TTF_OpenFont("Tinsnips.ttf", 30); // ttf file in executable's dir if (!times) { err_ttf("TTF_OpenFont"); goto CleanUp; } SDL_Color white = {255, 255, 255}; //test function calls if (argc > 1) { test(window, renderer, &balla, &bat, &game, &ballb, &f1, &f2); goto CleanUp; } //ttf text SDL_Surface *message = TTF_RenderText_Solid(times, "Hello World", white); if (message == NULL) { err_ttf("TTF_RenderText_Solid"); goto CleanUp; } SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, message); if (texture == NULL) { err("SDL_CreateTextureFromSurface"); goto CleanUp; } SDL_Rect mess_rect = { 100, 100, message->w, message->h }; SDL_FreeSurface(message); //main game loop while (!events(window, &bat)) { SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255); SDL_RenderClear(renderer); // ball b drop zone SDL_SetRenderDrawColor(renderer, 255, 0, 50, 255); renderFillRect(renderer, 350, 0, 100, 7); // fire ball drop zones SDL_SetRenderDrawColor(renderer, 255, 217, 0, 255); renderFillRect(renderer, 0, 100, 7, 80); renderFillRect(renderer, 793, 100, 7, 80); //set new life zones SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255); renderFillRect(renderer, 0, 250, 7, 50); renderFillRect(renderer, 793, 250, 7, 50); //main function calls bat_ren(renderer, &bat); mball(renderer, &balla, &bat, &game, &ballb, &f1, &f2); // ball b logic if (game.bbhold < 2) bball(renderer, &ballb, &bat, &game); //f ball logic if (game.f1hold > 0) { ballf1(renderer, &f1, &bat, &game); ballf2(renderer, &f2, &bat, &game); } SDL_RenderCopyEx(renderer, texture, NULL, &mess_rect, 18, NULL, SDL_FLIP_NONE); // rotate 18 degrees //render objects SDL_RenderPresent(renderer); SDL_Delay(20); } ret = 0; CleanUp: if (window) SDL_DestroyWindow(window); if (renderer) SDL_DestroyRenderer(renderer); if (times) TTF_CloseFont(times); return ret; }
Last edited by algorism; 11-27-2016 at 11:44 AM.
I just realized that I screwed up when installing sdl ttf so the manual copying wasn't necessary.
Assuming linux, just download the source from:
https://www.libsdl.org/projects/SDL_ttf/
Extract it, open a terminal in that directory and type:
./configure
make all
make install
You may (or may not) also have to install freetype like this:
sudo apt-get install libfreetype6-dev
(It may be built and installed by the previous step, though.)
The includes at the top of the program should just be:
#include <stdio.h>
#include <SDL.h> // no SDL/ or SDL2/
#include <SDL_ttf.h> // ditto
My compile line:
gcc -std=c99 -Wall `sdl2-config --cflags` -o sdl04 sdl04.c \
`sdl2-config --libs` -lSDL2_ttf -lfreetype
where the sdl2-config calls yield:
$ echo `sdl2-config --cflags`
-I/usr/include/SDL2 -D_REENTRANT
$ echo `sdl2-config --libs`
-L/usr/lib/x86_64-linux-gnu -lSDL2
Algorism You are a legend!! Thanks!!