Hacer lo mismo de esta "cosa" de la película ochentera

Iniciado por Meta, 4 Mayo 2019, 21:52 PM

0 Miembros y 1 Visitante están viendo este tema.

Meta

Hola:

Quiero hacer los dibujos exactamente lo mismo como en este ordenador ochentero de esta película exactamente indicado en el minuto 6:56 de este vídeo.

Lo que he hecho hasta ahora son solo textos, en el cual no se el motivo, no me sale el rellenado de la parte derecha de la pantalla con el │ ASCII 179.



Código (csharp) [Seleccionar]
using System;
using System.Threading;

namespace The_Thing_La_Cosa_Consola_01_cs
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.Title = "The Thing - La Cosa - C#";
            Console.WindowWidth = 38;   // X ancho.
            Console.WindowHeight = 15;  // Y altura.

            int tiempo = 1;

            // Cursor invisible.
            Console.CursorVisible = false;

            // Dibujar cuadro.
            DrawMarco(1, 1, 35, 14);

            // Escribir textos.
            Console.SetCursorPosition(2, 4);
            Escribir("PROJECTION: \n", 25);
            Console.SetCursorPosition(2, 5);
            Escribir("IF INTRUDER ORGANISM REACHES \n", 25);
            Console.SetCursorPosition(2, 6);
            Escribir("CIVILIZED AREAS . . . \n", 25);
            Thread.Sleep(100);
            Console.SetCursorPosition(2, 10);
            Escribir("ENTIRE WORLD POPULATION INFECTED \n", 25);
            Console.SetCursorPosition(2, 11);
            Escribir("27,000 HOURS FROM FIRST CONTACT. \n", 25);

            // En español.
            Thread.Sleep(2000);

            // Limpiar pantalla.
            Console.Clear();

            // Dibujar cuadro.
            DrawMarco(1, 1, 35, 14);

            // Escribir textos.
            Console.SetCursorPosition(2, 3);
            Escribir("PROYECCIÓN: \n", 25);
            Console.SetCursorPosition(2, 4);
            Escribir("SI ORGANISMO INTRUSO ALCANZA \n", 25);
            Console.SetCursorPosition(2, 5);
            Escribir("ZONAS CIVILIZADAS . . . \n", 25);
            Thread.Sleep(100);
            Console.SetCursorPosition(2, 9);
            Escribir("TODA LA POBLACIÓN MUNDIAL INFECTÓ\n", 25);
            Console.SetCursorPosition(2, 10);
            Escribir("27,000 HORAS DESDE EL PRIMER\n", 25);
            Console.SetCursorPosition(2, 11);
            Escribir("CONTACTO. \n", 25);

            Console.ReadKey();
        }

        public static void Escribir(string Cadena, int tiempo)
        {
            foreach (char letra in Cadena)
            {
                Console.Write(letra);
                Thread.Sleep(tiempo);
            }
        }

        private static void DrawMarco(int v1, int v2, int v3, int v4)
        {
            Console.ForegroundColor = ConsoleColor.Cyan; // Texto azul claro.
            Console.BackgroundColor = ConsoleColor.DarkBlue; // Fondo azul oscuro.
            Console.Clear(); // Para poner fondo azul oscuro en la pantalla completa.

            Console.CursorVisible = false;
            gotoXY(v1, v2, "┌");

            for (int i = v1 + 1; i < v3; i++)
            {
                gotoXY(i, v2, "─");
            }
            gotoXY(v3, v2, "┐");
            for (int i = v2 + 1; i < v4; i++)
            {
                gotoXY(v3, i, "│");
            }
            gotoXY(v3, v4, "┘");
            for (int i = v3 - 1; i > v1; i--)
            {
                gotoXY(i, v4, "─");
            }
            gotoXY(v1, v4, "└");
            for (int i = v4 - 1; i > v2; i--)
            {
                gotoXY(v1, i, "│");
            }
            //Console.CursorVisible = true;
        }

        private static void gotoXY(int v1, int v2, string cadena)
        {
            Console.SetCursorPosition(v1, v2);
            Console.WriteLine(cadena);
            Thread.Sleep(1);
        }
    }
}


¿Alguna idea de como hacerlo?

Por lo que parece, a pesar de que es del 1982, hoy en día exige mucho tiempo y complicado.

Saludos.
Tutoriales Electrónica y PIC: http://electronica-pic.blogspot.com/

Eleкtro

#1
Que quieras reproducir un efecto cinemático de software de los años 80, no significa que debas hacerlo como se podría hacer en los años 80...

En lugar de una aplicación de consola puedes utilizar la tecnologia WindowsForms o WPF. Lo siguiente lo hice en WinForms en apenas 40 lineas de código:



Código (vbnet) [Seleccionar]
Imports System.Drawing.Drawing2D
Imports System.Threading

Public Class Form1

   Dim str As String =
"PROJECTION:
IF INTRUDER ORGANISM REACHES
CIVILIZED AREAS...

ENTIRE WORLD POPULATION INFECTED
27,000 HOURS FROM FIRST CONTACT."

   Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown

       ' Draw Panel Border.
       Using g As Graphics = Me.Panel1.CreateGraphics(),
             pen As New Pen(Color.FromArgb(255, 36, 244, 248), 6)

           pen.Alignment = PenAlignment.Inset
           g.DrawRectangle(pen, Me.Panel1.ClientRectangle)
       End Using

       ' Clear label text and set text font.
       Me.Label1.Text = ""
       Me.Label1.Font = New Font("MODESEVEN", 20)
       Me.Update()
       Thread.Sleep(1000)

       ' Write the text.
       For Each c As Char In Me.str
           Me.Label1.Text &= c
           Me.Label1.Update()
           Thread.Sleep(80)
       Next c

   End Sub

End Class


El form consiste de un Panel y un Label, nada más.

Aquí puedes descargar el proyecto:

Y la fuente true-type que utilicé:




Logicamente si pretendes reproducirlo en una ventana de consola, es un procedimiento bastante más tedioso al carecer de funcionalidades avanzadas de dibujado.

Para empezar, el rectángulo o borde lo puedes dibujar de manera muy sencilla con mi código reusable de ConsoleRectangle:

Cita de: Elektro

Y para escribir el texto disculpa que te diga pero yo sinceramente alucino con la que te has montado en tu código. A estas alturas y todavía sigues haciendo estas cosas...

Cita de: Meta
Código (csharp) [Seleccionar]
           // Escribir textos.
           Console.SetCursorPosition(2, 3);
           Escribir("PROYECCIÓN: \n", 25);
           Console.SetCursorPosition(2, 4);
           Escribir("SI ORGANISMO INTRUSO ALCANZA \n", 25);
           Console.SetCursorPosition(2, 5);
           Escribir("ZONAS CIVILIZADAS . . . \n", 25);
           Thread.Sleep(100);
           Console.SetCursorPosition(2, 9);
           Escribir("TODA LA POBLACIÓN MUNDIAL INFECTÓ\n", 25);
           Console.SetCursorPosition(2, 10);
           Escribir("27,000 HORAS DESDE EL PRIMER\n", 25);
           Console.SetCursorPosition(2, 11);
           Escribir("CONTACTO. \n", 25);

Mira, simplemente declara una variable multilinea con el texto a escribir (del mismo modo que en el código que he mostrado arriba) y con un foreach en C# iteras los caracteres, haces una pausa de 80-100 ms entre cada caracter y lo escribes. fin.

Ah, y si quieres modificar la fuente de la instancia de la consola actual, deberás usar la función SetCurrentConsoleFontEx:

Hice este código que podría servir como ejemplo...



Código (vbnet) [Seleccionar]
Imports System.ComponentModel
Imports System.Drawing
Imports System.Runtime.InteropServices
Imports System.Security
Imports System.Text
Imports System.Threading

Module Module1

   ReadOnly str As String =
"PROJECTION:
IF INTRUDER ORGANISM REACHES
CIVILIZED AREAS...

ENTIRE WORLD POPULATION INFECTED
27,000 HOURS FROM FIRST CONTACT."

   Sub Main()
       Console.Title = "The Thing - La Cosa"
       Console.WindowWidth = 60
       Console.WindowHeight = 20

       ' Paint background.
       Console.BackgroundColor = ConsoleColor.DarkBlue
       Console.Clear()

       ' Draw border.
       Console.ForegroundColor = ConsoleColor.Cyan
       Dim rc As ConsoleRectangle = New Rectangle(2, 2, Console.WindowWidth - 4, Console.WindowHeight - 4)
       rc.Write()

       ' Draw Text.
       Dim x As Integer = (rc.Width \ 5)
       Dim y As Integer = (rc.Height \ 3)
       ConsoleUtil.SetConsolefont("Consolas", bold:=False)
       Console.SetCursorPosition(x, y)

       For Each c As Char In str
           If c.Equals(ControlChars.Cr) Then
               Console.SetCursorPosition(x, Interlocked.Increment(y))
               Continue For
           End If

           If c.Equals(ControlChars.Lf) Then
               Continue For
           End If

           Console.Write(c)
           Thread.Sleep(80)
       Next

       Console.ReadKey(intercept:=True)
   End Sub

End Module


El proyecto (con el resto del código que no he mostrado) lo puedes descargar aquí:

Nótese que el proyecto que he compartido incluye extractos del código fuente de mi librería comercial DevCase for .NET Framework para programadores de C# y VB.NET.
También incluí un método para cambiar la fuente de texto de la consola, el cual lo he escrito practicamente para responderte a tu duda, y no lo he testeado mucho, pero encontré problemas para cambiarle el tamaño a la fuente por que al cambiarle el tamaño también se agranda la ventana de la consola. Parece ser el comportamiento por defecto de Windows, así que dejé el tamaño por defecto para no comerme mucho la cabeza. Tampoco me esmeré nada para alinear el texto dentro del rectángulo ya que es solo un ejemplo y no quiero darle más vueltas haciendo cálculos más sofisticados, eso te lo dejo a ti.

Saludos.








Machacador

Que bonito.. como yo no soy programador de repente lo puedo hacer con el EASY-GIF...  :silbar:

:rolleyes: :o :rolleyes:

Saludos.
"Solo tu perro puede admirarte mas de lo que tu te admiras a ti mismo"

Meta

#3
Fantático ejemplos visuales.  ;-) ;-) ;-) ;-) ;-) ;-)

Si te fija en el vídeo, primero la formación del rectángulo se hace poco a poco, no de golpe, algo parecido hice en modo consola.

En Windows Form el cuadro se hace directo, no poco a poco con GDI+, por eso mejor usar los ASCII para la formación del retángulo como en modo consola. Por ahora solo he heche textos en Windows Form.

Añado un timer, luego hago el resto. Con Window Form.
Código (csharp) [Seleccionar]
using System;
using System.Windows.Forms;

namespace The_Thing_La_Cosa
{
   public partial class Form1 : Form
   {
       public Form1()
       {
           InitializeComponent();
       }

       string texto = @"
PROJECTION:
IF INTRUDER ORGANISM REACHES
CIVILIZED AREAS . . .


ENTIRE WORLD POPULATION INFECTED
27,000 HOURS FROM FIRST CONTACT.
";
       int contador = 0;

       private void timer1_Tick(object sender, EventArgs e)
       {
           
          label1.Text += texto[contador++];

           if (contador >= texto.Length)
           {
               timer1.Enabled = false;
               Console.Beep(600, 25); // Console.Beep(frecuencia, duracion);
           }
       }

       private void Form1_Load(object sender, EventArgs e)
       {
           timer1.Enabled = true;
       }
   }
}


Lo intenté hacer con WPF pero no tiene el componente timer, habrá que crear hasta su propio evento y vete a saber cuántos códigos más.

Gracias por compartir.
Tutoriales Electrónica y PIC: http://electronica-pic.blogspot.com/

Eleкtro

Cita de: Meta en  5 Mayo 2019, 16:56 PM
En Windows Form el cuadro se hace directo, no poco a poco con GDI+

Lo puedes hacer como quieras, de forma directa, o dibujando una linea poco a poco (usando un For)...


Saludos.








Meta

Vale. ;)

Código no hecho por mi.

Código (csharp) [Seleccionar]
private void Form1_Load(object sender, EventArgs e)
        {
            Thread tr = new Thread(new ThreadStart(drawlines));
            tr.Start();
        }

        public delegate void Function();
        Point A = new Point(5, 5);
        Point B = new Point(5, 5);

        private void drawlines()
        {
            Thread.Sleep(1000);
            drawMarco();
            Thread.Sleep(25);
            SetText("2", "PROJECTION:");
            SetText("3", "IF INTRUDER ORGANISM REACHES");
            SetText("4", "CIVILIZED AREAS . . .");
            Thread.Sleep(100);
            SetText("7", "ENTIRE WORLD POPULATION INFECTED");
            SetText("8", "27,000 HOURS FROM FIRST CONTACT.");
            Thread.Sleep(2000);
            clrscr();
            drawMarco();
            SetText("1", "PROYECCIÓN:");
            SetText("2", "SI ORGANISMO INTRUSO ALCANZA");
            SetText("3", "ZONAS CIVILIZADAS . . . ");
            Thread.Sleep(100);
            SetText("7", "TODA LA POBLACIÓN MUNDIAL INFECTÓ");
            SetText("8", "27,000 HORAS DESDE EL PRIMER");
            SetText("9", "CONTACTO.");
            Thread.Sleep(2000);
            Application.Exit();

        }
       
        private void clrscr()
        {
            A = B;
            Graphics ps = this.CreateGraphics();
            ps.FillRectangle(new SolidBrush(Color.DarkBlue), 0,0, this.Width, this.Height);
            foreach (Control control in Controls)
            {
                this.Invoke(new Function(delegate ()
                {               
                    control.Text = "";
                }));               
            }

        }

        private void SetText(string name, string txt)
        {
            string nombre = $"label{name}";
            foreach (char letra in txt)
            {
                this.Invoke(new Function(delegate ()
                {           
               
                    Controls[nombre].Text += letra;
                }));
                Console.Beep(600, 25);
                Thread.Sleep(25);

            }
        }

       

        private void drawMarco()
        {
            for (int i = 5; i < this.Width - 20; i++)
                SetMarco(i, B.Y);           
            for (int i = 5; i < this.Height - 40; i++)
                SetMarco(B.X, i);           
            for (int i = this.Width - 20; i > 5; i--)
                 SetMarco(i, B.Y);           
            for (int i = this.Height - 40; i > 5; i--)
                 SetMarco(B.X, i);
        }

        private void SetMarco(int x,int y)
        {
            this.Invoke(new Function(delegate ()
              {
                  A = B;
                  B = new Point(x, y);
                  Graphics ps = this.CreateGraphics();
                  ps.DrawLine(new Pen(Color.Blue,3), A, B);
              }));
            Thread.Sleep(1);
        }
Tutoriales Electrónica y PIC: http://electronica-pic.blogspot.com/