struct failed_flip : std::runtime_error {};void attempt_flip(SDL_Surface* screen) { if (SDL_Flip(screen) == -1) { throw failed_flip(); }}bool handle_arrows(const Keystate* keystates, Rect& player) { if (keystates[SDLK_LEFT]) { // Logic for handling screen collision belongs inside the object. // As does some encapsulation of the position data :) player.move(-STEP, 0); } if (keystates[SDLK_RIGHT]) { player.move(STEP, 0); } if (keystates[SDLK_UP]) { player.move(0, -STEP); } if (keystates[SDLK_DOWN]) { player.move(0, STEP); }}enum game_result { PLAYER_WINS, COMPUTER_WINS, STILL_GOING };game_result check_result() { // Instead of doing raw math for the ball/line ("end zone") collision, use the ball/rect collision code you already have. SDL_Rect computerTarget = {0, SCREEN_HEIGHT, SCREEN_WIDTH, 0}; SDL_Rect playerTarget = {0, 0, SCREEN_WIDTH, 0}; if (collision(ball.getOffset(), computerTarget)) { return COMPUTER_WINS; } if (collision(ball.getOffset(), humanTarget)) { return HUMAN_WINS; } return STILL_GOING;}void physics(Rect& player, Rect& computer, Sprite& ball) { AI(computer, ball); ball.move(); result = check_result(ball); // Again, the logic belongs inside the object. Accessor/mutator pairs are a bad code smell. if (ball.collideWith(player) || ball.collideWith(computer)) { // collideWith() calls the collision() code and does a changeDirectionOnCollision() if necessary. // There should be no need to .setDirectionY() explicitly; what is changeDirectionOnCollision() for, after all? ball.speedUp(); }}void applyRelativeToCenter(SDL_Surface* toApply, SDL_Surface* screen, int dx, int dy) { applySurface(dx + ((screen->w - toApply->w) / 2), dy + ((screen->h - toApply->h) / 2), toApply, screen);}void draw(Rect& player, Rect& computer, Sprite& ball) { applySurface(0, 0, background, screen); player.draw(); computer.draw(); // If the paddles know how to draw themselves, why shouldn't the ball? ball.draw(); if (result != STILL_GOING) { applyRelativeToCenter(message, screen, 0, 20); applyRelativeToCenter(result == COMPUTER_WINS ? youLoseMessage : youWinMessage, screen, 0, -20); } attempt_flip(screen);}bool gameloop(Rect& player, Rect& computer, Sprite& ball) { game_result result = STILL_GOING; attempt_flip(screen); Timer timer; // .start() in the constructor while (true) { if (!timer.ready()) { continue; } // again, the math belongs inside SDL_Event event; Keystate keystates[NUM_KEYS]; game_result result; while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: return false; case SDL_KEYDOWN: keystates[event.keysym] = true; break; case SDL_KEYUP: keystates[event.keysym] = false; break; } } if (keystates[SDLK_ESCAPE]) { return false; } handle_arrows(keystates, player); if ((result != STILL_GOING) && keystates[SDLK_RETURN]) { return true; } if (timer.running()) { // probably a better name physics(player, computer, ball); result = check_result(); } draw(player, computer, ball); }}int main(int argc, char *args[]) { // init() should set the random number seed, too... isn't that part of initialization? if (!init()) { return 1; } background = loadImage("background.jpg"); message = loadImage("play_again.jpg"); youWinMessage = loadImage("you_win.jpg"); youLoseMessage = loadImage("you_lose.jpg"); SDL_Rect bounds = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT}; Sprite ball(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, loadImage("ball.gif"), bounds); ball.setStep(BALL_SPEED); randomizeDirections(ball); Rect player(SCREEN_WIDTH / 2 - RECT_WIDTH / 2, SCREEN_HEIGHT - int(RECT_HEIGHT * 1.5), RECT_WIDTH, RECT_HEIGHT), computer(SCREEN_WIDTH / 2 - RECT_WIDTH / 2, int(RECT_HEIGHT * 1.5) - RECT_HEIGHT, RECT_WIDTH, RECT_HEIGHT); player.setColor(rand() % 256, rand() % 256, rand() % 256); computer.setColor(rand() % 256, rand() % 256, rand() % 256); // Use an outer loop to control requests to play repeatedly. int result = 0; try { while (play(player, computer, ball)) {} SDL_Quit(); } catch (failed_flip&) { result = 1; } cleanup(); return result;}
Code mess
A few suggestions. By no means did I find everything. :)
if(SDL_Init(SDL_INIT_EVERYTHING) == -1) { throw std::runtime_error; }
'std::runtime_error' : illegal use of this type as an expression
(I included its header file) (stdexcept)
What's wrong here?
The error is telling you that the type name 'std::runtime_error' does not qualify as an expression (portion of a statement that would evaluate to a value). It's analogous to:
Anyway, please study the example carefully. There are more changes illustrated than I could easily explain in words :)
// throw int; <-- not valid; what value of int would you like to throw exactly?throw 42; // valid, although poor style (please only throw instances of classes derived from std::exception)
Anyway, please study the example carefully. There are more changes illustrated than I could easily explain in words :)
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement