3 Formas de Criar Sua Árvore de Natal com C++ 🎄

Incluindo formas no terminal e também com SFML e OpenGL.


3 Formas de Criar Sua Árvore de Natal com C++ 🎄

Não julgue a imagem! =) Essa foi uma das primeiras Pixel Art que eu fiz com LibreSprite ! 😃


Então, é Natal! Que tal aproveitarmos essa data ímpar do ano para treinarmos mais um pouquinho do nosso conhecimento em C++?

Nesse artigo vamos ver três formas de criarmos nossa Árvore de Natal com C++, incluindo formas no terminal e também com OpenGL e SFML. 🎄


1º Forma, a mais básica possível

Se criarmos um loop aninhado podemos desenhar diversas formas geométricas, no entanto, a mais treinada é um triângulo. No código abaixo, conseguimos fazer um triângulo reto, ou seja, para nossa solução, seria metade do problema resolvido.

Note que pus a função separada para que possamos customizar o tamanho do triângulo que queiramos

vim 01-christmas-tree.cpp

#include <iostream>

void drawTree(int min, int max){
  for (int i = min; i <= max; ++i){
    for (int x = 0; x < i; ++x){
      std::cout << "*";
    }
    std::cout << '\n';
  }
}

int main(){
  drawTree(1,4);
  return 0;
}

Após compilar e rodar teremos a possível saída abaixo:

g++ 01-christmas-tree.cpp && ./a.out 

*
**
***
****

Ou seja, somente algums básicas linhas! Se quiser um pouco maior, basta alterar a função drawTree() para 1,10 ou qualquer número que você queira:

...
drawTree(1, 10);
....

E então, teremos um tamanho ligeiramente maior:

*
**
***
****
*****
******
*******
********
*********
**********

Mas, queremos mesmo ter um triâgulo equilátero(bom, não é tão equilátero assim, mas tá valendo! :) ), logo, adicionaremos mais dois loops dentro do loop principal com cálculos que crie a parte esquerda do triângulo e dê espaço à esquerda, além de remover o parâmetro min para que possamos mostrar todo o triângulo, veja o código para notar a diferença:

#include <iostream>

void drawTree(int max){
  for (int i {}; i < max; ++i){
    for (int x {}; x < max; ++x){
      std::cout << " ";
    }
    for (int j = max - i; j > 0; j--){
      std::cout << " ";
    }
    for (int k {}; k < 2 * i + 1; ++k){
      std::cout << "*";
    }
    std::cout << '\n';
  }
}

int main(){
  drawTree(10);
  return 0;
}

Agora ficou legal! Podemos ainda customizar o tamanho via argc e argv, mas isso aí fica com você! 😃

                    *
                   ***
                  *****
                 *******
                *********
               ***********
              *************
             ***************
            *****************
           *******************

2º Forma - Uma Árvore de Natal mais estilosa e com animação!

Nessa outra forma vamos incrementar mais alguns caracteres ASCII para ficar mais legal, também vamos usar a biblioteca unistd.h para obtermos um lag(sleep) de 1 segundo na troca da aniimação, para mais detalhes veja o artigo: 4 Formas diferentes de usar sleep() em C++ .

Além também de adicioarmos CORES! Para isso vamos usar uma biblioteca que criamos aqui mesmo no blog, para mais detalhes veja o artigo: Crie sua própria biblioteca de cores para C++ . O legal dessa biblioteca é que ela é simples e funciona legal no LSP, veja o gif abaixo ele informando cada string, note que ele informa: sublinhado, itálico, normal, background e entre outros:

LSP Color Lib


Ou seja, copie o código da postagem e salve em um arquivo de nome colors.hpp e deixe no mesmo diretório do código abaixo!

O código em resumo será:

vim 02-christmas-tree.cpp

#include <iostream>
#include <unistd.h>
#include "colors.hpp" // inclui as cores

int main(){
  srand(time(NULL));
  for (;;) {
    for (int x = 0; x < 20; x++) {
      for (int y = 0; y < 22 - x; y++)
        std::cout << " ";

      for (int i = 0; i <= x * 2; i++) {
        int randm = rand() % 40;
        if (randm ==i)
        {
          std::cout << hey::white << "O";
        }
        else if (randm + i % 2 == 0) {
          std::cout << hey::red << "@";
        }
        else {
          std::cout << hey::green << "*";
        }
      }
      std::cout.put('\n');
    }

    for (int t = 0; t < 3; t++) {
      for (int o = 0; o < 19; o++) {
        std::cout << hey::white << " ";
      }
      std::cout << hey::white << "|  |\n";
    }
    sleep(1);
    system("clear");
  }
}

Compile e rode: g++ 02-christmas-tree.cpp && ./a.out

A árvore possívelmente aparecerá assim:

02-christmas-tree.cpp running...



3º Forma - Usando C++ com SFML e OpenGL

E por final temos com SFML e OpenGL, esse exemplo eu encontrei na internet, só fiz algumas modificaçãozinhas!

Leia o código para mais detalhes, mas antes prepare um diretório para os arquivos:

mkdir christmas-tree
cd christmas-tree
vim tree.{hpp,cpp} main.cpp Makefile

tree.hpp

#pragma once

#include <SFML/Graphics.hpp>
#include <SFML/OpenGL.hpp>
#include <unistd.h>
#include <cmath>
#include <memory>

class ChristmasTree {

  std::shared_ptr<sf::RenderWindow> window;

  public:
    ChristmasTree();
    void events();
    void draw();
    void run();

    void lineto(float,float,float,float);
    void tree(float,float,float,float);
};

tree.cpp

#include "tree.hpp"

ChristmasTree::ChristmasTree(){
  window = std::make_shared<sf::RenderWindow>(
    sf::VideoMode(400, 600),
    "Christmas Tree: C++, OpenGL and SFML",
    sf::Style::Titlebar | sf::Style::Close
  );
  window->setPosition(sf::Vector2i(0, 0));
  window->setFramerateLimit(30);
  glOrtho(0.0, window->getSize().x, window->getSize().y, 0.0, 1.0, -1.0);
}

void ChristmasTree::events(){
  auto e = std::make_shared<sf::Event>();
  while( window->pollEvent( *e ) ){
    if( e->type == sf::Event::Closed){
      window->close();
    }
  }
}

void ChristmasTree::draw(){
  window->clear(sf::Color::Black);
  glColor3f(0.0, 1.0, 0.0);
  lineto(210.0, 400.0, 160.0, M_PI/2.0);
  tree(210.0, 400.0, 75.0, -M_PI/2.0);
  window->display();
  usleep(10000);
}

void ChristmasTree::run(){
  while( window->isOpen() ){
    events();
    draw();
  }
}

void ChristmasTree::lineto(float x, float y, float len, float angle) {
  glBegin(GL_LINES);
  glVertex2f(x, y);
  glVertex2f(x+len*cos(angle), y+len*sin(angle));
  glEnd();
}

void ChristmasTree::tree(float x, float y, float len, float angle){
  const float strange_angle = M_PI/24.0;
  lineto(x, y, len, angle+strange_angle);
  lineto(x, y, -len, angle);
  lineto(x, y, len, angle+2*M_PI/3.0+strange_angle);
  lineto(x, y, len, angle-2*M_PI/3.0+strange_angle);

  const float len_min = 2.0;
  if(len > len_min){
    const float len_div = 0.4;

    tree(x+len*cos(angle+strange_angle), 
        y+len*sin(angle+strange_angle),
        2*len*len_div, angle+strange_angle);
    tree(x+len*cos(angle+2*M_PI/3.0+strange_angle), 
        y+len*sin(angle+2*M_PI/3.0+strange_angle), 
        len*len_div, angle+2*M_PI/3.0+strange_angle);
    tree(x+len*cos(angle-2*M_PI/3.0+strange_angle), 
        y+len*sin(angle-2*M_PI/3.0+strange_angle), 
        len*len_div, angle-2*M_PI/3.0+strange_angle);
  }
}

main.cpp

#include "tree.hpp"

int main( int argc , char **argv ){
  auto cmas = std::make_shared<ChristmasTree>();
  cmas->run();
  return 0;
}

Makefile

TARGET=a.out
CXX=g++
DEBUG=-g
OPT=-O0
WARN=-Wall
SFML=-lsfml-graphics -lsfml-window -lsfml-system -lGL
CXXFLAGS=$(DEBUG) $(OPT) $(WARN) $(SFML)
LD=g++
OBJS= main.o tree.o
all: $(OBJS)
	$(LD) -o $(TARGET) $(OBJS) $(CXXFLAGS)
	@rm *.o
	@./$(TARGET)

main.o: main.cpp
	$(CXX) -c $(CXXFLAGS) main.cpp -o main.o

tree.o: tree.cpp
	$(CXX) -c $(CXXFLAGS) tree.cpp -o tree.o

Agora é só compilar e rodar:

make

Saída:

Christmas Tree C++ SFML OpenGL

Show de bola, né?!

Queria desejar Boas Festas e um Feliz Natal para tod@s vocês!



Links úteis


cpp pixelart


Compartilhe


Nosso canal no Youtube

Inscreva-se


Marcos Oliveira

Marcos Oliveira

Desenvolvedor de software
https://github.com/terroo

Artigos Relacionados




Crie Aplicativos Gráficos para Linux e Windows com C++

Aprenda C++ Moderno e crie Games, Programas CLI, GUI e TUI de forma fácil.

Saiba Mais

Receba as novidades no seu e-mail!

Após cadastro e confirmação do e-mail, enviaremos semanalmente resumos e também sempre que houver novidades por aqui para que você mantenha-se atualizado!