Skip to content
Snippets Groups Projects
Commit d2a40a8b authored by Filip Strömbäck's avatar Filip Strömbäck
Browse files

Initial commit

parents
No related branches found
No related tags found
No related merge requests found
((c++-mode . ((indent-tabs-mode . nil)
(fill-column . 80))))
*
!*.*
!*/
!Makefile
bin/
build/
*.o
*.aux
*.fdb_latexmk
*.pdf
*.fls
*.log
stages:
- auto
pdf:
image: "texlive/texlive:latest"
stage: auto
artifacts:
paths:
- ./*.pdf
script:
- cd $CI_PROJECT_DIR/
- mkdir out
- shopt -s globstar nullglob
- for i in **/*.tex; do
- cd "$CI_PROJECT_DIR/$(dirname "$i")"
- latexmk -xelatex -pvc- "$(basename "$i")"
- cp "$(basename "$i" .tex).pdf" "$CI_PROJECT_DIR"/"$(dirname "$i").pdf"
- done
[]
library+=sfml-graphics
library+=sfml-window
library+=sfml-system
SFML-demo
=========
Detta repo innehåller tre mappar:
- basic: en stegvis introduktion till SFML
- inheritance: ett exempel på struktur baserat på arv
- component: ett exempel på struktur baserat på s.k. komponenter
All kod kan byggas genom att gå till mappen och köra `make`.
De två sistnämnda mapparna innehåller även ett klassdiagram. Dessa finns både
[här](../builds/artifacts/master/browse?job=pdf), och kan produceras med kommandot `make pdf` i
respektive mapp.
CXXFLAGS := -std=c++17
LDFLAGS := -lsfml-graphics -lsfml-window -lsfml-system
SOURCES := $(wildcard *.cpp)
EXECUTABLES := $(patsubst %.cpp,%,$(SOURCES))
all: $(EXECUTABLES)
.PHONY: clean
clean:
rm -f $(EXECUTABLES)
$(EXECUTABLES): %: %.cpp
g++ $(CXXFLAGS) -o $@ $< $(LDFLAGS)
#pragma once
#include <SFML/Graphics.hpp>
#include <cmath>
inline float length(const sf::Vector2f &v) {
return sqrt(v.x*v.x + v.y*v.y);
}
inline sf::Vector2f normalize(const sf::Vector2f &v) {
float len = length(v);
if (len <= 0.0f)
return sf::Vector2f{0, 0};
else
return v * (1.0f/len);
}
#pragma once
#include <iostream>
using std::cout;
using std::endl;
#include <SFML/Graphics.hpp>
/**
* Steg 0: Skapa ett fönster
*
* Kompilera med:
* g++ step00.cpp -lsfml-system -lsfml-graphics -lsfml-window
*/
const size_t width = 1024;
const size_t height = 768;
int main() {
sf::RenderWindow window{sf::VideoMode{width, height}, "Demo"};
sf::sleep(sf::milliseconds(1000));
return 0;
}
#include <SFML/Graphics.hpp>
#include "standard.h"
/**
* Steg 1: Hantera "event"
*
* Testa:
* - Vad händer om vi inte hanterar sf::Event::Closed?
*/
const size_t width = 1024;
const size_t height = 768;
int main() {
sf::RenderWindow window{sf::VideoMode{width, height}, "Demo"};
bool quit = false;
sf::Event event;
while (window.waitEvent(event)) {
switch (event.type) {
case sf::Event::Closed:
quit = true;
break;
default:
cout << "Event: " << event.type << endl;
break;
}
if (quit)
break;
}
return 0;
}
#include <SFML/Graphics.hpp>
#include "standard.h"
/**
* Steg 2: Rita något på skärmen!
*
* Testa:
* - Vad händer om vi inte har med "window.display()"?
* - Var är punkten (0, 0)?
* - Vad händer om vi kör circle.setOrigin(sf::Vector2f{40, 40});
*/
const size_t width = 1024;
const size_t height = 768;
int main() {
sf::RenderWindow window{sf::VideoMode{width, height}, "Demo"};
sf::CircleShape circle{40};
circle.setPosition(sf::Vector2f{300, 300});
bool quit = false;
sf::Event event;
while (window.waitEvent(event)) {
switch (event.type) {
case sf::Event::Closed:
quit = true;
break;
default:
break;
}
if (quit)
break;
window.draw(circle);
window.display();
}
return 0;
}
#include <SFML/Graphics.hpp>
#include "standard.h"
/**
* Steg 3: Flytta objektet!
*
* Testa:
* - Vad händer om du lägger till window.setKeyRepeatEnabled(false)?
* - Vad händer om du kör window.clear() innan du ritar?
*/
const size_t width = 1024;
const size_t height = 768;
void updateLocation(sf::Vector2f &location, sf::Keyboard::Key key) {
switch (key) {
case sf::Keyboard::W:
case sf::Keyboard::Up:
location.y -= 10;
break;
case sf::Keyboard::S:
case sf::Keyboard::Down:
location.y += 10;
break;
case sf::Keyboard::A:
case sf::Keyboard::Left:
location.x -= 10;
break;
case sf::Keyboard::D:
case sf::Keyboard::Right:
location.x += 10;
break;
default:
break;
}
}
int main() {
sf::RenderWindow window{sf::VideoMode{width, height}, "Demo"};
sf::CircleShape circle{40};
sf::Vector2f location{300, 300};
bool quit = false;
sf::Event event;
while (window.waitEvent(event)) {
switch (event.type) {
case sf::Event::Closed:
quit = true;
break;
case sf::Event::KeyPressed:
updateLocation(location, event.key.code);
break;
default:
break;
}
if (quit)
break;
circle.setPosition(location);
window.draw(circle);
window.display();
}
return 0;
}
#include <SFML/Graphics.hpp>
#include "point.h"
#include "standard.h"
/**
* Steg 4: Bättre förflyttning av objekt(?)
*
* Fundera på:
* - Varför fungerar inte detta särskilt bra?
*/
const size_t width = 1024;
const size_t height = 768;
sf::Vector2f find_direction() {
sf::Vector2f direction;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W) || sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
direction.y -= 1;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::S) || sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
direction.y += 1;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::A) || sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
direction.x -= 1;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::D) || sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
direction.x += 1;
return normalize(direction);
}
int main() {
sf::RenderWindow window{sf::VideoMode{width, height}, "Demo"};
window.setKeyRepeatEnabled(false);
sf::CircleShape circle{40};
sf::Vector2f location{300, 300};
bool quit = false;
sf::Event event;
while (window.waitEvent(event)) {
switch (event.type) {
case sf::Event::Closed:
quit = true;
break;
default:
break;
}
if (quit)
break;
sf::Vector2f direction = find_direction();
location += direction;
window.clear();
circle.setPosition(location);
window.draw(circle);
window.display();
}
return 0;
}
#include <SFML/Graphics.hpp>
#include "point.h"
#include "standard.h"
/**
* Steg 5: Bättre förflyttning av objekt!
*
* Fundera på:
* - Vad är skillnaden här jämfört med förra?
* - Hur påverkas hastigheten av olika hastighet på programmet?
*/
const size_t width = 1024;
const size_t height = 768;
sf::Vector2f find_direction() {
sf::Vector2f direction;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W) || sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
direction.y -= 1;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::S) || sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
direction.y += 1;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::A) || sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
direction.x -= 1;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::D) || sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
direction.x += 1;
return normalize(direction);
}
int main() {
sf::RenderWindow window{sf::VideoMode{width, height}, "Demo"};
window.setKeyRepeatEnabled(false);
// window.setVerticalSyncEnabled(true);
sf::CircleShape circle{40};
sf::Vector2f location{300, 300};
bool quit = false;
while (!quit) {
sf::Event event;
while (window.pollEvent(event)) {
switch (event.type) {
case sf::Event::Closed:
quit = true;
break;
default:
break;
}
}
if (quit)
break;
sf::Vector2f direction = find_direction();
location += direction;
window.clear();
circle.setPosition(location);
window.draw(circle);
window.display();
}
return 0;
}
#include <SFML/Graphics.hpp>
#include "point.h"
#include "standard.h"
/**
* Steg 6: Bättre förflyttning av objekt, konstant hastighet
*
* Fundera på:
* - Finns det några problem med detta?
*/
const size_t width = 1024;
const size_t height = 768;
sf::Vector2f find_direction() {
sf::Vector2f direction;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W) || sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
direction.y -= 1;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::S) || sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
direction.y += 1;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::A) || sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
direction.x -= 1;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::D) || sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
direction.x += 1;
return normalize(direction);
}
int main() {
sf::RenderWindow window{sf::VideoMode{width, height}, "Demo"};
window.setKeyRepeatEnabled(false);
window.setVerticalSyncEnabled(true);
sf::CircleShape circle{40};
sf::Vector2f location{300, 300};
sf::Clock clock;
bool quit = false;
while (!quit) {
sf::Event event;
while (window.pollEvent(event)) {
switch (event.type) {
case sf::Event::Closed:
quit = true;
break;
default:
break;
}
}
if (quit)
break;
sf::Vector2f direction = find_direction();
auto delta = clock.restart();
{
float distance = 250.0f * (delta.asMicroseconds() / 1000000.0f);
location += direction * distance;
}
window.clear();
circle.setPosition(location);
window.draw(circle);
window.display();
}
return 0;
}
[]
input=main.cpp
CXXFLAGS := -std=c++17 -Wall -Wextra
LDFLAGS := -lsfml-graphics -lsfml-window -lsfml-system
SOURCES := $(wildcard *.cpp)
OBJECTS := $(patsubst %.cpp,%.o,$(SOURCES))
# Note: This makefile is not entirely correct, it does not take header dependencies into account.
# It is, however, enough to compile the project here, which is the intended use. If you wish to
# develop the code further, I suggest either mymake or writing a CMake-file.
all: game
pdf: uml.pdf
.PHONY: clean
clean:
rm -f game $(OBJECTS)
find . -name "uml.*" | grep -Ev "(pdf|tex)$$" | xargs rm -f
uml.pdf: uml.tex
latexmk -xelatex -pvc- uml.tex
game: $(OBJECTS)
g++ $(CXXFLAGS) -o game $(OBJECTS) $(LDFLAGS)
$(OBJECTS): %.o: %.cpp
g++ $(CXXFLAGS) -c -o $@ $<
#include "behavior.h"
#include "world.h"
#include "entity.h"
Player_Control::Player_Control(float speed) : speed{speed} {}
static sf::Vector2f find_direction() {
sf::Vector2f direction;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W) || sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
direction.y -= 1;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::S) || sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
direction.y += 1;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::A) || sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
direction.x -= 1;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::D) || sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
direction.x += 1;
float len = sqrt(pow(direction.x, 2) + pow(direction.y, 2));
if (len > 0.0f)
return direction * (1.0f / len);
else
return direction;
}
bool Player_Control::tick(sf::Time time, Entity &entity, World &) {
sf::Vector2f dir = find_direction();
entity.center += dir * (speed * time.asMicroseconds() / 1000000.0f);
return true;
}
bool Remove_Outside::tick(sf::Time, Entity &entity, World &) {
if (entity.center.x < -margin)
return false;
if (entity.center.x > width + margin)
return false;
if (entity.center.y < -margin)
return false;
if (entity.center.y > height + margin)
return false;
return true;
}
Spawn::Spawn(sf::Time interval, std::function<shared_ptr<Entity>(Entity &)> create)
: create{create}, spawn_interval{interval}, remaining{interval} {}
bool Spawn::tick(sf::Time delta, Entity &entity, World &world) {
remaining -= delta;
if (remaining <= sf::Time{}) {
world.add(create(std::ref(entity)));
remaining += spawn_interval;
}
return true;
}
Sine_Movement::Sine_Movement(float x, sf::Time duration)
: cumulated_time{}, lifetime{duration}, x{x} {}
bool Sine_Movement::tick(sf::Time delta, Entity &entity, World &) {
float t = float(cumulated_time.asMicroseconds()) / float(lifetime.asMicroseconds());
entity.center.y = height * t;
float amplitude = 1.0f - t;
entity.center.x = x + sin((t + x / width) * 12) * amplitude * width / 4.0f;
if (x > width / 2) {
entity.center.x += (width - x) * t;
} else {
entity.center.x -= x * t;
}
if (t >= 1.0f)
return false;
cumulated_time += delta;
return true;
}
bool Down_Movement::tick(sf::Time delta, Entity &entity, World &) {
entity.center.y += speed * delta.asMicroseconds() / 1000000.0f;
return true;
}
bool Down_Center_Movement::tick(sf::Time delta, Entity &entity, World &) {
sf::Vector2f heading = sf::Vector2f(width / 2, height + 15) - entity.center;
float length = sqrt(pow(heading.x, 2) + pow(heading.y, 2));
if (length > 1.0f)
heading = heading * (1.0f / length);
else
return false;
entity.center += heading * (speed * delta.asMicroseconds() / 1000000.0f);
return true;
}
#include "component.h"
#include <functional>
/**
* This file contains a set of components that define how an entity behaves.
*/
/**
* Component that lets the player steer the component.
*/
class Player_Control : public Component {
public:
/**
* Create, and set the speed.
*/
Player_Control(float speed);
/**
* Update the object.
*/
bool tick(sf::Time time, Entity &entity, World &world) override;
private:
/**
* The speed.
*/
float speed;
};
/**
* Component that removes the entity whenever it is outside of the screen.
*/
class Remove_Outside : public Component {
public:
/**
* Create, optionally with additional margins.
*/
Remove_Outside(float margin = 0.0f)
: margin{margin} {}
/**
* Update.
*/
bool tick(sf::Time time, Entity &entity, World &world) override;
private:
/**
* Additional margin.
*/
float margin;
};
/**
* Component that spawns other components regularly.
*/
class Spawn : public Component {
public:
/**
* Create, specify what to create and how often.
*/
Spawn(sf::Time interval, std::function<shared_ptr<Entity>(Entity &)> create);
/**
* Update.
*/
bool tick(sf::Time time, Entity &entity, World &world) override;
private:
/**
* Function to create new entities.
*/
std::function<shared_ptr<Entity>(Entity &)> create;
/**
* How often to spawn things.
*/
sf::Time spawn_interval;
/**
* How much time left to the next spawn.
*/
sf::Time remaining;
};
/**
* Component that moves the entity in a sine-wave pattern from the top to the
* bottom of the screen.
*/
class Sine_Movement : public Component {
public:
/**
* Create, specify initial x coordinate and desired duration.
*/
Sine_Movement(float x, sf::Time duration);
/**
* Update.
*/
bool tick(sf::Time time, Entity &entity, World &world) override;
private:
/**
* Total time we have been alive.
*/
sf::Time cumulated_time;
/**
* Total lifetime.
*/
sf::Time lifetime;
/**
* Original x position.
*/
float x;
};
/**
* Component that moves the entity in a straight line towards the bottom of the
* screen.
*/
class Down_Movement : public Component {
public:
/**
* Create, specify speed.
*/
Down_Movement(float speed) : speed{speed} {}
/**
* Update.
*/
bool tick(sf::Time time, Entity &entity, World &world) override;
private:
/**
* Speed.
*/
float speed;
};
/**
* Component that moves the entity in a straight line towards the bottom center
* of the screen.
*/
class Down_Center_Movement : public Component {
public:
/**
* Create, specify speed.
*/
Down_Center_Movement(float speed) : speed{speed} {}
/**
* Update.
*/
bool tick(sf::Time time, Entity &entity, World &world) override;
private:
/**
* Speed.
*/
float speed;
};
components/bullet.png

437 B

0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment