Browse Source

Merge pull request #1 from sauer2/parallax-background

Parallax background
master
sauer2 2 years ago
parent
commit
d54b094a7b
6 changed files with 172 additions and 92 deletions
  1. +70
    -10
      background.cpp
  2. +9
    -3
      background.hpp
  3. +6
    -33
      game.cpp
  4. +66
    -24
      main.cpp
  5. +19
    -21
      mainmenu.cpp
  6. +2
    -1
      mainmenu.hpp

+ 70
- 10
background.cpp View File

@@ -6,21 +6,81 @@
#include "main.hpp"

namespace Proto4 {
void Background::init(sf::Texture bg0, sf::Texture bg1) {
void Background::init(sf::Texture bg0, sf::Texture bg1,
sf::View &gameView) {
bg0Tex = bg0;
bg1Tex = bg1;
bg0Tex.setRepeated(true);
bg1Tex.setRepeated(true);
bg0Tex.setSmooth(true);
bg1Tex.setSmooth(true);
bg0Sprite.setTexture(bg0Tex);
bg1Sprite.setTexture(bg1Tex);
bg0Sprite.setTextureRect(sf::IntRect(0, 0, xResolution, yResolution));
bg1Sprite.setTextureRect(sf::IntRect(0, 0, xResolution, yResolution));
bg0Tex.setRepeated(true);
bg1Tex.setRepeated(true);
bg0Tex.setSmooth(true);
bg1Tex.setSmooth(true);

bg0View = bg1View = gameView;
bg0Size = bg0Tex.getSize().x;
bg1Size = bg1Tex.getSize().x;
bg0Sprite.setTextureRect(sf::IntRect(0, 0, xResolution + 2 * bg0Size,
yResolution + 2 * bg0Size));
bg1Sprite.setTextureRect(sf::IntRect(0, 0, xResolution + 2 * bg1Size,
yResolution + 2 * bg1Size));
// bg0Sprite.setPosition(window.mapPixelToCoords(sf::Vector2i(-bg0Size,
// -bg0Size), bg0View));
// bg1Sprite.setPosition(window.mapPixelToCoords(sf::Vector2i(-bg1Size,
// -bg1Size), bg1View));
bg0Sprite.setPosition(gameView.getCenter() - gameView.getSize() * 0.5f);
bg1Sprite.setPosition(gameView.getCenter() - gameView.getSize() * 0.5f);
}

void Background::update(sf::View &gameView, sf::RenderTarget &window) {
// parallax
bg0View.setCenter(gameView.getCenter() / 3.5f);
bg1View.setCenter(gameView.getCenter() / 2.f);

// move endless backgrounds if parallax has moved one -step, to offset
// parallax-movement
// sf::Vector2f bg0Pos = gameView.getCenter() - bg0View.getCenter(); //
// alternative solution without coord2pixel transformation? doesnt work
// currently
sf::Vector2i bg0Pos =
window.mapCoordsToPixel(bg0Sprite.getPosition(), bg0View);
if (bg0Pos.x >= 0)
bg0Sprite.move(sf::Vector2f(-bg0Size, 0));
else if (bg0Pos.x <= -2 * bg0Size)
bg0Sprite.move(sf::Vector2f(bg0Size, 0));
if (bg0Pos.y >= 0)
bg0Sprite.move(sf::Vector2f(0, -bg0Size));
else if (bg0Pos.y <= -2 * bg0Size)
bg0Sprite.move(sf::Vector2f(0, bg0Size));

sf::Vector2i bg1Pos =
window.mapCoordsToPixel(bg1Sprite.getPosition(), bg1View);
if (bg1Pos.x >= 0)
bg1Sprite.move(sf::Vector2f(-bg1Size, 0));
else if (bg1Pos.x <= -2 * bg1Size)
bg1Sprite.move(sf::Vector2f(bg1Size, 0));
if (bg1Pos.y >= 0)
bg1Sprite.move(sf::Vector2f(0, -bg1Size));
else if (bg1Pos.y <= -2 * bg1Size)
bg1Sprite.move(sf::Vector2f(0, bg1Size));
}
void Background::update(float x, float y) {}
void Background::draw(sf::RenderTarget& target, sf::RenderStates states) const {

void Background::draw(sf::RenderTarget &target,
sf::RenderStates states) const {
target.setView(bg0View);
target.draw(bg0Sprite);
target.setView(bg1View);
target.draw(bg1Sprite);
}
}

void Background::resize(sf::Event &resizeEvent) {
bg0View.setSize(resizeEvent.size.width, resizeEvent.size.height);
bg1View.setSize(resizeEvent.size.width, resizeEvent.size.height);
bg0Sprite.setTextureRect(
sf::IntRect(0, 0, resizeEvent.size.width + 2 * bg0Size,
resizeEvent.size.height + 2 * bg0Size));
bg1Sprite.setTextureRect(
sf::IntRect(0, 0, resizeEvent.size.width + 2 * bg1Size,
resizeEvent.size.height + 2 * bg1Size));
}
}

+ 9
- 3
background.hpp View File

@@ -9,14 +9,20 @@
namespace Proto4 {
class Background : public sf::Drawable {
public:
void init(sf::Texture bg0, sf::Texture bg1);
void update(float x, float y);
void init(sf::Texture bg0, sf::Texture bg1, sf::View &gameView);
void update(sf::View &gameView, sf::RenderTarget &window);
void resize(sf::Event& resizeEvent);

private:
sf::Sprite bg0Sprite;
sf::Sprite bg1Sprite;
sf::Texture bg0Tex;
sf::Texture bg1Tex;
uint8_t bg0Size;
uint8_t bg1Size;
sf::View bg0View;
sf::View bg1View;

virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const;
};
}
}

+ 6
- 33
game.cpp View File

@@ -6,46 +6,19 @@

namespace Proto4 {

bool Game::init() {
return true;
}
bool Game::init() { return true; }

AppState Game::update(sf::RenderWindow &window, sf::Time timestep) {
sf::Event event;

while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed) {
window.close();
} else if (event.type == sf::Event::Resized) {
// resize the views, so everything is still displayed
// proportionally
//view.setSize(event.size.width, event.size.height);
//view.setCenter(event.size.width / 2, event.size.height / 2);
} else if (event.type == sf::Event::KeyPressed) {
if (event.key.code == sf::Keyboard::Q)
return AppState::MainMenu;
}
}

return AppState::Game;
}

void Game::draw(sf::RenderTarget &window, sf::RenderStates states) const {
}
void Game::draw(sf::RenderTarget &window, sf::RenderStates states) const {}

bool Game::start() {
return true;
}
bool Game::start() { return true; }

bool Game::pause() {
return true;
}
bool Game::pause() { return true; }

bool Game::resume() {
return true;
}
bool Game::resume() { return true; }

bool Game::reset() {
return true;
}
bool Game::reset() { return true; }
}

+ 66
- 24
main.cpp View File

@@ -1,3 +1,4 @@
#include <cmath>
#include <iostream>
#include <string>

@@ -5,10 +6,10 @@
#include <SFML/System.hpp>
#include <SFML/Window.hpp>

#include "main.hpp"
#include "background.hpp"
#include "mainmenu.hpp"
#include "game.hpp"
#include "main.hpp"
#include "mainmenu.hpp"

namespace Proto4 {

@@ -19,6 +20,7 @@ namespace Proto4 {
MainMenu menu{};
Game game{};
Background background{};
sf::View gameView;
sf::Texture bg0, bg1;
sf::Font font;

@@ -29,18 +31,20 @@ namespace Proto4 {
return false;
}


if (!bg0.loadFromFile("img/bg_grid_48.png") || !bg1.loadFromFile("img/bg_grid_72.png")) {
std::cout << "Unable to load background images. Aborting execution.";
if (!bg0.loadFromFile("img/bg_grid_48.png") ||
!bg1.loadFromFile("img/bg_grid_72.png")) {
std::cout
<< "Unable to load background images. Aborting execution.";
return false;
}
background.init(bg0, bg1);

if (
!menu.init(font) ||
!game.init()
) {
gameView.setCenter(middleX, middleY);
gameView.setSize(xResolution, yResolution);
gameView.setViewport(sf::FloatRect(0, 0, 1, 1));

background.init(bg0, bg1, gameView);

if (!menu.init(font) || !game.init()) {
return false;
}

@@ -65,10 +69,51 @@ namespace Proto4 {
return true;
}

void update(sf::Time timestep) {
void update(sf::Time timestep, sf::Time currentTime) {

// poll for events and pass them to components
sf::Event event;
while (window.pollEvent(event)) {
switch (event.type) {
case sf::Event::Resized:
background.resize(event);

switch (state) {

case AppState::MainMenu:
menu.resize(event);
break;

/* TODO: add a resize method to the game object, similar to
* the one in mainmenu */
default:
break;
}

break;
case sf::Event::KeyPressed:
switch (state) {
case AppState::MainMenu:
state = menu.update(window, timestep, event);
break;
/* TODO: add keyboard input queue for game */
default:
break;
}
break;
default:
break;
}
}

background.update(1.0f, 1.0f);
// (temporary!) move camera to show off parallax background
gameView.setCenter(sf::Vector2f(
gameView.getCenter().x +
timestep.asSeconds() * 100 * std::sin(currentTime.asSeconds()),
gameView.getCenter().y + timestep.asSeconds() * 100));
background.update(gameView, window);

// Update everything that gets updated without events...
switch (state) {
case AppState::Game:
state = game.update(window, timestep);
@@ -77,23 +122,19 @@ namespace Proto4 {
}
break;

case AppState::MainMenu:
state = menu.update(window, timestep);
if (state == AppState::Game) {
game.start();
}
break;

case AppState::Exit:
window.close();
break;
default:
break;
}
}

void draw(sf::Time timestep) {
void draw() {

window.clear(sf::Color::Black);
window.draw(background);
window.setView(gameView);

switch (state) {
case AppState::Game:
@@ -126,16 +167,17 @@ namespace Proto4 {
lagTime += elapsedTime;

while (lagTime >= updateTimestep) {
update(updateTimestep);
update(updateTimestep, clock.getElapsedTime());
lagTime -= updateTimestep;
}
draw(lagTime);
draw();
}
}
}

int main() {
if (!Proto4::init()) return 1;
if (!Proto4::init())
return 1;
Proto4::mainloop();
return 0;
}

+ 19
- 21
mainmenu.cpp View File

@@ -7,8 +7,10 @@

namespace Proto4 {

// IDEA: implement Menu superclass, which has a sf::Text title, vector<MenuAction> actions, and implements updating and drawing?
// eg. struct MenuAction { sf::Keyboard key, String text, AppState transition }
// IDEA: implement Menu superclass, which has a sf::Text title,
// vector<MenuAction> actions, and implements updating and drawing?
// eg. struct MenuAction { sf::Keyboard key, String text, AppState
// transition }

bool MainMenu::init(sf::Font &font) {
font = font;
@@ -30,29 +32,25 @@ namespace Proto4 {
return true;
}

AppState MainMenu::update(sf::RenderWindow &window, sf::Time timestep) {
sf::Event event;

while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed) {
window.close();
} else if (event.type == sf::Event::Resized) {
// resize the views, so everything is still displayed
// proportionally
view.setSize(event.size.width, event.size.height);
view.setCenter(event.size.width / 2, event.size.height / 2);
} else if (event.type == sf::Event::KeyPressed) {
if (event.key.code == sf::Keyboard::Q)
return AppState::Exit;
if (event.key.code == sf::Keyboard::S)
return AppState::Game;
}
}
void MainMenu::resize(sf::Event &resizeEvent) {
view.setSize(resizeEvent.size.width, resizeEvent.size.height);
view.setCenter(resizeEvent.size.width / 2, resizeEvent.size.height / 2);
}

// Unlike in game, this gets only called on keypresses.
AppState MainMenu::update(sf::RenderWindow &window, sf::Time timestep,
sf::Event keyEvent) {
if (keyEvent.key.code == sf::Keyboard::Q)
return AppState::Exit;
if (keyEvent.key.code == sf::Keyboard::S)
return AppState::Game;

// to satisfy the analyzer
return AppState::MainMenu;
}

void MainMenu::draw(sf::RenderTarget &window, sf::RenderStates states) const {
void MainMenu::draw(sf::RenderTarget &window,
sf::RenderStates states) const {
window.setView(view);
window.draw(mainLine);
window.draw(entry1);

+ 2
- 1
mainmenu.hpp View File

@@ -11,8 +11,9 @@ namespace Proto4 {
class MainMenu : public sf::Drawable, public sf::Transformable {
public:
bool init(sf::Font &font);
AppState update(sf::RenderWindow &window, sf::Time timestep);
AppState update(sf::RenderWindow &window, sf::Time timestep, sf::Event keyEvent);
virtual void draw(sf::RenderTarget &window, sf::RenderStates states) const;
void resize(sf::Event& resizeEvent);

private:
sf::View view{};

Loading…
Cancel
Save