From: Nils Forssén Date: Thu, 9 Nov 2023 13:00:02 +0000 (+0100) Subject: Added UML code skeleton X-Git-Url: https://gitweb.forssennils.se/?a=commitdiff_plain;h=c3291fb01abfe1c63c79ba597f298aa12d084ef4;p=TDDC76_proj.git Added UML code skeleton --- diff --git a/src/Autonomous_object.cc b/src/Autonomous_object.cc new file mode 100644 index 0000000..e69de29 diff --git a/src/Autonomous_object.h b/src/Autonomous_object.h new file mode 100644 index 0000000..e69de29 diff --git a/src/Ball.cc b/src/Ball.cc deleted file mode 100644 index edcfbcf..0000000 --- a/src/Ball.cc +++ /dev/null @@ -1,101 +0,0 @@ -#include "Ball.h" - -#include -#include - -using namespace std; - -/* - * One way to create variables, functions and classes - * which are only visible in one file is by using an - * anonymous namespace (that is, a namespace which - * has no name). - * - * This will ensure that no other file will get - * access to these variables. - */ -namespace -{ - /* - * an engine which generates random numbers - */ - random_device rd { }; - - /* - * wrappers which defines various ranges - * we want to generate numbers in. - */ - - // used to randomly choose what sprite to use - uniform_int_distribution index { 0, 1 }; - - // randomly choose a radius - uniform_real_distribution radius { 10, 50 }; - - // randomly choose a velocity direction - uniform_real_distribution angle { 0, 2*3.14 }; - - // randomly choose a speed for our ball - uniform_real_distribution length { 0.5, 8.0 }; -} - -/* - * This constructor uses some basic trigonometry - * to create a velocity vector. - */ -//Ball :: Ball (Spritesheet & sheet, -// float x, -// float y) -// : sprite { sheet.get_sprite (0, index (rd)) }, -// velocity { } -//{ -// float direction { angle (rd) }; -// float speed { length (rd) }; -// -// velocity = sf::Vector2f { speed * cos (direction), -// speed * sin (direction) }; -// -// /* position the ball, and make sure that we place -// * the center of the ball where the mouse clicked */ -// auto sprite_size { sheet.sprite_size () }; -// sprite.setPosition (x, y); -// sprite.setOrigin (sprite_size.x / 2, sprite_size.y / 2); -//} - -Ball :: Ball (float x, - float y) - : - sprite{radius(rd)}, velocity { } -{ - float direction { angle (rd) }; - float speed { length (rd) }; - - velocity = sf::Vector2f { speed * cos (direction), - speed * sin (direction) }; - - /* position the ball, and make sure that we place - * the center of the ball where the mouse clicked */ - - // Create a sprite - float sprite_size { sprite.getRadius () }; - sprite.setPosition (x, y); - sprite.setOrigin (sprite_size / 2, sprite_size / 2); -} - -void Ball :: update () -{ - // move the sprite according to the velocity - sprite.move (velocity); -} - -void Ball :: render (sf::RenderTarget & target) -{ - // draw the sprite - target.draw (sprite); -} - -sf::FloatRect Ball :: bounds () const -{ - // get the hitbox of the sprite - return sprite.getGlobalBounds (); -} diff --git a/src/Ball.h b/src/Ball.h deleted file mode 100644 index efa71ad..0000000 --- a/src/Ball.h +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include - -/* - * Class representing a moving ball on the screen. - * - * This class serves as a demonstration of a moving - * object. - */ -class Ball -{ - -public: - - /* - * Create a ball and place it at the supplied coordinates. - */ - Ball( float x, float y); - /* - * This function contains all logic that needs - * to be run for the ball each iteration in the - * game loop. - */ - void update (); - - /* - * draw the ball to 'target' - */ - void render (sf::RenderTarget & target); - - /* - * Get a rectangle which covers the ball - * completly (a hitbox) - */ - sf::FloatRect bounds () const; - -private: - - // graphical representation of the ball - sf::CircleShape sprite; - - - // the velocity (speed + direction) in - // which this ball is moving - sf::Vector2f velocity; - -}; diff --git a/src/Bike_enemy.cc b/src/Bike_enemy.cc new file mode 100644 index 0000000..e69de29 diff --git a/src/Bike_enemy.h b/src/Bike_enemy.h new file mode 100644 index 0000000..e69de29 diff --git a/src/Bottle.cc b/src/Bottle.cc new file mode 100644 index 0000000..e69de29 diff --git a/src/Bottle.h b/src/Bottle.h new file mode 100644 index 0000000..e69de29 diff --git a/src/Game.cc b/src/Game.cc index f40f3d9..e69de29 100644 --- a/src/Game.cc +++ b/src/Game.cc @@ -1,128 +0,0 @@ -#include "constants.h" -#include "Game.h" -#include "Menu_State.h" -#include "Game_State.h" - -using namespace sf; - -/* - * Initialize the window and the first state is Menu_State. - * - * The constructor of RenderWindow takes a 'VideoMode' - * which defines the width, height and bits per pixel - * (default 32), a title which should be visible in - * the titlebar of the windows, as well as a style flag. - * The style flag is a bit mask (i.e. a value where - * each bit represents a property) of properties we - * want our window to have. If we do not care, - * we can omitt this argument or use sf::Style::Default. - */ -Game :: Game (std::string const & title, - unsigned width, - unsigned height) - : window { VideoMode { width, height }, - title, Style::Titlebar | Style::Close }, - current_state{ MENU_STATE }, - running { true } -{ - // Insert all sates you want in your game in the states map - states.insert(std::pair>({MENU_STATE, - std::make_unique()})); - - states.insert(std::pair>({GAME_STATE, - std::make_unique()})); -} - - -void Game :: start () -{ - // The clock is used to measure of long each iteration took - // this is used to keep the framerate as steady as possible. - Clock clock { }; - while ( running ) - { - // Handle user events e.g. mouse click or key pressed - handle_events(); - - // Let the current state do its update - states.at(current_state) -> update(); - - /* - * clear fills the entire window with one color - * (by default black) thus overwriting everything - * that was drawn before. - * - * If we do not perform this step we allow for weird - * graphical artifacts to show up. - */ - window.clear (); - - // let the current state render itself onto the window - states.at(current_state) -> render(window); - - /* - * No drawn pixels will be shown in the window - * until this function is called. - * - * All drawing operations are performed on a - * hidden buffer in memory, so if we want them - * to actually show up on the screen we have - * make sure that the window switches to drawing - * that buffer instead of its current one. - * (This technique is called 'double buffering') - */ - window.display (); - - /* - * When all logic and rendering has been performed - * we are now ready to update the current_state - */ - current_state = states.at(current_state) -> get_next_state(); - - /* - * Wait if we still haven't reached the target - * time for a frame. - */ - delay (clock); - } -} - - -void Game :: handle_events () -{ - /* - * event is an object which contains all - * relevant information for an event that - * occured in the window (i.e. key-pressed, - * mouse clicks etc.). - * - * The function 'pollEvent' takes the next - * event in the event queue and places it - * in the 'event' variable so that we can - * read what that event was. - * - * While there are events in event queue - * 'pollEvent' will return true. - */ - Event event; - while ( window.pollEvent (event) ) - { - // Check if the window has been closed. - // This event fires whenever the user - // presses the X icon, or if the operating - // system kills it. - if ( event.type == Event::Closed ) - running = false; - - // send the event to 'state' - states.at(current_state) -> handle_event (event); - } -} - -void Game :: delay (sf::Clock & clock) const -{ - sleep (milliseconds (1000.0 / fps) - clock.getElapsedTime ()); - clock.restart (); -} diff --git a/src/Game.h b/src/Game.h index baac0e2..e69de29 100644 --- a/src/Game.h +++ b/src/Game.h @@ -1,96 +0,0 @@ -#ifndef GAME_H -#define GAME_H - -#include - -#include -#include - -#include "State.h" - -class Game { - -public: - - /* - * Constructor of Game. - * - * Will perform these tasks: - * - initialize the current_state with an initial state (welcome - * screen), - * - Fill the states map with the States needed during the game - * - spawn a window with the specified titlebar, width and height - * (in pixels) - */ - Game (std::string const & title, unsigned width, unsigned height); - - /* - * Run the main loop of the state machine, and therefore by extension - * the entire game. - * - * Each iteration of the main loop go through these steps: - * - Handle all window events from the event queue (these include - * key presses/releases, mouse movement, resizing of the window - * and more). - * - * What this means is that we check if the user has requested - * to close the window and therefore the game, and for any other - * events we pass them on to the state. - * - Update the current state. - * - * This means running any logic that the state might have, for - * example; move objects, check for collision, manage resources - * etc. This step will probably perform the vast majority of the - * logic in the project (depending on the project of course). - * - * - Draw the currently active state to the window. - * - * This step will simply pass the window to the state and will - * thus allow the state to draw itself onto the windows. This - * is beneficial since we now have completely decoupled the - * state from the Game class, thus allowing all behaviour of a - * state to be implemented in the corresponding class without - * having to touch any other code. - */ - void start (); - -private: - /* - * SFML representation of window which we can draw on. - */ - sf::RenderWindow window; - - - /* - * Container for all states in the game. - * Current_state keeps track on the current state - */ - std::map> states; - int current_state; - - - /* - * If true, then the game should keep on run, otherwise the next - * iteration of the game loop will not run. - */ - bool running; - - - void handle_events(); - - /* - * This function puts the program to sleep for a certain - * period of time in order to keep a steady framerate. - * The inargument is how many milliseconds the current iteration - * took to complete. - * - * Say that the game is supposed to run at 60 frames per second (fps). - * This means that each frame should take exactly 1000/60 = 16.666... - * milliseconds to run. If it took longer, then there is not much - * we can do about it, but if it took a shorter amount of time, - * then request that our program sleep for the remaining time. - */ - void delay (sf::Clock & clock) const; -}; - -#endif // GAME_H diff --git a/src/Game_State.cc b/src/Game_State.cc deleted file mode 100644 index 090e528..0000000 --- a/src/Game_State.cc +++ /dev/null @@ -1,156 +0,0 @@ -#include "Game_State.h" -#include "constants.h" - -#include - -using namespace sf; - -/* - * Check for mouse button presses. - * - * If a mouse button press is detected, when that - * mouse button is release we add a new ball to - * the screen at the mouse's location. - * - * This demonstrates how we can integrate the mouse - * into our project. - */ -void Game_State :: handle_event (Event event) -{ - if ( event.type == Event::MouseButtonReleased ) - { - if ( event.mouseButton.button == Mouse::Button::Left ) - { - balls.emplace_back ( - // get the coordinates of the mouse right now - event.mouseButton.x, - event.mouseButton.y); - } - } - else if ( event.type == Event::KeyPressed ) - { - if ( event.key.code == Keyboard::Key::Return ) - end_game = true; - } -} - -void Game_State :: update () -{ - // Iterate over all balls and let - // them update themselves. - for ( auto & ball : balls ) - ball.update (); -} - -void Game_State :: render (RenderTarget & target) -{ - // Let each ball render itself onto the - // supplied RenderTarget - for ( auto & ball : balls ) - ball.render (target); -} - -/* - * If return was pressed, we jump back to MENU_STATE, - * otherwise we stay in this state GAME_STATE - */ -int Game_State :: get_next_state() -{ - if (end_game) - { - end_game = false; - return MENU_STATE; - } - return GAME_STATE; -} - -/* - * If we want to remove all balls which are outside - * of the screen we need to iterate all balls and - * do two things for each ball: - * 1. Check if it is outside of the screen - * 2. If it is, make sure that we remove it from - * the vector. - * - * The first part can be solved in several ways. - * We can for instance implement our own logic - * for checking if a sprite is on the screen - * or not, or we can use some built-in functions - * in SFML. - * - * In this example we use the latter. - * - * We begin by getting the global bounds of each ball. - * - * A bounds is the smallest possible rectangle which - * covers the entire ball (these are basically the - * "hitboxes" of our balls). - * - * There are two kinds of bounds for each ball, a - * global bound and a local bound, the difference - * is where the (0, 0) coordinate is placed. - * - * In a global bound, (0, 0) referes to top-left - * corner of the window, while in a local bounds - * it referes to the origin of the ball (in this - * example, the center of the ball (see Ball.cpp - * for details)). - * - * Using the global bounds we can use the built-in - * 'intersects' function to check if the bounds - * intersects the screen. If it does, it is still - * visible, if not it is safe to remove. - * - * The second part is a bit trickier. - * - * A problem arises when we iterate over the - * balls and then remove one of them; the current - * index has been changed so we have now potentially - * skipped over an element. - * - * Example of how this might happen: - * - * Say that we are iterating over this list, with - * a standard index based for-loop (here ^ denotes - * the element we are currently looking at): - * - * 1 5 7 2 4 3 - * ^ - * Now say that we remove the 7, then we have: - * - * 1 5 2 4 3 - * ^ - * Note that ^ now points to the next element, but the - * same location as before, which might at first glance - * seem like what we exactly want. But we must not - * forget that the final step in a for loop is to step - * the index, so the next iteration will look like this: - * - * 1 5 2 4 3 - * ^ - * Which shows that we have skipped an element. - * - * This means that we have to be a bit more cleaver - * when removing elements from the list we are - * iterating. - * - * But we are in luck, we can use an iterator based - * for-loop, since erase (the function which removes - * elements from the vector) removes elements pointed - * to by iterators, and returns an iterator to the next - * element. - */ -void Game_State :: cleanup () -{ - for ( auto it { std::begin (balls) }; it != std::end (balls); ) - { - // get the global bounds of our current ball - auto bounds { it -> bounds () }; - // get a rectangle representing the screen - FloatRect screen { 0, 0, screen_width, screen_height }; - if ( !screen.intersects (bounds) ) - it = balls.erase (it); - else - ++it; - } -} diff --git a/src/Game_State.h b/src/Game_State.h deleted file mode 100644 index d145559..0000000 --- a/src/Game_State.h +++ /dev/null @@ -1,49 +0,0 @@ -#include "State.h" -#include "Ball.h" - -#include - -/* - * This class represents the "game". - * - * It is a simple program where a ball appears wherever - * the user has clicked with the mouse. This ball - * is assigned a random velocity and will begin moving - * according to that velocity. - * - * This class serves as an example of a state, but also - * of how the various functions of the State class can - * be used to get moving objects in the game. - * - * It also demonstrates how to remove objects from - * the game in a safe way, as to avoid memory leaks. - */ -class Game_State : public State -{ -public: - - Game_State () = default; - - void handle_event (sf::Event event) override; - void update () override; - void render (sf::RenderTarget & target) override; - virtual int get_next_state() override; - - -private: - bool end_game{false}; - - /* - * Remove all balls which are no longer visible on the - * screen. - */ - void cleanup (); - - - /* - * A collection which contains all balls that are currently - * visible on the screen (see Ball.h). - */ - std::vector balls { }; - -}; \ No newline at end of file diff --git a/src/Helper.cc b/src/Helper.cc new file mode 100644 index 0000000..e69de29 diff --git a/src/Helper.h b/src/Helper.h new file mode 100644 index 0000000..e69de29 diff --git a/src/Main_enemy.cc b/src/Main_enemy.cc new file mode 100644 index 0000000..e69de29 diff --git a/src/Main_enemy.h b/src/Main_enemy.h new file mode 100644 index 0000000..e69de29 diff --git a/src/Map.cc b/src/Map.cc new file mode 100644 index 0000000..e69de29 diff --git a/src/Map.h b/src/Map.h new file mode 100644 index 0000000..e69de29 diff --git a/src/Menu_State.cc b/src/Menu_State.cc deleted file mode 100644 index fefb66f..0000000 --- a/src/Menu_State.cc +++ /dev/null @@ -1,73 +0,0 @@ -#include "Menu_State.h" - -#include -#include - -using namespace sf; - -/* - * Create the welcome message using the font given in - * 'resources/fonts/font.ttf'. - * - * The first argument of the sf::Text constructor is what string - * it should draw, the second argument is what font should be used - * to draw the text and the final argument specifies the font-size - * (in pixels) of the text. - */ -Menu_State :: Menu_State () - :play { false } -{ - std::string file = "resources/fonts/font.ttf"; - if ( !font.loadFromFile (file) ) - throw std::invalid_argument ("Unable to load font"); - text = sf::Text{ "Press to start", font, 16 }; -} - -/* - * check for the 'enter' key. - * - * If it has been pressed we want to change to a new state. - */ -void Menu_State :: handle_event (Event event) -{ - if ( event.type == Event::KeyPressed ) - { - if ( event.key.code == Keyboard::Key::Return ) - play = true; - } -} - - -void Menu_State :: update () -{ - -} - -void Menu_State :: render (RenderTarget & target) -{ - auto bounds { text.getGlobalBounds () }; - auto size { target.getSize () }; - - text.setPosition ((size.x - bounds.width) / 2, - (size.y - bounds.height) / 2); - - target.draw (text); -} - -/* - * If return has been pressed we change to the GAME_STATE, otherwise - * we stay in MENU_STATE - */ -int Menu_State :: get_next_state() -{ - if (play) - { - play = false; - return GAME_STATE; - } - else - { - return MENU_STATE; - } -} - diff --git a/src/Menu_State.h b/src/Menu_State.h deleted file mode 100644 index 2e43574..0000000 --- a/src/Menu_State.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include -#include "State.h" - -class Menu_State: public State -{ -public: - Menu_State (); - - virtual void handle_event (sf::Event event) override; - virtual void update () override; - virtual void render (sf::RenderTarget & taget) override; - virtual int get_next_state() override; - - -private: - - /* - * sf::Text is a drawable object representing a string. - * - * sf::Text can be drawn to any RenderTarget as long as - * a font and a string is supplied. - * - * It works like a sf::Sprite but represents text instead - * of an image. - */ - sf::Text text; - sf::Font font{}; - - - /* - * Flag to determine wheter or not the 'enter' key has been - * pressed (see Menu_State.cpp for details). - */ - bool play; - - - -}; diff --git a/src/Moving_object.cc b/src/Moving_object.cc new file mode 100644 index 0000000..e69de29 diff --git a/src/Moving_object.h b/src/Moving_object.h new file mode 100644 index 0000000..e69de29 diff --git a/src/Object.cc b/src/Object.cc new file mode 100644 index 0000000..e69de29 diff --git a/src/Object.h b/src/Object.h new file mode 100644 index 0000000..e69de29 diff --git a/src/Pause_menu.cc b/src/Pause_menu.cc new file mode 100644 index 0000000..e69de29 diff --git a/src/Pause_menu.h b/src/Pause_menu.h new file mode 100644 index 0000000..e69de29 diff --git a/src/Player.cc b/src/Player.cc new file mode 100644 index 0000000..e69de29 diff --git a/src/Player.h b/src/Player.h new file mode 100644 index 0000000..e69de29 diff --git a/src/Start_menu.cc b/src/Start_menu.cc new file mode 100644 index 0000000..e69de29 diff --git a/src/Start_menu.h b/src/Start_menu.h new file mode 100644 index 0000000..e69de29 diff --git a/src/State.cc b/src/State.cc new file mode 100644 index 0000000..e69de29 diff --git a/src/State.h b/src/State.h index 276199d..e69de29 100644 --- a/src/State.h +++ b/src/State.h @@ -1,55 +0,0 @@ -#ifndef STATE_H -#define STATE_H -#include -#include - -int const MENU_STATE{0}; -int const GAME_STATE{1}; - - -class State -{ -public: - - // this is a base class so a virtual destructor is needed - virtual ~State () = default; - - /* - * This function is called for each event which occurs - * in the window. It is the responsibility of the state - * to filter out any events it is interested in, since - * no filtering is performed before calling this function. - * - * What this means is that if a state only wants to know - * if a certain event has happened, the state needs to - * check for that event inside this function. - */ - virtual void handle_event (sf::Event event) = 0; - - /* - * The 'update' function is called every iteration of the - * game loop, no more and no less. - */ - virtual void update () = 0; - - /* - * Render the state onto the screen through a 'RenderTarget'. - * - * A RenderTarget is an abstract class which defines an - * interface for rendering to a canvas. Two types - * of RenderTargets exist in SFML: - * - RenderWindow; draw directly to a window. - * - RenderTexture; draw onto a texture which can be extracted - * later on using the 'getTexture' member function. - */ - virtual void render(sf::RenderTarget & target) = 0; - - /* - * Return the new state if it should change, - * otherwise return the current state - */ - virtual int get_next_state() = 0; - -}; - -#endif //STATE_H diff --git a/src/Static_object.cc b/src/Static_object.cc new file mode 100644 index 0000000..e69de29 diff --git a/src/Static_object.h b/src/Static_object.h new file mode 100644 index 0000000..e69de29 diff --git a/src/Voi_enemy.cc b/src/Voi_enemy.cc new file mode 100644 index 0000000..e69de29 diff --git a/src/Voi_enemy.h b/src/Voi_enemy.h new file mode 100644 index 0000000..e69de29 diff --git a/src/constants.h b/src/constants.h deleted file mode 100644 index f5c8183..0000000 --- a/src/constants.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -/* - * In this file we define some global constants. - * - * Please note that the problem with global variables - * is that anyone can change them whenever which makes - * it extremely hard to reason about your code. But for - * constants, this is not a problem since we cannot - * change them, and therefore they stay the same during - * the entire execution of the program. - */ - -/* - * define the size of the window. - */ -int const screen_width { 640 }; -int const screen_height { 480 }; - -/* - * define how many fps we want our program to run in. - */ -double const fps { 60.0 };