Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementação da biblioteca Graficos #353

Merged
merged 28 commits into from
Jan 7, 2025
Merged

Implementação da biblioteca Graficos #353

merged 28 commits into from
Jan 7, 2025

Conversation

dngadelha
Copy link
Collaborator

@dngadelha dngadelha commented Jan 5, 2025

Foi implementado a biblioteca Graficos, utilizando um elemento <canvas> para a renderização.

A renderização está sendo realizada dentro do Worker, utilizando um OffscreenCanvas

Funções que ainda não foram implementadas:

  • altura_imagem
  • carregar_fonte
  • carregar_imagem
  • definir_icone_janela
  • definir_quadro_gif
  • desenhar_imagem
  • desenhar_porcao_imagem
  • desenhar_quadro_atual_gif
  • largura_imagem
  • liberar_imagem
  • obter_cor_pixel
  • obter_intervalo_gif
  • obter_numero_quadro_atual_gif
  • obter_numero_quadros_gif
  • obter_quadro_gif
  • proximo_frame_gif
  • redimensionar_imagem
  • renderizar_imagem
  • salvar_imagem
  • transformar_imagem
  • transformar_porcao_imagem

Para testar a biblioteca utilize os seguintes códigos:

Teste Geral

programa {
  inclua biblioteca Graficos --> g
  inclua biblioteca Util --> u

  inteiro janela_largura = 750
  inteiro janela_altura = 700
  cadeia janela_titulo = "Teste Geral"

  inteiro triangulo1[3][2] = {{100, 100}, {200, 200}, {100, 200}}
  inteiro triangulo2[3][2] = {{250, 100}, {350, 200}, {250, 200}}
  inteiro triangulo3[3][2] = {{400, 100}, {500, 200}, {400, 200}}
  inteiro triangulo4[3][2] = {{550, 65}, {650, 165}, {550, 165}}

  funcao inicializar() {
    escreva("1. Inicializando Modo Gráfico", "\n")
    escreva("g.iniciar_modo_grafico(verdadeiro)", "\n")
    g.iniciar_modo_grafico(verdadeiro)

    escreva("\n")
    escreva("2. Definindo Dimensões da Janela", "\n")
    escreva("g.definir_dimensoes_janela(" + janela_largura + ", " + janela_altura + ")", "\n")
    g.definir_dimensoes_janela(janela_largura, janela_altura)

    escreva("\n")
    escreva("3. Definindo Título da Janela", "\n")
    escreva("g.definir_titulo_janela(\"" + janela_titulo + "\")", "\n")
    g.definir_titulo_janela(janela_titulo)
  }

  funcao desenhar() {
    g.definir_cor(g.COR_PRETO)
    g.limpar()

    g.definir_cor(g.COR_BRANCO)
    g.definir_opacidade(255)

    g.desenhar_ponto(100, 50)
    g.definir_opacidade(100)
    g.desenhar_ponto(125, 50)
    g.definir_opacidade(255)
    g.desenhar_ponto(150, 50)
    g.definir_opacidade(100)
    g.desenhar_ponto(175, 50)
    g.definir_opacidade(255)
    g.desenhar_ponto(200, 50)
    g.definir_opacidade(100)
    g.desenhar_ponto(225, 50)
    g.definir_opacidade(255)
    g.desenhar_ponto(250, 50)

    g.desenhar_poligono(triangulo1, verdadeiro)
    g.desenhar_poligono(triangulo2, falso)
    g.definir_opacidade(100)
    g.desenhar_poligono(triangulo3, verdadeiro)
    g.definir_opacidade(255)

    g.definir_rotacao(45)
    g.desenhar_poligono(triangulo4, verdadeiro)
    g.definir_rotacao(0)

    g.desenhar_elipse(100, 250, 60, 60, verdadeiro)
    g.desenhar_elipse(200, 250, 60, 60, falso)
    g.definir_opacidade(100)
    g.desenhar_elipse(300, 250, 60, 60, verdadeiro)
    g.definir_opacidade(255)

    g.definir_gradiente(g.GRADIENTE_ABAIXO, g.COR_AZUL, g.COR_VERMELHO)
    g.desenhar_elipse(400, 250, 60, 60, verdadeiro)

    g.definir_gradiente(g.GRADIENTE_ESQUERDA, g.COR_AMARELO, g.COR_VERMELHO)
    g.desenhar_elipse(500, 250, 60, 60, verdadeiro)

    g.definir_gradiente(g.GRADIENTE_INFERIOR_DIREITO, g.COR_AZUL, g.COR_VERDE)
    g.desenhar_elipse(600, 250, 60, 60, verdadeiro)

    g.definir_cor(g.COR_BRANCO)

    g.definir_tamanho_texto(14)
    g.definir_fonte_texto("Arial")

    g.definir_estilo_texto(falso, falso, falso)
    g.desenhar_texto(100, 350, "Teste Texto")
    g.definir_estilo_texto(verdadeiro, falso, falso)
    g.desenhar_texto(200, 350, "Teste Texto")
    g.definir_estilo_texto(falso, verdadeiro, falso)
    g.desenhar_texto(300, 350, "Teste Texto")
    g.definir_estilo_texto(falso, falso, verdadeiro)
    g.desenhar_texto(400, 350, "Teste Texto")
    g.definir_estilo_texto(falso, falso, falso)

    g.definir_tamanho_texto(18)
    g.definir_fonte_texto("Tahoma")

    g.definir_estilo_texto(falso, falso, falso)
    g.desenhar_texto(100, 400, "Teste Texto")
    g.definir_estilo_texto(verdadeiro, falso, falso)
    g.desenhar_texto(225, 400, "Teste Texto")
    g.definir_estilo_texto(falso, verdadeiro, falso)
    g.desenhar_texto(350, 400, "Teste Texto")
    g.definir_estilo_texto(falso, falso, verdadeiro)
    g.desenhar_texto(475, 400, "Teste Texto")
    g.definir_estilo_texto(falso, falso, falso)

    g.desenhar_retangulo(100, 460, 100, 60, falso, verdadeiro)
    g.desenhar_retangulo(250, 460, 100, 60, falso, falso)

    g.desenhar_retangulo(100, 570, 100, 60, verdadeiro, verdadeiro)
    g.desenhar_retangulo(250, 570, 100, 60, verdadeiro, falso)

    g.definir_rotacao(45)
    g.desenhar_retangulo(450, 500, 100, 100, verdadeiro, verdadeiro)
    g.definir_rotacao(0)
  }

  funcao teste_cores() {
    escreva("\n")
    escreva("4. Teste de Cores", "\n")

    inteiro cor = g.criar_cor(0, 148, 255)
    escreva("cor = g.criar_cor(0, 148, 255) = " + cor, "\n")
    escreva("g.obter_RGB(cor, g.CANAL_R) = " + g.obter_RGB(cor, g.CANAL_R), "\n")
    escreva("g.obter_RGB(cor, g.CANAL_G) = " + g.obter_RGB(cor, g.CANAL_G), "\n")
    escreva("g.obter_RGB(cor, g.CANAL_B) = " + g.obter_RGB(cor, g.CANAL_B), "\n")
  }

  funcao teste_janela() {
    escreva("\n")
    escreva("5. Obtendo Dimensões da Janela", "\n")
    escreva("g.largura_janela() = " + g.largura_janela(), "\n")
    escreva("g.altura_janela() = " + g.altura_janela(), "\n")
  }

  funcao teste_tela() {
    escreva("\n")
    escreva("5. Obtendo Dimensões da Tela", "\n")
    escreva("g.largura_tela() = " + g.largura_tela(), "\n")
    escreva("g.altura_tela() = " + g.altura_tela(), "\n")
  }

  funcao inicio() {
    inicializar()

    teste_cores()
    teste_janela()
    teste_tela()

    escreva("\n")
    escreva("6. Renderização", "\n")

    enquanto(verdadeiro) {
      desenhar()
      g.renderizar()
      u.aguarde(10)
    }
  }
}

Resultado do Portugol Studio:

image

Saída do Console:

1. Inicializando Modo Gráfico
g.iniciar_modo_grafico(verdadeiro)

2. Definindo Dimensões da Janela
g.definir_dimensoes_janela(700, 700)

3. Definindo Título da Janela
g.definir_titulo_janela("Teste Geral")

4. Teste de Cores
cor = g.criar_cor(0, 148, 255) = -16739073
g.obter_RGB(cor, g.CANAL_R) = 0
g.obter_RGB(cor, g.CANAL_G) = 148
g.obter_RGB(cor, g.CANAL_B) = 255

5. Obtendo Dimensões da Janela
g.largura_janela() = 700
g.altura_janela() = 700

5. Obtendo Dimensões da Tela
g.largura_tela() = 1920
g.altura_tela() = 1080

6. Renderização

O programa foi interrompido!

Efeito de Onda (Portugol Studio)

programa {
  inclua biblioteca Graficos --> g
  inclua biblioteca Matematica --> m
  inclua biblioteca Tipos --> tp
  inclua biblioteca Util --> u

  const inteiro largura_janela = 350
  const inteiro altura_janela = 350

  const inteiro raio_movimento = 20
  const inteiro tamanho_particula = 4

  inteiro cor_fundo = g.criar_cor(210, 210, 255)
  inteiro cor_particula = g.COR_PRETO

  inteiro iteracao = 0
  inteiro coordenadas_x[360]
  inteiro coordenadas_y[360]

  inteiro particulas_horizontal = 0
  inteiro particulas_vertical = 0
  inteiro raio_particula = tamanho_particula / 2

  funcao inicio() {
    inicializar()

    enquanto (verdadeiro) {
      g.definir_cor(cor_fundo)
      g.limpar()

      desenhar_ondas()

      g.renderizar()

      iteracao = (iteracao + 1) % 360
      u.aguarde(15)
    }

    finalizar()
  }

  funcao desenhar_ondas() {
    inteiro it = iteracao

    g.definir_cor(cor_particula)

    para (inteiro i = -1; i <= particulas_horizontal; i++) {
      para (inteiro j = -1; j <= particulas_vertical; j++) {
        desenhar_particula(i * raio_movimento, j * raio_movimento, it)
        it = (it + 1) % 360
      }
    }
  }

  funcao inteiro desenhar_particula(inteiro centro_x, inteiro centro_y, inteiro iteracao_atual) {
    inteiro x = centro_x + coordenadas_x[iteracao_atual] - raio_particula
    inteiro y = centro_y + coordenadas_y[iteracao_atual] - raio_particula

    g.desenhar_retangulo(x, y, raio_particula, raio_particula, falso, verdadeiro)
    retorne 1
  }

  funcao calcular_numero_particulas() {
    particulas_horizontal = (largura_janela / raio_movimento) + 2
    particulas_vertical = (altura_janela / raio_movimento) + 2
  }

  funcao calcular_coordenadas() {
    real x, y
    real angulo = 0.0
    real incremento_angulo = (m.PI * 2.0) / 360.0

    para (inteiro i = 0; i < 360; i++) {
      x = m.cosseno(angulo) * raio_movimento
      x = m.arredondar(x, 0)

      y = m.seno(angulo) * raio_movimento
      y = m.arredondar(y, 0)

      coordenadas_x[i] = tp.real_para_inteiro(x)
      coordenadas_y[i] = tp.real_para_inteiro(y)

      angulo = angulo + incremento_angulo
    }
  }

  funcao inicializar() {
    g.iniciar_modo_grafico(verdadeiro)
    g.definir_dimensoes_janela(largura_janela, altura_janela)
    g.definir_titulo_janela("Onda")

    calcular_numero_particulas()
    calcular_coordenadas()
  }

  funcao finalizar() {
    g.encerrar_modo_grafico()
  }
}

Resultado do Portugol Studio:

javaw_IgqiHaTMoz


Esfera 3D (Portugol Studio)

programa {
  inclua biblioteca Graficos --> g
  inclua biblioteca Util --> u
  inclua biblioteca Tipos --> tp
  inclua biblioteca Matematica --> m

  /* Dimensões da tela do jogo */
  const inteiro LARGURA_TELA = 800, ALTURA_TELA = 600

  /* Define quantos quadros serão desenhados por segundo (FPS) */
  /* Mude o valor para 0 para rodar com a velocidade máxima */
  const inteiro TAXA_ATUALIZACAO = 60

  /* Variáveis utilizadas para fazer o controle de FPS e contabilizar o tempo de jogo */
  inteiro tempo_inicio_fps = 0, tempo_fps = 0, frames = 0, fps = 0

  inteiro tempo_inicio = 0, tempo_decorrido = 0, tempo_restante = 0

  inteiro tempo_inicio_jogo = 0, tempo_total_jogo = 0

  inteiro tempo_quadro = 1000 / tp.real_para_inteiro(m.maior_numero(1.0, tp.inteiro_para_real(TAXA_ATUALIZACAO)))

  inteiro cor = 1986630
  real scale = -45

  real projx = 0
  real projy = 0

  real z_index = 0

  logico horario = verdadeiro

  funcao inicio() {
    inicializar()
    loop()
    finalizar()
  }

  real vertices[] = {
    0.017268, -0.988219, -0.009926,
    0.740875, -0.435438, 0.515799,
    -0.259120, -0.435438, 0.840723,
    -0.877159, -0.435434, -0.009926,
    -0.259120, -0.435438, -0.860575,
    0.740875, -0.435438, -0.535651,
    0.293656, 0.459001, 0.840723,
    -0.706340, 0.459001, 0.515799,
    -0.706340, 0.459001, -0.535651,
    0.293656, 0.459001, -0.860575,
    0.911694, 0.458997, -0.009926,
    0.017268, 1.011781, -0.009926,
    -0.145188, -0.838873, 0.490069,
    0.442590, -0.838873, 0.299085,
    0.280136, -0.513956, 0.799086,
    0.867915, -0.513954, -0.009926,
    0.442590, -0.838873, -0.318937,
    -0.508462, -0.838870, -0.009926,
    -0.670922, -0.513955, 0.490071,
    -0.145188, -0.838873, -0.509921,
    -0.670922, -0.513955, -0.509923,
    0.280136, -0.513956, -0.818938,
    0.968325, 0.011781, 0.299087,
    0.968325, 0.011781, -0.318939,
    0.017268, 0.011781, 0.990074,
    0.605053, 0.011781, 0.799091,
    -0.933790, 0.011781, 0.299087,
    -0.570518, 0.011781, 0.799091,
    -0.570518, 0.011781, -0.818943,
    -0.933790, 0.011781, -0.318939,
    0.605053, 0.011781, -0.818943,
    0.017268, 0.011781, -1.009926,
    0.705457, 0.537518, 0.490071,
    -0.245601, 0.537519, 0.799086,
    -0.833380, 0.537517, -0.009926,
    -0.245601, 0.537519, -0.818938,
    0.705457, 0.537518, -0.509923,
    0.179723, 0.862436, 0.490069,
    0.542997, 0.862433, -0.009926,
    -0.408055, 0.862436, 0.299085,
    -0.408055, 0.862436, -0.318937,
    0.179723, 0.862436, -0.509921
  }

  inteiro tris[] = {
    1, 14, 13,
    2, 14, 16,
    1, 13, 18,
    1, 18, 20,
    1, 20, 17,
    2, 16, 23,
    3, 15, 25,
    4, 19, 27,
    5, 21, 29,
    6, 22, 31,
    2, 23, 26,
    3, 25, 28,
    4, 27, 30,
    5, 29, 32,
    6, 31, 24,
    7, 33, 38,
    8, 34, 40,
    9, 35, 41,
    10, 36, 42,
    11, 37, 39,
    39, 42, 12,
    39, 37, 42,
    37, 10, 42,
    42, 41, 12,
    42, 36, 41,
    36, 9, 41,
    41, 40, 12,
    41, 35, 40,
    35, 8, 40,
    40, 38, 12,
    40, 34, 38,
    34, 7, 38,
    38, 39, 12,
    38, 33, 39,
    33, 11, 39,
    24, 37, 11,
    24, 31, 37,
    31, 10, 37,
    32, 36, 10,
    32, 29, 36,
    29, 9, 36,
    30, 35, 9,
    30, 27, 35,
    27, 8, 35,
    28, 34, 8,
    28, 25, 34,
    25, 7, 34,
    26, 33, 7,
    26, 23, 33,
    23, 11, 33,
    31, 32, 10,
    31, 22, 32,
    22, 5, 32,
    29, 30, 9,
    29, 21, 30,
    21, 4, 30,
    27, 28, 8,
    27, 19, 28,
    19, 3, 28,
    25, 26, 7,
    25, 15, 26,
    15, 2, 26,
    23, 24, 11,
    23, 16, 24,
    16, 6, 24,
    17, 22, 6,
    17, 20, 22,
    20, 5, 22,
    20, 21, 5,
    20, 18, 21,
    18, 4, 21,
    18, 19, 4,
    18, 13, 19,
    13, 3, 19,
    16, 17, 6,
    16, 14, 17,
    14, 1, 17,
    13, 15, 3,
    13, 14, 15,
    14, 2, 15
  }

  real rot = 0.0
  real cosr = 0.0
  real senr = 0.0

  funcao loop() {
    tempo_inicio_fps = u.tempo_decorrido()
    tempo_inicio_jogo = u.tempo_decorrido() - tempo_total_jogo

    enquanto (verdadeiro) {
      tempo_total_jogo = u.tempo_decorrido() - tempo_inicio_jogo
      tempo_inicio = u.tempo_decorrido() + tempo_restante

      g.definir_cor(0x000000)
      g.limpar()

      desenhar()
      desenhar_fps()

      g.renderizar()

      se (horario) {
        rot += 0.01
        se (rot > 6.28) {
          rot = 0.0
        }
      } senao {
        rot -= 0.01
        se (rot < 0) {
          rot = 6.28
        }
      }

      cosr = m.cosseno(rot)
      senr = m.seno(rot)

      atualizar_fps()

      tempo_decorrido = u.tempo_decorrido() - tempo_inicio
      tempo_restante = tempo_quadro - tempo_decorrido

      enquanto (TAXA_ATUALIZACAO > 0 e tempo_restante > 0) {
        tempo_decorrido = u.tempo_decorrido() - tempo_inicio
        tempo_restante = tempo_quadro - tempo_decorrido
      }
    }
  }

  funcao desenhar_fps() {
    g.definir_tamanho_texto(12.0)
    g.definir_cor(0xFFFFFF)
    g.definir_estilo_texto(falso, verdadeiro, falso)
    g.desenhar_texto(25, 40, "FPS: " + fps)
  }

  funcao atualizar_fps() {
    frames = frames + 1
    tempo_fps = u.tempo_decorrido() - tempo_inicio_fps

    se (tempo_fps >= 1000) {
      fps = frames
      tempo_inicio_fps = u.tempo_decorrido() - (tempo_fps - 1000)
      frames = 0
    }
  }

  funcao desenhar() {
    g.definir_gradiente(g.GRADIENTE_INFERIOR_DIREITO, 0xFC466B, 0x3F5EFB)
    g.desenhar_retangulo(0, 0, 800, 600, falso, verdadeiro)
    g.definir_cor(0xffffff)

    inteiro faces = u.numero_elementos(tris) / 3
    para (inteiro count = 0; count < faces; count++) {
      inteiro f = count * 3
      inteiro v0 = tris[f + 0] - 1
      inteiro v1 = tris[f + 1] - 1
      inteiro v2 = tris[f + 2] - 1

      poligon3d(v0, v1, v2, falso)
      poligon3d(v0, v1, v2, verdadeiro)
    }
  }

  inteiro tempo_inicio_cor = u.tempo_decorrido()

  funcao poligon3d(inteiro v1, inteiro v2, inteiro v3, logico frente) {
    inteiro pontos[3][2]
    _proj(v1)
    pontos[0][0] = scale * projx * ALTURA_TELA + LARGURA_TELA / 2
    pontos[0][1] = scale * projy * ALTURA_TELA + ALTURA_TELA / 2
    real pz1 = scale * z_index

    _proj(v2)
    pontos[1][0] = scale * projx * ALTURA_TELA + LARGURA_TELA / 2
    pontos[1][1] = scale * projy * ALTURA_TELA + ALTURA_TELA / 2
    real pz2 = scale * z_index

    _proj(v3)
    pontos[2][0] = scale * projx * ALTURA_TELA + LARGURA_TELA / 2
    pontos[2][1] = scale * projy * ALTURA_TELA + ALTURA_TELA / 2
    real pz3 = scale * z_index

    se (frente) {
      se (pz1 >= 0 e pz2 >= 0 e pz3 >= 0) {
        inteiro index = 1
        inteiro somax = pontos[0][0] + pontos[1][0] + pontos[2][0]
        inteiro somay = pontos[0][1] + pontos[1][1] + pontos[2][1]
        somax = somax / 3
        somax = somax / scale
        somay = somay / 3
        inteiro px = somax * -20
        g.definir_cor((px * 65536 * index) + (px * 256 * index) + (px * 1 * index))
        g.desenhar_poligono(pontos, verdadeiro)
        g.desenhar_poligono(pontos, falso)
      }
    } senao {
      se (pz1 >= 0 ou pz2 >= 0 ou pz3 >= 0) {
        inteiro index = 1
        inteiro menor = pontos[0][0] / scale

        se (v1 > v2) {
          menor = pontos[1][0] / scale
        } senao se (menor > v3) {
          menor = pontos[2][0] / scale
        }

        inteiro px = menor * -20
        g.definir_cor((px * 65536 * index) + (px * 256 * index) + (px * 1 * index))
        g.desenhar_poligono(pontos, verdadeiro)
      }
    }
  }

  funcao linha3d(inteiro v1, inteiro v2) {
    _proj(v1)
    real px1 = scale * projx * ALTURA_TELA + LARGURA_TELA / 2
    real py1 = scale * projy * ALTURA_TELA + ALTURA_TELA / 2

    _proj(v2)
    real px2 = scale * projx * ALTURA_TELA + LARGURA_TELA / 2
    real py2 = scale * projy * ALTURA_TELA + ALTURA_TELA / 2

    inteiro index = 1
    inteiro menor = px1 / scale

    se (v1 > v2) {
      menor = px2 / scale
    }

    inteiro px = menor * -20

    g.definir_cor(0xffffff)
    g.desenhar_linha(px1, py1, px2, py2)
  }

  funcao _proj(inteiro v) {
    real px = vertices[v * 3 + 0]
    real py = vertices[v * 3 + 2]
    real pz = vertices[v * 3 + 1]

    real tz = (pz * cosr) - (px * senr)
    real tx = (pz * senr) + (px * cosr)
    real ty = py
    z_index = tz

    tz = tz + 150.0

    projx = tx / tz
    projy = ty / tz
  }

  funcao inicializar() {
    g.iniciar_modo_grafico(verdadeiro)
    g.definir_dimensoes_janela(LARGURA_TELA, ALTURA_TELA)
    g.definir_titulo_janela("Raymarcher")
  }

  funcao finalizar() {
    g.encerrar_modo_grafico()
  }
}

Resultado do Portugol Studio:

javaw_m8EPK9LfQs

@dngadelha dngadelha marked this pull request as draft January 5, 2025 16:49
@dgadelha dgadelha marked this pull request as ready for review January 7, 2025 00:46
@dgadelha dgadelha merged commit 1088ff0 into beta Jan 7, 2025
3 checks passed
@dgadelha dgadelha deleted the feat/graphics branch January 7, 2025 00:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants